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