OSDN Git Service

Added support for route controls
authorJaroslav Kysela <perex@perex.cz>
Tue, 22 Aug 2000 18:02:43 +0000 (18:02 +0000)
committerJaroslav Kysela <perex@perex.cz>
Tue, 22 Aug 2000 18:02:43 +0000 (18:02 +0000)
src/mixer/mixer_local.h
src/mixer/simple.c

index 1d69cd5..e9901c8 100644 (file)
@@ -32,11 +32,14 @@ typedef int (mixer_simple_event_add_t) (snd_mixer_t *handle, snd_hcontrol_t *hco
 
 #define MIXER_PRESENT_GLOBAL_SWITCH    (1<<0)
 #define MIXER_PRESENT_GLOBAL_VOLUME    (1<<1)
-#define MIXER_PRESENT_PLAYBACK_SWITCH  (1<<2)
-#define MIXER_PRESENT_PLAYBACK_VOLUME  (1<<3)
-#define MIXER_PRESENT_CAPTURE_SWITCH   (1<<4)
-#define MIXER_PRESENT_CAPTURE_VOLUME   (1<<5)
-#define MIXER_PRESENT_CAPTURE_SOURCE   (1<<6)
+#define MIXER_PRESENT_GLOBAL_ROUTE     (1<<2)
+#define MIXER_PRESENT_PLAYBACK_SWITCH  (1<<3)
+#define MIXER_PRESENT_PLAYBACK_VOLUME  (1<<4)
+#define MIXER_PRESENT_PLAYBACK_ROUTE   (1<<5)
+#define MIXER_PRESENT_CAPTURE_SWITCH   (1<<6)
+#define MIXER_PRESENT_CAPTURE_VOLUME   (1<<7)
+#define MIXER_PRESENT_CAPTURE_ROUTE    (1<<8)
+#define MIXER_PRESENT_CAPTURE_SOURCE   (1<<9)
 
 struct mixer_simple {
        /* this may be moved to a private area */
@@ -47,6 +50,9 @@ struct mixer_simple {
        unsigned int gvolume_values;
        unsigned int pvolume_values;
        unsigned int cvolume_values;
+       unsigned int groute_values;
+       unsigned int proute_values;
+       unsigned int croute_values;
        unsigned int ccapture_values;
        unsigned int capture_item;
        unsigned int caps;
index 63b4818..5cd0f12 100644 (file)
@@ -166,6 +166,21 @@ static int input_get_mute_switch(snd_mixer_t *handle, mixer_simple_t *simple, sn
        return 0;
 }
 
+static int input_get_mute_route(snd_mixer_t *handle, mixer_simple_t *simple, snd_mixer_simple_control_t *control, const char *direction, int voices)
+{
+       char str[128];
+       snd_control_t ctl;
+       int idx, err;
+       
+       sprintf(str, "%s %sRoute", simple->sid.name, direction);
+       if ((err = get_mixer_read(handle, str, simple->sid.index, &ctl)) < 0)
+               return err;
+       for (idx = 0; idx < simple->voices && idx < 32; idx++)
+               if (ctl.value.integer.value[(idx * voices) + idx] == 0)
+                       control->mute |= 1 << idx;
+       return 0;
+}
+
 static int input_get_capture_switch(snd_mixer_t *handle, mixer_simple_t *simple, snd_mixer_simple_control_t *control, const char *direction, int voices)
 {
        char str[128];
@@ -181,6 +196,21 @@ static int input_get_capture_switch(snd_mixer_t *handle, mixer_simple_t *simple,
        return 0;
 }
 
+static int input_get_capture_route(snd_mixer_t *handle, mixer_simple_t *simple, snd_mixer_simple_control_t *control, const char *direction, int voices)
+{
+       char str[128];
+       snd_control_t ctl;
+       int idx, err;
+       
+       sprintf(str, "%s %sRoute", simple->sid.name, direction);
+       if ((err = get_mixer_read(handle, str, simple->sid.index, &ctl)) < 0)
+               return err;
+       for (idx = 0; idx < simple->voices && idx < 32; idx++)
+               if (ctl.value.integer.value[(idx * voices) + idx])
+                       control->capture |= 1 << idx;
+       return 0;
+}
+
 static int input_get(snd_mixer_t *handle, mixer_simple_t *simple, snd_mixer_simple_control_t *control)
 {
        int idx, err;
@@ -210,13 +240,19 @@ static int input_get(snd_mixer_t *handle, mixer_simple_t *simple, snd_mixer_simp
        if (simple->caps & SND_MIXER_SCTCAP_MUTE) {
                if (simple->present & MIXER_PRESENT_PLAYBACK_SWITCH) {
                        input_get_mute_switch(handle, simple, control, "Playback ", simple->pswitch_values);
-               } else if (simple->present & MIXER_PRESENT_GLOBAL_VOLUME) {
+               } else if (simple->present & MIXER_PRESENT_GLOBAL_SWITCH) {
                        input_get_mute_switch(handle, simple, control, "", simple->pvolume_values);
+               } else if (simple->present & MIXER_PRESENT_PLAYBACK_ROUTE) {
+                       input_get_mute_route(handle, simple, control, "Playback ", simple->proute_values);
+               } else if (simple->present & MIXER_PRESENT_GLOBAL_ROUTE) {
+                       input_get_mute_route(handle, simple, control, "", simple->groute_values);
                }
        }
        if (simple->caps & SND_MIXER_SCTCAP_CAPTURE) {
                if (simple->present & MIXER_PRESENT_CAPTURE_SWITCH) {
                        input_get_capture_switch(handle, simple, control, "Capture ", simple->cswitch_values);
+               } else if (simple->present & MIXER_PRESENT_CAPTURE_ROUTE) {
+                       input_get_capture_route(handle, simple, control, "Capture ", simple->croute_values);
                } else if (simple->present & MIXER_PRESENT_CAPTURE_SOURCE) {
                        snd_control_t ctl;
                        if ((err = get_mixer_read(handle, "Capture Source", 0, &ctl)) < 0)
@@ -256,10 +292,27 @@ static int input_put_mute_switch(snd_mixer_t *handle, mixer_simple_t *simple, sn
        sprintf(str, "%s %sSwitch", simple->sid.name, direction);
        if ((err = get_mixer_read(handle, str, simple->sid.index, &ctl)) < 0)
                return err;
-       for (idx = 0; idx < voices && idx < 32; idx++) {
+       for (idx = 0; idx < voices && idx < 32; idx++)
                ctl.value.integer.value[idx] = (control->mute & (1 << idx)) ? 0 : 1;
-               // fprintf(stderr, "ctl.id.name = '%s', switch = %i\n", ctl.id.name, ctl.value.integer.value[idx]);
-       }
+       err = put_mixer_write(handle, str, simple->sid.index, &ctl);
+       if ((err = put_mixer_write(handle, str, simple->sid.index, &ctl)) < 0)
+               return err;
+       return 0;
+}
+
+static int input_put_mute_route(snd_mixer_t *handle, mixer_simple_t *simple, snd_mixer_simple_control_t *control, const char *direction, int voices)
+{
+       char str[128];
+       snd_control_t ctl;
+       int idx, err;
+       
+       sprintf(str, "%s %sRoute", simple->sid.name, direction);
+       if ((err = get_mixer_read(handle, str, simple->sid.index, &ctl)) < 0)
+               return err;
+       for (idx = 0; idx < voices * voices; idx++)
+               ctl.value.integer.value[idx] = 0;
+       for (idx = 0; idx < voices && idx < 32; idx++)
+               ctl.value.integer.value[(idx * voices) + idx] = (control->mute & (1 << idx)) ? 0 : 1;
        err = put_mixer_write(handle, str, simple->sid.index, &ctl);
        if ((err = put_mixer_write(handle, str, simple->sid.index, &ctl)) < 0)
                return err;
@@ -282,6 +335,24 @@ static int input_put_capture_switch(snd_mixer_t *handle, mixer_simple_t *simple,
        return 0;
 }
 
+static int input_put_capture_route(snd_mixer_t *handle, mixer_simple_t *simple, snd_mixer_simple_control_t *control, const char *direction, int voices)
+{
+       char str[128];
+       snd_control_t ctl;
+       int idx, err;
+       
+       sprintf(str, "%s %sRoute", simple->sid.name, direction);
+       if ((err = get_mixer_read(handle, str, simple->sid.index, &ctl)) < 0)
+               return err;
+       for (idx = 0; idx < voices * voices; idx++)
+               ctl.value.integer.value[idx] = 0;
+       for (idx = 0; idx < voices && idx < 32; idx++)
+               ctl.value.integer.value[(idx * voices) + idx] = (control->capture & (1 << idx)) ? 1 : 0;
+       if ((err = put_mixer_write(handle, str, simple->sid.index, &ctl)) < 0)
+               return err;
+       return 0;
+}
+
 static int input_put(snd_mixer_t *handle, mixer_simple_t *simple, snd_mixer_simple_control_t *control)
 {
        int err, idx;
@@ -303,12 +374,18 @@ static int input_put(snd_mixer_t *handle, mixer_simple_t *simple, snd_mixer_simp
                        input_put_mute_switch(handle, simple, control, "Playback ", simple->pswitch_values);
                } else if (simple->present & MIXER_PRESENT_GLOBAL_VOLUME) {
                        input_put_mute_switch(handle, simple, control, "", simple->pvolume_values);
+               } else if (simple->present & MIXER_PRESENT_PLAYBACK_ROUTE) {
+                       input_put_mute_route(handle, simple, control, "Playback ", simple->proute_values);
+               } else if (simple->present & MIXER_PRESENT_GLOBAL_ROUTE) {
+                       input_put_mute_route(handle, simple, control, "", simple->groute_values);
                }
        }
        if (simple->caps & SND_MIXER_SCTCAP_CAPTURE) {
                // fprintf(stderr, "capture: present = 0x%x\n", simple->present);
                if (simple->present & MIXER_PRESENT_CAPTURE_SWITCH) {
                        input_put_capture_switch(handle, simple, control, "Capture ", simple->cswitch_values);
+               } else if (simple->present & MIXER_PRESENT_CAPTURE_ROUTE) {
+                       input_put_capture_route(handle, simple, control, "Capture ", simple->croute_values);
                } else if (simple->present & MIXER_PRESENT_CAPTURE_SOURCE) {
                        snd_control_t ctl;
                        if ((err = get_mixer_read(handle, "Capture Source", 0, &ctl)) < 0)
@@ -348,6 +425,7 @@ static int build_input(snd_mixer_t *handle, const char *sname)
        int index = -1, err;
        snd_control_info_t gswitch_info, pswitch_info, cswitch_info;
        snd_control_info_t gvolume_info, pvolume_info, cvolume_info;
+       snd_control_info_t groute_info, proute_info, croute_info;
        snd_control_info_t csource_info;
        long min, max;
        void *bag;
@@ -360,6 +438,9 @@ static int build_input(snd_mixer_t *handle, const char *sname)
        memset(&gvolume_info, 0, sizeof(gvolume_info));
        memset(&pvolume_info, 0, sizeof(pvolume_info));
        memset(&cvolume_info, 0, sizeof(cvolume_info));
+       memset(&groute_info, 0, sizeof(groute_info));
+       memset(&proute_info, 0, sizeof(proute_info));
+       memset(&croute_info, 0, sizeof(croute_info));
        while (1) {
                index++;
                voices = 0;
@@ -378,6 +459,18 @@ static int build_input(snd_mixer_t *handle, const char *sname)
                                hcontrol_add(handle, &bag, hcontrol);
                        }
                }
+               sprintf(str, "%s Route", sname);
+               if ((hcontrol = test_mixer_id(handle, str, index)) != NULL) {
+                       if ((err = get_mixer_info(handle, str, index, &groute_info)) < 0)
+                               return err;
+                       if (groute_info.type == SND_CONTROL_TYPE_BOOLEAN && groute_info.values_count == 4) {
+                               if (voices < 2)
+                                       voices = 2;
+                               caps |= SND_MIXER_SCTCAP_MUTE;
+                               present |= MIXER_PRESENT_GLOBAL_ROUTE;
+                               hcontrol_add(handle, &bag, hcontrol);
+                       }
+               }
                sprintf(str, "%s Volume", sname);
                if ((hcontrol = test_mixer_id(handle, str, index)) != NULL) {
                        if ((err = get_mixer_info(handle, str, index, &gvolume_info)) < 0)
@@ -406,6 +499,18 @@ static int build_input(snd_mixer_t *handle, const char *sname)
                                hcontrol_add(handle, &bag, hcontrol);
                        }
                }
+               sprintf(str, "%s Playback Route", sname);
+               if ((hcontrol = test_mixer_id(handle, str, index)) != NULL) {
+                       if ((err = get_mixer_info(handle, str, index, &proute_info)) < 0)
+                               return err;
+                       if (proute_info.type == SND_CONTROL_TYPE_BOOLEAN && proute_info.values_count == 4) {
+                               if (voices < 2)
+                                       voices = 2;
+                               caps |= SND_MIXER_SCTCAP_MUTE;
+                               present |= MIXER_PRESENT_PLAYBACK_ROUTE;
+                               hcontrol_add(handle, &bag, hcontrol);
+                       }
+               }
                sprintf(str, "%s Capture Switch", sname);
                if ((hcontrol = test_mixer_id(handle, str, index)) != NULL) {
                        if ((err = get_mixer_info(handle, str, index, &cswitch_info)) < 0)
@@ -418,6 +523,18 @@ static int build_input(snd_mixer_t *handle, const char *sname)
                                hcontrol_add(handle, &bag, hcontrol);
                        }
                }
+               sprintf(str, "%s Capture Route", sname);
+               if ((hcontrol = test_mixer_id(handle, str, index)) != NULL) {
+                       if ((err = get_mixer_info(handle, str, index, &croute_info)) < 0)
+                               return err;
+                       if (croute_info.type == SND_CONTROL_TYPE_BOOLEAN && croute_info.values_count == 4) {
+                               if (voices < 2)
+                                       voices = 2;
+                               caps |= SND_MIXER_SCTCAP_CAPTURE;
+                               present |= MIXER_PRESENT_CAPTURE_ROUTE;
+                               hcontrol_add(handle, &bag, hcontrol);
+                       }
+               }
                sprintf(str, "%s Playback Volume", sname);
                if ((hcontrol = test_mixer_id(handle, str, index)) != NULL) {
                        if ((err = get_mixer_info(handle, str, index, &pvolume_info)) < 0)
@@ -482,7 +599,12 @@ static int build_input(snd_mixer_t *handle, const char *sname)
                        }
                }
                if (voices > 1) {
-                       caps |= SND_MIXER_SCTCAP_JOINTLY_MUTE | SND_MIXER_SCTCAP_JOINTLY_CAPTURE | SND_MIXER_SCTCAP_JOINTLY_VOLUME;
+                       if (present & (MIXER_PRESENT_GLOBAL_SWITCH|MIXER_PRESENT_GLOBAL_ROUTE|MIXER_PRESENT_PLAYBACK_SWITCH|MIXER_PRESENT_GLOBAL_SWITCH))
+                               caps |= SND_MIXER_SCTCAP_JOINTLY_MUTE;
+                       if (present & (MIXER_PRESENT_CAPTURE_SWITCH|MIXER_PRESENT_CAPTURE_ROUTE|MIXER_PRESENT_CAPTURE_SOURCE))
+                               caps |= SND_MIXER_SCTCAP_JOINTLY_CAPTURE;
+                       if (present & (MIXER_PRESENT_GLOBAL_VOLUME|MIXER_PRESENT_PLAYBACK_VOLUME|MIXER_PRESENT_CAPTURE_VOLUME))
+                               caps |= SND_MIXER_SCTCAP_JOINTLY_VOLUME;
                        if (present & MIXER_PRESENT_GLOBAL_SWITCH) {
                                if (gswitch_info.values_count > 1)
                                        caps &= ~SND_MIXER_SCTCAP_JOINTLY_MUTE;
@@ -491,10 +613,14 @@ static int build_input(snd_mixer_t *handle, const char *sname)
                                if (pswitch_info.values_count > 1)
                                        caps &= ~SND_MIXER_SCTCAP_JOINTLY_MUTE;
                        }
+                       if (present & (MIXER_PRESENT_GLOBAL_ROUTE | MIXER_PRESENT_PLAYBACK_ROUTE))
+                               caps &= ~SND_MIXER_SCTCAP_JOINTLY_MUTE;
                        if (present & MIXER_PRESENT_CAPTURE_SWITCH) {
                                if (cswitch_info.values_count > 1)
                                        caps &= ~SND_MIXER_SCTCAP_JOINTLY_CAPTURE;
                        }
+                       if (present & MIXER_PRESENT_CAPTURE_ROUTE)
+                               caps &= ~SND_MIXER_SCTCAP_JOINTLY_CAPTURE;
                        if (present & MIXER_PRESENT_GLOBAL_VOLUME) {
                                if (gswitch_info.values_count > 1)
                                        caps &= ~SND_MIXER_SCTCAP_JOINTLY_VOLUME;
@@ -522,6 +648,9 @@ static int build_input(snd_mixer_t *handle, const char *sname)
                simple->gvolume_values = gvolume_info.values_count;
                simple->pvolume_values = pvolume_info.values_count;
                simple->cvolume_values = cvolume_info.values_count;
+               simple->groute_values = 2;
+               simple->proute_values = 2;
+               simple->croute_values = 2;
                simple->ccapture_values = csource_info.values_count;
                simple->capture_item = capture_item;
                simple->caps = caps;