proto.c
来自「Windows NT声卡驱动VXD」· C语言 代码 · 共 936 行 · 第 1/2 页
C
936 行
/*******************************************************************//* play a sample cached by the client, return boolean ok */int esd_proto_sample_play( esd_client_t *client ){ int sample_id, client_id, actual; client_id = *(int*)(client->proto_data); sample_id = maybe_swap_32( client->swap_byte_order, client_id ); ESDBG_TRACE( printf( "(%02d) proto: playing sample <%d>\n", client->fd, sample_id ); ); if ( !play_sample( sample_id, 0 ) ) sample_id = 0; ESD_WRITE_INT( client->fd, &client_id, sizeof(client_id), actual, "smp play" ); if ( sizeof( client_id ) != actual ) return 0; return 1;}/*******************************************************************//* play a sample cached by the client, return boolean ok */int esd_proto_sample_loop( esd_client_t *client ){ int sample_id, client_id, actual; client_id = *(int*)(client->proto_data); sample_id = maybe_swap_32( client->swap_byte_order, client_id ); ESDBG_TRACE( printf( "(%02d) proto: looping sample <%d>\n", client->fd, sample_id ); ); if ( !play_sample( sample_id, 1 ) ) sample_id = 0; ESD_WRITE_INT( client->fd, &client_id, sizeof(client_id), actual, "smp loop" ); if ( sizeof( sample_id ) != actual ) return 0; return 1;}/*******************************************************************//* play a sample cached by the client, return boolean ok */int esd_proto_sample_stop( esd_client_t *client ){ int sample_id, client_id, actual; client_id = *(int*)(client->proto_data); sample_id = maybe_swap_32( client->swap_byte_order, client_id ); ESDBG_TRACE( printf( "(%02d) proto: stopping sample <%d>\n", client->fd, sample_id ); ); if ( !stop_sample( sample_id ) ) sample_id = 0; ESD_WRITE_INT( client->fd, &client_id, sizeof(client_id), actual, "smp stop" ); if ( sizeof( client_id ) != actual ) return 0; return 1;}/*******************************************************************//* play a sample cached by the client, return boolean ok */int esd_proto_server_info( esd_client_t *client ){ int version, rate, format, actual; version = maybe_swap_32( client->swap_byte_order, 0 ); rate = maybe_swap_32( client->swap_byte_order, esd_audio_rate ); format = maybe_swap_32( client->swap_byte_order, esd_audio_format ); ESDBG_TRACE( printf( "(%02d) proto: server info\n", client->fd ); ); /* send back the server information */ ESD_WRITE_INT( client->fd, &version, sizeof(version), actual, "si ver" ); ESD_WRITE_INT( client->fd, &rate, sizeof(rate), actual, "si rate" ); ESD_WRITE_INT( client->fd, &format, sizeof(format), actual, "si fmt" ); if ( sizeof( format ) != actual ) return 0; return 1;}/*******************************************************************//* play a sample cached by the client, return boolean ok */int esd_proto_all_info( esd_client_t *client ){ int version, rate, left, right, format; int actual, source_id, sample_id, length; esd_player_t *player; esd_sample_t *sample; const char *name; char no_name[ ESD_NAME_MAX ] = ""; version = maybe_swap_32( client->swap_byte_order, 0 ); rate = maybe_swap_32( client->swap_byte_order, esd_audio_rate ); format = maybe_swap_32( client->swap_byte_order, esd_audio_format ); ESDBG_TRACE( printf( "(%02d) proto: server info\n", client->fd ); ); /* send back the server information */ ESD_WRITE_INT( client->fd, &version, sizeof(version), actual, "ai ver" ); ESD_WRITE_INT( client->fd, &rate, sizeof(rate), actual, "ai rate" ); ESD_WRITE_INT( client->fd, &format, sizeof(format), actual, "ai fmt" ); if ( sizeof( format ) != actual ) return 0; /* send back the player information */ for ( player = esd_players_list; /* NULL breaks */ ; player = player->next ) { if ( player ) { source_id = maybe_swap_32( client->swap_byte_order, player->source_id ); name = ( (player->format & ESD_MASK_MODE) == ESD_STREAM ) ? player->name : ( (esd_sample_t*) (player->parent) )->name; rate = maybe_swap_32( client->swap_byte_order, player->rate ); left = maybe_swap_32( client->swap_byte_order, player->left_vol_scale ); right = maybe_swap_32( client->swap_byte_order, player->right_vol_scale ); format = maybe_swap_32( client->swap_byte_order, player->format ); } else { source_id = rate = format = 0; name = no_name; } ESD_WRITE_INT( client->fd, &source_id, sizeof(source_id), actual, "ai p.id" ); ESD_WRITE_BIN( client->fd, name, ESD_NAME_MAX, actual, "ai p.nm" ); ESD_WRITE_INT( client->fd, &rate, sizeof(rate), actual, "ai p.rate" ); ESD_WRITE_INT( client->fd, &left, sizeof(left), actual, "ai p.lt" ); ESD_WRITE_INT( client->fd, &right, sizeof(right), actual, "ai p.rt" ); ESD_WRITE_INT( client->fd, &format, sizeof(format), actual, "ai p.fmt" ); if ( sizeof( format ) != actual ) return 0; if ( !player ) break; } /* send back the sample information */ for ( sample = esd_samples_list; /* NULL breaks */ ; sample = sample->next ) { if ( sample ) { sample_id = maybe_swap_32( client->swap_byte_order, sample->sample_id ); name = sample->name; rate = maybe_swap_32( client->swap_byte_order, sample->rate ); left = maybe_swap_32( client->swap_byte_order, sample->left_vol_scale ); right = maybe_swap_32( client->swap_byte_order, sample->right_vol_scale ); format = maybe_swap_32( client->swap_byte_order, sample->format ); length = maybe_swap_32( client->swap_byte_order, sample->sample_length ); } else { sample_id = rate = format = length = 0; name = no_name; } ESD_WRITE_INT( client->fd, &sample_id, sizeof(sample_id), actual, "ai s.id" ); ESD_WRITE_BIN( client->fd, name, ESD_NAME_MAX, actual, "ai s.nm" ); ESD_WRITE_INT( client->fd, &rate, sizeof(rate), actual, "ai s.rate" ); ESD_WRITE_INT( client->fd, &left, sizeof(left), actual, "ai s.lt" ); ESD_WRITE_INT( client->fd, &right, sizeof(right), actual, "ai s.rt" ); ESD_WRITE_INT( client->fd, &format, sizeof(format), actual, "ai s.fmt" ); ESD_WRITE_INT( client->fd, &length, sizeof(length), actual, "ai s.fmt" ); if ( sizeof( length ) != actual ) return 0; if ( !sample ) break; } return 1;}/*******************************************************************//* set the stereo panning for a stream */int esd_proto_stream_pan( esd_client_t *client ){ int client_id, client_left, client_right, client_ok, actual; int stream_id, left, right, ok; esd_player_t *player; client_id = *(int*)(client->proto_data); client_left = *(int*)(client->proto_data + sizeof(int)); client_right = *(int*)(client->proto_data + 2 * sizeof(int)); stream_id = maybe_swap_32( client->swap_byte_order, client_id ); left = maybe_swap_32( client->swap_byte_order, client_left ); right = maybe_swap_32( client->swap_byte_order, client_right ); ESDBG_TRACE( printf( "(%02d) proto: panning stream <%d> [%d, %d]\n", client->fd, stream_id, left, right ); ); /* find the stream, and reset panning */ ok = 0; for ( player = esd_players_list ; player != NULL ; player = player->next ) { if ( player->source_id == stream_id && ( (player->format & ESD_MASK_MODE) == ESD_STREAM ) ) { player->left_vol_scale = left; player->right_vol_scale = right; player->mix_func = get_mix_func( player ); ok = 1; break; } } /* let the client know how it went */ client_ok = maybe_swap_32( client->swap_byte_order, ok ); ESD_WRITE_INT( client->fd, &client_ok, sizeof(client_ok), actual, "panstr ok" ); if ( sizeof( client_ok ) != actual ) return 0; return 1;}/*******************************************************************//* set the default panning for a stream */int esd_proto_sample_pan( esd_client_t *client ){ int client_id, client_left, client_right, client_ok, actual; int sample_id, left, right, ok; esd_sample_t *sample; client_id = *(int*)(client->proto_data); client_left = *(int*)(client->proto_data + sizeof(int)); client_right = *(int*)(client->proto_data + 2 * sizeof(int)); sample_id = maybe_swap_32( client->swap_byte_order, client_id ); left = maybe_swap_32( client->swap_byte_order, client_left ); right = maybe_swap_32( client->swap_byte_order, client_right ); ESDBG_TRACE( printf( "(%02d) proto: panning sample <%d> [%d, %d]\n", client->fd, sample_id, left, right ); ); /* find the stream, and reset panning */ ok = 0; for ( sample = esd_samples_list ; sample != NULL ; sample = sample->next ) { if ( sample->sample_id == sample_id ) { sample->left_vol_scale = left; sample->right_vol_scale = right; ok = 1; break; } } /* let the client know how it went */ client_ok = maybe_swap_32( client->swap_byte_order, ok ); ESD_WRITE_INT( client->fd, &client_ok, sizeof(client_ok), actual, "panstr ok" ); if ( sizeof( client_ok ) != actual ) return 0; return 1;}/*******************************************************************//* daemon rejects untrusted clients, return boolean ok */int esd_proto_standby_mode( esd_client_t *client ){ int ok = 1, mode, client_mode, actual; if ( esd_on_autostandby && !esd_forced_standby ) mode = ESM_ON_AUTOSTANDBY; else if ( esd_on_standby ) mode = ESM_ON_STANDBY; else mode = ESM_RUNNING; client_mode = maybe_swap_32( client->swap_byte_order, mode ); ESDBG_TRACE( printf( "(%02d) getting standby mode\n", client->fd ); ); ESD_WRITE_INT( client->fd, &client_mode, sizeof(client_mode), actual, "stby mode" ); if ( sizeof( client_mode ) != actual ) return 0; return ok;}/*******************************************************************//* checks for new client requiests - returns 1 */int poll_client_requests(){ int can_read, length = 0, is_ok = 0; esd_client_t *client = NULL; esd_client_t *erase = NULL; fd_set rd_fds; struct timeval timeout; /* check all clients, as some may become readable between the previous blocking select() and now */ /* for each client */ client = esd_clients_list; while ( client != NULL ) { /* if it's a streaming client connection, just skip it data will be read (if available) during the mix phase */ if ( client->state == ESD_STREAMING_DATA ) { client = client->next; continue; } /* find out if this client wants to do anything yet */ timeout.tv_sec = 0; timeout.tv_usec = 0; FD_ZERO( &rd_fds ); FD_SET( client->fd, &rd_fds ); can_read = select( client->fd + 1, &rd_fds, NULL, NULL, &timeout ); if ( !can_read ) { client = client->next; continue; } /* see what the client needs to do next */ ESDBG_TRACE( printf( "(%02d) client state %d.\n", client->fd, client->state ); ); switch ( client->state ) { case ESD_NEEDS_REQDATA: /* check for insanity */ if ( client->proto_data_length > esd_proto_map[ client->request ].data_length ) { ESDBG_TRACE( printf( "(%02d) REQDATA insanity detected, expecting %d, got %d\n", client->fd, esd_proto_map[ client->request ].data_length, client->proto_data_length); ); is_ok = 0; break; } /* read another chunk of data, if any more is required */ if ( esd_proto_map[ client->request ].data_length ) { ESD_READ_BIN( client->fd, client->proto_data + client->proto_data_length, esd_proto_map[ client->request ].data_length - client->proto_data_length , length, "req dat" ); client->proto_data_length += length; } /* check length, as EOF returns readable */ if ( !length || ( length < 0 && errno != EAGAIN && errno != EINTR ) ) { ESDBG_TRACE( printf( "(%02d) interrupted request %d, %s.\n", client->fd, client->request, esd_proto_map[ client->request ].description ); ); is_ok = 0; break; } /* see if we have it all */ if ( client->proto_data_length == esd_proto_map[ client->request ].data_length ) { ESDBG_TRACE( printf( "(%02d) handling request %d, %s.\n", client->fd, client->request, esd_proto_map[ client->request ].description ); ); client->state = ESD_NEXT_REQUEST; /* handler may override */ is_ok = esd_proto_map[ client->request ].handler( client ); } else { ESDBG_TRACE( printf( "(%02d) need more data.\n", client->fd ); ); is_ok = 1; } break; case ESD_NEXT_REQUEST: /* make sure there's a request as EOF may return as readable */ ESDBG_COMMS( printf( "--------------------------------\n" ); ); ESD_READ_INT( client->fd, &client->request, sizeof(client->request), length, "request" ); if ( client->swap_byte_order ) client->request = swap_endian_32( client->request ); if ( length == 0 || ( length < 0 && errno != EAGAIN && errno != EINTR ) ) { /* no more data available from that client, close it */ ESDBG_TRACE( printf( "(%02d) no more protocol requests for client\n", client->fd ); ); is_ok = 0; break; } else if ( client->request > ESD_PROTO_CONNECT && client->request < ESD_PROTO_MAX ) { /* set up to read more data */ client->state = ESD_NEEDS_REQDATA; client->proto_data_length = 0; /* TODO: do one read, and handle if we get all the data */ /* this should fix the "all handlers requrie data oddity */ is_ok = 1; } else { ESDBG_TRACE( printf( "(%02d) invalid request: %d\n", client->fd, client->request ); ); is_ok = 0; } break; default: ESDBG_TRACE( printf( "(%02d) invalid state: %d\n", client->fd, client->state ); ); is_ok = 0; } /* if there was a problem, erase the client */ if ( !is_ok ) { ESDBG_TRACE( printf( "(%02d) error handling request %d, %s.\n", client->fd, client->request, esd_proto_map[ client->request ].description ); ); erase = client; } /* update the iterator before removing */ client = client->next; if ( erase != NULL ) { erase_client( erase ); erase = NULL; } } return 1;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?