Example #1
0
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(&timestamp);
        strftime(datetime, DATETIME_BUFFER, DATETIME_FORMAT, localtime(&timestamp));

        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;
}
Example #2
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;
}
Example #3
0
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);
        }
    }
}
Example #4
0
/**
 * Closes the alsa mixer handle.
 */
void
alsa_close(void)
{
    snd_mixer_close(handle);
}
Example #5
0
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;
}
Example #6
0
static int alsa_mixer_close(void)
{
	snd_mixer_close(alsa_mixer_handle);
	return 0;
}
Example #7
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;
}
Example #8
0
/******************************************************************************
 *   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;
}
Example #9
0
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;
}
Example #10
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(&params);
        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;
}
Example #11
0
void AlsaMixer::clean_up()
{
    if (this->handle)
        snd_mixer_close(this->handle);
}
Example #12
0
AlsaMixer::~AlsaMixer()
{
    snd_mixer_close(m_handle);
}
Example #13
0
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);
}
Example #14
0
/**
 * 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");
    }
}
Example #15
0
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);
}
Example #16
0
void cleanup_handle(snd_mixer_t* handle) {
  snd_mixer_detach(handle, "default");
  snd_mixer_close(handle);
}
Example #17
0
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, &currentVolume))
   {
        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, &currentVolume))
   {
        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, &currentVolume))
              {
        		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);
}
Example #18
0
static void deinit(void) {
    stop();
    if (alsa_mix_handle) {
        snd_mixer_close(alsa_mix_handle);
    }
}
Example #19
0
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;

}
Example #20
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;
}
Example #21
0
File: ao_alsa.c Project: 2ion/mpv
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);
}
Example #23
0
static void alsa_mixer_close(snd_mixer_t *mix){
	snd_mixer_close(mix);
}
Example #24
0
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;
}
Example #25
0
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);
	}
Example #26
0
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
}
Example #28
0
void deinit(void) {
	snd_mixer_close(handle);
}
Example #29
0
void alsactl_close(void* handle) {
    snd_mixer_close((snd_mixer_t*)handle);
}
Example #30
0
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);
}