1 | typedef struct phys_snd_dev
|
---|
2 | {
|
---|
3 | char name[64];
|
---|
4 | int play_id;
|
---|
5 | int rec_id;
|
---|
6 | } phys_snd_dev;
|
---|
7 |
|
---|
8 |
|
---|
9 | static 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 |
|
---|
88 | static 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 |
|
---|