int main(void) { Display *xdisplay; XkbEvent xevent; int opcode, xkbEventBase, xkbErrorBase, major, minor; int currentLayout = 0; time_t timestamp; char datetime[DATETIME_BUFFER + 1]; int status; snd_mixer_t *amixer; snd_mixer_elem_t *amixer_elem; snd_mixer_selem_id_t *amixer_selem; long int volume, volumeMin, volumeMax, volumePercent; struct udev *udev; struct udev_monitor *udev_monitor; struct udev_device *udev_device; int udev_fd; int ps_current = 0, ps_total = 0; openlog(NULL, LOG_CONS|LOG_PERROR|LOG_PID, LOG_DAEMON); if (!(xdisplay = XOpenDisplay(NULL))) { syslog(LOG_ERR, "Can't open display: %s!\n", strerror(errno)); return EXIT_FAILURE; } if (!XkbQueryExtension(xdisplay, &opcode, &xkbEventBase, &xkbErrorBase, &major, &minor)) { syslog(LOG_ERR, "X doesn't support a compatible Xkb!\n"); return EXIT_FAILURE; } if (!XkbSelectEvents(xdisplay, XkbUseCoreKbd, XkbStateNotifyMask, XkbStateNotifyMask)) { syslog(LOG_ERR, "Could not set Xkb event mask!\n"); return EXIT_FAILURE; } if ((status = snd_mixer_open(&amixer, 0)) < 0 || (status = snd_mixer_selem_register(amixer, NULL, NULL)) < 0 || (status = snd_mixer_attach(amixer, "default")) < 0) { syslog(LOG_ERR, "Alsa failed: %s!\n", snd_strerror(status)); return EXIT_FAILURE; } if ((status = snd_mixer_load(amixer)) || (status = snd_mixer_selem_id_malloc(&amixer_selem)) < 0) { syslog(LOG_ERR, "Alsa failed: %s!\n", snd_strerror(status)); return EXIT_FAILURE; } snd_mixer_selem_id_set_index(amixer_selem, 0); snd_mixer_selem_id_set_name(amixer_selem, "Master"); amixer_elem = snd_mixer_find_selem(amixer, amixer_selem); snd_mixer_selem_get_playback_volume_range(amixer_elem, &volumeMin, &volumeMax); if (amixer_elem == NULL) { syslog(LOG_ERR, "Mixer simple element handle not found!\n"); return EXIT_FAILURE; } udev = udev_new(); if (udev == NULL) { syslog(LOG_ERR, "Can't create udev object!\n"); return EXIT_FAILURE; } udev_monitor = udev_monitor_new_from_netlink(udev, "udev"); if (udev_monitor == NULL) { syslog(LOG_ERR, "Can't create udev monitor!\n"); return EXIT_SUCCESS; } if (udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "power_supply", NULL) < 0) { syslog(LOG_ERR, "Could't watch power_supply events!\n"); return EXIT_FAILURE; } if (udev_monitor_enable_receiving(udev_monitor) < 0) { syslog(LOG_ERR, "Could't bind udev monitor event!\n"); return EXIT_FAILURE; } udev_fd = udev_monitor_get_fd(udev_monitor); while(1) { time(×tamp); strftime(datetime, DATETIME_BUFFER, DATETIME_FORMAT, localtime(×tamp)); while(XPending(xdisplay)) { XNextEvent(xdisplay, &xevent.core); if (xevent.type == xkbEventBase && xevent.any.xkb_type == XkbStateNotify) { currentLayout = xevent.state.group; } } if ((status = snd_mixer_handle_events(amixer)) < 0) { syslog(LOG_ERR, "Alsa failed: %s!\n", snd_strerror(status)); return EXIT_FAILURE; } if ((status = snd_mixer_selem_get_playback_volume(amixer_elem, SND_MIXER_SCHN_MONO, &volume)) < 0) { syslog(LOG_ERR, "Alsa failed: %s!\n", snd_strerror(status)); return EXIT_FAILURE; } volumePercent = (volume * 100) / volumeMax; fd_set fds; int ret; struct timeval tv = {.tv_sec = 0, .tv_usec = 0}; FD_ZERO(&fds); FD_SET(udev_fd, &fds); ret = select(udev_fd + 1, &fds, NULL, NULL, &tv); if (ret > 0 && FD_ISSET(udev_fd, &fds)) { udev_device = udev_monitor_receive_device(udev_monitor); if (udev_device == NULL) { syslog(LOG_ERR, "Can't get udev device!\n"); return EXIT_SUCCESS; } printf("Name: %s\n", udev_device_get_sysname(udev_device)); printf("Node: %s\n", udev_device_get_devnode(udev_device)); printf("Subsystem: %s\n", udev_device_get_subsystem(udev_device)); printf("Devtype: %s\n", udev_device_get_devtype(udev_device)); printf("Action: %s\n", udev_device_get_action(udev_device)); /*ps_current = atoi(udev_device_get_property_value(udev_device, "POWER_SUPPLY_CHARGE_NOW"));*/ /*ps_total = atoi(udev_device_get_property_value(udev_device, "POWER_SUPPLY_CHARGE_FULL"));*/ printf("%s\n", udev_device_get_sysattr_value(udev_device, "energy_now")); printf("%s\n", udev_device_get_sysattr_value(udev_device, "energy_full")); udev_device_unref(udev_device); } printf("%s %s\t%s %li\t%s %i\t%s %s\n", GLYPH_KEYBOARD, layouts[currentLayout], GLYPH_VOLUME, volumePercent, GLYPH_BATTERY, ps_current, GLYPH_CLOCK, datetime ); usleep(SLEEP_MSECONDS * 1000); } snd_mixer_selem_id_free(amixer_selem); snd_mixer_close(amixer); XCloseDisplay(xdisplay); closelog(); return EXIT_SUCCESS; }
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 void alsa_configure (struct sound_device *sd) { int val, err, dir; unsigned uval; struct alsa_params *p = (struct alsa_params *) sd->data; snd_pcm_uframes_t buffer_size; eassert (p->handle != 0); err = snd_pcm_hw_params_malloc (&p->hwparams); if (err < 0) alsa_sound_perror ("Could not allocate hardware parameter structure", err); err = snd_pcm_sw_params_malloc (&p->swparams); if (err < 0) alsa_sound_perror ("Could not allocate software parameter structure", err); err = snd_pcm_hw_params_any (p->handle, p->hwparams); if (err < 0) alsa_sound_perror ("Could not initialize hardware parameter structure", err); err = snd_pcm_hw_params_set_access (p->handle, p->hwparams, SND_PCM_ACCESS_RW_INTERLEAVED); if (err < 0) alsa_sound_perror ("Could not set access type", err); val = sd->format; err = snd_pcm_hw_params_set_format (p->handle, p->hwparams, val); if (err < 0) alsa_sound_perror ("Could not set sound format", err); uval = sd->sample_rate; err = snd_pcm_hw_params_set_rate_near (p->handle, p->hwparams, &uval, 0); if (err < 0) alsa_sound_perror ("Could not set sample rate", err); val = sd->channels; err = snd_pcm_hw_params_set_channels (p->handle, p->hwparams, val); if (err < 0) alsa_sound_perror ("Could not set channel count", err); err = snd_pcm_hw_params (p->handle, p->hwparams); if (err < 0) alsa_sound_perror ("Could not set parameters", err); err = snd_pcm_hw_params_get_period_size (p->hwparams, &p->period_size, &dir); if (err < 0) alsa_sound_perror ("Unable to get period size for playback", err); err = snd_pcm_hw_params_get_buffer_size (p->hwparams, &buffer_size); if (err < 0) alsa_sound_perror ("Unable to get buffer size for playback", err); err = snd_pcm_sw_params_current (p->handle, p->swparams); if (err < 0) alsa_sound_perror ("Unable to determine current swparams for playback", err); /* Start the transfer when the buffer is almost full */ err = snd_pcm_sw_params_set_start_threshold (p->handle, p->swparams, (buffer_size / p->period_size) * p->period_size); if (err < 0) alsa_sound_perror ("Unable to set start threshold mode for playback", err); /* Allow the transfer when at least period_size samples can be processed */ err = snd_pcm_sw_params_set_avail_min (p->handle, p->swparams, p->period_size); if (err < 0) alsa_sound_perror ("Unable to set avail min for playback", err); err = snd_pcm_sw_params (p->handle, p->swparams); if (err < 0) alsa_sound_perror ("Unable to set sw params for playback\n", err); snd_pcm_hw_params_free (p->hwparams); p->hwparams = NULL; snd_pcm_sw_params_free (p->swparams); p->swparams = NULL; err = snd_pcm_prepare (p->handle); if (err < 0) alsa_sound_perror ("Could not prepare audio interface for use", err); if (sd->volume > 0) { int chn; snd_mixer_t *handle; snd_mixer_elem_t *e; if (snd_mixer_open (&handle, 0) >= 0) { char const *file = string_default (sd->file, DEFAULT_ALSA_SOUND_DEVICE); if (snd_mixer_attach (handle, file) >= 0 && snd_mixer_load (handle) >= 0 && snd_mixer_selem_register (handle, NULL, NULL) >= 0) for (e = snd_mixer_first_elem (handle); e; e = snd_mixer_elem_next (e)) { if (snd_mixer_selem_has_playback_volume (e)) { long pmin, pmax, vol; snd_mixer_selem_get_playback_volume_range (e, &pmin, &pmax); vol = pmin + (sd->volume * (pmax - pmin)) / 100; for (chn = 0; chn <= SND_MIXER_SCHN_LAST; chn++) snd_mixer_selem_set_playback_volume (e, chn, vol); } } snd_mixer_close (handle); } } }
/** * Closes the alsa mixer handle. */ void alsa_close(void) { snd_mixer_close(handle); }
int main(int argc, char **argv) { FILE *file; int samples; char *sample_buffer; int rtn, final_return_code = -1, exit_application = 0; int bsize, bytes_read, total_written = 0; fd_set rfds, wfds; char input_file[PATH_MAX]; char cwd[PATH_MAX]; /* * Before we can listen for events from the BlackBerry Tablet OS platform * services, we need to initialize the BPS infrastructure */ bps_initialize(); if (setup_screen() != EXIT_SUCCESS) { printf("Unable to set up the screen. Exiting."); exit(-1); } /* * Once the BPS infrastructure has been initialized we can register for * events from the various BlackBerry Tablet OS platform services. The * Navigator service manages and delivers application life cycle and * visibility events. * * For this sample, we request Navigator events so we can track when * the system is terminating the application (NAVIGATOR_EXIT event). * This allows us to clean up application resources. * * We request Audio Device events because we want to make sure that * we properly handle changes in audio output. * * We request dialog events to properly initialize the dialog * subsystem in order to display status and error messages. */ if (BPS_SUCCESS != navigator_request_events(0)) { fprintf(stderr, "Error requesting navigator events: %s", strerror(errno)); exit(-1); } if (BPS_SUCCESS != dialog_request_events(0)) { fprintf(stderr, "Error requesting dialog events: %s", strerror(errno)); exit(-1); } if (BPS_SUCCESS != audiodevice_request_events(0)) { fprintf(stderr, "Error requesting audio device events: %s", strerror(errno)); exit(-1); } /* * Create and display the dialog. */ create_dialog(); /* * Open and check the input file. */ getcwd(cwd, PATH_MAX); rtn = snprintf(input_file, PATH_MAX, "%s/%s", cwd, WAV_RELATIVE_PATH); if (rtn > PATH_MAX - 1) { err("File name and path too long"); goto fail1; } if ((file = fopen(input_file, "r")) == 0) { err("File open failed"); goto fail1; } if (check_hdr(file) == -1) { err("check_hdr failed"); goto fail2; } /* * Parse the headers in the wav file to figure out what kind of data we * are dealing with in the file. */ samples = find_tag(file, "fmt "); fread(&wav_header, sizeof(wav_header), 1, file); fseek(file,(samples - sizeof(wave_hdr)), SEEK_CUR); sample_rate = ENDIAN_LE32(wav_header.samples_per_sec); sample_channels = ENDIAN_LE16(wav_header.channels); sample_bits = ENDIAN_LE16(wav_header.bits_per_sample); snprintf(msg, MSG_SIZE, "SampleRate = %d, channels = %d, SampleBits = %d\n", sample_rate, sample_channels, sample_bits); show_dialog_message(msg); if (setup_snd(NULL)) { goto fail2; } bsize = setup.buf.block.frag_size; samples = find_tag(file, "data"); sample_buffer = malloc(bsize); if (!sample_buffer) { goto fail3; } FD_ZERO(&rfds); FD_ZERO(&wfds); bytes_read = 1; while (total_written < samples && bytes_read > 0 ) { bps_event_t *event = NULL; while (BPS_SUCCESS == bps_get_event(&event, 0) && event) { /* * If it is a NAVIGATOR_EXIT event then we are done so stop * processing events, clean up and exit */ if (bps_event_get_domain(event) == navigator_get_domain()) { if (NAVIGATOR_EXIT == bps_event_get_code(event)) { exit_application = 1; goto success; } } if (bps_event_get_domain(event) == audiodevice_get_domain()) { /* * If it is a audio device event then it means a new audio device * has been enabled and a switch is required. We close the old, * open the new audio device using the path and get the card number so * that we can close and re-open the mixer with the new card * number. */ const char * audiodevice_path = audiodevice_event_get_path(event); if (NULL == audiodevice_path) { snprintf(msg, MSG_SIZE, "audiodevice_event_get_path failed: %s\n", snd_strerror(rtn)); show_dialog_message(msg); goto fail5; } if ((rtn = snd_mixer_close(mixer_handle)) < 0) { snprintf(msg, MSG_SIZE, "snd_mixer_close failed: %s\n", snd_strerror(rtn)); show_dialog_message(msg); goto fail4; } if ((rtn = snd_pcm_close(pcm_handle)) < 0) { snprintf(msg, MSG_SIZE, "snd_pcm_close failed: %s\n", snd_strerror(rtn)); show_dialog_message(msg); goto fail3; } if (setup_snd(audiodevice_path)) { /* * setup_snd() closes pcm and mixer handles in the case of error so we * skip clean up of the handles in the case of failure. */ goto fail3; } } } if (tcgetpgrp(0) == getpid()) FD_SET(STDIN_FILENO, &rfds); FD_SET(snd_mixer_file_descriptor(mixer_handle), &rfds); FD_SET(snd_pcm_file_descriptor(pcm_handle, SND_PCM_CHANNEL_PLAYBACK), &wfds); rtn = max(snd_mixer_file_descriptor(mixer_handle), snd_pcm_file_descriptor(pcm_handle, SND_PCM_CHANNEL_PLAYBACK)); if (select(rtn + 1, &rfds, &wfds, NULL, NULL) == -1) { err("select"); goto fail5; } if (FD_ISSET(snd_pcm_file_descriptor(pcm_handle, SND_PCM_CHANNEL_PLAYBACK), &wfds)) { snd_pcm_channel_status_t status; int written = 0; if ((bytes_read = fread(sample_buffer, 1, min(samples - total_written, bsize), file)) <= 0) continue; written = snd_pcm_plugin_write(pcm_handle, sample_buffer, bytes_read); if (written < bytes_read) { memset(&status, 0, sizeof(status)); status.channel = SND_PCM_CHANNEL_PLAYBACK; if (snd_pcm_plugin_status(pcm_handle, &status) < 0) { show_dialog_message("underrun: playback channel status error\n"); goto fail5; } if (status.status == SND_PCM_STATUS_READY || status.status == SND_PCM_STATUS_UNDERRUN) { if (snd_pcm_plugin_prepare(pcm_handle, SND_PCM_CHANNEL_PLAYBACK) < 0) { show_dialog_message("underrun: playback channel prepare error\n"); goto fail5; } } if (written < 0) written = 0; written += snd_pcm_plugin_write(pcm_handle, sample_buffer + written, bytes_read - written); } total_written += written; } } success: bytes_read = snd_pcm_plugin_flush(pcm_handle, SND_PCM_CHANNEL_PLAYBACK); final_return_code = 0; /* * there are return codes to these close calls, but we would do the same * thing regardless of error or success so we do not check the return codes. */ fail5: snd_mixer_close(mixer_handle); fail4: snd_pcm_close(pcm_handle); fail3: free(sample_buffer); sample_buffer = NULL; fail2: fclose(file); fail1: while (!exit_application) { /* * Something went wrong so there is probably an error message and * we don't want to exit right away because we want the user to see * the message in the dialog. * * Using a negative timeout (-1) in the call to bps_get_event(...) * ensures that we don't busy wait by blocking until an event is * available. */ bps_event_t *event = NULL; bps_get_event(&event, -1); if (event) { /* * If it is a NAVIGATOR_EXIT event then we are done so stop * processing events, clean up and exit */ if (bps_event_get_domain(event) == navigator_get_domain()) { if (NAVIGATOR_EXIT == bps_event_get_code(event)) { exit_application = 1; } } } } /* * Destroy the dialog, if it exists and cleanup screen resources. */ destroy_dialog(); cleanup_screen(); bps_shutdown(); return final_return_code; }
static int alsa_mixer_close(void) { snd_mixer_close(alsa_mixer_handle); return 0; }
/* 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_AC3(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; }
/****************************************************************************** * setMixerVolume *****************************************************************************/ static Int setMixerVolume (Sound_Attrs *attrs) { Int status; snd_mixer_t *rcMixer; snd_mixer_elem_t *elem; snd_mixer_selem_id_t *sid; snd_mixer_selem_id_malloc (&sid); /* Open the mixer device */ status = snd_mixer_open (&rcMixer, 0); if ( status<0 ) { Dmai_err2 ("Failed to open mixer on %s (%s)\n", AUDIO_MIXER, snd_strerror (status)); return Dmai_EFAIL; } /* Attach mixer with sound card */ status = snd_mixer_attach (rcMixer,AUDIO_MIXER); if (status <0) { Dmai_err2 ("Failed to attach mixer on %s (%s)\n", AUDIO_MIXER, snd_strerror (status)); return Dmai_EFAIL; } /* Register mixer with selected elements */ status = snd_mixer_selem_register (rcMixer, NULL, NULL); if (status <0) { Dmai_err2 ("Failed to register mixer on %s (%s)\n", AUDIO_MIXER, snd_strerror (status)); return Dmai_EFAIL; } /* Load mixer */ status = snd_mixer_load (rcMixer); if (status <0) { Dmai_err2 ("Failed to load mixer on %s (%s)\n", AUDIO_MIXER, snd_strerror (status)); return Dmai_EFAIL; } for (elem = snd_mixer_first_elem (rcMixer); elem; elem=snd_mixer_elem_next(elem)) { snd_mixer_selem_get_id(elem,sid); if (!snd_mixer_selem_is_active(elem)) continue; if (attrs->mode == Sound_Mode_OUTPUT || attrs->mode == Sound_Mode_FULLDUPLEX) { if (snd_mixer_selem_has_playback_channel(elem, SND_MIXER_SCHN_FRONT_LEFT)) snd_mixer_selem_set_playback_volume (elem, SND_MIXER_SCHN_FRONT_LEFT,attrs->leftGain); if (snd_mixer_selem_has_playback_channel(elem, SND_MIXER_SCHN_FRONT_RIGHT)) snd_mixer_selem_set_playback_volume (elem, SND_MIXER_SCHN_FRONT_RIGHT,attrs->rightGain); } if (attrs->mode == Sound_Mode_INPUT || attrs->mode == Sound_Mode_FULLDUPLEX) { if (snd_mixer_selem_has_capture_channel(elem, SND_MIXER_SCHN_FRONT_LEFT)) snd_mixer_selem_set_capture_volume (elem, SND_MIXER_SCHN_FRONT_LEFT,attrs->leftGain); if (snd_mixer_selem_has_capture_channel(elem, SND_MIXER_SCHN_FRONT_RIGHT)) snd_mixer_selem_set_capture_volume (elem, SND_MIXER_SCHN_FRONT_RIGHT,attrs->rightGain); } } snd_mixer_selem_id_free (sid); snd_mixer_close (rcMixer); return Dmai_EOK; }
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; }
int play_sound(char* filename,int rate,int bits,int channel,int order) { long loops; int rc,size,dir; snd_pcm_t *handle; snd_pcm_hw_params_t *params; snd_pcm_uframes_t frames,periodsize; snd_mixer_t *mixer; snd_mixer_elem_t *pcm_element; char *buffer; unsigned int val; FILE *fp = fopen(filename,"rb"); rc = snd_pcm_open(&handle,"default",SND_PCM_STREAM_PLAYBACK,0); snd_pcm_hw_params_alloca(¶ms); snd_pcm_hw_params_any(handle,params); snd_pcm_hw_params_set_access(handle,params,SND_PCM_ACCESS_RW_INTERLEAVED); switch(order){ case 1: snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S16_LE); break; case 2: snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S16_BE); break; defualt: break; } snd_pcm_hw_params_set_channels(handle,params,channel); val = rate; snd_pcm_hw_params_set_rate_near(handle,params,&val,0); snd_pcm_hw_params_get_buffer_size_max(params,&frames); frames = frames < ALSA_MAX_BUF_SIZE? frames:ALSA_MAX_BUF_SIZE; rc = snd_pcm_hw_params_set_buffer_size_near(handle,params,&frames); snd_pcm_hw_params_get_period_size_min(params,&periodsize,NULL); if(!periodsize){ periodsize=size/4; } rc = snd_pcm_hw_params_set_period_size_near(handle,params,&periodsize,NULL); rc = snd_pcm_hw_params(handle,params); snd_mixer_open(&mixer,0); snd_mixer_attach(mixer,"default"); snd_mixer_selem_register(mixer,NULL,NULL); snd_mixer_load(mixer); for(pcm_element = snd_mixer_first_elem(mixer);pcm_element;pcm_element=snd_mixer_elem_next(pcm_element)) { if(snd_mixer_elem_get_type(pcm_element)==SND_MIXER_ELEM_SIMPLE && snd_mixer_selem_is_active(pcm_element)) { if(!strcmp(snd_mixer_selem_get_name(pcm_element),"Master")) { snd_mixer_selem_set_playback_volume_range(pcm_element,0,100); snd_mixer_selem_set_playback_volume_all(pcm_element,(long)100); } } } buffer = (char*)malloc(size); while(1) { rc = fread(buffer,1,size,fp); if(0== rc) break; while((rc = snd_pcm_writei(handle,buffer,size))<0) { usleep(200); if(-EPIPE == rc) snd_pcm_prepare(handle); else if(0 > rc) printf("error fomr writei\n"); } } snd_pcm_drain(handle); snd_pcm_close(handle); free(buffer); snd_mixer_close(mixer); fclose(fp); return 0; }
void AlsaMixer::clean_up() { if (this->handle) snd_mixer_close(this->handle); }
AlsaMixer::~AlsaMixer() { snd_mixer_close(m_handle); }
static int alsa_init (struct output_driver_caps *caps) { int err; logit ("Initialising ALSA device"); if ((err = snd_mixer_open(&mixer_handle, 0)) < 0) { error ("Can't open ALSA mixer: %s", snd_strerror(err)); mixer_handle = NULL; } else if ((err = snd_mixer_attach(mixer_handle, options_get_str("AlsaDevice"))) < 0) { snd_mixer_close (mixer_handle); mixer_handle = NULL; error ("Can't attach mixer: %s", snd_strerror(err)); } else if ((err = snd_mixer_selem_register(mixer_handle, NULL, NULL)) < 0) { snd_mixer_close (mixer_handle); mixer_handle = NULL; error ("Can't register mixer: %s", snd_strerror(err)); } else if ((err = snd_mixer_load(mixer_handle)) < 0) { snd_mixer_close (mixer_handle); mixer_handle = NULL; error ("Can't load mixer: %s", snd_strerror(err)); } if (mixer_handle) { mixer_elem1 = alsa_init_mixer_channel ( options_get_str("AlsaMixer"), &mixer1_min, &mixer1_max); mixer_elem2 = alsa_init_mixer_channel ( options_get_str("AlsaMixer2"), &mixer2_min, &mixer2_max); } mixer_elem_curr = mixer_elem1 ? mixer_elem1 : mixer_elem2; if (mixer_elem_curr) { if (mixer_elem1 && (real_volume1 = alsa_read_mixer_raw(mixer_elem1)) != -1) volume1 = scale_volume1 (real_volume1); else { mixer_elem1 = NULL; mixer_elem_curr = mixer_elem2; } if (mixer_elem2 && (real_volume2 = alsa_read_mixer_raw(mixer_elem2)) != -1) volume2 = scale_volume2 (real_volume2); else { mixer_elem2 = NULL; mixer_elem_curr = mixer_elem1; } if (!mixer_elem_curr) { snd_mixer_close (mixer_handle); mixer_handle = NULL; } } else if (mixer_handle) { snd_mixer_close (mixer_handle); mixer_handle = NULL; } return fill_capabilities (caps); }
/** * Constructor of MMSAudioCtrl class. * * The first instance of this class assigns * an audio channel, attaches to the mixer * of the sound card and gets the current * settings. * * @param channel [in] audio channel */ MMSAudioCtrl::MMSAudioCtrl(string channel) { int err; if(this->channel=="") { this->channel=channel; } if (!this->handle) { /* open the mixer */ if ((err = snd_mixer_open(&(this->handle), 0)) < 0) throw MMSAudioCtrlError(err,"snd_mixer_open() failed"); /* attach the card */ if ((err = snd_mixer_attach(this->handle, this->card.c_str())) < 0) { snd_mixer_close(this->handle); throw MMSAudioCtrlError(err,"snd_mixer_attach() with card = '" + this->card + "' failed"); } /* register */ if ((err = snd_mixer_selem_register(this->handle, NULL, NULL)) < 0) { snd_mixer_close(this->handle); string s = snd_strerror(err); throw MMSAudioCtrlError(err,"snd_mixer_selem_register() failed with '" + s + "'"); } /* load */ if ((err = snd_mixer_load(this->handle)) < 0) { snd_mixer_close(this->handle); string s = snd_strerror(err); throw MMSAudioCtrlError(err,"snd_mixer_load() failed with '" + s + "'"); } } if (!this->elem) { /* searching for the first active element */ for (this->elem = snd_mixer_first_elem(this->handle); this->elem; this->elem = snd_mixer_elem_next(this->elem)) { string mix = snd_mixer_selem_get_name(this->elem); DEBUGMSG("MMSMedia", "got mixer channel: %s", mix.c_str()); /* is active? */ if (!snd_mixer_selem_is_active(this->elem)) continue; /* has playback volume? */ if (!snd_mixer_selem_has_playback_volume(this->elem)) continue; if (this->channel!="") { if(strcmp(this->channel.c_str(),snd_mixer_selem_get_name(this->elem))!=0) continue; } /* we have found our channel*/ /* get volume range */ snd_mixer_selem_get_playback_volume_range(this->elem, &(this->pmin), &(this->pmax)); /* check if this elem is mutable */ isSwitchable = (snd_mixer_selem_has_playback_switch(elem) > 0); /* get the current volume settings */ getVolume(); return; } throw MMSAudioCtrlError(0,"no element found"); } }
void asound_setup(const gchar * card, const gchar * channel, void (*volume_changed)(int,gboolean)) { gchar * card_override = NULL; // used to hold a string like hw:0 if a nice // device name was given as 'card' // Clean up resources from previous calls to setup g_free(m_channel); m_channel = NULL; if(m_elem) { snd_mixer_elem_set_callback(m_elem, NULL); m_elem = NULL; } if(m_mixer) { snd_mixer_close(m_mixer); m_mixer = NULL; } g_list_free_full(m_channel_names, g_free); m_channel_names = NULL; g_list_free_full(m_device_names, g_free); m_device_names = NULL; // Save card, volume_changed g_free(m_device); m_device = g_strdup(card); m_volume_changed = volume_changed; // Populate list of device names int card_number = -1; int ret = snd_card_next(&card_number); snd_ctl_card_info_t * info = NULL; snd_ctl_card_info_alloca(&info); m_device_names = g_list_append(m_device_names, (gpointer)g_strdup("default")); while(ret == 0 && card_number != -1) { char buf[16]; sprintf(buf, "hw:%d", card_number); snd_ctl_t * ctl = NULL; if(snd_ctl_open(&ctl, buf, 0) < 0) { continue; } if(snd_ctl_card_info(ctl, info) < 0) { snd_ctl_close(ctl); continue; } snd_ctl_close(ctl); gchar * nice_name = g_strdup(snd_ctl_card_info_get_name(info)); m_device_names = g_list_append(m_device_names, (gpointer)nice_name); if(g_strcmp0(nice_name, m_device) == 0) { g_free(card_override); card_override = g_strdup_printf("hw:%d", card_number); } ret = snd_card_next(&card_number); } // Load the mixer for the provided cardname snd_mixer_open(&m_mixer, 0); if(snd_mixer_attach(m_mixer, (card_override != NULL ? card_override : m_device)) < 0) { fprintf(stderr, "Failed to open sound device with name: %s\n", (card_override != NULL ? card_override : m_device)); snd_mixer_close(m_mixer); m_mixer = NULL; g_free(card_override); return; } else { g_free(card_override); } snd_mixer_selem_register(m_mixer, NULL, NULL); snd_mixer_load(m_mixer); // Setup g_io_watch for the mixer int count = snd_mixer_poll_descriptors_count(m_mixer); if(count >= 1) { struct pollfd pfd; count = snd_mixer_poll_descriptors(m_mixer, &pfd, 1); if(count == 1) { GIOChannel * giochannel = g_io_channel_unix_new(pfd.fd); g_io_add_watch_full(giochannel, G_PRIORITY_DEFAULT, G_IO_IN | G_IO_ERR , asound_poll_cb, NULL, NULL); } } // Iterate over the elements in the mixer and store them in m_channel_names int elemcount = snd_mixer_get_count(m_mixer); snd_mixer_elem_t * elem = snd_mixer_first_elem(m_mixer); int loop; for(loop = 0; loop < elemcount; loop++) { const char * elemname = snd_mixer_selem_get_name(elem); if(snd_mixer_selem_has_playback_volume(elem)) { m_channel_names = g_list_append(m_channel_names, (gpointer)g_strdup(elemname)); } elem = snd_mixer_elem_next(elem); } // Setup m_elem using the provided channelname if(channel != NULL && asound_channel_exists(channel)) asound_set_channel(channel); else if(m_channel_names != NULL) asound_set_channel((const gchar*)m_channel_names->data); }
void cleanup_handle(snd_mixer_t* handle) { snd_mixer_detach(handle, "default"); 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 void deinit(void) { stop(); if (alsa_mix_handle) { snd_mixer_close(alsa_mix_handle); } }
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; }
static int mixer_open(void) { snd_mixer_elem_t *elem; snd_mixer_elem_t *master; snd_mixer_elem_t *pcm; snd_mixer_elem_t *custom; snd_mixer_selem_id_t *sid; int ret; ret = snd_mixer_open(&mixer_hdl, 0); if (ret < 0) { DPRINTF(E_LOG, L_LAUDIO, "Failed to open mixer: %s\n", snd_strerror(ret)); mixer_hdl = NULL; return -1; } ret = snd_mixer_attach(mixer_hdl, card_name); if (ret < 0) { DPRINTF(E_LOG, L_LAUDIO, "Failed to attach mixer: %s\n", snd_strerror(ret)); goto out_close; } ret = snd_mixer_selem_register(mixer_hdl, NULL, NULL); if (ret < 0) { DPRINTF(E_LOG, L_LAUDIO, "Failed to register mixer: %s\n", snd_strerror(ret)); goto out_detach; } ret = snd_mixer_load(mixer_hdl); if (ret < 0) { DPRINTF(E_LOG, L_LAUDIO, "Failed to load mixer: %s\n", snd_strerror(ret)); goto out_detach; } /* Grab interesting elements */ snd_mixer_selem_id_alloca(&sid); pcm = NULL; master = NULL; custom = NULL; for (elem = snd_mixer_first_elem(mixer_hdl); elem; elem = snd_mixer_elem_next(elem)) { snd_mixer_selem_get_id(elem, sid); if (mixer_name && (strcmp(snd_mixer_selem_id_get_name(sid), mixer_name) == 0)) { custom = elem; break; } else if (strcmp(snd_mixer_selem_id_get_name(sid), "PCM") == 0) pcm = elem; else if (strcmp(snd_mixer_selem_id_get_name(sid), "Master") == 0) master = elem; } if (mixer_name) { if (custom) vol_elem = custom; else { DPRINTF(E_LOG, L_LAUDIO, "Failed to open configured mixer element '%s'\n", mixer_name); goto out_detach; } } else if (pcm) vol_elem = pcm; else if (master) vol_elem = master; else { DPRINTF(E_LOG, L_LAUDIO, "Failed to open PCM or Master mixer element\n"); goto out_detach; } /* Get min & max volume */ snd_mixer_selem_get_playback_volume_range(vol_elem, &vol_min, &vol_max); return 0; out_detach: snd_mixer_detach(mixer_hdl, card_name); out_close: snd_mixer_close(mixer_hdl); mixer_hdl = NULL; vol_elem = NULL; return -1; }
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; }
mixerVolume::~mixerVolume() { if (handle) snd_mixer_close(handle); }
static void alsa_mixer_close(snd_mixer_t *mix){ snd_mixer_close(mix); }
void* PORT_Open(INT32 mixerIndex) { char devname[16]; snd_mixer_t* mixer_handle; int err; PortMixer* handle; TRACE0("> PORT_Open\n"); sprintf(devname, ALSA_HARDWARE_CARD, (int) mixerIndex); if ((err = snd_mixer_open(&mixer_handle, 0)) < 0) { ERROR2("Mixer %s open error: %s", devname, snd_strerror(err)); return NULL; } if ((err = snd_mixer_attach(mixer_handle, devname)) < 0) { ERROR2("Mixer attach %s error: %s", devname, snd_strerror(err)); snd_mixer_close(mixer_handle); return NULL; } if ((err = snd_mixer_selem_register(mixer_handle, NULL, NULL)) < 0) { ERROR1("Mixer register error: %s", snd_strerror(err)); snd_mixer_close(mixer_handle); return NULL; } err = snd_mixer_load(mixer_handle); if (err < 0) { ERROR2("Mixer %s load error: %s", devname, snd_strerror(err)); snd_mixer_close(mixer_handle); return NULL; } handle = (PortMixer*) calloc(1, sizeof(PortMixer)); if (handle == NULL) { ERROR0("malloc() failed."); snd_mixer_close(mixer_handle); return NULL; } handle->numElems = 0; handle->elems = (snd_mixer_elem_t**) calloc(MAX_ELEMS, sizeof(snd_mixer_elem_t*)); if (handle->elems == NULL) { ERROR0("malloc() failed."); snd_mixer_close(mixer_handle); free(handle); return NULL; } handle->types = (INT32*) calloc(MAX_ELEMS, sizeof(INT32)); if (handle->types == NULL) { ERROR0("malloc() failed."); snd_mixer_close(mixer_handle); free(handle->elems); free(handle); return NULL; } handle->controls = (PortControl*) calloc(MAX_CONTROLS, sizeof(PortControl)); if (handle->controls == NULL) { ERROR0("malloc() failed."); snd_mixer_close(mixer_handle); free(handle->elems); free(handle->types); free(handle); return NULL; } handle->mixer_handle = mixer_handle; // necessary to initialize data structures PORT_GetPortCount(handle); TRACE0("< PORT_Open\n"); return handle; }
static void alsaOpenDevice(void) { int err; snd_mixer_elem_t *current; alsa_mixers_n=0; if (alsa_pcm) { #ifdef ALSA_DEBUG fprintf(stderr, "ALSA snd_pcm_drain(alsa_pcm) = "); #endif err=snd_pcm_drain(alsa_pcm); #ifdef ALSA_DEBUG if (err) fprintf(stderr, "failed: %s\n", snd_strerror(-err)); else fprintf(stderr, "ok\n"); fprintf(stderr, "ALSA snd_pcm_close(alsa_pcm) = "); #endif err=snd_pcm_close(alsa_pcm); #ifdef ALSA_DEBUG if (err) fprintf(stderr, "failed: %s\n", snd_strerror(-err)); else fprintf(stderr, "ok\n"); #endif alsa_pcm=NULL; } if (mixer) { #ifdef ALSA_DEBUG fprintf(stderr, "ALSA snd_mixer_close(mixer) = "); #endif err=snd_mixer_close(mixer); #ifdef ALSA_DEBUG if (err) fprintf(stderr, "failed: %s\n", snd_strerror(-err)); else fprintf(stderr, "ok\n"); #endif mixer=NULL; } #ifdef ALSA_DEBUG fprintf(stderr, "ALSA snd_pcm_open(&alsa_pcm, device = \"%s\", SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK) = ", alsaCardName); #endif if ((err=snd_pcm_open(&alsa_pcm, alsaCardName, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK))<0) { #ifdef ALSA_DEBUG fprintf(stderr, "failed: %s\n", snd_strerror(-err)); #endif fprintf(stderr, "ALSA: failed to open pcm device (%s): %s\n", alsaCardName, snd_strerror(-err)); alsa_pcm=NULL; return; } #ifdef ALSA_DEBUG fprintf(stderr, "ok\n"); #endif if (!strlen(alsaMixerName)) return; #ifdef ALSA_DEBUG fprintf(stderr, "ALSA snd_mixer_open(&mixer, 0) = "); #endif if ((err=snd_mixer_open(&mixer, 0))<0) { #ifdef ALSA_DEBUG fprintf(stderr, "failed: %s\n", snd_strerror(-err)); #endif fprintf(stderr, "ALSA: snd_mixer_open() failed: %s\n", snd_strerror(-err)); return; } #ifdef ALSA_DEBUG fprintf(stderr, "ok\n"); fprintf(stderr, "ALSA snd_mixer_attach(mixer, device = \"%s\") = ", alsaMixerName); #endif if ((err=snd_mixer_attach(mixer, alsaMixerName))<0) { #ifdef ALSA_DEBUG fprintf(stderr, "failed: %s\n", snd_strerror(-err)); #endif fprintf(stderr, "ALSA: snd_mixer_attach() failed: %s\n", snd_strerror(-err)); #ifdef ALSA_DEBUG fprintf(stderr, "ALSA ans_mixer_close(mixer) = "); #endif err=snd_mixer_close(mixer); #ifdef ALSA_DEBUG if (err) fprintf(stderr, "failed: %s\n", snd_strerror(-err)); else fprintf(stderr, "ok\n"); #endif mixer=NULL; return; } #ifdef ALSA_DEBUG fprintf(stderr, "ok\n"); fprintf(stderr, "ALSA snd_mixer_selem_register(mixer, NULL, NULL) = "); #endif if ((err=snd_mixer_selem_register(mixer, NULL, NULL))<0) { #ifdef ALSA_DEBUG fprintf(stderr, "failed: %s\n", snd_strerror(-err)); #endif fprintf(stderr, "ALSA: snd_mixer_selem_register() failed: %s\n", snd_strerror(-err)); #ifdef ALSA_DEBUG fprintf(stderr, "ALSA snd_mixer_close(mixer) = "); #endif err=snd_mixer_close(mixer); #ifdef ALSA_DEBUG if (err) fprintf(stderr, "failed: %s\n", snd_strerror(-err)); else fprintf(stderr, "ok\n"); #endif mixer=NULL; return; } #ifdef ALSA_DEBUG fprintf(stderr, "ok\n"); fprintf(stderr, "ALSA snd_mixer_load(mixer) = "); #endif if ((err=snd_mixer_load(mixer))<0) { #ifdef ALSA_DEBUG fprintf(stderr, "failed: %s\n", snd_strerror(-err)); #endif fprintf(stderr, "ALSA: snd_mixer_load() failed: %s\n", snd_strerror(-err)); #ifdef ALSA_DEBUG fprintf(stderr, "ALSA snd_mixer_close(mixer) = "); #endif err=snd_mixer_close(mixer); #ifdef ALSA_DEBUG if (err) fprintf(stderr, "failed: %s\n", snd_strerror(-err)); else fprintf(stderr, "ok\n"); #endif mixer=NULL; return; } #ifdef ALSA_DEBUG fprintf(stderr, "ok\n"); #endif current = snd_mixer_first_elem(mixer); while (current) { if (snd_mixer_selem_is_active(current) && snd_mixer_selem_has_playback_volume(current) && (alsa_mixers_n<MAX_ALSA_MIXER)) { long int a, b; long min, max; snd_mixer_selem_get_playback_volume(current, SND_MIXER_SCHN_FRONT_LEFT, &a); snd_mixer_selem_get_playback_volume(current, SND_MIXER_SCHN_FRONT_RIGHT, &b); mixer_entries[alsa_mixers_n].val=(a+b)>>1; snd_mixer_selem_get_playback_volume_range(current, &min, &max); mixer_entries[alsa_mixers_n].min=min; mixer_entries[alsa_mixers_n].max=max; mixer_entries[alsa_mixers_n].step=1; mixer_entries[alsa_mixers_n].log=0; mixer_entries[alsa_mixers_n].name=snd_mixer_selem_get_name(current); alsa_mixers_n++; } current = snd_mixer_elem_next(current); }
static int setlevels(const char *dev) { snd_mixer_t *handle; snd_mixer_selem_id_t *sid; snd_mixer_elem_t *elem; int err; char *mixer_dev, *c; /* Basically we just want to turn on Mic capture. */ if ((err = snd_mixer_open(&handle, 0)) < 0) { fprintf(stderr, "Mixer open failed: %s\n", snd_strerror(err)); return -1; } mixer_dev = strdup(dev); if (strncmp(mixer_dev, "plug", 4) == 0) memmove(mixer_dev, mixer_dev + 4, strlen(mixer_dev) - 4 + 1); if ((c = strchr(mixer_dev, ','))) *c = '\0'; if ((err = snd_mixer_attach(handle, mixer_dev)) < 0) { fprintf(stderr, "Mixer attach to %s failed: %s\n", mixer_dev, snd_strerror(err)); free(mixer_dev); snd_mixer_close(handle); return -1; } free(mixer_dev); if ((err = snd_mixer_selem_register(handle, NULL, NULL)) < 0) { fprintf(stderr, "Mixer register failed: %s\n", snd_strerror(err)); snd_mixer_close(handle); return -1; } if ((err = snd_mixer_load(handle)) < 0) { fprintf(stderr, "Mixer load failed: %s\n", snd_strerror(err)); snd_mixer_close(handle); return -1; } snd_mixer_selem_id_alloca(&sid); snd_mixer_selem_id_set_name(sid, "Mic"); if ((elem = snd_mixer_find_selem(handle, sid)) == NULL) { fprintf(stderr, "Warning: Could not find Mic element\n"); } else { if ((err = snd_mixer_selem_set_capture_switch_all(elem, 1)) < 0) { fprintf(stderr, "Failed to enable microphone capture: %s\n", snd_strerror(err)); snd_mixer_close(handle); return -1; } } snd_mixer_selem_id_set_name(sid, "Capture"); if ((elem = snd_mixer_find_selem(handle, sid)) == NULL) { fprintf(stderr, "Warning: Could not find Capture element\n"); } else { if ((err = snd_mixer_selem_set_capture_switch_all(elem, 1)) < 0) { fprintf(stderr, "Failed to enable microphone capture: %s\n", snd_strerror(err)); snd_mixer_close(handle); return -1; } } return 0; }
void VolumeControl::init() { //initialize audio mixer interface #if defined (__APPLE__) #error 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 }
void deinit(void) { snd_mixer_close(handle); }
void alsactl_close(void* handle) { snd_mixer_close((snd_mixer_t*)handle); }
static void set_mixer(const char *device, const char *mixer, int mixer_index, bool setmax, float ldB, float rdB) { int err; long nleft, nright; long min, max; snd_mixer_t *handle; snd_mixer_selem_id_t *sid; snd_mixer_elem_t* elem; if ((err = snd_mixer_open(&handle, 0)) < 0) { LOG_ERROR("open error: %s", snd_strerror(err)); return; } if ((err = snd_mixer_attach(handle, device)) < 0) { LOG_ERROR("attach error: %s", snd_strerror(err)); snd_mixer_close(handle); return; } if ((err = snd_mixer_selem_register(handle, NULL, NULL)) < 0) { LOG_ERROR("register error: %s", snd_strerror(err)); snd_mixer_close(handle); return; } if ((err = snd_mixer_load(handle)) < 0) { LOG_ERROR("load error: %s", snd_strerror(err)); snd_mixer_close(handle); return; } snd_mixer_selem_id_alloca(&sid); snd_mixer_selem_id_set_index(sid, mixer_index); snd_mixer_selem_id_set_name(sid, mixer); if ((elem = snd_mixer_find_selem(handle, sid)) == NULL) { LOG_ERROR("error find selem %s", mixer); snd_mixer_close(handle); return; } if (snd_mixer_selem_has_playback_switch(elem)) { snd_mixer_selem_set_playback_switch_all(elem, 1); // unmute } err = snd_mixer_selem_get_playback_dB_range(elem, &min, &max); if (err < 0 || max - min < 1000) { // unable to get db range or range is less than 10dB - ignore and set using raw values if ((err = snd_mixer_selem_get_playback_volume_range(elem, &min, &max)) < 0) { LOG_ERROR("unable to get volume raw range"); } else { long lraw, rraw; if (setmax) { lraw = rraw = max; } else { lraw = ((ldB > -MINVOL_DB ? MINVOL_DB + floor(ldB) : 0) / MINVOL_DB * (max-min)) + min; rraw = ((rdB > -MINVOL_DB ? MINVOL_DB + floor(rdB) : 0) / MINVOL_DB * (max-min)) + min; } LOG_DEBUG("setting vol raw [%ld..%ld]", min, max); if ((err = snd_mixer_selem_set_playback_volume(elem, SND_MIXER_SCHN_FRONT_LEFT, lraw)) < 0) { LOG_ERROR("error setting left volume: %s", snd_strerror(err)); } if ((err = snd_mixer_selem_set_playback_volume(elem, SND_MIXER_SCHN_FRONT_RIGHT, rraw)) < 0) { LOG_ERROR("error setting right volume: %s", snd_strerror(err)); } } } else { // set db directly LOG_DEBUG("setting vol dB [%ld..%ld]", min, max); if (setmax) { // set to 0dB if available as this should be max volume for music recored at max pcm values if (max >= 0 && min <= 0) { ldB = rdB = 0; } else { ldB = rdB = max; } } if ((err = snd_mixer_selem_set_playback_dB(elem, SND_MIXER_SCHN_FRONT_LEFT, 100 * ldB, 1)) < 0) { LOG_ERROR("error setting left volume: %s", snd_strerror(err)); } if ((err = snd_mixer_selem_set_playback_dB(elem, SND_MIXER_SCHN_FRONT_RIGHT, 100 * rdB, 1)) < 0) { LOG_ERROR("error setting right volume: %s", snd_strerror(err)); } } if ((err = snd_mixer_selem_get_playback_volume(elem, SND_MIXER_SCHN_FRONT_LEFT, &nleft)) < 0) { LOG_ERROR("error getting left vol: %s", snd_strerror(err)); } if ((err = snd_mixer_selem_get_playback_volume(elem, SND_MIXER_SCHN_FRONT_RIGHT, &nright)) < 0) { LOG_ERROR("error getting right vol: %s", snd_strerror(err)); } LOG_DEBUG("%s left: %3.1fdB -> %ld right: %3.1fdB -> %ld", mixer, ldB, nleft, rdB, nright); snd_mixer_close(handle); }