players.c

来自「Windows NT声卡驱动VXD」· C语言 代码 · 共 581 行 · 第 1/2 页

C
581
字号
#include "esd-server.h"#include <errno.h>/*******************************************************************//* globals */esd_player_t *esd_players_list = NULL;esd_player_t *esd_recorder = NULL;esd_player_t *esd_monitor_list = NULL;/*******************************************************************//* for debugging purposes, dump the list of the clients and data */void dump_players(){    esd_player_t *player = esd_players_list;    if ( !esdbg_trace ) return;    while ( player != NULL ) {	printf( "-%02d- player: [%p]\n", 		player->source_id, player );	player = player->next;    }    return;}/*******************************************************************//* deallocate memory for the player */void free_player( esd_player_t *player ){    esd_sample_t *sample;    /* see if we need to do any housekeeping */    if ( ( player->format & ESD_MASK_MODE ) == ESD_STREAM ) {	/* TODO: erase client should be independent of players */	erase_client( player->parent );    } else if ( ( player->format & ESD_MASK_MODE ) == ESD_SAMPLE ) {	sample = (esd_sample_t *) (player->parent);	sample->ref_count--;	esd_playing_samples--;	ESDBG_TRACE( printf( "<%02d> free player: [%p] refs=%d erase?=%d samps=%d\n", 			     player->source_id, player, sample->ref_count, 			     sample->erase_when_done, esd_playing_samples ); );	if ( sample->erase_when_done && !sample->ref_count ) {	    ESDBG_TRACE( printf( "<%02d> free_player: erasing sample\n", 				 sample->sample_id ); );	    erase_sample( sample->sample_id, 0 );	}    }    /* free any memory allocated with the player */    free( player->data_buffer );    /* free the player memory itself */    free( player );    return;}/*******************************************************************//* add a complete new player into the list of players at head */void add_player( esd_player_t *player ){    /* printf ( "adding player %p\n", new_player ); */    if ( !player ) {	ESDBG_TRACE( printf( "<NIL> can't add non-existent player!\n" ); );	return;    }    player->next = esd_players_list;    esd_players_list = player;    return;}/*******************************************************************//* erase a player from the player list */void erase_player( esd_player_t *player ){    esd_player_t *previous = NULL;    esd_player_t *current = esd_players_list;    /* iterate until we hit a NULL */    while ( current != NULL )    {	/* see if we hit the target player */	if ( current == player ) {	    if( previous != NULL ){		/* we are deleting in the middle of the list */		previous->next = current->next;	    } else { 		/* we are deleting the head of the list */		esd_players_list = current->next;	    }	    /* TODO: delete if needed */	    free_player( player );	    return;	}	/* iterate through the list */	previous = current;	current = current->next;    }    /* hmm, we didn't find the desired player, just get on with life */    ESDBG_TRACE( printf( "-%02d- player not found\n", player->source_id ); );    return;}/*******************************************************************//* erase a monitor from the monitor list */void erase_monitor( esd_player_t *monitor ){    esd_player_t *previous = NULL;    esd_player_t *current = esd_monitor_list;    /* iterate until we hit a NULL */    while ( current != NULL )    {	/* see if we hit the target monitor */	if ( current == monitor ) {	    if( previous != NULL ){		/* we are deleting in the middle of the list */		previous->next = current->next;	    } else { 		/* we are deleting the head of the list */		esd_monitor_list = current->next;	    }	    /* TODO: delete if needed */	    free_player( monitor );	    return;	}	/* iterate through the list */	previous = current;	current = current->next;    }    /* hmm, we didn't find the desired monitor, just get on with life */    ESDBG_TRACE( printf( "-%02d- monitor not found\n", monitor->source_id ); );    return;}/*******************************************************************//* write block of data from client, return < 0 to have it erased */int write_player( esd_player_t *player, void *src_buffer, int src_length, 		  int src_rate, int src_format ){    fd_set wr_fds;    int length = 0, actual = 0, can_write = 0;    struct timeval timeout;    char message[ 100 ];    short data, *pos; /* used for swapping */    esd_client_t *client;    short *buffer;    /* use select to prevent blocking clients that are ready */    timeout.tv_sec = 0;    timeout.tv_usec = 0;    FD_ZERO( &wr_fds );    FD_SET( player->source_id, &wr_fds );        /* if the data is ready, read a block */    can_write = select( player->source_id + 1, 			NULL, &wr_fds, NULL, &timeout ) ;    if ( can_write > 0 )    {	/* translate the data */	length = player->translate_func( player->data_buffer, 					 player->buffer_length, 					 player->rate, 					 player->format, 					 src_buffer, 					 src_length, 					 src_rate, 					 src_format );	/* endian swap multi-byte data if we need to */	client = (esd_client_t *) (player->parent);	if ( client->swap_byte_order 	     && ( (player->format & ESD_MASK_BITS) == ESD_BITS16 ) )	{	    printf( "swapping...\n" );	    buffer = (short*) player->data_buffer;	    for ( pos = buffer 		      ; pos < buffer + length / sizeof(short)		      ; pos += sizeof(short) )	    {		data = swap_endian_16( (*pos) );		*pos = data;	    }	}	/* write out the data */	ESD_WRITE_BIN( player->source_id, player->data_buffer, 		       player->buffer_length, length, "str rd" );    } else if ( can_write < 0 ) {	sprintf( message, "error writing client (%d)\n", 		 player->source_id );	perror( message );	return -1;    }    /* check for end of stream */    if ( length < 0 ) return -1;    if ( length == 0 ) return 0;     return actual;}/*******************************************************************//* read block of data from client, return < 0 to have it erased */int read_player( esd_player_t *player ){    fd_set rd_fds;    int actual = 0, actual_2nd = 0, can_read = 0;    struct timeval timeout;    char message[ 100 ];    short data, *pos; /* used for swapping */    esd_client_t *client;    short *buffer;    switch( player->format & ESD_MASK_MODE ) {    case ESD_STREAM:	/* use select to prevent blocking clients that are ready */	timeout.tv_sec = 0;	timeout.tv_usec = 0;	FD_ZERO( &rd_fds );	FD_SET( player->source_id, &rd_fds );	/* if the data is ready, read a block */	can_read = select( player->source_id + 1, 			   &rd_fds, NULL, NULL, &timeout ) ;	if ( can_read > 0 )	{	    ESD_READ_BIN( player->source_id, player->data_buffer, 			  player->buffer_length, actual, "str rd" );	    /* check for end of stream */	    if ( actual == 0 		 || ( actual < 0 && errno != EAGAIN && errno != EINTR ) )		return -1; 	    /* more data, save how much we got */	    player->actual_length = actual;	    /* endian swap multi-byte data if we need to */	    client = (esd_client_t *) (player->parent);	    if ( client->swap_byte_order 		 && ( (player->format & ESD_MASK_BITS) == ESD_BITS16 ) )	    {		printf( "swapping...\n" );		buffer = (short*) player->data_buffer;		for ( pos = buffer 			  ; pos < buffer + actual / sizeof(short)			  ; pos += sizeof(short) )		{		    data = swap_endian_16( (*pos) );		    *pos = data;		}	    }	} else if ( can_read < 0 ) {	    sprintf( message, "error reading client (%d)\n", 		     player->source_id );	    perror( message );	    return -1;	}	break;    case ESD_SAMPLE:	/* printf( "player [%p], pos = %d, format = 0x%08x\n", 		player, player->last_pos, player->format ); */		/* only keep going if we didn't want to stop looping */	if ( ( player->last_pos ) == 0 &&	    ( ( ((esd_sample_t*)player->parent)->format & ESD_MASK_FUNC ) 	      == ESD_STOP ) ) 	{

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?