summaryrefslogtreecommitdiff
path: root/backends/oss/oss-switch.c
diff options
context:
space:
mode:
Diffstat (limited to 'backends/oss/oss-switch.c')
-rw-r--r--backends/oss/oss-switch.c113
1 files changed, 86 insertions, 27 deletions
diff --git a/backends/oss/oss-switch.c b/backends/oss/oss-switch.c
index b138051..8e32281 100644
--- a/backends/oss/oss-switch.c
+++ b/backends/oss/oss-switch.c
@@ -38,10 +38,12 @@ static void oss_switch_finalize (GObject *object);
G_DEFINE_TYPE (OssSwitch, oss_switch, MATE_MIXER_TYPE_SWITCH)
-static gboolean oss_switch_set_active_option (MateMixerSwitch *mms,
- MateMixerSwitchOption *mmso);
+static gboolean oss_switch_set_active_option (MateMixerSwitch *mms,
+ MateMixerSwitchOption *mmso);
-static const GList *oss_switch_list_options (MateMixerSwitch *mms);
+static const GList * oss_switch_list_options (MateMixerSwitch *mms);
+
+static OssSwitchOption *choose_default_option (OssSwitch *swtch);
static void
oss_switch_class_init (OssSwitchClass *klass)
@@ -104,10 +106,14 @@ oss_switch_new (const gchar *name,
{
OssSwitch *swtch;
+ g_return_val_if_fail (name != NULL, NULL);
+ g_return_val_if_fail (label != NULL, NULL);
+ g_return_val_if_fail (fd != -1, NULL);
+ g_return_val_if_fail (options != NULL, NULL);
+
swtch = g_object_new (OSS_TYPE_SWITCH,
"name", name,
"label", label,
- "flags", MATE_MIXER_SWITCH_ALLOWS_NO_ACTIVE_OPTION,
"role", MATE_MIXER_SWITCH_ROLE_PORT,
NULL);
@@ -121,39 +127,70 @@ oss_switch_new (const gchar *name,
void
oss_switch_load (OssSwitch *swtch)
{
- GList *list;
- gint recsrc;
- gint ret;
+ OssSwitchOption *option;
+ gint recsrc;
+ gint devnum;
+ gint ret;
g_return_if_fail (OSS_IS_SWITCH (swtch));
if G_UNLIKELY (swtch->priv->fd == -1)
return;
+ /* Recsrc contains a bitmask of currently enabled recording sources */
ret = ioctl (swtch->priv->fd, MIXER_READ (SOUND_MIXER_RECSRC), &recsrc);
if (ret == -1)
return;
- if (recsrc == 0) {
- _mate_mixer_switch_set_active_option (MATE_MIXER_SWITCH (swtch), NULL);
- return;
- }
- list = swtch->priv->options;
- while (list != NULL) {
- OssSwitchOption *option = OSS_SWITCH_OPTION (list->data);
- gint devnum = oss_switch_option_get_devnum (option);
-
- /* Mark the selected option when we find it */
- if (recsrc & (1 << devnum)) {
- _mate_mixer_switch_set_active_option (MATE_MIXER_SWITCH (swtch),
- MATE_MIXER_SWITCH_OPTION (option));
- return;
+ if (recsrc != 0) {
+ GList *list = swtch->priv->options;
+
+ /* Find out which option is currently selected */
+ while (list != NULL) {
+ gint devnum;
+
+ option = OSS_SWITCH_OPTION (list->data);
+ devnum = oss_switch_option_get_devnum (option);
+
+ if (recsrc & (1 << devnum)) {
+ /* It is possible that some hardware might allow and have more recording
+ * sources active at the same time, but we only support one active
+ * source at a time */
+ _mate_mixer_switch_set_active_option (MATE_MIXER_SWITCH (swtch),
+ MATE_MIXER_SWITCH_OPTION (option));
+ return;
+ }
+ list = list->next;
}
- list = list->next;
+
+ g_debug ("Switch %s has unknown device %d as the active option",
+ mate_mixer_switch_get_name (MATE_MIXER_SWITCH (swtch)),
+ devnum);
+
+ /* OSS shouldn't let a non-record device be selected, let's step in and select
+ * something reasonable instead... */
+ } else {
+ g_debug ("Switch %s has no active device",
+ mate_mixer_switch_get_name (MATE_MIXER_SWITCH (swtch)));
+
+ /* According to the OSS Programmer's Guide, if the recsrc value is 0, the
+ * microphone will be selected implicitly.
+ * Let's not assume that's true everywhere and select something explicitly... */
}
- g_warning ("Unknown active option of switch %s",
- mate_mixer_switch_get_name (MATE_MIXER_SWITCH (swtch)));
+ option = choose_default_option (swtch);
+
+ g_debug ("Selecting default device %s as active for switch %s",
+ mate_mixer_switch_option_get_name (MATE_MIXER_SWITCH_OPTION (option)),
+ mate_mixer_switch_get_name (MATE_MIXER_SWITCH (swtch)));
+
+ if (mate_mixer_switch_set_active_option (MATE_MIXER_SWITCH (swtch),
+ MATE_MIXER_SWITCH_OPTION (option)) == FALSE) {
+ g_debug ("Failed to set the default device, assuming it is selected anyway");
+
+ _mate_mixer_switch_set_active_option (MATE_MIXER_SWITCH (swtch),
+ MATE_MIXER_SWITCH_OPTION (option));
+ }
}
void
@@ -174,7 +211,6 @@ oss_switch_set_active_option (MateMixerSwitch *mms, MateMixerSwitchOption *mmso)
OssSwitch *swtch;
gint ret;
gint recsrc;
- gint devnum;
g_return_val_if_fail (OSS_IS_SWITCH (mms), FALSE);
g_return_val_if_fail (OSS_IS_SWITCH_OPTION (mmso), FALSE);
@@ -184,8 +220,7 @@ oss_switch_set_active_option (MateMixerSwitch *mms, MateMixerSwitchOption *mmso)
if G_UNLIKELY (swtch->priv->fd == -1)
return FALSE;
- devnum = oss_switch_option_get_devnum (OSS_SWITCH_OPTION (mmso));
- recsrc = 1 << devnum;
+ recsrc = 1 << oss_switch_option_get_devnum (OSS_SWITCH_OPTION (mmso));
ret = ioctl (swtch->priv->fd, MIXER_WRITE (SOUND_MIXER_RECSRC), &recsrc);
if (ret == -1)
@@ -201,3 +236,27 @@ oss_switch_list_options (MateMixerSwitch *mms)
return OSS_SWITCH (mms)->priv->options;
}
+
+#define OSS_SWITCH_PREFERRED_DEFAULT_DEVNUM 7 /* Microphone */
+
+static OssSwitchOption *
+choose_default_option (OssSwitch *swtch)
+{
+ GList *list = swtch->priv->options;
+
+ /* Search for the preferred device */
+ while (list != NULL) {
+ OssSwitchOption *option;
+ gint devnum;
+
+ option = OSS_SWITCH_OPTION (list->data);
+ devnum = oss_switch_option_get_devnum (option);
+
+ if (devnum == OSS_SWITCH_PREFERRED_DEFAULT_DEVNUM)
+ return option;
+
+ list = list->next;
+ }
+ /* If the preferred device is not present, use the first available one */
+ return OSS_SWITCH_OPTION (swtch->priv->options->data);
+}