static void mix_init (int *esd, int *player) { esd_info_t *all_info; esd_player_info_t *player_info; if (*esd < 0 && (*esd = esd_open_sound (NULL)) < 0) return; if (*player < 0) { all_info = esd_get_all_info (*esd); if (all_info) { for (player_info = all_info->player_list; player_info; player_info = player_info->next) if (!strcmp(player_info->name, ident)) { *player = player_info->source_id; break; } esd_free_all_info (all_info); } } }
static int ao_esd_get_property (ao_driver_t *this_gen, int property) { esd_driver_t *this = (esd_driver_t *) this_gen; int mixer_fd; esd_player_info_t *esd_pi; esd_info_t *esd_i; switch(property) { case AO_PROP_MIXER_VOL: if((mixer_fd = esd_open_sound(NULL)) >= 0) { if((esd_i = esd_get_all_info(mixer_fd)) != NULL) { for(esd_pi = esd_i->player_list; esd_pi != NULL; esd_pi = esd_pi->next) { if(!strcmp(this->pname, esd_pi->name)) { this->mixer.source_id = esd_pi->source_id; if(!this->mixer.mute) this->mixer.volume = (((esd_pi->left_vol_scale * 100) / 256) + ((esd_pi->right_vol_scale * 100) / 256)) >> 1; } } esd_free_all_info(esd_i); } esd_close(mixer_fd); } return this->mixer.volume; break; case AO_PROP_MUTE_VOL: return this->mixer.mute; break; }
int mixctl (int fd, request_t request, void *argp) { static int esd = -1, player = -1; static int left, right; int *arg = (int *) argp; DPRINTF ("hijacking /dev/mixer ioctl, and sending it to esd " "(%d : %x - %p)\n", fd, request, argp); switch (request) { case SOUND_MIXER_READ_DEVMASK: *arg = 5113; break; case SOUND_MIXER_READ_PCM: mix_init (&esd, &player); if (player > 0) { esd_info_t *all_info; all_info = esd_get_all_info (esd); if (all_info) { esd_player_info_t *player_info; for (player_info = all_info->player_list; player_info; player_info = player_info->next) if (player_info->source_id == player) { *arg = ESD_VOL_TO_OSS (player_info->left_vol_scale, player_info->right_vol_scale); } esd_free_all_info (all_info); } else return -1; } else { get_volume (&left, &right); *arg = ESD_VOL_TO_OSS (left, right); } break; case SOUND_MIXER_WRITE_PCM: mix_init (&esd, &player); left = OSS_VOL_TO_ESD_LEFT (*arg); right = OSS_VOL_TO_ESD_RIGHT (*arg); set_volume (left, right); if (player > 0) { DPRINTF ("panning %d - %d %d\n", player, left, right); esd_set_stream_pan (esd, player, left, right); } break; default: DPRINTF ("unhandled /dev/mixer ioctl (%x - %p)\n", request, argp); break; } return 0; }
/* * to set/get/query special features/parameters */ static int control(int cmd, void *arg) { esd_player_info_t *esd_pi; esd_info_t *esd_i; time_t now; static time_t vol_cache_time; static ao_control_vol_t vol_cache; switch (cmd) { case AOCONTROL_GET_VOLUME: time(&now); if (now == vol_cache_time) { *(ao_control_vol_t *)arg = vol_cache; return CONTROL_OK; } dprintf("esd: get vol\n"); if ((esd_i = esd_get_all_info(esd_fd)) == NULL) return CONTROL_ERROR; for (esd_pi = esd_i->player_list; esd_pi != NULL; esd_pi = esd_pi->next) if (strcmp(esd_pi->name, ESD_CLIENT_NAME) == 0) break; if (esd_pi != NULL) { ao_control_vol_t *vol = (ao_control_vol_t *)arg; vol->left = esd_pi->left_vol_scale * 100 / ESD_VOLUME_BASE; vol->right = esd_pi->right_vol_scale * 100 / ESD_VOLUME_BASE; vol_cache = *vol; vol_cache_time = now; } esd_free_all_info(esd_i); return CONTROL_OK; case AOCONTROL_SET_VOLUME: dprintf("esd: set vol\n"); if ((esd_i = esd_get_all_info(esd_fd)) == NULL) return CONTROL_ERROR; for (esd_pi = esd_i->player_list; esd_pi != NULL; esd_pi = esd_pi->next) if (strcmp(esd_pi->name, ESD_CLIENT_NAME) == 0) break; if (esd_pi != NULL) { ao_control_vol_t *vol = (ao_control_vol_t *)arg; esd_set_stream_pan(esd_fd, esd_pi->source_id, vol->left * ESD_VOLUME_BASE / 100, vol->right * ESD_VOLUME_BASE / 100); vol_cache = *vol; time(&vol_cache_time); } esd_free_all_info(esd_i); return CONTROL_OK; default: return CONTROL_UNKNOWN; } }
/* retrieve all information from server */ esd_info_t *esd_get_all_info( int esd ) { int proto = ESD_PROTO_ALL_INFO; int version = 0; esd_server_info_t *server_info; esd_player_info_t *player_info; esd_sample_info_t *sample_info; /* allocate the entire info structure, and set defaults to NULL */ esd_info_t *info = (esd_info_t *) malloc( sizeof(esd_info_t) ); info->player_list = NULL; info->sample_list = NULL; /* allocate the server info structure */ server_info = (esd_server_info_t *) malloc( sizeof(esd_server_info_t) ); if ( !server_info ) { esd_free_all_info( info ); return NULL; } /* tell the server to cough up the info */ write( esd, &proto, sizeof(proto) ); if ( write( esd, &version, sizeof(version) ) != sizeof(version) ) { esd_free_all_info( info ); free( server_info ); return NULL; } /* get the server info */ read( esd, &server_info->version, sizeof(server_info->version) ); read( esd, &server_info->rate, sizeof(server_info->rate) ); if ( read( esd, &server_info->format, sizeof(server_info->format) ) != sizeof(server_info->format) ) { esd_free_all_info( info ); free( server_info ); return NULL; } info->server = server_info; /* get the player info */ do { player_info = (esd_player_info_t *) malloc( sizeof(esd_player_info_t) ); if ( !player_info ) { esd_free_all_info( info ); return NULL; } read( esd, &player_info->source_id, sizeof(player_info->source_id) ); read( esd, &player_info->name, ESD_NAME_MAX ); player_info->name[ ESD_NAME_MAX - 1 ] = '\0'; read( esd, &player_info->rate, sizeof(player_info->rate) ); read( esd, &player_info->left_vol_scale, sizeof(player_info->left_vol_scale) ); read( esd, &player_info->right_vol_scale, sizeof(player_info->right_vol_scale) ); if ( read( esd, &player_info->format, sizeof(player_info->format) ) != sizeof(player_info->format) ) { free( player_info ); esd_free_all_info( info ); return NULL; } if ( player_info->source_id > 0 ) { player_info->next = info->player_list; info->player_list = player_info; } } while( player_info->source_id > 0 ); free( player_info ); /* get the sample info */ do { sample_info = (esd_sample_info_t *) malloc( sizeof(esd_sample_info_t) ); if ( !sample_info ) { esd_free_all_info( info ); return NULL; } read( esd, &sample_info->sample_id, sizeof(sample_info->sample_id) ); read( esd, &sample_info->name, ESD_NAME_MAX ); sample_info->name[ ESD_NAME_MAX - 1 ] = '\0'; read( esd, &sample_info->rate, sizeof(sample_info->rate) ); read( esd, &sample_info->left_vol_scale, sizeof(sample_info->left_vol_scale) ); read( esd, &sample_info->right_vol_scale, sizeof(sample_info->right_vol_scale) ); read( esd, &sample_info->format, sizeof(sample_info->format) ); if ( read( esd, &sample_info->length, sizeof(sample_info->length) ) != sizeof(sample_info->length) ) { free( sample_info ); esd_free_all_info( info ); return NULL; } if ( sample_info->sample_id > 0 ) { sample_info->next = info->sample_list; info->sample_list = sample_info; } } while( sample_info->sample_id > 0 ); free( sample_info ); return info; }