int eDVBVolumecontrol::openMixer() { #ifdef HAVE_ALSA if (!mainVolume) { int err; char *card = "default"; /* Perform the necessary pre-amble to start up ALSA Mixer */ err = snd_mixer_open(&alsaMixerHandle, 0); if (err < 0) { eDebug("Mixer %s open error: %s", card, snd_strerror(err)); return err; } err = snd_mixer_attach(alsaMixerHandle, card); if (err < 0) { eDebug("Mixer attach %s error: %s", card, snd_strerror(err)); snd_mixer_close(alsaMixerHandle); alsaMixerHandle = NULL; return err; } err = snd_mixer_selem_register(alsaMixerHandle, NULL, NULL); if (err < 0) { eDebug("Mixer register error: %s", snd_strerror(err)); snd_mixer_close(alsaMixerHandle); alsaMixerHandle = NULL; return err; } err = snd_mixer_load(alsaMixerHandle); if (err < 0) { eDebug("Mixer %s load error: %s", card, snd_strerror(err)); snd_mixer_close(alsaMixerHandle); alsaMixerHandle = NULL; return err; } /* Set up Decoder 0 as the main volume control. */ snd_mixer_selem_id_t *sid; snd_mixer_selem_id_alloca(&sid); snd_mixer_selem_id_set_name(sid, ALSA_VOLUME_MIXER); snd_mixer_selem_id_set_index(sid, 0); mainVolume = snd_mixer_find_selem(alsaMixerHandle, sid); } return mainVolume ? 0 : -1; #else return open( AUDIO_DEV, O_RDWR ); #endif }
int get_vol_mute(long* vol, int* mute) { snd_mixer_t* handle; int open_code = snd_mixer_open(&handle, 0); if (open_code != 0) return open_code; int attach_code = snd_mixer_attach(handle, "default"); if (attach_code != 0) { snd_mixer_close(handle); return attach_code; } int register_code = snd_mixer_selem_register(handle, NULL, NULL); if (register_code != 0) { cleanup_handle(handle); return register_code; } int load_code = snd_mixer_load(handle); if (load_code != 0) { cleanup_handle(handle); return load_code; } snd_mixer_selem_id_t *sid; snd_mixer_selem_id_alloca(&sid); snd_mixer_selem_id_set_index(sid, 0); snd_mixer_selem_id_set_name(sid, "Master"); snd_mixer_elem_t* elem = snd_mixer_find_selem(handle, sid); if (elem == 0) { cleanup_handle(handle); return 1; } int vol_code = snd_mixer_selem_get_playback_dB(elem, SND_MIXER_SCHN_UNKNOWN, vol); if (vol_code != 0) { cleanup_handle(handle); return vol_code; } int switch_code = snd_mixer_selem_get_playback_switch(elem, SND_MIXER_SCHN_UNKNOWN, mute); if (switch_code != 0) { cleanup_handle(handle); return switch_code; } /* snd_mixer_selem_id_free(sid); */ snd_mixer_detach(handle, "default"); snd_mixer_close(handle); return 0; }
snd_mixer_elem_t* AmeSystemSound::getMixerElem(snd_mixer_t *mixer, char *name, int index) { snd_mixer_selem_id_t* selem_id; snd_mixer_elem_t* elem; snd_mixer_selem_id_alloca(&selem_id); if (index != -1) snd_mixer_selem_id_set_index(selem_id, index); if (name != NULL) snd_mixer_selem_id_set_name(selem_id, name); elem = snd_mixer_find_selem(mixer, selem_id); return elem; }
/* Retrieve a mixer element by name * * \param mixer The mixer to search the element from * \param element_name The element name to search for */ snd_mixer_elem_t *mixer_get_element(snd_mixer_t *mixer, const char *element_name) { pa_assert(mixer); pa_assert(element_name); snd_mixer_selem_id_t *sid = NULL; snd_mixer_elem_t *mixer_element = NULL; snd_mixer_selem_id_alloca(&sid); snd_mixer_selem_id_set_name(sid, element_name); snd_mixer_selem_id_set_index(sid, 0); mixer_element = snd_mixer_find_selem(mixer, sid); return mixer_element; }
long AudioALSA::getVolume() const { snd_mixer_t* handle; snd_mixer_elem_t* elem; snd_mixer_selem_id_t* sid; // Open sound card snd_mixer_selem_id_alloca(&sid); snd_mixer_selem_id_set_index(sid, this->mixIndex); snd_mixer_selem_id_set_name(sid, this->mixName.c_str()); if (snd_mixer_open(&handle, 0) < 0) { throw std::runtime_error("Error while mixer channel \"" + mixName + "\" opening"); } if (snd_mixer_attach(handle, this->card.c_str())) { snd_mixer_close(handle); throw std::runtime_error("Error while attaching soundcard \"" + card + "\" to mixer"); } if (snd_mixer_selem_register(handle, NULL, NULL) < 0) { snd_mixer_close(handle); throw std::runtime_error("Error while mixer channel registering"); } if (snd_mixer_load(handle) < 0) { snd_mixer_close(handle); throw std::runtime_error("Error while loading mixer elements"); } elem = snd_mixer_find_selem(handle, sid); if (!elem) { snd_mixer_close(handle); throw std::runtime_error("Error while finding mixer element"); } // Get sound volume long volume, vmin, vmax; snd_mixer_selem_get_playback_volume_range(elem, &vmin, &vmax); if (snd_mixer_selem_get_playback_volume(elem, SND_MIXER_SCHN_FRONT_LEFT, &volume) < 0) { snd_mixer_close(handle); throw std::runtime_error("Error while getting playback volume"); } volume -= vmin; vmax -= vmin; volume = 100 * volume / vmax; snd_mixer_close(handle); return volume; }
bool AlsaMixer::GetChannelSwitch( const char* channel, bool* on ) { bool success = false; snd_mixer_elem_t *elem; snd_mixer_selem_id_t *sid; snd_mixer_selem_id_alloca(&sid); snd_mixer_selem_id_set_index( sid, 0); snd_mixer_selem_id_set_name( sid, channel); elem = snd_mixer_find_selem(_handle, sid); if (!elem) { LOG( Logger::LOG_ERROR, "Unable to find simple control '%s',%i\n", snd_mixer_selem_id_get_name(sid), snd_mixer_selem_id_get_index(sid)); goto end; } if( snd_mixer_selem_has_playback_switch(elem) ) { for (int chn = 0; chn <= SND_MIXER_SCHN_LAST; chn++) { int value; if (snd_mixer_selem_get_playback_switch(elem, (snd_mixer_selem_channel_id_t)chn, &value) >= 0) { *on = value != 0; success = true; break; } } }else if( snd_mixer_selem_has_capture_switch(elem) ) { for (int chn = 0; chn <= SND_MIXER_SCHN_LAST; chn++) { int value; if (snd_mixer_selem_get_capture_switch(elem, (snd_mixer_selem_channel_id_t)chn, &value ) >= 0) { *on = value != 0; success = true; break; } } } if( !success ) { LOG( Logger::LOG_ERROR, "Error getting control '%s',%i\n", snd_mixer_selem_id_get_name(sid), snd_mixer_selem_id_get_index(sid)); } end: return success; }
/* API: set capability */ static pj_status_t alsa_stream_set_cap(pjmedia_aud_stream *strm, pjmedia_aud_dev_cap cap, const void *value) { struct alsa_factory *af = ((struct alsa_stream*)strm)->af; if (cap==PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING && pj_ansi_strlen(af->pb_mixer_name)) { pj_ssize_t min, max; snd_mixer_t *handle; snd_mixer_selem_id_t *sid; snd_mixer_elem_t* elem; unsigned vol = *(unsigned*)value; if (snd_mixer_open(&handle, 0) < 0) return PJMEDIA_EAUD_SYSERR; if (snd_mixer_attach(handle, "default") < 0) return PJMEDIA_EAUD_SYSERR; if (snd_mixer_selem_register(handle, NULL, NULL) < 0) return PJMEDIA_EAUD_SYSERR; if (snd_mixer_load(handle) < 0) return PJMEDIA_EAUD_SYSERR; snd_mixer_selem_id_alloca(&sid); snd_mixer_selem_id_set_index(sid, 0); snd_mixer_selem_id_set_name(sid, af->pb_mixer_name); elem = snd_mixer_find_selem(handle, sid); if (!elem) return PJMEDIA_EAUD_SYSERR; snd_mixer_selem_get_playback_volume_range(elem, &min, &max); if (snd_mixer_selem_set_playback_volume_all(elem, vol * max / 100) < 0) return PJMEDIA_EAUD_SYSERR; snd_mixer_close(handle); return PJ_SUCCESS; } return PJMEDIA_EAUD_INVCAP; }
sound_ops_t * alsa_probe( int exact ) { snd_pcm_t *pcm; const char *name = alsa_devname(0); if( !snd_mixer_open(&alsa.mixer, 0) ) { snd_mixer_selem_id_t *selem_id; const char *s, *mixername = get_str_res("alsa.mixer"); const char *devname = alsa_devname(1); int mixerindex=0; if( (s=get_str_res_ind("alsa.mixer", 0, 1)) ) mixerindex = atoi(s); if( mixername ) printm("Using ALSA mixer %s %d (mixerdevice '%s')\n", mixername, mixerindex, devname ); if( !mixername ) mixername = "PCM"; snd_mixer_selem_id_alloca( &selem_id ); snd_mixer_selem_id_set_index( selem_id, mixerindex ); snd_mixer_selem_id_set_name( selem_id, mixername ); int err = snd_mixer_attach( alsa.mixer, devname ) || snd_mixer_selem_register( alsa.mixer, NULL, NULL ) || snd_mixer_load( alsa.mixer ); if( !err ) alsa.pcm_elem=snd_mixer_find_selem( alsa.mixer, selem_id ); if( alsa.pcm_elem ) snd_mixer_selem_set_playback_volume_range( alsa.pcm_elem, 0, 0xff ); } if( !snd_pcm_open(&pcm, name, SND_PCM_STREAM_PLAYBACK, 1 * SND_PCM_NONBLOCK) ) snd_pcm_close( pcm ); else if( !exact ) return NULL; else printm("ALSA device unavailable (will be used anyway)\n"); printm("ALSA sound driver loaded (device '%s')\n", name); if( !alsa.pcm_elem ) printm("ALSA: failed to setup mixer\n"); return &alsa_driver_ops; }
int audio_set_volume( long volume ) { // int infos[3]; // int infos; long min, max; snd_mixer_t *handle; snd_mixer_selem_id_t *sid; const char *card = "default";//Ensoniq AudioPCI const char *selem_name = "Master"; char response[255] = { 0 }; snd_mixer_open(&handle, 0); snd_mixer_attach(handle, card); snd_mixer_selem_register(handle, NULL, NULL); snd_mixer_load(handle); snd_mixer_selem_id_alloca(&sid); snd_mixer_selem_id_set_index(sid, 0); snd_mixer_selem_id_set_name(sid, selem_name); snd_mixer_elem_t* elem = snd_mixer_find_selem(handle, sid); snd_mixer_selem_get_playback_volume_range(elem, &min, &max); snd_mixer_selem_set_playback_volume_all(elem, volume * max / 100); snd_mixer_close(handle); snprintf( response , 255 , "OK"); sendVoid( ( void * )response , strlen( response ) ); //Sending the info to the remote // infos[0] = CURRENTVOL; // infos[1] = ( int )volume; // infos[2] = END; // infos = CURRENTVOL; // sendVoid( ( void * )&infos , sizeof( infos ) ); // infos = ( int )volume; // sendVoid( ( void * )&infos , sizeof( infos ) ); // infos = END; // sendVoid( ( void * )&infos , sizeof( infos ) ); }
struct alsa_control_struct GetStruct(const char* card, const char* selem_name) { struct alsa_control_struct c_struct; snd_mixer_t *handle; snd_mixer_selem_id_t *sid; snd_mixer_open(&handle, 0); snd_mixer_attach(handle, card); snd_mixer_selem_register(handle, NULL, NULL); snd_mixer_load(handle); snd_mixer_selem_id_alloca(&sid); snd_mixer_selem_id_set_index(sid, 0); snd_mixer_selem_id_set_name(sid, selem_name); snd_mixer_elem_t* elem = snd_mixer_find_selem(handle, sid); c_struct.handle = handle; c_struct.elem = elem; return c_struct; }
void SetAlsaMasterVolume(long volume) { long min, max; snd_mixer_t *handle; snd_mixer_selem_id_t *sid; const char *card = "default"; const char *selem_name = "Master"; snd_mixer_open(&handle, 0); snd_mixer_attach(handle, card); snd_mixer_selem_register(handle, NULL, NULL); snd_mixer_load(handle); snd_mixer_selem_id_alloca(&sid); snd_mixer_selem_id_set_index(sid, 0); snd_mixer_selem_id_set_name(sid, selem_name); snd_mixer_elem_t *elem = snd_mixer_find_selem(handle, sid); snd_mixer_selem_get_playback_volume_range(elem, &min, &max); snd_mixer_selem_set_playback_volume_all(elem, volume * max / 100); snd_mixer_close(handle); }
static void set_headphones_plugged(int* plugged) { snd_mixer_t *handle; snd_mixer_open(&handle, 0); snd_mixer_attach(handle, Y50_CTL_NAME); snd_mixer_selem_register(handle, NULL, NULL); snd_mixer_load(handle); snd_mixer_selem_id_t *headphone_sid; const char *headphone_selem_name = "Headphone"; snd_mixer_selem_id_alloca(&headphone_sid); snd_mixer_selem_id_set_index(headphone_sid, 0); snd_mixer_selem_id_set_name(headphone_sid, headphone_selem_name); snd_mixer_elem_t *elem = snd_mixer_find_selem(handle, headphone_sid); snd_mixer_selem_get_playback_switch(elem, SND_MIXER_SCHN_MONO, plugged); snd_mixer_close(handle); }
void VolumeControl::setupAlsa(){ const char *card = "default"; const char *selem_name = "Master";//or Master if(snd_mixer_open(&handle, 0) == 0 ) mixer_opened = true; if(mixer_opened){ //std::cout << "Mixer Opened" << std::endl; snd_config_update_free_global();//should make valgrind STFU snd_mixer_attach(handle, card); snd_mixer_selem_register(handle, NULL, NULL); snd_mixer_load(handle); snd_mixer_selem_id_alloca(&sid); snd_mixer_selem_id_set_index(sid, 0); snd_mixer_selem_id_set_name(sid, selem_name); elem = snd_mixer_find_selem(handle, sid); snd_mixer_selem_get_playback_volume_range(elem, &min, &max); //std::cout << "Min:" << min << " Max:" << max << std::endl; snd_config_update_free_global();//should make valgrind STFU }else{ std::cout << "Failed to open mixer" << std::endl; } }
/* * Class: org_tritonus_lowlevel_alsa_AlsaMixerElement * Method: open * Signature: (Lorg/tritonus/lowlevel/alsa/AlsaMixer;ILjava/lang/String;)I */ JNIEXPORT jint JNICALL Java_org_tritonus_lowlevel_alsa_AlsaMixerElement_open (JNIEnv *env, jobject obj, jobject mixer, jint nIndex, jstring strName) { snd_mixer_elem_t* handle; snd_mixer_t* mixerHandle; snd_mixer_selem_id_t* id; int nReturn; const char* name; if (debug_flag) { (void) fprintf(debug_file, "Java_org_tritonus_lowlevel_alsa_AlsaMixerElement_open(): begin\n"); } mixerHandle = getMixerNativeHandle(env, mixer); snd_mixer_selem_id_alloca(&id); snd_mixer_selem_id_set_index(id, nIndex); name= (*env)->GetStringUTFChars(env, strName, NULL); if (name == NULL) { throwRuntimeException(env, "GetStringUTFChars() failed"); return -1; } snd_mixer_selem_id_set_name(id, name); (*env)->ReleaseStringUTFChars(env, strName, name); handle = snd_mixer_find_selem(mixerHandle, id); if (handle == NULL) { nReturn = -1; } else { setHandle(env, obj, handle); nReturn = 0; } if (debug_flag) { (void) fprintf(debug_file, "Java_org_tritonus_lowlevel_alsa_AlsaMixerElement_open(): end\n"); } return nReturn; }
void GetAlsaMasterVolume(long *volume) { long min, max; snd_mixer_t *handle; snd_mixer_selem_id_t *sid; const char *card = "default"; const char *selem_name = "Master"; snd_mixer_open(&handle, 0); snd_mixer_attach(handle, card); snd_mixer_selem_register(handle, NULL, NULL); snd_mixer_load(handle); snd_mixer_selem_id_alloca(&sid); snd_mixer_selem_id_set_index(sid, 0); snd_mixer_selem_id_set_name(sid, selem_name); snd_mixer_elem_t* elem = snd_mixer_find_selem(handle, sid); snd_mixer_selem_get_playback_volume(elem, SND_MIXER_SCHN_FRONT_LEFT, volume); snd_mixer_close(handle); }
AlsaMixer *AlsaMixer::create(Sound *m) { AlsaMixer *alsa = new AlsaMixer(m); if (!alsa) { return nullptr; } snd_mixer_open(&alsa->m_handle, 0); snd_mixer_attach(alsa->m_handle, card); snd_mixer_selem_register(alsa->m_handle, NULL, NULL); snd_mixer_load(alsa->m_handle); snd_mixer_selem_id_alloca(&alsa->m_sid); snd_mixer_selem_id_set_index(alsa->m_sid, 0); snd_mixer_selem_id_set_name(alsa->m_sid, selem_name); alsa->m_elem = snd_mixer_find_selem(alsa->m_handle, alsa->m_sid); if (!alsa->m_elem) { delete alsa; return nullptr; } snd_mixer_selem_get_playback_volume_range(alsa->m_elem, &alsa->m_min, &alsa->m_max); return alsa; }
void KplAudioSetMasterVolume(long left, long right) { long min, max; snd_mixer_t *handle; snd_mixer_selem_id_t *sid; const char *card = "default"; const char *selem_name = "Master"; snd_mixer_open(&handle, 0); snd_mixer_attach(handle, card); snd_mixer_selem_register(handle, NULL, NULL); snd_mixer_load(handle); snd_mixer_selem_id_alloca(&sid); snd_mixer_selem_id_set_index(sid, 0); snd_mixer_selem_id_set_name(sid, selem_name); snd_mixer_elem_t* elem = snd_mixer_find_selem(handle, sid); snd_mixer_selem_get_playback_volume_range(elem, &min, &max); snd_mixer_selem_set_playback_volume(elem, SND_MIXER_SCHN_FRONT_LEFT, min + (left * (max - min)) / 256); snd_mixer_selem_set_playback_volume(elem, SND_MIXER_SCHN_FRONT_RIGHT, min + (right * (max - min)) / 256); snd_mixer_close(handle); }
int main(int argc, char * argv[]) { int pos = 125; long min, max; long gpiodelay_value = 250; // was 50 snd_mixer_t *handle; snd_mixer_selem_id_t *sid; const char *card = "default"; // Previous linux driver's mixer name // const char *selem_name = "Playback Digital"; // const char *selem_name = "PCM"; const char *selem_name = "Digital"; // Linux 4.1.6-v7+ #810 int x, mute_state; long i, currentVolume; printf("IQaudIO.com Pi-DAC Volume Control support Rotary Encoder) v1.5 Aug 30th 2015\n\n"); wiringPiSetup (); /* pull up is needed as encoder common is grounded */ pinMode (ENCODER_A, INPUT); pullUpDnControl (ENCODER_A, PUD_UP); pinMode (ENCODER_B, INPUT); pullUpDnControl (ENCODER_B, PUD_UP); encoderPos = pos; // Setup ALSA access snd_mixer_open(&handle, 0); snd_mixer_attach(handle, card); snd_mixer_selem_register(handle, NULL, NULL); snd_mixer_load(handle); snd_mixer_selem_id_alloca(&sid); snd_mixer_selem_id_set_index(sid, 0); snd_mixer_selem_id_set_name(sid, selem_name); snd_mixer_elem_t* elem = snd_mixer_find_selem(handle, sid); snd_mixer_selem_get_playback_volume_range(elem, &min, &max); if (DEBUG_PRINT) printf("Returned card VOLUME range - min: %ld, max: %ld\n", min, max); // Minimum given is mute, we need the first real value min++; // Get current volume if (x = snd_mixer_selem_get_playback_volume (elem, SND_MIXER_SCHN_FRONT_LEFT, ¤tVolume)) { printf("%d %s\n", x, snd_strerror(x)); } else if (DEBUG_PRINT) printf("Current ALSA volume LEFT: %ld\n", currentVolume); if (x = snd_mixer_selem_get_playback_volume (elem, SND_MIXER_SCHN_FRONT_RIGHT, ¤tVolume)) { printf("%d %s\n", x, snd_strerror(x)); } else if (DEBUG_PRINT) printf("Current ALSA volume RIGHT: %ld\n", currentVolume); /* monitor encoder level changes */ wiringPiISR (ENCODER_A, INT_EDGE_BOTH, &encoderPulse); wiringPiISR (ENCODER_B, INT_EDGE_BOTH, &encoderPulse); // Now sit and spin waiting for GPIO pins to go active... while (1) { if (encoderPos != pos) { // get current volume if (x = snd_mixer_selem_get_playback_volume (elem, SND_MIXER_SCHN_FRONT_LEFT, ¤tVolume)) { printf("%d %s\n", x, snd_strerror(x)); } else if (DEBUG_PRINT) printf(" Current ALSA volume: %ld\n", currentVolume); // Adjust for MUTE if (currentVolume < min) { currentVolume = 0; if (DEBUG_PRINT) printf(" Current ALSA volume set to min: %ld\n", currentVolume); } // What way did the encoder go? if (encoderPos > pos) { pos = encoderPos; currentVolume = currentVolume + 10; // Adjust for MAX volume if (currentVolume > max) currentVolume = max; if (DEBUG_PRINT) printf("Volume UP %d - %ld", pos, currentVolume); } else if (encoderPos < pos) { pos = encoderPos; currentVolume = currentVolume - 10; // Adjust for MUTE if (currentVolume < min) currentVolume = 0; if (DEBUG_PRINT) printf("Volume DOWN %d - %ld", pos, currentVolume); } if (x = snd_mixer_selem_set_playback_volume_all(elem, currentVolume)) { printf(" ERROR %d %s\n", x, snd_strerror(x)); } else if (DEBUG_PRINT) printf(" Volume successfully set to %ld using ALSA!\n", currentVolume); } // Check x times per second, MAY NEED TO ADJUST THS FREQUENCY FOR SOME ENCODERS */ delay(gpiodelay_value); /* check pos x times per second */ } // We never get here but should close the sockets etc. on exit. snd_mixer_close(handle); }
static int init(int argc, char **argv) { const char *str; int value; int hardware_mixer = 0; config.audio_backend_latency_offset = 0; // this is the default for ALSA config.audio_backend_buffer_desired_length = 6615; // default for alsa with a software mixer // get settings from settings file first, allow them to be overridden by command line options if (config.cfg != NULL) { /* Get the desired buffer size setting. */ if (config_lookup_int(config.cfg, "alsa.audio_backend_buffer_desired_length_software", &value)) { if ((value < 0) || (value > 66150)) die("Invalid alsa audio backend buffer desired length (software) \"%d\". It should be between 0 and " "66150, default is 6615", value); else { config.audio_backend_buffer_desired_length = value; } } /* Get the latency offset. */ if (config_lookup_int(config.cfg, "alsa.audio_backend_latency_offset", &value)) { if ((value < -66150) || (value > 66150)) die("Invalid alsa audio backend buffer latency offset \"%d\". It should be between -66150 and +66150, default is 0", value); else config.audio_backend_latency_offset = value; } /* Get the Output Device Name. */ if (config_lookup_string(config.cfg, "alsa.output_device", &str)) { alsa_out_dev = (char *)str; } /* Get the Mixer Type setting. */ if (config_lookup_string(config.cfg, "alsa.mixer_type", &str)) { inform("The alsa mixer_type setting is deprecated and has been ignored. FYI, using the \"mixer_control_name\" setting automatically chooses a hardware mixer."); } /* Get the Mixer Device Name. */ if (config_lookup_string(config.cfg, "alsa.mixer_device", &str)) { alsa_mix_dev = (char *)str; } /* Get the Mixer Control Name. */ if (config_lookup_string(config.cfg, "alsa.mixer_control_name", &str)) { alsa_mix_ctrl = (char *)str; hardware_mixer = 1; } } optind = 1; // optind=0 is equivalent to optind=1 plus special behaviour argv--; // so we shift the arguments to satisfy getopt() argc++; // some platforms apparently require optreset = 1; - which? int opt; while ((opt = getopt(argc, argv, "d:t:m:c:i:")) > 0) { switch (opt) { case 'd': alsa_out_dev = optarg; break; case 't': inform("The alsa backend -t option is deprecated and has been ignored. FYI, using the -c option automatically chooses a hardware mixer."); break; case 'm': alsa_mix_dev = optarg; break; case 'c': alsa_mix_ctrl = optarg; hardware_mixer = 1; break; case 'i': alsa_mix_index = strtol(optarg, NULL, 10); break; default: help(); die("Invalid audio option -%c specified", opt); } } if (optind < argc) die("Invalid audio argument: %s", argv[optind]); debug(1,"Output device name is \"%s\".",alsa_out_dev); if (!hardware_mixer) return 0; if (alsa_mix_dev == NULL) alsa_mix_dev = alsa_out_dev; int ret = 0; snd_mixer_selem_id_alloca(&alsa_mix_sid); snd_mixer_selem_id_set_index(alsa_mix_sid, alsa_mix_index); snd_mixer_selem_id_set_name(alsa_mix_sid, alsa_mix_ctrl); if ((snd_mixer_open(&alsa_mix_handle, 0)) < 0) die("Failed to open mixer"); debug(1,"Mixer device name is \"%s\".",alsa_mix_dev); if ((snd_mixer_attach(alsa_mix_handle, alsa_mix_dev)) < 0) die("Failed to attach mixer"); if ((snd_mixer_selem_register(alsa_mix_handle, NULL, NULL)) < 0) die("Failed to register mixer element"); ret = snd_mixer_load(alsa_mix_handle); if (ret < 0) die("Failed to load mixer element"); debug(1,"Mixer Control name is \"%s\".",alsa_mix_ctrl); alsa_mix_elem = snd_mixer_find_selem(alsa_mix_handle, alsa_mix_sid); if (!alsa_mix_elem) die("Failed to find mixer element"); if (snd_mixer_selem_get_playback_volume_range(alsa_mix_elem, &alsa_mix_minv, &alsa_mix_maxv) < 0) debug(1, "Can't read mixer's [linear] min and max volumes."); else { if (snd_mixer_selem_get_playback_dB_range (alsa_mix_elem, &alsa_mix_mindb, &alsa_mix_maxdb) == 0) { audio_alsa.volume = &volume; // insert the volume function now we know it can do dB stuff audio_alsa.parameters = ¶meters; // likewise the parameters stuff if (alsa_mix_mindb == SND_CTL_TLV_DB_GAIN_MUTE) { // Raspberry Pi does this debug(1, "Lowest dB value is a mute."); if (snd_mixer_selem_ask_playback_vol_dB(alsa_mix_elem, alsa_mix_minv + 1, &alsa_mix_mindb) == 0) debug(1, "Can't get dB value corresponding to a \"volume\" of 1."); } debug(1, "Hardware mixer has dB volume from %f to %f.", (1.0 * alsa_mix_mindb) / 100.0, (1.0 * alsa_mix_maxdb) / 100.0); if (config.volume_range_db) { long suggested_alsa_min_db = alsa_mix_maxdb - (long)trunc(config.volume_range_db*100); if (suggested_alsa_min_db > alsa_mix_mindb) alsa_mix_mindb = suggested_alsa_min_db; else inform("The volume_range_db setting, %f is greater than the native range of the mixer %f, so it is ignored.",config.volume_range_db,(alsa_mix_maxdb-alsa_mix_mindb)/100.0); }else{ if(config.isset_volume_min_db){ long suggested_alsa_min_db = (long) trunc(config.volume_min_db * 100); if(suggested_alsa_min_db > alsa_mix_mindb){ alsa_mix_mindb = suggested_alsa_min_db; } } if(config.isset_volume_max_db){ long suggested_alsa_max_db = (long) trunc(config.volume_max_db * 100); if(suggested_alsa_max_db < alsa_mix_maxdb){ alsa_mix_maxdb = suggested_alsa_max_db; } } } } else { // use the linear scale and do the db conversion ourselves debug(1, "note: the hardware mixer specified -- \"%s\" -- does not have a dB volume scale, so it can't be used.",alsa_mix_ctrl); /* debug(1, "Min and max volumes are %d and %d.",alsa_mix_minv,alsa_mix_maxv); alsa_mix_maxdb = 0; if ((alsa_mix_maxv!=0) && (alsa_mix_minv!=0)) alsa_mix_mindb = -20*100*(log10(alsa_mix_maxv*1.0)-log10(alsa_mix_minv*1.0)); else if (alsa_mix_maxv!=0) alsa_mix_mindb = -20*100*log10(alsa_mix_maxv*1.0); audio_alsa.volume = &linear_volume; // insert the linear volume function audio_alsa.parameters = ¶meters; // likewise the parameters stuff debug(1,"Max and min dB calculated are %d and %d.",alsa_mix_maxdb,alsa_mix_mindb); */ } } if (snd_mixer_selem_has_playback_switch(alsa_mix_elem)) { has_mute = 1; debug(1, "Has mute ability."); } return 0; }
/* Controls the alsamixer atributes of GCW device */ void mixer_control(int mode, long *volume, long *min, long *max) { snd_mixer_t *handle; snd_mixer_selem_id_t *sid; snd_mixer_elem_t *elem; snd_mixer_selem_channel_id_t channel = SND_MIXER_SCHN_FRONT_LEFT; snd_mixer_open(&handle, 0); snd_mixer_attach(handle, "default"); snd_mixer_selem_register(handle, NULL, NULL); snd_mixer_load(handle); snd_mixer_selem_id_alloca(&sid); snd_mixer_selem_id_set_index(sid, 0); if (mode == VOLUME_GET || mode == VOLUME_SET) { snd_mixer_selem_id_set_name(sid, "Headphone"); elem = snd_mixer_find_selem(handle, sid); if (mode == VOLUME_GET) { snd_mixer_selem_get_playback_volume(elem, channel, volume); snd_mixer_selem_get_playback_volume_range(elem, min, max); } else if (mode == VOLUME_SET) { printf("GCW: Volume set to %ld\n", *volume); snd_mixer_selem_set_playback_volume_all(elem, *volume); } /* adjust volume to Bypass too */ snd_mixer_selem_id_set_name(sid, "Line In Bypass"); elem = snd_mixer_find_selem(handle, sid); if (mode == VOLUME_SET) { printf("Line in Bypass: Volume set to %ld\n", *volume); snd_mixer_selem_set_playback_volume_all(elem, *volume); } } else if (mode == HEADPHONE_TURN_ON || mode == HEADPHONE_TURN_OFF) { snd_mixer_selem_id_set_name(sid, "Headphone Source"); elem = snd_mixer_find_selem(handle, sid); if (mode == HEADPHONE_TURN_ON) { printf("Headphone Source: Line In\n"); snd_mixer_selem_set_enum_item(elem, channel, 1); } else if (mode == HEADPHONE_TURN_OFF) { printf("Headphone Source: PCM\n"); snd_mixer_selem_set_enum_item(elem, channel, 0); } } else if (mode == SPEAKER_TURN_ON || mode == SPEAKER_TURN_OFF) { snd_mixer_selem_id_set_name(sid, "Speakers"); elem = snd_mixer_find_selem(handle, sid); if (mode == SPEAKER_TURN_ON) { printf("Speaker turned on\n"); snd_mixer_selem_set_playback_switch_all(elem, 1); } else if (mode == SPEAKER_TURN_OFF) { printf("Speaker turned off\n"); snd_mixer_selem_set_playback_switch_all(elem, 0); } snd_mixer_selem_id_set_name(sid, "Line Out Source"); elem = snd_mixer_find_selem(handle, sid); if (mode == SPEAKER_TURN_ON) { printf("Line Out Source turned on\n"); snd_mixer_selem_set_enum_item(elem, channel, 1); } else if (mode == SPEAKER_TURN_OFF) { printf("Line Out Source turned off\n"); snd_mixer_selem_set_enum_item(elem, channel, 0); } } else if (mode == BYPASS_VERIFICATION) { // volume here means that the radio is running in background or not *volume = 0; unsigned int setting = 0; snd_mixer_selem_id_set_name(sid, "Headphone Source"); elem = snd_mixer_find_selem(handle, sid); snd_mixer_selem_get_enum_item(elem, channel, &setting); // the headphone is turned on if (setting == 1) { *volume = 1; return; } snd_mixer_selem_id_set_name(sid, "Line Out Source"); elem = snd_mixer_find_selem(handle, sid); snd_mixer_selem_get_enum_item(elem, channel, &setting); // if both headphone and speakers are off, return 0 in volume to tell the screen that we need // to setup the radio *volume = setting == 1; } }
int getvolume(long* left_volume, long* right_volume) { int ret = 0; snd_mixer_t* handle; snd_mixer_elem_t* elem; snd_mixer_selem_id_t* sid; static const char* mix_name = "Master"; static const char* card = "default"; static int mix_index = 0; snd_mixer_selem_id_alloca(&sid); //sets simple-mixer index and name snd_mixer_selem_id_set_index(sid, mix_index); snd_mixer_selem_id_set_name(sid, mix_name); if ((snd_mixer_open(&handle, 0)) < 0) return -1; if ((snd_mixer_attach(handle, card)) < 0) { snd_mixer_close(handle); return -2; } if ((snd_mixer_selem_register(handle, NULL, NULL)) < 0) { snd_mixer_close(handle); return -3; } ret = snd_mixer_load(handle); if (ret < 0) { snd_mixer_close(handle); return -4; } elem = snd_mixer_find_selem(handle, sid); if (!elem) { snd_mixer_close(handle); return -5; } long minv; long maxv; snd_mixer_selem_get_playback_volume_range (elem, &minv, &maxv); if(snd_mixer_selem_get_playback_volume(elem, 0, left_volume) < 0) { snd_mixer_close(handle); return -3; } /* make the value bound to 100 */ *left_volume -= minv; maxv -= minv; minv = 0; *left_volume = 100 * (*left_volume) / maxv; // make the value bound from 0 to 100 snd_mixer_selem_get_playback_volume_range (elem, &minv, &maxv); if(snd_mixer_selem_get_playback_volume(elem, 1, right_volume) < 0) { snd_mixer_close(handle); return -4; } /* make the value bound to 100 */ *right_volume -= minv; maxv -= minv; minv = 0; *right_volume = 100 * (*right_volume) / maxv; // make the value bound from 0 to 100 snd_mixer_close(handle); return 0; }
void VolumeControl::init() { //initialize audio mixer interface #if defined (__APPLE__) #warning TODO: Not implemented for MacOS yet!!! #elif defined(__linux__) //try to open mixer device if (mixerHandle == nullptr) { snd_mixer_selem_id_alloca(&mixerSelemId); //sets simple-mixer index and name snd_mixer_selem_id_set_index(mixerSelemId, mixerIndex); snd_mixer_selem_id_set_name(mixerSelemId, mixerName); //open mixer if (snd_mixer_open(&mixerHandle, 0) >= 0) { LOG(LogDebug) << "VolumeControl::init() - Opened ALSA mixer"; //ok. attach to defualt card if (snd_mixer_attach(mixerHandle, mixerCard) >= 0) { LOG(LogDebug) << "VolumeControl::init() - Attached to default card"; //ok. register simple element class if (snd_mixer_selem_register(mixerHandle, NULL, NULL) >= 0) { LOG(LogDebug) << "VolumeControl::init() - Registered simple element class"; //ok. load registered elements if (snd_mixer_load(mixerHandle) >= 0) { LOG(LogDebug) << "VolumeControl::init() - Loaded mixer elements"; //ok. find elements now mixerElem = snd_mixer_find_selem(mixerHandle, mixerSelemId); if (mixerElem != nullptr) { //wohoo. good to go... LOG(LogDebug) << "VolumeControl::init() - Mixer initialized"; } else { LOG(LogError) << "VolumeControl::init() - Failed to find mixer elements!"; snd_mixer_close(mixerHandle); mixerHandle = nullptr; } } else { LOG(LogError) << "VolumeControl::init() - Failed to load mixer elements!"; snd_mixer_close(mixerHandle); mixerHandle = nullptr; } } else { LOG(LogError) << "VolumeControl::init() - Failed to register simple element class!"; snd_mixer_close(mixerHandle); mixerHandle = nullptr; } } else { LOG(LogError) << "VolumeControl::init() - Failed to attach to default card!"; snd_mixer_close(mixerHandle); mixerHandle = nullptr; } } else { LOG(LogError) << "VolumeControl::init() - Failed to open ALSA mixer!"; } } #elif defined(WIN32) || defined(_WIN32) //get windows version information OSVERSIONINFOEXA osVer = {sizeof(OSVERSIONINFO)}; ::GetVersionExA(reinterpret_cast<LPOSVERSIONINFOA>(&osVer)); //check windows version if(osVer.dwMajorVersion < 6) { //Windows older than Vista. use mixer API. open default mixer if (mixerHandle == nullptr) { if (mixerOpen(&mixerHandle, 0, NULL, 0, 0) == MMSYSERR_NOERROR) { //retrieve info on the volume slider control for the "Speaker Out" line MIXERLINECONTROLS mixerLineControls; mixerLineControls.cbStruct = sizeof(MIXERLINECONTROLS); mixerLineControls.dwLineID = 0xFFFF0000; //Id of "Speaker Out" line mixerLineControls.cControls = 1; //mixerLineControls.dwControlID = 0x00000000; //Id of "Speaker Out" line's volume slider mixerLineControls.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME; //Get volume control mixerLineControls.pamxctrl = &mixerControl; mixerLineControls.cbmxctrl = sizeof(MIXERCONTROL); if (mixerGetLineControls((HMIXEROBJ)mixerHandle, &mixerLineControls, MIXER_GETLINECONTROLSF_ONEBYTYPE) != MMSYSERR_NOERROR) { LOG(LogError) << "VolumeControl::getVolume() - Failed to get mixer volume control!"; mixerClose(mixerHandle); mixerHandle = nullptr; } } else { LOG(LogError) << "VolumeControl::init() - Failed to open mixer!"; } } } else { //Windows Vista or above. use EndpointVolume API. get device enumerator if (endpointVolume == nullptr) { CoInitialize(nullptr); IMMDeviceEnumerator * deviceEnumerator = nullptr; CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr, CLSCTX_INPROC_SERVER, __uuidof(IMMDeviceEnumerator), (LPVOID *)&deviceEnumerator); if (deviceEnumerator != nullptr) { //get default endpoint IMMDevice * defaultDevice = nullptr; deviceEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &defaultDevice); if (defaultDevice != nullptr) { //retrieve endpoint volume defaultDevice->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_INPROC_SERVER, nullptr, (LPVOID *)&endpointVolume); if (endpointVolume == nullptr) { LOG(LogError) << "VolumeControl::init() - Failed to get default audio endpoint volume!"; } //release default device. we don't need it anymore defaultDevice->Release(); } else { LOG(LogError) << "VolumeControl::init() - Failed to get default audio endpoint!"; } //release device enumerator. we don't need it anymore deviceEnumerator->Release(); } else { LOG(LogError) << "VolumeControl::init() - Failed to get audio endpoint enumerator!"; CoUninitialize(); } } } #endif }
static int control(struct ao *ao, enum aocontrol cmd, void *arg) { struct priv *p = ao->priv; snd_mixer_t *handle = NULL; switch (cmd) { case AOCONTROL_GET_MUTE: case AOCONTROL_SET_MUTE: case AOCONTROL_GET_VOLUME: case AOCONTROL_SET_VOLUME: { int err; snd_mixer_elem_t *elem; snd_mixer_selem_id_t *sid; long pmin, pmax; long get_vol, set_vol; float f_multi; if (!af_fmt_is_pcm(ao->format)) return CONTROL_FALSE; snd_mixer_selem_id_alloca(&sid); snd_mixer_selem_id_set_index(sid, p->cfg_mixer_index); snd_mixer_selem_id_set_name(sid, p->cfg_mixer_name); err = snd_mixer_open(&handle, 0); CHECK_ALSA_ERROR("Mixer open error"); err = snd_mixer_attach(handle, p->cfg_mixer_device); CHECK_ALSA_ERROR("Mixer attach error"); err = snd_mixer_selem_register(handle, NULL, NULL); CHECK_ALSA_ERROR("Mixer register error"); err = snd_mixer_load(handle); CHECK_ALSA_ERROR("Mixer load error"); elem = snd_mixer_find_selem(handle, sid); if (!elem) { MP_VERBOSE(ao, "Unable to find simple control '%s',%i.\n", snd_mixer_selem_id_get_name(sid), snd_mixer_selem_id_get_index(sid)); goto alsa_error; } snd_mixer_selem_get_playback_volume_range(elem, &pmin, &pmax); f_multi = (100 / (float)(pmax - pmin)); switch (cmd) { case AOCONTROL_SET_VOLUME: { ao_control_vol_t *vol = arg; set_vol = vol->left / f_multi + pmin + 0.5; err = snd_mixer_selem_set_playback_volume (elem, SND_MIXER_SCHN_FRONT_LEFT, set_vol); CHECK_ALSA_ERROR("Error setting left channel"); MP_DBG(ao, "left=%li, ", set_vol); set_vol = vol->right / f_multi + pmin + 0.5; err = snd_mixer_selem_set_playback_volume (elem, SND_MIXER_SCHN_FRONT_RIGHT, set_vol); CHECK_ALSA_ERROR("Error setting right channel"); MP_DBG(ao, "right=%li, pmin=%li, pmax=%li, mult=%f\n", set_vol, pmin, pmax, f_multi); break; } case AOCONTROL_GET_VOLUME: { ao_control_vol_t *vol = arg; snd_mixer_selem_get_playback_volume (elem, SND_MIXER_SCHN_FRONT_LEFT, &get_vol); vol->left = (get_vol - pmin) * f_multi; snd_mixer_selem_get_playback_volume (elem, SND_MIXER_SCHN_FRONT_RIGHT, &get_vol); vol->right = (get_vol - pmin) * f_multi; MP_DBG(ao, "left=%f, right=%f\n", vol->left, vol->right); break; } case AOCONTROL_SET_MUTE: { bool *mute = arg; if (!snd_mixer_selem_has_playback_switch(elem)) goto alsa_error; if (!snd_mixer_selem_has_playback_switch_joined(elem)) { snd_mixer_selem_set_playback_switch (elem, SND_MIXER_SCHN_FRONT_RIGHT, !*mute); } snd_mixer_selem_set_playback_switch (elem, SND_MIXER_SCHN_FRONT_LEFT, !*mute); break; } case AOCONTROL_GET_MUTE: { bool *mute = arg; if (!snd_mixer_selem_has_playback_switch(elem)) goto alsa_error; int tmp = 1; snd_mixer_selem_get_playback_switch (elem, SND_MIXER_SCHN_FRONT_LEFT, &tmp); *mute = !tmp; if (!snd_mixer_selem_has_playback_switch_joined(elem)) { snd_mixer_selem_get_playback_switch (elem, SND_MIXER_SCHN_FRONT_RIGHT, &tmp); *mute &= !tmp; } break; } } snd_mixer_close(handle); return CONTROL_OK; } } //end switch return CONTROL_UNKNOWN; alsa_error: if (handle) snd_mixer_close(handle); return CONTROL_ERROR; }
/* Drawbacks. Sets volume on both channels but gets volume on one. Can be easily adapted. */ int audio_volume(audio_volume_action action, long* outvol) { int ret = 0; snd_mixer_t* handle; snd_mixer_elem_t* elem; snd_mixer_selem_id_t* sid; static const char* mix_name = "Master"; static const char* card = "default"; static int mix_index = 0; long pmin, pmax; long get_vol, set_vol; float f_multi; snd_mixer_selem_id_alloca(&sid); //sets simple-mixer index and name snd_mixer_selem_id_set_index(sid, mix_index); snd_mixer_selem_id_set_name(sid, mix_name); if ((snd_mixer_open(&handle, 0)) < 0) return -1; if ((snd_mixer_attach(handle, card)) < 0) { snd_mixer_close(handle); return -2; } if ((snd_mixer_selem_register(handle, NULL, NULL)) < 0) { snd_mixer_close(handle); return -3; } ret = snd_mixer_load(handle); if (ret < 0) { snd_mixer_close(handle); return -4; } elem = snd_mixer_find_selem(handle, sid); if (!elem) { snd_mixer_close(handle); return -5; } long minv, maxv; snd_mixer_selem_get_playback_volume_range (elem, &minv, &maxv); fprintf(stderr, "Volume range <%li,%li>\n", minv, maxv); if(action == AUDIO_VOLUME_GET) { if(snd_mixer_selem_get_playback_volume(elem, 0, outvol) < 0) { snd_mixer_close(handle); return -6; } fprintf(stderr, "Get volume %li with status %i\n", *outvol, ret); /* make the value bound to 100 */ *outvol -= minv; maxv -= minv; minv = 0; *outvol = 100 * (*outvol) / maxv; // make the value bound from 0 to 100 } else if(action == AUDIO_VOLUME_SET) { if(*outvol < 0 || *outvol > VOLUME_BOUND) // out of bounds return -7; *outvol = (*outvol * (maxv - minv) / (100-1)) + minv; if(snd_mixer_selem_set_playback_volume(elem, 0, *outvol) < 0) { snd_mixer_close(handle); return -8; } if(snd_mixer_selem_set_playback_volume(elem, 1, *outvol) < 0) { snd_mixer_close(handle); return -9; } fprintf(stderr, "Set volume %li with status %i\n", *outvol, ret); } snd_mixer_close(handle); return 0; }
gboolean show_mixer(GtkWidget *widget, GdkEvent *event, gpointer user_data) { GtkWidget *win = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(win), "SIDE Mixer"); gtk_container_set_border_width(GTK_CONTAINER(win), 10); gtk_window_resize(GTK_WINDOW(win), 150, 300); GdkScreen *screen = gdk_screen_get_default(); fwin = win; g_timeout_add(100, check_focus, win); GtkWidget *box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5); GtkWidget *dsc = gtk_label_new("master"); GtkAdjustment *adj = gtk_adjustment_new(50, 0, 100, 5, 0, 0); g_signal_connect(G_OBJECT(adj), "value-changed", G_CALLBACK(set_volume), NULL); GtkWidget *scl = gtk_scale_new(GTK_ORIENTATION_VERTICAL, adj); gtk_scale_set_draw_value(GTK_SCALE(scl), FALSE); s_mute = gtk_toggle_button_new_with_label("mute"); g_signal_connect(G_OBJECT(s_mute), "toggled", G_CALLBACK(set_mute), (gpointer) adj); gtk_box_pack_end(GTK_BOX(box), s_mute, FALSE, FALSE, 0); gtk_container_add(GTK_CONTAINER(box), dsc); gtk_box_pack_end(GTK_BOX(box), scl, TRUE, TRUE, 5); int x, y; gtk_window_get_size(GTK_WINDOW(win), &x, &y); gtk_window_set_decorated(GTK_WINDOW(win), FALSE); gtk_window_move(GTK_WINDOW(win), gdk_screen_get_width(screen), gdk_screen_get_height(screen) - (y+25)); gtk_container_add(GTK_CONTAINER(win), box); gtk_widget_show_all(win); snd_mixer_t *mix; snd_mixer_selem_id_t *sid; const char *card = "default"; const char *selem_name = "Master"; long val, max, min; snd_mixer_open(&mix, 0); snd_mixer_attach(mix, card); snd_mixer_selem_register(mix, NULL, NULL); snd_mixer_load(mix); snd_mixer_selem_id_alloca(&sid); snd_mixer_selem_id_set_index(sid, 0); snd_mixer_selem_id_set_name(sid, selem_name); snd_mixer_elem_t* elem = snd_mixer_find_selem(mix, sid); snd_mixer_selem_get_playback_volume_range(elem, &min, &max); snd_mixer_selem_get_playback_volume(elem, SND_MIXER_SCHN_MONO , &val); gtk_adjustment_set_value(adj, 100 - (int) 100 * val / max); snd_mixer_close(mix); return FALSE; }
static int init(int argc, char **argv) { int hardware_mixer = 0; optind = 1; // optind=0 is equivalent to optind=1 plus special behaviour argv--; // so we shift the arguments to satisfy getopt() argc++; // some platforms apparently require optreset = 1; - which? int opt; while ((opt = getopt(argc, argv, "d:t:m:c:i:")) > 0) { switch (opt) { case 'd': alsa_out_dev = optarg; break; case 't': if (strcmp(optarg, "hardware") == 0) hardware_mixer = 1; break; case 'm': alsa_mix_dev = optarg; break; case 'c': alsa_mix_ctrl = optarg; break; case 'i': alsa_mix_index = strtol(optarg, NULL, 10); break; default: help(); die("Invalid audio option -%c specified", opt); } } if (optind < argc) die("Invalid audio argument: %s", argv[optind]); if (!hardware_mixer) return 0; if (alsa_mix_dev == NULL) alsa_mix_dev = alsa_out_dev; audio_alsa.volume = &volume; int ret = 0; long alsa_mix_maxv; snd_mixer_selem_id_alloca(&alsa_mix_sid); snd_mixer_selem_id_set_index(alsa_mix_sid, alsa_mix_index); snd_mixer_selem_id_set_name(alsa_mix_sid, alsa_mix_ctrl); if ((snd_mixer_open(&alsa_mix_handle, 0)) < 0) die ("Failed to open mixer"); if ((snd_mixer_attach(alsa_mix_handle, alsa_mix_dev)) < 0) die ("Failed to attach mixer"); if ((snd_mixer_selem_register(alsa_mix_handle, NULL, NULL)) < 0) die ("Failed to register mixer element"); ret = snd_mixer_load(alsa_mix_handle); if (ret < 0) die ("Failed to load mixer element"); alsa_mix_elem = snd_mixer_find_selem(alsa_mix_handle, alsa_mix_sid); if (!alsa_mix_elem) die ("Failed to find mixer element"); snd_mixer_selem_get_playback_volume_range (alsa_mix_elem, &alsa_mix_minv, &alsa_mix_maxv); alsa_mix_range = alsa_mix_maxv - alsa_mix_minv; return 0; }
void toggleMute(struct playerHandles *ph, int *mute){ long val; int err; float range_p; long current=*mute; long vmin,vmax; char tail[OUTPUT_TAIL_SIZE]; snd_mixer_t *handle; snd_mixer_elem_t *elem; snd_mixer_selem_id_t *sid; snd_mixer_selem_id_alloca(&sid); snd_mixer_selem_id_set_index(sid,0); snd_mixer_selem_id_set_name(sid,"PCM"); if(snd_mixer_open(&handle,0)<0) return; if(snd_mixer_attach(handle,"default")<0){ snd_mixer_close(handle); return; } if(snd_mixer_selem_register(handle,NULL,NULL)<0){ snd_mixer_close(handle); return; } if(snd_mixer_load(handle)<0){ snd_mixer_close(handle); return; } elem=snd_mixer_find_selem(handle,sid); if(!elem){ snd_mixer_close(handle); return; } snd_mixer_selem_get_playback_volume_range(elem,&vmin,&vmax); range_p = (100.0f/(float)(vmax-vmin)); if(*mute>0){ // Unmute and perform volume change *mute=0; sprintf(tail,"Volume: %ld%%",current); addStatusTail(tail,ph->outdetail); current=current/range_p+vmin; } else{ // Mute snd_mixer_selem_get_playback_volume(elem,0,¤t); *mute=current*range_p+vmin; current=0; addStatusTail("Volume Muted",ph->outdetail); } fflush(stdout); if(snd_mixer_selem_set_playback_volume(elem,0,current)<0){ snd_mixer_close(handle); return; } if(snd_mixer_selem_set_playback_volume(elem,1,current)<0){ snd_mixer_close(handle); return; } snd_mixer_close(handle); }
void changeVolume(struct playerHandles *ph, int mod){ long val; int err; float range_p; long cur_vol,new_volume; long vmin,vmax; char tail[OUTPUT_TAIL_SIZE]; snd_mixer_t *handle; snd_mixer_elem_t *elem; snd_mixer_selem_id_t *sid; snd_mixer_selem_id_alloca(&sid); snd_mixer_selem_id_set_index(sid,0); snd_mixer_selem_id_set_name(sid,"PCM"); if(snd_mixer_open(&handle,0)<0) return; if(snd_mixer_attach(handle,"default")<0){ snd_mixer_close(handle); return; } if(snd_mixer_selem_register(handle,NULL,NULL)<0){ snd_mixer_close(handle); return; } if(snd_mixer_load(handle)<0){ snd_mixer_close(handle); return; } elem=snd_mixer_find_selem(handle,sid); if(!elem){ snd_mixer_close(handle); return; } snd_mixer_selem_get_playback_volume_range(elem,&vmin,&vmax); range_p = (100.0f/(float)(vmax-vmin)); snd_mixer_selem_get_playback_volume(elem,0,&cur_vol); new_volume = cur_vol+vmin+mod/range_p; if(new_volume==cur_vol && mod!=0)new_volume+=(mod<0?-1:1); if(new_volume<vmin)new_volume=vmin; if(new_volume>vmax)new_volume=vmax; if(snd_mixer_selem_set_playback_volume(elem,0,new_volume)<0){ snd_mixer_close(handle); return; } sprintf(tail,"Volume: %d%%",(int)((float)range_p*(float)new_volume)); addStatusTail(tail,ph->outdetail); snd_mixer_selem_get_playback_volume(elem,1,&cur_vol); new_volume = cur_vol+vmin+mod/range_p; if(new_volume==cur_vol && mod!=0)new_volume+=(mod<0?-1:1); if(new_volume<vmin)new_volume=vmin; if(new_volume>vmax)new_volume=vmax; if(snd_mixer_selem_set_playback_volume(elem,1,new_volume)<0){ snd_mixer_close(handle); return; } snd_mixer_close(handle); }
/* to set/get/query special features/parameters */ static int control(int cmd, void *arg) { switch(cmd) { case AOCONTROL_QUERY_FORMAT: return CONTROL_TRUE; case AOCONTROL_GET_VOLUME: case AOCONTROL_SET_VOLUME: { ao_control_vol_t *vol = (ao_control_vol_t *)arg; int err; snd_mixer_t *handle; snd_mixer_elem_t *elem; snd_mixer_selem_id_t *sid; char *mix_name = "PCM"; char *card = "default"; int mix_index = 0; long pmin, pmax; long get_vol, set_vol; float f_multi; if(AF_FORMAT_IS_IEC61937(ao_data.format)) return CONTROL_TRUE; if(mixer_channel) { char *test_mix_index; mix_name = strdup(mixer_channel); if ((test_mix_index = strchr(mix_name, ','))){ *test_mix_index = 0; test_mix_index++; mix_index = strtol(test_mix_index, &test_mix_index, 0); if (*test_mix_index){ mp_msg(MSGT_AO,MSGL_ERR, MSGTR_AO_ALSA_InvalidMixerIndexDefaultingToZero); mix_index = 0 ; } } } if(mixer_device) card = mixer_device; //allocate simple id snd_mixer_selem_id_alloca(&sid); //sets simple-mixer index and name snd_mixer_selem_id_set_index(sid, mix_index); snd_mixer_selem_id_set_name(sid, mix_name); if (mixer_channel) { free(mix_name); mix_name = NULL; } if ((err = snd_mixer_open(&handle, 0)) < 0) { mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_MixerOpenError, snd_strerror(err)); return CONTROL_ERROR; } if ((err = snd_mixer_attach(handle, card)) < 0) { mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_MixerAttachError, card, snd_strerror(err)); snd_mixer_close(handle); return CONTROL_ERROR; } if ((err = snd_mixer_selem_register(handle, NULL, NULL)) < 0) { mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_MixerRegisterError, snd_strerror(err)); snd_mixer_close(handle); return CONTROL_ERROR; } err = snd_mixer_load(handle); if (err < 0) { mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_MixerLoadError, snd_strerror(err)); snd_mixer_close(handle); return CONTROL_ERROR; } elem = snd_mixer_find_selem(handle, sid); if (!elem) { mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToFindSimpleControl, snd_mixer_selem_id_get_name(sid), snd_mixer_selem_id_get_index(sid)); snd_mixer_close(handle); return CONTROL_ERROR; } snd_mixer_selem_get_playback_volume_range(elem,&pmin,&pmax); f_multi = (100 / (float)(pmax - pmin)); if (cmd == AOCONTROL_SET_VOLUME) { set_vol = vol->left / f_multi + pmin + 0.5; //setting channels if ((err = snd_mixer_selem_set_playback_volume(elem, SND_MIXER_SCHN_FRONT_LEFT, set_vol)) < 0) { mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_ErrorSettingLeftChannel, snd_strerror(err)); snd_mixer_close(handle); return CONTROL_ERROR; } mp_msg(MSGT_AO,MSGL_DBG2,"left=%li, ", set_vol); set_vol = vol->right / f_multi + pmin + 0.5; if ((err = snd_mixer_selem_set_playback_volume(elem, SND_MIXER_SCHN_FRONT_RIGHT, set_vol)) < 0) { mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_ErrorSettingRightChannel, snd_strerror(err)); snd_mixer_close(handle); return CONTROL_ERROR; } mp_msg(MSGT_AO,MSGL_DBG2,"right=%li, pmin=%li, pmax=%li, mult=%f\n", set_vol, pmin, pmax, f_multi); if (snd_mixer_selem_has_playback_switch(elem)) { int lmute = (vol->left == 0.0); int rmute = (vol->right == 0.0); if (snd_mixer_selem_has_playback_switch_joined(elem)) { lmute = rmute = lmute && rmute; } else { snd_mixer_selem_set_playback_switch(elem, SND_MIXER_SCHN_FRONT_RIGHT, !rmute); } snd_mixer_selem_set_playback_switch(elem, SND_MIXER_SCHN_FRONT_LEFT, !lmute); } } else { snd_mixer_selem_get_playback_volume(elem, SND_MIXER_SCHN_FRONT_LEFT, &get_vol); vol->left = (get_vol - pmin) * f_multi; snd_mixer_selem_get_playback_volume(elem, SND_MIXER_SCHN_FRONT_RIGHT, &get_vol); vol->right = (get_vol - pmin) * f_multi; mp_msg(MSGT_AO,MSGL_DBG2,"left=%f, right=%f\n",vol->left,vol->right); } snd_mixer_close(handle); return CONTROL_OK; } } //end switch return CONTROL_UNKNOWN; }
int indicator_music_init(Indicator *indicator) { DBusMessage* msg; DBusMessageIter args, element; DBusPendingCall* pending; char *player; int current_type; if(!dbus.session.connection) return -1; if(!(msg=dbus_message_new_method_call(dbus.interface, dbus.object, dbus.interface, "ListNames"))) return -1; if(!dbus_connection_send_with_reply(dbus.session.connection, msg, &pending, -1)) { dbus_connection_unref(dbus.session.connection); return -1; } if(!pending) { dbus_message_unref(msg); dbus_connection_unref(dbus.session.connection); return -1; } dbus_connection_flush(dbus.session.connection); dbus_message_unref(msg); dbus_pending_call_block(pending); if(!(msg=dbus_pending_call_steal_reply(pending))) { dbus_connection_unref(dbus.session.connection); return -1; } dbus_pending_call_unref(pending); if(!(dbus_message_iter_init(msg, &args)&&dbus_message_iter_get_arg_type(&args)==DBUS_TYPE_ARRAY)) { dbus_message_unref(msg); dbus_connection_unref(dbus.session.connection); return -1; } for(dbus_message_iter_recurse(&args, &element); (current_type=dbus_message_iter_get_arg_type(&element))!=DBUS_TYPE_INVALID; dbus_message_iter_next(&element)) { if(current_type!=DBUS_TYPE_STRING) continue; dbus_message_iter_get_basic(&element, &player); if(!strncmp(player, mpris.base, strlen(mpris.base))) { mediaplayer_register(player+strlen(mpris.base)); } } dbus_message_unref(msg); dbus_bus_add_match(dbus.session.connection, "type='signal',interface='org.freedesktop.DBus',member='NameOwnerChanged'", &dbus.session.error); dbus_connection_flush(dbus.session.connection); if(dbus_error_is_set(&dbus.session.error)) { dbus_connection_unref(dbus.session.connection); mediaplayer_deregister_all(); return -1; } /*init alsa*/ snd_mixer_selem_id_alloca(&alsa.sid); snd_mixer_selem_id_set_index(alsa.sid, alsa.mix_index); snd_mixer_selem_id_set_name(alsa.sid, alsa.mix_name); if((snd_mixer_open(&alsa.handle, 0))<0) return -1; if((snd_mixer_attach(alsa.handle, alsa.card))<0) { snd_mixer_close(alsa.handle); return -1; } if((snd_mixer_selem_register(alsa.handle, NULL, NULL))<0) { snd_mixer_close(alsa.handle); return -1; } if(snd_mixer_load(alsa.handle)<0) { snd_mixer_close(alsa.handle); return -1; } if(!(alsa.elem=snd_mixer_find_selem(alsa.handle, alsa.sid))) { snd_mixer_close(alsa.handle); return -1; } snd_mixer_selem_get_playback_volume_range (alsa.elem, &alsa.minv, &alsa.maxv); return 0; }