Ticket #438: multiple_snd_devs.c

File multiple_snd_devs.c, 4.1 KB (added by bennylp, 16 years ago)

A function to be added in pjsua_app.c to instantiate multiple sound devices, for splitcomb testing

Line 
1typedef struct phys_snd_dev
2{
3    char    name[64];
4    int     play_id;
5    int     rec_id;
6} phys_snd_dev;
7
8
9static pj_status_t enum_phys_snd_devs(pj_bool_t wmme, unsigned *dev_cnt,
10                                      phys_snd_dev devs[])
11{
12    char *keyword[2] = { "Primary Sound ", "Microsoft Sound Mapper"};
13    unsigned i, all_cnt, max;
14    const pjmedia_snd_dev_info *di;
15    unsigned start_rec, start_play;
16
17    max = *dev_cnt;
18    *dev_cnt = 0;
19
20    all_cnt = pjmedia_snd_get_dev_count();
21
22    /* Find the start of input devices */
23    for (i=0; i<all_cnt; ++i) {
24        di = pjmedia_snd_get_dev_info(i);
25        if (strstr(di->name, keyword[wmme]) != 0) {
26            start_rec = i;
27            break;
28        }
29    }
30    if (i==all_cnt)
31        return PJ_ENOTFOUND;
32
33    /* Make sure this is an input device */
34    di = pjmedia_snd_get_dev_info(start_rec);
35    PJ_ASSERT_RETURN(di->input_count != 0, PJ_EINVALIDOP);
36
37    /* Find the start of output device */
38    for (i=start_rec+1; i<all_cnt; ++i) {
39        di = pjmedia_snd_get_dev_info(i);
40        if (strstr(di->name, keyword[wmme]) != 0) {
41            start_play = i;
42            break;
43        }
44    }
45    if (i==all_cnt)
46        return PJ_ENOTFOUND;
47
48    /* Make sure this is an output device */
49    di = pjmedia_snd_get_dev_info(start_play);
50    PJ_ASSERT_RETURN(di->output_count != 0, PJ_EINVALIDOP);
51
52    /* Pair devices */
53    for (i=start_rec; i<start_play; ++i) {
54        unsigned j;
55
56        di = pjmedia_snd_get_dev_info(i);
57        strcpy(devs[*dev_cnt].name, di->name);
58        devs[*dev_cnt].rec_id = i;
59
60        /* Try to guess the output device index. */
61        j = start_play+i-start_rec;
62        di = pjmedia_snd_get_dev_info(j);
63        if (strcmp(devs[*dev_cnt].name, di->name)==0) {
64            devs[*dev_cnt].play_id = j;
65            (*dev_cnt)++;
66            continue;
67        }
68
69        /* Find output device with matching name. This will not
70         * work with DirectSound if there are multiple sound
71         * devices with the same name!
72         */
73        for (j=start_play; j<all_cnt; ++j) {
74            di = pjmedia_snd_get_dev_info(j);
75            if (strcmp(devs[*dev_cnt].name, di->name)==0) {
76                devs[*dev_cnt].play_id = j;
77                break;
78            }
79        }
80
81        if (j != all_cnt)
82            (*dev_cnt)++;
83    }
84
85    return PJ_SUCCESS;
86}
87
88static void Setup_USBAudio()
89{
90    phys_snd_dev devs[32];
91    unsigned i, count = PJ_ARRAY_SIZE(devs);
92    pj_pool_t *pool;
93    pj_status_t status;
94
95    status = enum_phys_snd_devs(PJ_TRUE, &count, devs);
96    if (status != PJ_SUCCESS) {
97        PJ_LOG(1,(THIS_FILE, "Error enumerating physical sound devices"));
98        return;
99    }
100
101    if (count == 0) {
102        PJ_LOG(1,(THIS_FILE, "Error: no devices were found!"));
103        return;
104    }
105
106    PJ_LOG(3,(THIS_FILE, "Found %d devices:", count));
107    for (i=0; i<count; ++i) {
108        PJ_LOG(3,(THIS_FILE, " %d. %s (play_id=%d, rec_id=%d)", i+1,
109                             devs[i].name, devs[i].play_id,
110                             devs[i].rec_id));
111    }
112
113
114    /* Set the first device as the primary sound */
115    pjsua_set_snd_dev(devs[0].rec_id, devs[0].play_id);
116
117    pool = pjsua_pool_create("appsnd", 1000, 1000);
118
119    /* Add remaining devices to the bridge */
120    for (i=1; i<count; ++i) {
121        unsigned             Clock = 16000;
122        pjmedia_port        *Splitter;
123        pjmedia_port        *Port;
124        pjmedia_snd_port    *SoundPort;
125        pjsua_conf_port_id   ConferencePort;
126        pj_str_t             ConferenceName;
127        pj_status_t          Status;
128
129        Status = pjmedia_splitcomb_create(pool, Clock, 1, Clock/50, 16, 0, &Splitter);
130        pj_assert(Status == PJ_SUCCESS);
131
132        Status = pjmedia_snd_port_create(pool, devs[i].rec_id, devs[i].play_id, Clock, 1, Clock/50, 16, 0, &SoundPort);
133        pj_assert(Status == PJ_SUCCESS);
134
135        Status = pjmedia_snd_port_connect(SoundPort, Splitter);
136        pj_assert(Status == PJ_SUCCESS);
137
138        Status = pjmedia_splitcomb_create_rev_channel(pool, Splitter, 0, 0, &Port);
139        pj_assert(Status == PJ_SUCCESS);
140
141        ConferenceName = pj_str(devs[i].name);
142        Status = pjmedia_conf_add_port(pjsua_var.mconf,pool, Port, &ConferenceName, &ConferencePort);
143        pj_assert(Status == PJ_SUCCESS);
144
145        PJ_LOG(3,(THIS_FILE, "Sound device '%s' added at slot %d",
146                  devs[i].name, ConferencePort));
147    }
148}
149
150