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 + -
显示快捷键?