/** * Callback function for the mixer element which is * set in alsaset(). * * @param e mixer element * @param mask event mask * @return 0 on success otherwise a negative error code */ static int alsa_cb(snd_mixer_elem_t *e, unsigned int mask) { /* Test MASK_REMOVE first, according to Alsa documentation */ if (mask == SND_CTL_EVENT_MASK_REMOVE) { return 0; } /* Then check if mixer value changed */ if (mask & SND_CTL_EVENT_MASK_VALUE) { int muted; get_current_levels(); muted = ismuted(); on_volume_has_changed(); if (enable_noti && external_noti) { int vol = getvol(); if (muted) do_notify_volume(vol, FALSE); else do_notify_volume(vol, TRUE); } } return 0; }
/** * Reinitializes alsa and updates the various states. */ void do_alsa_reinit(void) { alsa_init(); update_status_icons(); update_vol_text(); on_volume_has_changed(); }
/** * This function is called before gdk/gtk can respond * to any(!) window event and handles pressed hotkeys. * * @param gdk_xevent the native event to filter * @param event the GDK event to which the X event will be translated * @param data user data set when the filter was installed * @return a GdkFilterReturn value, should be GDK_FILTER_CONTINUE only */ static GdkFilterReturn key_filter(GdkXEvent *gdk_xevent, G_GNUC_UNUSED GdkEvent *event, G_GNUC_UNUSED gpointer data) { int type; guint key, state; XKeyEvent *xevent; //gboolean bResult; xevent = gdk_xevent; type = xevent->type; if (type == KeyPress) { key = ((XKeyEvent *) xevent)->keycode; state = ((XKeyEvent *) xevent)->state; if ((int) key == volMuteKey && checkModKey(state, volMuteMods)) { setmute(enable_noti && hotkey_noti); on_volume_has_changed(); return GDK_FILTER_CONTINUE; } else { int cv = getvol(); if ((int) key == volUpKey && checkModKey(state, volUpMods)) { setvol(cv + volStep, 1, enable_noti && hotkey_noti); } else if ((int) key == volDownKey && checkModKey(state, volDownMods)) { setvol(cv - volStep, -1, enable_noti && hotkey_noti); } // just ignore unknown hotkeys if (ismuted() == 0) setmute(enable_noti && hotkey_noti); on_volume_has_changed(); // this will set the slider value get_current_levels(); } } return GDK_FILTER_CONTINUE; }
/** * Handles button-release-event' signal on the tray_icon, currently * only used for middle-click. * * @param status_icon the object which received the signal * @param event the GdkEventButton which triggered this signal * @param user_data user data set when the signal handler was * connected */ void tray_icon_button(G_GNUC_UNUSED GtkStatusIcon *status_icon, GdkEventButton *event, G_GNUC_UNUSED gpointer user_data) { gint action; if (event->button != 2) return; action = prefs_get_integer("MiddleClickAction", 0); switch (action) { case 0: // mute/unmute setmute(mouse_noti); on_volume_has_changed(); break; case 1: do_prefs(); break; case 2: on_mixer(); break; case 3: { gchar *cmd; cmd = prefs_get_string("CustomCommand", NULL); if (cmd) { run_command(cmd); g_free(cmd); } else report_error(_("You have not specified a custom command to run, " "please specify one in preferences.")); break; } default: { } // nothing } }
/** * Updates all status icons for the different volume states like * muted, low, medium, high as well as the volume meter. This * is triggered either by apply_prefs() in the preferences subsystem, * do_alsa_reinit() or tray_icon_resized(). */ void update_status_icons(void) { int i, icon_width; GdkPixbuf *old_icons[N_VOLUME_ICONS]; int size = tray_icon_size(); for (i = 0; i < N_VOLUME_ICONS; i++) old_icons[i] = status_icons[i]; /* Handle icons depending on the theme */ if (prefs_get_boolean("SystemTheme", FALSE)) { status_icons[VOLUME_MUTED] = get_stock_pixbuf("audio-volume-muted", size); status_icons[VOLUME_OFF] = get_stock_pixbuf("audio-volume-off", size); status_icons[VOLUME_LOW] = get_stock_pixbuf("audio-volume-low", size); status_icons[VOLUME_MEDIUM] = get_stock_pixbuf("audio-volume-medium", size); status_icons[VOLUME_HIGH] = get_stock_pixbuf("audio-volume-high", size); /* 'audio-volume-off' is not available in every icon set. More info at: * http://standards.freedesktop.org/icon-naming-spec/icon-naming-spec-latest.html */ if (status_icons[VOLUME_OFF] == NULL) status_icons[VOLUME_OFF] = get_stock_pixbuf("audio-volume-low", size); } else { status_icons[VOLUME_MUTED] = create_pixbuf("pnmixer-muted.png"); status_icons[VOLUME_OFF] = create_pixbuf("pnmixer-off.png"); status_icons[VOLUME_LOW] = create_pixbuf("pnmixer-low.png"); status_icons[VOLUME_MEDIUM] = create_pixbuf("pnmixer-medium.png"); status_icons[VOLUME_HIGH] = create_pixbuf("pnmixer-high.png"); } /* Handle volume meter */ icon_width = gdk_pixbuf_get_height(status_icons[0]); vol_div_factor = ((gdk_pixbuf_get_height(status_icons[0]) - 10) / 100.0); vol_meter_width = 1.25 * icon_width; if (vol_meter_width % 4 != 0) vol_meter_width -= (vol_meter_width % 4); if (prefs_get_boolean("DrawVolMeter", FALSE)) { int lim; if (vol_meter_row) g_free(vol_meter_row); vol_meter_row = g_malloc(vol_meter_width * sizeof(guchar)); lim = vol_meter_width / 4; for (i = 0; i < lim; i++) { vol_meter_row[i * 4] = vol_meter_red; vol_meter_row[i * 4 + 1] = vol_meter_green; vol_meter_row[i * 4 + 2] = vol_meter_blue; vol_meter_row[i * 4 + 3] = 255; } } else { if (vol_meter_row) g_free(vol_meter_row); vol_meter_row = NULL; if (icon_copy) g_object_unref(icon_copy); icon_copy = NULL; } draw_offset = prefs_get_integer("VolMeterPos", 0); if (tray_icon) on_volume_has_changed(); for (i = 0; i < N_VOLUME_ICONS; i++) if (old_icons[i]) g_object_unref(old_icons[i]); }