root/rat/trunk/mbus_engine.c @ 3969

Revision 3969, 49.2 KB (checked in by piers, 7 years ago)

Updates for to bring the code into line with AG sources
- Site app extension
- Per participant volume sliders
- Added a new card defination to auddev_oss

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2* FILE:    mbus_engine.c
3* AUTHORS: Colin Perkins
4* MODIFICATIONS: Orion Hodson
5*
6* Copyright (c) 1998-2001 University College London
7* All rights reserved.
8*/
9
10#ifndef HIDE_SOURCE_STRINGS
11static const char cvsid[] =
12"$Id$";
13#endif /* HIDE_SOURCE_STRINGS */
14
15#include "config_unix.h"
16#include "config_win32.h"
17#include "debug.h"
18#include "mbus_engine.h"
19#include "mbus.h"
20#include "mbus_parser.h"
21#include "net_udp.h"
22#include "session.h"
23#include "net.h"
24#include "transmit.h"
25#include "codec_types.h"
26#include "codec.h"
27#include "audio.h"
28#include "session.h"
29#include "channel.h"
30#include "converter.h"
31#include "repair.h"
32#include "render_3D.h"
33#include "settings.h"
34#include "pdb.h"
35#include "source.h"
36#include "sndfile.h"
37#include "voxlet.h"
38#include "tonegen.h"
39#include "util.h"
40#include "codec_types.h"
41#include "channel_types.h"
42#include "parameters.h"
43#include "rtp.h"
44#include "rtp_callback.h"
45#include "ui_send_rtp.h"
46#include "ui_send_audio.h"
47#include "ui_send_prefs.h"
48#include "version.h"
49
50#define SECS_BETWEEN_1900_1970 2208988800u
51
52extern int       should_exit;
53extern FILE     *stats_file;
54
55extern void rtp_callback_open_logfile(char *file);
56
57/* Mbus command reception function type */
58typedef void (*mbus_rx_proc)(char *srce, char *args, session_t *sp);
59
60/* Tuple to associate string received with it's parsing fn */
61typedef struct {
62        const char   *rxname;
63        mbus_rx_proc  rxproc;
64} mbus_cmd_tuple;
65
66static void rx_session_title(char *srce, char *args, session_t *sp)
67{
68        char                    *title;
69        struct mbus_parser      *mp;
70
71        UNUSED(srce);
72
73        mp = mbus_parse_init(args);
74        if (mbus_parse_str(mp, &title)) {
75                sp->title = xstrdup(mbus_decode_str(title));
76        } else {
77                debug_msg("mbus: usage \"session.title <title>\"\n");
78        }
79        mbus_parse_done(mp);
80}
81
82static void rx_tool_rat_powermeter(char *srce, char *args, session_t *sp)
83{
84        int                      i;
85        struct mbus_parser      *mp;
86
87        UNUSED(srce);
88
89        mp = mbus_parse_init(args);
90        if (mbus_parse_int(mp, &i)) {
91                sp->meter = i;
92                ui_send_audio_input_powermeter(sp, sp->mbus_ui_addr, 0);
93                ui_send_audio_output_powermeter(sp, sp->mbus_ui_addr, 0);
94        } else {
95                debug_msg("mbus: usage \"tool.rat.powermeter <boolean>\"\n");
96        }
97        mbus_parse_done(mp);
98}
99
100static void rx_tool_rat_silence(char *srce, char *args, session_t *sp)
101{
102        char *detector;
103        struct mbus_parser      *mp;
104
105        UNUSED(srce);
106
107        mp = mbus_parse_init(args);
108        if (mbus_parse_str(mp, &detector)) {
109                mbus_decode_str(detector);
110                sp->silence_detection = sd_name_to_type(detector);
111                debug_msg("detector:%s index %d (%s)\n", detector, sp->silence_detection, srce);
112        } else {
113                debug_msg("mbus: usage \"tool.rat.silence <Auto|Manual|Off>\"\n");
114        }
115        mbus_parse_done(mp);
116}
117
118static void rx_tool_rat_silence_thresh(char *srce, char *args, session_t *sp)
119{
120        int                      i;
121        struct mbus_parser      *mp;
122
123        UNUSED(srce);
124
125        mp = mbus_parse_init(args);
126        if (mbus_parse_int(mp, &i)) {
127                sp->manual_sd_thresh = i;
128                manual_sd_set_thresh(sp->manual_sd, (uint16_t)i);
129                debug_msg("Setting threshold: %d\n", i);
130        } else {
131                debug_msg("mbus: usage \"tool.rat.silence.threshold <int>\"\n");
132        }
133        mbus_parse_done(mp);
134}
135
136static void rx_audio_3d_enable(char *srce, char *args, session_t *sp)
137{
138        int                      i;
139        struct mbus_parser      *mp;
140
141        UNUSED(srce);
142
143        mp = mbus_parse_init(args);
144        if (mbus_parse_int(mp, &i)) {
145                audio_device_register_change_render_3d(sp, i);
146        } else {
147                debug_msg("mbus: usage \"audio.3d.enabled <boolean>\"\n");
148        }
149        mbus_parse_done(mp);
150}
151
152static void
153rx_audio_3d_user_settings(char *srce, char *args, session_t *sp)
154{
155        pdb_entry_t             *p;
156        char                    *filter_name;
157        int                      filter_type, filter_length, azimuth, freq;
158        char                    *ss;
159        uint32_t                 ssrc;
160        struct mbus_parser      *mp;
161
162        UNUSED(srce);
163
164        mp = mbus_parse_init(args);
165        if (mbus_parse_str(mp, &ss) &&
166                mbus_parse_str(mp, &filter_name) &&
167                mbus_parse_int(mp, &filter_length) &&
168                mbus_parse_int(mp, &azimuth)) {
169
170                        mbus_decode_str(filter_name);
171                        ss = mbus_decode_str(ss);
172                        ssrc = strtoul(ss, 0, 16);
173
174                        if (pdb_item_get(sp->pdb, ssrc, &p)) {
175                                filter_type = render_3D_filter_get_by_name(filter_name);
176                                freq        = ts_get_freq(sp->cur_ts);
177                                if (p->render_3D_data == NULL) {
178                                        p->render_3D_data = render_3D_init(freq);
179                                }
180                                render_3D_set_parameters(p->render_3D_data,
181                                        freq,
182                                        azimuth,
183                                        filter_type,
184                                        filter_length);
185                        } else {
186                                debug_msg("Unknown source 0x%08lx\n", ssrc);
187                        }
188                } else {
189                        debug_msg("mbus: usage \"audio.3d.user.settings <cname> <filter name> <filter len> <azimuth>\"\n");
190                }
191                mbus_parse_done(mp);
192}
193
194static void
195rx_audio_3d_user_settings_req(char *srce, char *args, session_t *sp)
196{
197        char                    *ss;
198        uint32_t                 ssrc;
199        struct mbus_parser      *mp;
200
201        UNUSED(srce);
202
203        mp = mbus_parse_init(args);
204        if (mbus_parse_str(mp, &ss)) {
205                ss   = mbus_decode_str(ss);
206                ssrc = strtoul(ss, 0, 16);
207                ui_send_audio_3d_settings(sp, sp->mbus_ui_addr, ssrc);
208        }
209        mbus_parse_done(mp);
210}
211
212static void rx_tool_rat_lecture_mode(char *srce, char *args, session_t *sp)
213{
214        int                      i;
215        struct mbus_parser      *mp;
216
217        UNUSED(srce);
218
219        mp = mbus_parse_init(args);
220        if (mbus_parse_int(mp, &i)) {
221                sp->lecture = i;
222        } else {
223                debug_msg("mbus: usage \"tool.rat.lecture.mode <boolean>\"\n");
224        }
225        mbus_parse_done(mp);
226}
227
228static void rx_tool_rat_agc(char *srce, char *args, session_t *sp)
229{
230        int                      i;
231        struct mbus_parser      *mp;
232
233        UNUSED(srce);
234
235        mp = mbus_parse_init(args);
236        if (mbus_parse_int(mp, &i)) {
237                sp->agc_on = i;
238        } else {
239                debug_msg("mbus: usage \"tool.rat.agc <boolean>\"\n");
240        }
241        mbus_parse_done(mp);
242}
243
244static void rx_tool_rat_filter_loopback(char *srce, char *args, session_t *sp)
245{
246        int                      i;
247        struct mbus_parser      *mp;
248
249        UNUSED(srce);
250
251        mp = mbus_parse_init(args);
252        if (mbus_parse_int(mp, &i)) {
253                sp->filter_loopback = i;
254        } else {
255                debug_msg("mbus: usage \"tool.rat.filter.loopback <boolean>\"\n");
256        }
257        mbus_parse_done(mp);
258}
259
260static void rx_tool_rat_loopback_gain(char *srce, char *args, session_t *sp)
261{
262        int                      i;
263        struct mbus_parser      *mp;
264
265        UNUSED(srce);
266
267        mp = mbus_parse_init(args);
268        if (mbus_parse_int(mp, &i)) {
269                if (i) {
270                        audio_loopback(sp->audio_device, 100);
271                        sp->loopback_gain = 100;
272                } else {
273                        audio_loopback(sp->audio_device, 0);
274                        sp->loopback_gain = 0;
275                }
276        } else {
277                debug_msg("mbus: usage \"tool.rat.loopback.gain <boolean>\"\n");
278        }
279        mbus_parse_done(mp);
280}
281
282static void rx_tool_rat_echo_suppress(char *srce, char *args, session_t *sp)
283{
284        int                      i;
285        struct mbus_parser      *mp;
286
287        UNUSED(srce);
288
289        mp = mbus_parse_init(args);
290        if (mbus_parse_int(mp, &i)) {
291                sp->echo_suppress = i;
292                if (sp->echo_suppress     == FALSE &&
293                        sp->echo_tx_active    == TRUE  &&
294                        tx_is_sending(sp->tb) == FALSE) {
295                                /* Suppressor has just been disabled,  transmitter  */
296                                /* is in suppressed state and would otherwise be    */
297                                /* active.  Therefore start it up now.              */
298                                tx_start(sp->tb);
299                        }
300        } else {
301                debug_msg("mbus: usage \"tool.rat.echo.suppress <boolean>\"\n");
302        }
303        mbus_parse_done(mp);
304}
305
306static void rx_tool_rat_rate(char *srce, char *args, session_t *sp)
307{
308        int                      i;
309        struct mbus_parser      *mp;
310
311        UNUSED(srce);
312
313        mp = mbus_parse_init(args);
314        if (mbus_parse_int(mp, &i)) {
315                assert(sp->channel_coder != NULL);
316                channel_encoder_set_units_per_packet(sp->channel_coder, (uint16_t)i);
317                ui_send_rate(sp, sp->mbus_ui_addr);
318        } else {
319                debug_msg("mbus: usage \"tool.rat.rate <integer>\"\n");
320        }
321        mbus_parse_done(mp);
322}
323
324static void rx_audio_input_mute(char *srce, char *args, session_t *sp)
325{
326        int                      i;
327        struct mbus_parser      *mp;
328
329        UNUSED(srce);
330
331        mp = mbus_parse_init(args);
332        if (mbus_parse_int(mp, &i)) {
333                if (i) {
334                        if (tx_is_sending(sp->tb)) {
335                                tx_stop(sp->tb);
336                        }
337                } else {
338                        if (tx_is_sending(sp->tb) == FALSE) {
339                                tx_start(sp->tb);
340                        }
341                }
342                /* Keep echo suppressor informed of change */
343                sp->echo_tx_active = !i;
344                ui_send_audio_input_port(sp, sp->mbus_ui_addr);
345                ui_send_audio_input_mute(sp, sp->mbus_ui_addr);
346                ui_send_audio_input_gain(sp, sp->mbus_ui_addr);
347        } else {
348                debug_msg("mbus: usage \"audio.input.mute <boolean>\"\n");
349        }
350        mbus_parse_done(mp);
351}
352
353static void rx_audio_input_gain(char *srce, char *args, session_t *sp)
354{
355        int                      i;
356        struct mbus_parser      *mp;
357
358        UNUSED(srce);
359
360        mp = mbus_parse_init(args);
361        if (mbus_parse_int(mp, &i) &&
362                (i >= 0 && i <= 100)) {
363                        audio_set_igain(sp->audio_device, i);
364                        tx_igain_update(sp->tb);
365                } else {
366                        debug_msg("mbus: usage \"audio.input.gain <integer>\"\n");
367                }
368                mbus_parse_done(mp);
369}
370
371static void rx_audio_input_port(char *srce, char *args, session_t *sp)
372{
373        const audio_port_details_t *apd = NULL;
374        char                    *s;
375        int                      i, n, found;
376        struct mbus_parser      *mp;
377
378        UNUSED(srce);
379
380        mp = mbus_parse_init(args);
381        if (mbus_parse_str(mp, &s)) {
382                s = mbus_decode_str(s);
383                n = audio_get_iport_count(sp->audio_device);
384                found = FALSE;
385                for(i = 0; i < n; i++) {
386                        apd = audio_get_iport_details(sp->audio_device, i);
387                        if (!strcasecmp(s, apd->name)) {
388                                found = TRUE;
389                                break;
390                        }
391                }
392                if (found == FALSE) {
393                        debug_msg("%s does not match any port names\n", s);
394                        apd = audio_get_iport_details(sp->audio_device, 0);
395                }
396                audio_set_iport(sp->audio_device, apd->port);
397        } else {
398                debug_msg("mbus: usage \"audio.input.port <port>\"\n");
399        }
400        mbus_parse_done(mp);
401        ui_send_audio_input_port(sp, sp->mbus_ui_addr);
402        ui_send_audio_input_mute(sp, sp->mbus_ui_addr);
403        ui_send_audio_input_gain(sp, sp->mbus_ui_addr);
404}
405
406static void rx_audio_output_mute(char *srce, char *args, session_t *sp)
407{
408        struct mbus_parser      *mp;
409        struct s_source         *s;
410        int                      i, n;
411
412        UNUSED(srce);
413
414        mp = mbus_parse_init(args);
415        if (mbus_parse_int(mp, &i)) {
416                sp->playing_audio = !i;
417                ui_send_audio_output_port(sp, sp->mbus_ui_addr);
418                n = (int)source_list_source_count(sp->active_sources);
419                for (i = 0; i < n; i++) {
420                        s = source_list_get_source_no(sp->active_sources, i);
421                        ui_send_rtp_inactive(sp, sp->mbus_ui_addr, source_get_ssrc(s));
422                        source_remove(sp->active_sources, s);
423                        /* revise source no's since we removed a source */
424                        i--;
425                        n--;
426                }
427        } else {
428                debug_msg("mbus: usage \"audio.output.mute <boolean>\"\n");
429        }
430        mbus_parse_done(mp);
431}
432
433static void rx_audio_output_gain(char *srce, char *args, session_t *sp)
434{
435        struct mbus_parser      *mp;
436        int                      i;
437
438        UNUSED(srce);
439
440        mp = mbus_parse_init(args);
441        if (mbus_parse_int(mp, &i) &&
442                (i >= 0 && i <= 100)) {
443                        audio_set_ogain(sp->audio_device, i);
444                } else {
445                        debug_msg("mbus: usage \"audio.output.gain <integer>\"\n");
446                }
447                mbus_parse_done(mp);
448}
449
450static void rx_audio_output_port(char *srce, char *args, session_t *sp)
451{
452        const audio_port_details_t *apd = NULL;
453        char *s;
454        int   i, n, found;
455        struct mbus_parser      *mp;
456
457        UNUSED(srce);
458
459        mp = mbus_parse_init(args);
460        if (mbus_parse_str(mp, &s)) {
461                s = mbus_decode_str(s);
462                n     = audio_get_oport_count(sp->audio_device);
463                found = FALSE;
464
465                for(i = 0; i < n; i++) {
466                        apd = audio_get_oport_details(sp->audio_device, i);
467                        if (!strcasecmp(s, apd->name)) {
468                                found = TRUE;
469                                break;
470                        }
471                }
472                if (found == FALSE) {
473                        debug_msg("%s does not match any port names\n", s);
474                        apd = audio_get_oport_details(sp->audio_device, 0);
475                }
476                audio_set_oport(sp->audio_device, apd->port);
477        } else {
478                debug_msg("mbus: usage \"audio.output.port <port>\"\n");
479        }
480        mbus_parse_done(mp);
481        ui_send_audio_output_port(sp, sp->mbus_ui_addr);
482        ui_send_audio_output_mute(sp, sp->mbus_ui_addr); //SV-XXX: NetBSD
483        ui_send_audio_output_gain(sp, sp->mbus_ui_addr); //SV-XXX: NetBSD
484}
485
486static void rx_audio_channel_repair(char *srce, char *args, session_t *sp)
487{
488        const repair_details_t *r;
489        uint16_t i, n;
490        char    *s;
491        struct mbus_parser      *mp;
492
493        UNUSED(srce);
494
495        mp = mbus_parse_init(args);
496        if (mbus_parse_str(mp, &s)) {
497                s = mbus_decode_str(s);
498                if (strcasecmp(s, "first") == 0) {
499                        r = repair_get_details(0);
500                        sp->repair = r->id;
501                } else {
502                        n = repair_get_count();
503                        for(i = 0; i < n; i++) {
504                                r = repair_get_details(i);
505                                if (strcasecmp(r->name, s) == 0 || strcasecmp("first", s) == 0) {
506                                        sp->repair = r->id;
507                                        break;
508                                }
509                        }
510                }
511        } else {
512                debug_msg("mbus: usage \"audio.channel.repair <repair>\"\n");
513        }
514        mbus_parse_done(mp);
515        ui_send_audio_channel_repair(sp, sp->mbus_ui_addr);
516}
517
518static void rx_security_encryption_key(char *srce, char *args, session_t *sp)
519{
520        int      i;
521        char    *key;
522        struct mbus_parser      *mp;
523
524        UNUSED(sp);
525        UNUSED(srce);
526
527        mp = mbus_parse_init(args);
528        if (mbus_parse_str(mp, &key)) {
529                debug_msg("rx_security_encryption_key: key: %s\n",key);
530                key = mbus_decode_str(key);
531                for(i = 0; i < sp->rtp_session_count; i++) {
532                        if (strlen(key) == 0) {
533                                rtp_set_encryption_key(sp->rtp_session[i], NULL);
534                                sp->encrkey = NULL;
535                                ui_send_encryption_key(sp, sp->mbus_ui_addr);
536                        } else {
537                                rtp_set_encryption_key(sp->rtp_session[i], key);
538                                sp->encrkey = xstrdup(key);
539                                ui_send_encryption_key(sp, sp->mbus_ui_addr);
540                        }
541                }
542        } else {
543                debug_msg("mbus: usage \"security.encryption.key <key>\"\n");
544        }
545        mbus_parse_done(mp);
546}
547
548static void rx_audio_file_play_stop(char *srce, char *args, session_t *sp)
549{
550        UNUSED(srce);
551        UNUSED(args);
552
553        if (sp->in_file != NULL) {
554                snd_read_close(&sp->in_file);
555        }
556}
557
558static void rx_tool_rat_voxlet_play(char *srce, char *args, session_t *sp)
559{
560        char *file;
561        struct mbus_parser *mp;
562
563        UNUSED(srce);
564        UNUSED(sp);
565
566        mp = mbus_parse_init(args);
567        if (mbus_parse_str(mp, &file)) {
568                mbus_decode_str(file);
569                if (sp->local_file_player) {
570                        voxlet_destroy(&sp->local_file_player);
571                }
572                voxlet_create(&sp->local_file_player, sp->ms, sp->pdb, file);
573        } else {
574                debug_msg("mbus: usage \"tool.rat.voxlet.play <filename>\"\n");
575        }
576        mbus_parse_done(mp);
577}
578
579static void rx_tool_rat_logstats(char *srce, char *args, session_t *sp)
580{
581        int                      i;
582        struct mbus_parser      *mp;
583
584        UNUSED(srce);
585
586        mp = mbus_parse_init(args);
587        if (mbus_parse_int(mp, &i)) {
588                if (i) {
589                        struct timeval   t;
590                        char             fname[100];
591                        char             hname[64];
592                        char            *uname;
593                        const char      *cname;
594#ifndef WIN32
595                        struct passwd  *pwent;
596
597                        pwent = getpwuid(getuid());
598                        uname = pwent->pw_name;
599
600#else
601                        char    user[100];
602                        int     size = 100;
603
604                        if (!GetUserName(user, &size)) {
605                                uname = "UNKNOWN";
606                        } else {
607                                uname = (char *) user;
608                        }
609#endif
610                        gettimeofday(&t, NULL);
611                        gethostname(hname, 64);
612#ifdef WIN32
613                        sprintf(fname, "rat-%p-%I64d.%06ld-%s-%s.log", sp, (__int64)t.tv_sec, (long)t.tv_usec, hname, uname); //SV-XXX: Win32
614#else
615                        sprintf(fname, "rat-%p-%jd.%06ld-%s-%s.log", sp, (intmax_t)t.tv_sec, (long)t.tv_usec, hname, uname); //SV-XXX: FreeBSD
616#endif
617                        cname = rtp_get_sdes(sp->rtp_session[0], rtp_my_ssrc(sp->rtp_session[0]), RTCP_SDES_CNAME);
618
619                        sp->logger = fopen(fname, "w");
620#ifdef WIN32
621                        fprintf(sp->logger, "tool_start %I64u.%06lu ", (__int64)t.tv_sec + SECS_BETWEEN_1900_1970, (long)t.tv_usec); //SV-XXX: Win32
622#else
623                        fprintf(sp->logger, "tool_start %ju.%06lu ", (intmax_t)t.tv_sec + SECS_BETWEEN_1900_1970, (long)t.tv_usec); //SV-XXX: FreeBSD
624#endif
625                        fprintf(sp->logger, "0x%08lx\n", (unsigned long) rtp_my_ssrc(sp->rtp_session[0]));
626                } else {
627                        fclose(sp->logger);
628                }
629        } else {
630                debug_msg("mbus: usage \"tool.rat.logstats <boolean>\"\n");
631        }
632        mbus_parse_done(mp);
633}
634
635static void rx_tool_rat_logdebug(char *srce, char *args, session_t *sp)
636{
637    int enabled;
638    char *file;
639        struct mbus_parser      *mp;
640
641        UNUSED(srce);
642        UNUSED(sp);
643       
644                printf("Logdebug '%s'\n", args);
645
646        mp = mbus_parse_init(args);
647        if (mbus_parse_int(mp, &enabled) &&
648            mbus_parse_str(mp, &file))
649            {
650                mbus_decode_str(file);
651                printf("enabled=%d file=%s\n", enabled, file);
652                if (enabled) {
653                    rtp_callback_open_logfile(file);
654                }
655        } else {
656                debug_msg("mbus: usage \"tool.rat.logstats <boolean>\"\n");
657        }
658        mbus_parse_done(mp);
659}
660
661static void rx_tool_rat_tone_start(char *srce, char *args, session_t *sp)
662{
663        int freq, amp;
664        struct mbus_parser *mp;
665
666        UNUSED(srce);
667
668        if (sp->tone_generator) {
669                tonegen_destroy(&sp->tone_generator);
670        }
671
672        mp = mbus_parse_init(args);
673        if (mbus_parse_int(mp, &freq) &&
674                mbus_parse_int(mp, &amp)) {
675                        tonegen_create(&sp->tone_generator, sp->ms, sp->pdb, (uint16_t)freq, (uint16_t)amp);
676                } else {
677                        debug_msg("mbus: usage \"tool.rat.tone.start <freq> <amplitude>\"\n");
678                }
679                mbus_parse_done(mp);
680}
681
682static void rx_tool_rat_tone_stop(char *srce, char *args, session_t *sp)
683{
684        UNUSED(srce);
685        UNUSED(args);
686        if (sp->tone_generator) {
687                tonegen_destroy(&sp->tone_generator);
688        }
689}
690
691static void rx_audio_file_play_open(char *srce, char *args, session_t *sp)
692{
693        char    *file;
694        struct mbus_parser      *mp;
695
696        UNUSED(srce);
697        UNUSED(sp);
698
699        mp = mbus_parse_init(args);
700        if (mbus_parse_str(mp, &file)) {
701                mbus_decode_str(file);
702                if (sp->in_file) snd_read_close(&sp->in_file);
703                if (snd_read_open(&sp->in_file, file, NULL)) {
704                        debug_msg("Hooray opened %s\n",file);
705                }
706        } else {
707                debug_msg("mbus: usage \"audio.file.play.open <filename>\"\n");
708        }
709        mbus_parse_done(mp);
710
711        if (sp->in_file) {
712                ui_send_audio_file_play_ready(sp, sp->mbus_ui_addr, file);
713        }
714}
715
716static void rx_audio_file_play_pause(char *srce, char *args, session_t *sp)
717{
718        int pause;
719        struct mbus_parser      *mp;
720
721        UNUSED(srce);
722
723        mp = mbus_parse_init(args);
724
725        if (mbus_parse_int(mp, &pause)) {
726                if (sp->in_file) {
727                        if (pause) {
728                                snd_pause(sp->in_file);
729                        } else {
730                                snd_resume(sp->in_file);
731                        }
732                }
733        } else {
734                debug_msg("mbus: usage \"audio.file.play.pause <bool>\"\n");
735        }
736        mbus_parse_done(mp);
737}
738
739static void rx_audio_file_play_live(char *srce, char *args, session_t *sp)
740{
741        /* This is a request to see if file we are playing is still valid */
742        UNUSED(args);
743        UNUSED(srce);
744        ui_send_audio_file_alive(sp, sp->mbus_ui_addr, "play", (sp->in_file) ? 1 : 0);
745}
746
747static void rx_audio_file_rec_stop(char *srce, char *args, session_t *sp)
748{
749        UNUSED(srce);
750        UNUSED(args);
751
752        if (sp->out_file != NULL) {
753                snd_write_close(&sp->out_file);
754        }
755}
756
757static void rx_audio_file_rec_open(char *srce, char *args, session_t *sp)
758{
759        char    *file;
760        struct mbus_parser      *mp;
761
762        UNUSED(srce);
763
764        mp = mbus_parse_init(args);
765        if (mbus_parse_str(mp, &file)) {
766                sndfile_fmt_t sf_fmt;
767                const audio_format *ofmt;
768                ofmt = audio_get_ofmt(sp->audio_device);
769                mbus_decode_str(file);
770                if (sp->out_file) snd_write_close(&sp->out_file);
771
772                sf_fmt.encoding    = SNDFILE_ENCODING_L16;
773                sf_fmt.sample_rate = (uint32_t)ofmt->sample_rate;
774                sf_fmt.channels    = (uint16_t)ofmt->channels;
775#ifdef WIN32
776                if (snd_write_open(&sp->out_file, file, "wav", &sf_fmt)) {
777                        debug_msg("Hooray opened %s\n",file);
778                }
779#else
780                if (snd_write_open(&sp->out_file, file, "au", &sf_fmt)) {
781                        debug_msg("Hooray opened %s\n",file);
782                }
783#endif /* WIN32 */
784        } else {
785                debug_msg("mbus: usage \"audio.file.record.open <filename>\"\n");
786        }
787        mbus_parse_done(mp);
788
789        if (sp->out_file) ui_send_audio_file_record_ready(sp, sp->mbus_ui_addr, file);
790}
791
792static void rx_audio_file_rec_pause(char *srce, char *args, session_t *sp)
793{
794        int pause;
795        struct mbus_parser      *mp;
796
797        UNUSED(srce);
798
799        mp = mbus_parse_init(args);
800
801        if (mbus_parse_int(mp, &pause)) {
802                if (sp->out_file) {
803                        if (pause) {
804                                snd_pause(sp->out_file);
805                        } else {
806                                snd_resume(sp->out_file);
807                        }
808                }
809        } else {
810                debug_msg("mbus: usage \"audio.file.record.pause <bool>\"\n");
811        }
812        mbus_parse_done(mp);
813}
814
815static void rx_audio_file_rec_live(char *srce, char *args, session_t *sp)
816{
817        /* This is a request to see if file we are recording is still valid */
818        UNUSED(args);
819        UNUSED(srce);
820        ui_send_audio_file_alive(sp, sp->mbus_ui_addr, "record", (sp->out_file) ? 1 : 0);
821}
822
823static void
824rx_audio_device(char *srce, char *args, session_t *sp)
825{
826        char    *s, dev_name[64], first_dev_name[64];
827        struct mbus_parser      *mp;
828
829        UNUSED(srce);
830
831        mp = mbus_parse_init(args);
832        if (mbus_parse_str(mp, &s)) {
833                s = mbus_decode_str(s);
834                purge_chars(s, "[]()");
835                if (s) {
836                        const audio_device_details_t *add = NULL;
837                        audio_desc_t           first_dev_desc = 0;
838                        uint32_t i, n, stop_at_first_device = FALSE;
839                        dev_name[0] = 0;
840                        first_dev_name[0] = 0;
841                        n = audio_get_device_count();
842
843                        if (!strncasecmp("first", s, 5)) {
844                                /* The ui may send first if the saved device is the null audio
845                                * device so it starts up trying to play something.
846                                */
847                                stop_at_first_device = TRUE;
848                        }
849
850                        for(i = 0; i < n; i++) {
851                                /* Brackets are a problem so purge them */
852                                add = audio_get_device_details(i);
853                                strncpy(dev_name, add->name, AUDIO_DEVICE_NAME_LENGTH);
854                                purge_chars(dev_name, "[]()");
855                                if (first_dev_name[0] == 0) {
856                                        strncpy(first_dev_name, dev_name, AUDIO_DEVICE_NAME_LENGTH);
857                                        first_dev_desc = add->descriptor;
858                                }
859
860                                if (!strcmp(s, dev_name) | stop_at_first_device) {
861                                        break;
862                                }
863                        }
864                        if (i < n) {
865                                /* Found device looking for */
866                                audio_device_register_change_device(sp, add->descriptor);
867                        } else if (first_dev_name[0]) {
868                                /* Have a fall back */
869                                audio_device_register_change_device(sp, first_dev_desc);
870                        }
871                }
872        } else {
873                debug_msg("mbus: usage \"audio.device <string>\"\n");
874        }
875        mbus_parse_done(mp);
876}
877
878static void
879rx_audio_query(char *srce, char *args, session_t *sp)
880{
881        /* The audio.query() command solicits information about the audio device. */
882        /* We respond by dumping all our audio related state to the querier.     */
883        UNUSED(args);
884        ui_send_audio_update(sp, srce);
885}
886
887static void rx_rtp_source_sdes(char *srce, char *args, session_t *sp, uint8_t type)
888{
889        char               *arg, *ss;
890        uint32_t           ssrc;
891        struct mbus_parser *mp;
892        UNUSED(srce);
893
894        mp = mbus_parse_init(args);
895        if (mbus_parse_str(mp, &ss) &&
896                mbus_parse_str(mp, &arg)) {
897                        uint32_t my_ssrc = rtp_my_ssrc(sp->rtp_session[0]);
898                        ss = mbus_decode_str(ss);
899                        if (isalpha((int)ss[0])) {
900                                /*
901                                * Allow alpha so people can do my_src, me,
902                                * local_user, whatever.  Let the mbus police
903                                * pick something sane.
904                                */
905                                ssrc = my_ssrc;
906                        } else {
907                                ssrc = strtoul(ss, 0, 16);
908                        }
909                        if (ssrc == my_ssrc) {
910                                char *value;
911                                int i, vlen;
912                                value = mbus_decode_str(arg);
913                                vlen  = strlen(value);
914                                for (i = 0; i < sp->rtp_session_count; i++) {
915                                        rtp_set_sdes(sp->rtp_session[i], ssrc, type, value, vlen);
916                                }
917                        } else {
918                                debug_msg("mbus: ssrc %s (%08lx) != %08lx\n", ss, strtoul(ss, 0, 16), rtp_my_ssrc(sp->rtp_session[0]));
919                        }
920                } else {
921                        debug_msg("mbus: usage \"rtp_source_<sdes_item> <ssrc> <name>\"\n");
922                }
923                mbus_parse_done(mp);
924}
925
926static void rx_rtp_query(char *srce, char *args, session_t *sp)
927{
928        /* The rtp.query() command solicits information about the RTP session. */
929        /* We respond by dumping all our RTP related state to the querier.     */
930        uint32_t         ssrc, my_ssrc;
931        struct s_source *s;
932    pdb_entry_t *e;
933
934        UNUSED(args);
935        debug_msg("mbus: rx_rtp_query\n");
936        ui_send_rtp_ssrc(sp, srce);
937        pdb_get_first_id(sp->pdb, &ssrc);
938        my_ssrc = rtp_my_ssrc(sp->rtp_session[0]);
939
940        do {
941                ui_send_rtp_cname(sp, srce, ssrc);
942                ui_send_rtp_name(sp, srce, ssrc);
943                ui_send_rtp_email(sp, srce, ssrc);
944                ui_send_rtp_phone(sp, srce, ssrc);
945                ui_send_rtp_loc(sp, srce, ssrc);
946                ui_send_rtp_tool(sp, srce, ssrc);
947                ui_send_rtp_note(sp, srce, ssrc);
948                ui_send_rtp_mute(sp, srce, ssrc);
949
950                if (pdb_item_get(sp->pdb, ssrc, &e) == TRUE) {
951                  if (e->siteid != NULL) {
952                    ui_send_rtp_app_site(sp, srce, ssrc, e->siteid);
953                  }
954                }
955
956                if (ssrc != my_ssrc) {
957                        if ((s = source_get_by_ssrc(sp->active_sources, ssrc)) != NULL) {
958                                ui_send_rtp_active(sp, srce, ssrc);
959                        } else {
960                                ui_send_rtp_inactive(sp, srce, ssrc);
961                        }
962                } else {
963                        tx_update_ui(sp->tb);
964                }
965        } while (pdb_get_next_id(sp->pdb, ssrc, &ssrc));
966        ui_send_rtp_addr(sp, srce);
967        ui_send_rtp_title(sp, srce);
968}
969
970static void rx_rtp_addr_query(char *srce, char *args, session_t *sp)
971{
972        UNUSED(args);
973        ui_send_rtp_addr(sp, srce);
974}
975
976static void rx_rtp_source_mute(char *srce, char *args, session_t *sp)
977{
978        /* Sources are active whilst packets are arriving and maintaining      */
979        /* statistics on sender.  This is good, but we need to remove source   */
980        /* when changing mute state, if packets are still arriving source will */
981        /* be recreated when next packet arrives.  When muting we want to      */
982        /* remove source to stop audio already buffered from playing.  When    */
983        /* unmuting want to remove source to initialize state, particularly    */
984        /* timestamps of last repair etc.                                      */
985
986        pdb_entry_t             *pdbe;
987        char                    *ssrc;
988        int                      i;
989        struct mbus_parser      *mp;
990
991        UNUSED(srce);
992
993        mp = mbus_parse_init(args);
994        if (mbus_parse_str(mp, &ssrc) && mbus_parse_int(mp, &i)) {
995                ssrc = mbus_decode_str(ssrc);
996                if (strcmp(ssrc, "ALL") == 0) {
997                        uint32_t        id;
998                        pdb_get_first_id(sp->pdb, &id);
999                        do {
1000                                if (pdb_item_get(sp->pdb, id, &pdbe)) {
1001                                        struct s_source *s = source_get_by_ssrc(sp->active_sources, pdbe->ssrc);
1002                                        if (s != NULL) {
1003                                                source_remove(sp->active_sources, s);
1004                                        }
1005                                        pdbe->mute = i;
1006                                        ui_send_rtp_mute(sp, sp->mbus_ui_addr, pdbe->ssrc);
1007                                        debug_msg("mute ssrc 0x%08x (%d)\n", pdbe->ssrc, i);
1008                                } else {
1009                                        debug_msg("Unknown source 0x%08lx\n", ssrc);
1010                                }
1011                        } while (pdb_get_next_id(sp->pdb, id, &id));
1012                } else {
1013                        if (pdb_item_get(sp->pdb, strtoul(ssrc, 0, 16), &pdbe)) {
1014                                struct s_source *s = source_get_by_ssrc(sp->active_sources, pdbe->ssrc);
1015                                if (s != NULL) {
1016                                        source_remove(sp->active_sources, s);
1017                                }
1018                                pdbe->mute = i;
1019                                ui_send_rtp_mute(sp, sp->mbus_ui_addr, pdbe->ssrc);
1020                                debug_msg("mute ssrc 0x%08x (%d)\n", pdbe->ssrc, i);
1021                        } else {
1022                                debug_msg("Unknown source 0x%08lx\n", ssrc);
1023                        }
1024                }
1025        } else {
1026                debug_msg("mbus: usage \"rtp_source_mute <ssrc> <bool>\"\n");
1027        }
1028        mbus_parse_done(mp);
1029}
1030
1031static void rx_rtp_addr(char *srce, char *args, session_t *sp)
1032{
1033        /* rtp.addr ("224.1.2.3" 1234 1234 16) */
1034        char    *addr;
1035        int      rx_port, tx_port, ttl;
1036        struct mbus_parser      *mp;
1037        uint32_t           ssrc;
1038
1039        UNUSED(srce);
1040
1041        mp = mbus_parse_init(args);
1042        mbus_parse_str(mp, &addr); addr = mbus_decode_str(addr);
1043        mbus_parse_int(mp, &rx_port);
1044        mbus_parse_int(mp, &tx_port);
1045        mbus_parse_int(mp, &ttl);
1046        mbus_parse_done(mp);
1047        debug_msg("rx_rtp_addr: New Addr:%d,rx_port:%d,tx_port:%d,ttl:%d\n",addr, rx_port, tx_port, ttl);
1048
1049        if (sp->rtp_session_count) {
1050                /* Existing session present - delete and recreate with new params */
1051                sp->rtp_session_count--;
1052                rx_audio_input_mute(srce, "1", sp);
1053                rtp_set_encryption_key(sp->rtp_session[0], NULL);
1054                sp->encrkey = NULL;
1055                ui_send_encryption_key(sp, sp->mbus_ui_addr);
1056                settings_save(sp);
1057                rtp_send_bye(sp->rtp_session[sp->rtp_session_count]);
1058                rtp_callback_exit(sp->rtp_session[sp->rtp_session_count]);
1059                /* Remove existing sources from DB and UI , then destory DB and RTP sess */
1060                pdb_get_first_id(sp->pdb, &ssrc);
1061                do {
1062                        struct s_source *s = source_get_by_ssrc(sp->active_sources, ssrc);
1063                        if (s != NULL) {
1064                                source_remove(sp->active_sources, s);
1065                        }
1066                        ui_send_rtp_remove(sp, sp->mbus_ui_addr, ssrc);
1067                } while (pdb_get_next_id(sp->pdb, ssrc, &ssrc));
1068                pdb_destroy(&sp->pdb);
1069                rtp_done(sp->rtp_session[sp->rtp_session_count]);
1070
1071                /* Perform rtp session re-creation */
1072                if (!(sp->rtp_session[sp->rtp_session_count] =
1073                        rtp_init(addr, (uint16_t)rx_port, (uint16_t)tx_port, ttl, 64000, rtp_callback_proc, NULL))) {
1074                                debug_msg("Failed to reinitialise rtp session - exiting");
1075                                assert(sp->rtp_session[sp->rtp_session_count]);
1076                }
1077                rtp_set_option(sp->rtp_session[sp->rtp_session_count], RTP_OPT_PROMISC, sp->rtp_promiscuous_mode);
1078                rtp_callback_init(sp->rtp_session[0], sp);
1079
1080                if(sp->rtp_session_count < sp->layers && sp->rtp_session_count > 0) {
1081                        rtp_set_my_ssrc(sp->rtp_session[sp->rtp_session_count], rtp_my_ssrc(sp->rtp_session[0]));
1082                }
1083                sp->rtp_session_count++;
1084                /* Load saved settings, and create the participant database... */
1085                /* FIXME: probably needs updating for the transcoder so we can */
1086                /*        have different saved settings for each domain.       */
1087                /* FIXME: this gets the wrong device name for the transcoder.  */
1088                if (pdb_create(&sp->pdb) == FALSE) {
1089                        debug_msg("Failed to re-create new participant database\n");
1090                        abort();
1091                }
1092                pdb_item_create(sp->pdb, (uint16_t)ts_get_freq(sp->cur_ts), rtp_my_ssrc(sp->rtp_session[0]));
1093                settings_load_late(sp);
1094                session_validate(sp);
1095
1096                // Update src in UI
1097                rx_rtp_query(srce, args, sp);
1098        } else {
1099                sp->rtp_session[sp->rtp_session_count] = rtp_init(addr, (uint16_t)rx_port, (uint16_t)tx_port, ttl, 64000, rtp_callback_proc, NULL);
1100
1101                rtp_set_option(sp->rtp_session[sp->rtp_session_count], RTP_OPT_PROMISC, sp->rtp_promiscuous_mode);
1102                rtp_callback_init(sp->rtp_session[0], sp);
1103
1104                if(sp->rtp_session_count < sp->layers && sp->rtp_session_count > 0) {
1105                        rtp_set_my_ssrc(sp->rtp_session[sp->rtp_session_count], rtp_my_ssrc(sp->rtp_session[0]));
1106                }
1107                sp->rtp_session_count++;
1108        }
1109}
1110
1111
1112static void rx_rtp_source_name(char *srce, char *args, session_t *sp)
1113{
1114        rx_rtp_source_sdes(srce, args, sp, RTCP_SDES_NAME);
1115}
1116
1117static void rx_rtp_source_email(char *srce, char *args, session_t *sp)
1118{
1119        rx_rtp_source_sdes(srce, args, sp, RTCP_SDES_EMAIL);
1120}
1121
1122static void rx_rtp_source_phone(char *srce, char *args, session_t *sp)
1123{
1124        rx_rtp_source_sdes(srce, args, sp, RTCP_SDES_PHONE);
1125}
1126
1127static void rx_rtp_source_loc(char *srce, char *args, session_t *sp)
1128{
1129        rx_rtp_source_sdes(srce, args, sp, RTCP_SDES_LOC);
1130}
1131
1132static void rx_rtp_source_note(char *srce, char *args, session_t *sp)
1133{
1134        rx_rtp_source_sdes(srce, args, sp, RTCP_SDES_NOTE);
1135}
1136
1137static void rx_rtp_source_app_site(char *srce, char *args, session_t *sp)
1138{
1139        char               *arg, *ss;
1140        uint32_t           ssrc;
1141        struct mbus_parser *mp;
1142        UNUSED(srce);
1143
1144        mp = mbus_parse_init(args);
1145        if (mbus_parse_str(mp, &ss) &&
1146            mbus_parse_str(mp, &arg)) {
1147                uint32_t my_ssrc = rtp_my_ssrc(sp->rtp_session[0]);
1148                ss = mbus_decode_str(ss);
1149                if (isalpha((int)ss[0])) {
1150                        /*
1151                         * Allow alpha so people can do my_src, me,
1152                         * local_user, whatever.  Let the mbus police
1153                         * pick something sane.
1154                         */
1155                        ssrc = my_ssrc;
1156                } else {
1157                        ssrc = strtoul(ss, 0, 16);
1158                }
1159                if (ssrc == my_ssrc) {
1160                        char *value;
1161
1162                        value = mbus_decode_str(arg);
1163
1164                        if (sp->rtp_session_app_site != NULL) {
1165                                xfree(sp->rtp_session_app_site);
1166                        }
1167                        sp->rtp_session_app_site = xstrdup(value);
1168                } else {
1169                        debug_msg("mbus: rtp_source_app_site ssrc %s (%08lx) != %08lx\n", ss, strtoul(ss, 0, 16), rtp_my_ssrc(sp->rtp_session[0]));
1170                }
1171        } else {
1172                debug_msg("mbus: usage \"rtp_source_app_site <ssrc> <siteid>\"\n");
1173        }
1174        mbus_parse_done(mp);
1175}
1176
1177static void rx_rtp_source_gain(char *srce, char *args, session_t *sp)
1178{
1179        pdb_entry_t     *pdbe;
1180        char            *ssrc;
1181        double           g;
1182        struct mbus_parser      *mp;
1183
1184        UNUSED(srce);
1185
1186        mp = mbus_parse_init(args);
1187        if (mbus_parse_str(mp, &ssrc) && mbus_parse_flt(mp, &g)) {
1188                ssrc = mbus_decode_str(ssrc);
1189                if (pdb_item_get(sp->pdb, strtoul(ssrc, 0, 16), &pdbe)) {
1190                        pdbe->gain = g;
1191                } else {
1192                        debug_msg("Unknown source 0x%08lx\n", ssrc);
1193                }
1194        } else {
1195                debug_msg("mbus: usage \"rtp_source_gain <ssrc> <bool>\"\n");
1196        }
1197        mbus_parse_done(mp);
1198}
1199
1200static int
1201string_to_freq(const char *str) {
1202        int freq = atoi(str) * 1000;
1203        if ((freq % 11000) == 0) {
1204                freq /= 11000;
1205                freq *= 11025;
1206        }
1207        return freq;
1208}
1209
1210static void
1211rx_tool_rat_codec(char *srce, char *args, session_t *sp)
1212{
1213        char    *short_name, *sfreq, *schan;
1214        int      freq, channels;
1215        codec_id_t cid, next_cid;
1216        struct mbus_parser      *mp;
1217
1218        UNUSED(srce);
1219
1220        mp = mbus_parse_init(args);
1221        if (mbus_parse_str(mp, &short_name) &&
1222                mbus_parse_str(mp, &schan) &&
1223                mbus_parse_str(mp, &sfreq)) {
1224                        mbus_decode_str(short_name);
1225                        mbus_decode_str(schan);
1226                        mbus_decode_str(sfreq);
1227                        mbus_parse_done(mp);
1228                } else {
1229                        debug_msg("mbus: usage \"tool.rat.codec <codec> <channels> <freq>\"\n");
1230                        mbus_parse_done(mp);
1231                        return;
1232                }
1233
1234                if (strcasecmp(schan, "mono") == 0) {
1235                        channels = 1;
1236                } else if (strcasecmp(schan, "stereo") == 0) {
1237                        channels = 2;
1238                } else {
1239                        channels = 0;
1240                }
1241
1242                freq = string_to_freq(sfreq);
1243                assert(channels != 0);
1244                assert(freq     != 0);
1245                next_cid = codec_get_matching(short_name, (uint16_t)freq, (uint16_t)channels);
1246
1247                if (next_cid && codec_get_payload(next_cid) != 255) {
1248                        cid     = codec_get_by_payload ((u_char)sp->encodings[0]);
1249                        if (codec_audio_formats_compatible(next_cid, cid)) {
1250                                sp->encodings[0] = codec_get_payload(next_cid);
1251                                ui_send_audio_codec(sp, sp->mbus_ui_addr);
1252                        } else {
1253                                /* just register we want to make a change */
1254                                audio_device_register_change_primary(sp, next_cid);
1255                        }
1256                }
1257}
1258
1259static void
1260rx_tool_rat_codecs_request(char *srce, char *args, session_t *sp)
1261{
1262        UNUSED(args);
1263        ui_send_codec_list(sp, srce);
1264}
1265
1266static void rx_tool_rat_playout_limit(char *srce, char *args, session_t *sp)
1267{
1268        int i;
1269        struct mbus_parser      *mp;
1270
1271        UNUSED(srce);
1272        mp = mbus_parse_init(args);
1273        if (mbus_parse_int(mp, &i) && (1 == i || 0 == i)) {
1274                sp->limit_playout = i;
1275        } else {
1276                debug_msg("mbus: usage \"tool.rat.playout.limit <bool>\"\n");
1277        }
1278        mbus_parse_done(mp);
1279}
1280
1281static void rx_tool_rat_playout_min(char *srce, char *args, session_t *sp)
1282{
1283        int      i;
1284        struct mbus_parser      *mp;
1285
1286        UNUSED(srce);
1287
1288        mp = mbus_parse_init(args);
1289        if (mbus_parse_int(mp, &i)) {
1290                sp->min_playout = i;
1291        } else {
1292                debug_msg("mbus: usage \"tool.rat.playout.min <integer>\"\n");
1293        }
1294        mbus_parse_done(mp);
1295}
1296
1297static void rx_tool_rat_playout_max(char *srce, char *args, session_t *sp)
1298{
1299        int      i;
1300        struct mbus_parser      *mp;
1301
1302        UNUSED(srce);
1303
1304        mp = mbus_parse_init(args);
1305        if (mbus_parse_int(mp, &i)) {
1306                sp->max_playout = i;
1307        } else {
1308                debug_msg("mbus: usage \"tool.rat.playout.max <integer>\"\n");
1309        }
1310        mbus_parse_done(mp);
1311}
1312
1313static void rx_tool_rat_payload_set(char *srce, char *args, session_t *sp)
1314{
1315        codec_id_t cid, cid_replacing;
1316        char *codec_long_name;
1317        int   i, new_pt;
1318        struct mbus_parser      *mp;
1319
1320        UNUSED(srce);
1321
1322        mp = mbus_parse_init(args);
1323
1324        if (mbus_parse_str(mp, &codec_long_name) &&
1325                mbus_parse_int(mp, &new_pt)) {
1326                        mbus_decode_str(codec_long_name);
1327
1328                        if (payload_is_valid((u_char)new_pt) == FALSE ||
1329                                new_pt < 0 || new_pt > 255) {
1330                                        debug_msg("Invalid payload specified\n");
1331                                        mbus_parse_done(mp);
1332                                        return;
1333                                }
1334
1335                                /* Don't allow payloads to be mapped to channel_coder payloads - it doesn't seem to work */
1336                                if (channel_coder_exist_payload((uint8_t)new_pt)) {
1337                                        debug_msg("Channel coder payload specified\n");
1338                                        mbus_parse_done(mp);
1339                                        return;
1340                                }
1341
1342                                for(i = 0; i < sp->num_encodings; i++) {
1343                                        if (new_pt == sp->encodings[i]) {
1344                                                debug_msg("Doh! Attempting to remap encoding %d codec.\n", i);
1345                                                mbus_parse_done(mp);
1346                                                return;
1347                                        }
1348                                }
1349
1350                                cid_replacing = codec_get_by_payload((u_char)new_pt);
1351                                if (cid_replacing) {
1352                                        const codec_format_t *cf;
1353                                        cf = codec_get_format(cid_replacing);
1354                                        assert(cf);
1355                                        debug_msg("Codec map replacing %s\n", cf->long_name);
1356                                        codec_unmap_payload(cid_replacing, (u_char)new_pt);
1357                                        ui_send_codec_details(sp, sp->mbus_ui_addr, cid_replacing);
1358                                }
1359
1360                                cid = codec_get_by_name(codec_long_name);
1361                                if (cid && codec_map_payload(cid, (u_char)new_pt)) {
1362                                        ui_send_codec_details(sp, sp->mbus_ui_addr, cid);
1363                                        debug_msg("map %s %d succeeded.\n", codec_long_name, new_pt);
1364                                } else {
1365                                        debug_msg("map %s %d failed.\n", codec_long_name, new_pt);
1366                                }
1367                }
1368                mbus_parse_done(mp);
1369}
1370
1371static void rx_tool_rat_converters_request(char *srce, char *args, session_t *sp)
1372{
1373        UNUSED(args);
1374        ui_send_converter_list(sp, srce);
1375}
1376
1377static void rx_tool_rat_converter(char *srce, char *args, session_t *sp)
1378{
1379        const converter_details_t *d = NULL;
1380        uint32_t             i, n;
1381        char               *name;
1382        struct mbus_parser      *mp;
1383
1384        UNUSED(srce);
1385
1386        mp = mbus_parse_init(args);
1387        if (mbus_parse_str(mp, &name)) {
1388                mbus_decode_str(name);
1389                n = converter_get_count();
1390                for(i = 0; i < n; i++) {
1391                        d = converter_get_details(i);
1392                        if (0 == strcasecmp(d->name,name)) {
1393                                break;
1394                        }
1395                }
1396                if (i == n) {
1397                        d = converter_get_details(0);
1398                }
1399                sp->converter = d->id;
1400        } else {
1401                debug_msg("mbus: usage \"tool.rat.converter <name>\"\n");
1402        }
1403        mbus_parse_done(mp);
1404        ui_send_converter(sp, sp->mbus_ui_addr);
1405}
1406
1407/* set_red_parameters translates what mbus_receives into command
1408* redundancy encoder understands.
1409*/
1410
1411static void
1412set_red_parameters(session_t *sp, char *sec_enc, int offset)
1413{
1414        const codec_format_t *pcf, *rcf;
1415        codec_id_t            pri_id, red_id;
1416        char *cmd;
1417        int   clen;
1418        assert(offset>0);
1419
1420        pri_id = codec_get_by_payload(sp->encodings[0]);
1421        pcf    = codec_get_format(pri_id);
1422        red_id = codec_get_matching(sec_enc, (uint32_t)pcf->format.sample_rate, (uint16_t)pcf->format.channels);
1423        if (!codec_id_is_valid(red_id)) {
1424                debug_msg("Failed to get redundant codec requested (%s)\n", sec_enc);
1425                red_id = pri_id;  /* Use same as primary */
1426        }
1427        rcf = codec_get_format(red_id);
1428
1429        clen = 2 * (CODEC_LONG_NAME_LEN + 4);
1430        cmd  = (char*)xmalloc(clen);
1431        sprintf(cmd, "%s/%d/%s/%d", pcf->long_name, 0, rcf->long_name, offset);
1432
1433        xmemchk();
1434        if (channel_encoder_set_parameters(sp->channel_coder, cmd) == 0) {
1435                debug_msg("Red command failed: %s\n", cmd);
1436        }
1437        xmemchk();
1438        xfree(cmd);
1439        /* Now tweak session parameters */
1440        sp->num_encodings = 2;
1441        sp->encodings[1]  = codec_get_payload(red_id);
1442}
1443
1444
1445static void
1446set_layered_parameters(session_t *sp, char *sec_enc, char *schan, char *sfreq, int layerenc)
1447{
1448        const codec_format_t *pcf, *lcf;
1449        codec_id_t            pri_id, lay_id;
1450        char *cmd;
1451        int      freq, channels;
1452        int   clen;
1453        assert(layerenc>0);
1454
1455        if (strcasecmp(schan, "mono") == 0) {
1456                channels = 1;
1457        } else if (strcasecmp(schan, "stereo") == 0) {
1458                channels = 2;
1459        } else {
1460                channels = 0;
1461        }
1462
1463        freq = string_to_freq(sfreq);
1464        pri_id = codec_get_by_payload(sp->encodings[0]);
1465        pcf    = codec_get_format(pri_id);
1466        lay_id = codec_get_matching(sec_enc, (uint16_t)freq, (uint16_t)channels);
1467        if(lay_id == 0) {
1468                debug_msg("Can't find layered codec (%s) - need to change primary codec\n", sec_enc);
1469        }
1470        if (pri_id!=lay_id) {
1471                /* This can happen if you change codec and select layering    *
1472                * before pushing apply, so change the primary encoding here. */
1473                codec_id_t cid;
1474                if (lay_id && codec_get_payload(lay_id) != 255) {
1475                        cid     = codec_get_by_payload ((u_char)sp->encodings[0]);
1476                        if (codec_audio_formats_compatible(lay_id, cid)) {
1477                                sp->encodings[0] = codec_get_payload(lay_id);
1478                                ui_send_audio_codec(sp, sp->mbus_ui_addr);
1479                        } else {
1480                                /* just register we want to make a change */
1481                                audio_device_register_change_primary(sp, lay_id);
1482                        }
1483                }
1484        }
1485        lcf = codec_get_format(lay_id);
1486
1487        if(layerenc<=MAX_LAYERS) {
1488                if(layerenc > sp->rtp_session_count) {
1489                        debug_msg("%d is too many layers - ports not inited - forcing %d layers\n", layerenc, sp->rtp_session_count);
1490                        layerenc = sp->rtp_session_count;
1491                }
1492        }
1493
1494        clen = CODEC_LONG_NAME_LEN + 4;
1495        cmd  = (char*)xmalloc(clen);
1496        sprintf(cmd, "%s/%d", lcf->long_name, layerenc);
1497
1498        xmemchk();
1499        if (channel_encoder_set_parameters(sp->channel_coder, cmd) == 0) {
1500                debug_msg("Layered command failed: %s\n", cmd);
1501        }
1502        xmemchk();
1503        xfree(cmd);
1504        /* Now tweak session parameters */
1505        sp->layers = layerenc;
1506        sp->num_encodings = 1;
1507}
1508
1509/* This function is a bit nasty because it has to coerce what the
1510* mbus gives us into something the channel coders understand.  In addition,
1511* we assume we know what channel coders are which kind of defies point
1512* 'generic' structure but that's probably because it's not generic enough.
1513*/
1514static void rx_audio_channel_coding(char *srce, char *args, session_t *sp)
1515{
1516        const cc_details_t *ccd;
1517        char        *coding, *sec_enc, *schan, *sfreq;
1518        int          offset, layerenc;
1519        uint32_t      i, n;
1520        uint16_t      upp;
1521        struct mbus_parser      *mp;
1522
1523        UNUSED(srce);
1524
1525        mp = mbus_parse_init(args);
1526        if (mbus_parse_str(mp, &coding)) {
1527                mbus_decode_str(coding);
1528                upp = channel_encoder_get_units_per_packet(sp->channel_coder);
1529                n = channel_get_coder_count();
1530                for(i = 0; i < n; i++) {
1531                        ccd = channel_get_coder_details(i);
1532                        if (strncasecmp(ccd->name, coding, 3) == 0) {
1533                                debug_msg("rx_audio_channel_coding: 0x%08x, %s\n", ccd->descriptor, &ccd->name);
1534                                switch(tolower((int)ccd->name[0])) { //SV-XXX: NetBSD
1535                                                                case 'n':   /* No channel coding */
1536                                                                        sp->num_encodings = 1;
1537                                                                        sp->layers = 1;
1538                                                                        channel_encoder_destroy(&sp->channel_coder);
1539                                                                        channel_encoder_create(ccd->descriptor, &sp->channel_coder);
1540                                                                        channel_encoder_set_units_per_packet(sp->channel_coder, upp);
1541                                                                        break;
1542                                                                case 'r':   /* Redundancy -> extra parameters */
1543                                                                        if (mbus_parse_str(mp, &sec_enc) &&
1544                                                                                mbus_parse_int(mp, &offset)) {
1545                                                                                        mbus_decode_str(sec_enc);
1546                                                                                        sp->layers = 1;
1547                                                                                        channel_encoder_destroy(&sp->channel_coder);
1548                                                                                        channel_encoder_create(ccd->descriptor, &sp->channel_coder);
1549                                                                                        channel_encoder_set_units_per_packet(sp->channel_coder, upp);
1550                                                                                        set_red_parameters(sp, sec_enc, offset);
1551                                                                                }
1552                                                                                break;
1553                                                                case 'l':       /*Layering */
1554                                                                        if (mbus_parse_str(mp, &sec_enc) &&
1555                                                                                mbus_parse_str(mp, &schan) &&
1556                                                                                mbus_parse_str(mp, &sfreq) &&
1557                                                                                mbus_parse_int(mp, &layerenc)) {
1558                                                                                        mbus_decode_str(sec_enc);
1559                                                                                        mbus_decode_str(schan);
1560                                                                                        mbus_decode_str(sfreq);
1561                                                                                        channel_encoder_destroy(&sp->channel_coder);
1562                                                                                        channel_encoder_create(ccd->descriptor, &sp->channel_coder);
1563                                                                                        channel_encoder_set_units_per_packet(sp->channel_coder, upp);
1564                                                                                        set_layered_parameters(sp, sec_enc, schan, sfreq, layerenc);
1565                                                                                }
1566                                                                                break;
1567                                }
1568                                break;
1569                        }
1570                }
1571        }
1572        mbus_parse_done(mp);
1573#ifdef DEBUG
1574        ccd = channel_get_coder_identity(sp->channel_coder);
1575        debug_msg("***** %s\n", ccd->name);
1576#endif /* DEBUG */
1577        ui_send_audio_channel_coding(sp, sp->mbus_ui_addr);
1578}
1579
1580static void rx_tool_rat_settings(char *srce, char *args, session_t *sp)
1581{
1582        /* When we get a tool.rat.settings() message, we dump out state  */
1583        /* into the query source. We omit rtp and audio related state,   */
1584        /* since there are other mbus commands which solicit that info.  */
1585        /* It should be possible to query most of this information via   */
1586        /* specific commands for each variable, but I haven't got around */
1587        /* to implementing all that yet - please send in a patch! [csp]  */
1588        UNUSED(args);
1589        ui_send_repair_scheme_list(sp, srce);
1590        ui_send_codec_list        (sp, srce);
1591        ui_send_converter_list    (sp, srce);
1592        ui_send_converter         (sp, sp->mbus_ui_addr);
1593        ui_send_lecture_mode      (sp, sp->mbus_ui_addr);
1594        ui_send_sampling_mode_list(sp, srce);
1595        ui_send_powermeter        (sp, srce);
1596        ui_send_playout_bounds    (sp, srce);
1597        ui_send_agc               (sp, srce);
1598        ui_send_loopback_gain     (sp, srce);
1599        ui_send_echo_suppression  (sp, srce);
1600        ui_send_encryption_key    (sp, srce);
1601        ui_send_device_config     (sp, srce);
1602        ui_send_audio_codec       (sp, srce);
1603        ui_send_rate              (sp, srce);
1604}
1605
1606static void rx_mbus_quit(char *srce, char *args, session_t *sp)
1607{
1608        /* mbus.quit() means that we should quit */
1609        UNUSED(args);
1610        UNUSED(srce);
1611        UNUSED(sp);
1612        should_exit = TRUE;
1613        debug_msg("Media engine got mbus.quit()\n");
1614}
1615
1616static void rx_mbus_bye(char *srce, char *args, session_t *sp)
1617{
1618        /* mbus.bye() means that the sender of the message is about to quit */
1619        UNUSED(args);
1620        if (strstr(srce, "media:video") != NULL) {
1621                sp->sync_on = FALSE;
1622        }
1623}
1624
1625static void rx_mbus_waiting(char *srce, char *args, session_t *sp)
1626{
1627        char                    *s, *sd;
1628        struct mbus_parser      *mp;
1629
1630        UNUSED(srce);
1631
1632        mp = mbus_parse_init(args);
1633        if (mbus_parse_str(mp, &s)) {
1634                sd = mbus_decode_str(s);
1635                if (strcmp(sd, sp->mbus_waiting_token) == 0) {
1636                        sp->mbus_waiting = FALSE;
1637                } else {
1638                        debug_msg("Got mbus.waiting(%s)\n", sd);
1639                }
1640        } else {
1641                debug_msg("mbus: usage \"mbus.waiting(token)\"\n");
1642        }
1643        mbus_parse_done(mp);
1644}
1645
1646static void rx_mbus_go(char *srce, char *args, session_t *sp)
1647{
1648        char                    *s, *sd;
1649        struct mbus_parser      *mp;
1650
1651        mp = mbus_parse_init(args);
1652        if (mbus_parse_str(mp, &s)) {
1653                sd = mbus_decode_str(s);
1654                if (strcmp(sd, "rat-ui-requested") == 0) {
1655                        /* We now have a user interface... :-) */
1656                        sp->ui_on = TRUE;
1657                        sp->mbus_ui_addr = xstrdup(srce);
1658                } else if (strcmp(sd, sp->mbus_go_token) == 0) {
1659                        sp->mbus_go = FALSE;
1660                        debug_msg("Got required mbus.go(%s)\n", sd);
1661                } else {
1662                        debug_msg("Got spurious mbus.go(%s)\n", sd);
1663                }
1664        } else {
1665                debug_msg("mbus: usage \"mbus.go(token)\"\n");
1666        }
1667        mbus_parse_done(mp);
1668}
1669
1670static void rx_tool_rat_ui_detach_request(char *srce, char *args, session_t *sp)
1671{
1672        UNUSED(args);
1673        if (sp->ui_on == FALSE) {
1674                debug_msg("UI not enabled, cannot detach\n");
1675                return;
1676        }
1677        if (strcmp(sp->mbus_ui_addr, srce) != 0) {
1678                debug_msg("Cannot detach UI, addresses differ\n");
1679                return;
1680        }
1681        mbus_qmsgf(sp->mbus_engine, srce, TRUE, "tool.rat.ui.detach", "");
1682        sp->ui_on = FALSE;
1683}
1684
1685static void rx_tool_rat_layers(char *srce, char *args, session_t *sp)
1686{
1687        int      i;
1688        struct mbus_parser      *mp;
1689
1690        UNUSED(srce);
1691
1692        mp = mbus_parse_init(args);
1693        if (mbus_parse_int(mp, &i)) {
1694                if(i>MAX_LAYERS) {
1695                        debug_msg("too many layers: max = %d\n", MAX_LAYERS);
1696                        sp->layers = MAX_LAYERS;
1697                } else {
1698                        sp->layers = i;
1699                }
1700        } else {
1701                debug_msg("mbus: usage \"tool.rat.layers <integer>\"\n");
1702        }
1703        mbus_parse_done(mp);
1704}
1705
1706
1707static void rx_mbus_hello(char *srce, char *args, session_t *sp)
1708{
1709        UNUSED(args);
1710        if (strstr(srce, "media:video") != NULL) {
1711                sp->sync_on = TRUE;
1712        }
1713}
1714
1715static const mbus_cmd_tuple engine_cmds[] = {
1716        { "tool.rat.logstats",                     rx_tool_rat_logstats },
1717        { "tool.rat.logdebug",                     rx_tool_rat_logdebug },
1718        { "tool.rat.tone.start",                   rx_tool_rat_tone_start },
1719        { "tool.rat.tone.stop",                    rx_tool_rat_tone_stop },
1720        { "tool.rat.voxlet.play",                  rx_tool_rat_voxlet_play },
1721        { "session.title",                         rx_session_title },
1722        { "tool.rat.silence",                      rx_tool_rat_silence },
1723        { "tool.rat.silence.threshold",            rx_tool_rat_silence_thresh },
1724        { "tool.rat.lecture.mode",                 rx_tool_rat_lecture_mode },
1725        { "audio.3d.enabled",                      rx_audio_3d_enable },
1726        { "audio.3d.user.settings",                rx_audio_3d_user_settings },
1727        { "audio.3d.user.settings.request",        rx_audio_3d_user_settings_req },
1728        { "tool.rat.agc",                          rx_tool_rat_agc },
1729        { "tool.rat.loopback.gain",                rx_tool_rat_loopback_gain },
1730        { "tool.rat.echo.suppress",                rx_tool_rat_echo_suppress },
1731        { "tool.rat.rate",                         rx_tool_rat_rate },
1732        { "tool.rat.powermeter",                   rx_tool_rat_powermeter },
1733        { "tool.rat.converters.request",           rx_tool_rat_converters_request },
1734        { "tool.rat.converter",                    rx_tool_rat_converter },
1735        { "tool.rat.settings",                     rx_tool_rat_settings },
1736        { "tool.rat.codec",                        rx_tool_rat_codec },
1737        { "tool.rat.codecs.request",               rx_tool_rat_codecs_request },
1738        { "tool.rat.playout.limit",                rx_tool_rat_playout_limit },
1739        { "tool.rat.playout.min",                  rx_tool_rat_playout_min },
1740        { "tool.rat.playout.max",                  rx_tool_rat_playout_max },
1741        { "tool.rat.payload.set",                  rx_tool_rat_payload_set },
1742        { "tool.rat.ui.detach.request",            rx_tool_rat_ui_detach_request },
1743        { "tool.rat.filter.loopback",              rx_tool_rat_filter_loopback },
1744        { "tool.rat.layers",                       rx_tool_rat_layers },
1745        { "audio.input.mute",                      rx_audio_input_mute },
1746        { "audio.input.gain",                      rx_audio_input_gain },
1747        { "audio.input.port",                      rx_audio_input_port },
1748        { "audio.output.mute",                     rx_audio_output_mute },
1749        { "audio.output.gain",                     rx_audio_output_gain },
1750        { "audio.output.port",                     rx_audio_output_port },
1751        { "audio.channel.coding",                  rx_audio_channel_coding },
1752        { "audio.channel.repair",                  rx_audio_channel_repair },
1753        { "audio.file.play.open",                  rx_audio_file_play_open },
1754        { "audio.file.play.pause",                 rx_audio_file_play_pause },
1755        { "audio.file.play.stop",                  rx_audio_file_play_stop },
1756        { "audio.file.play.live",                  rx_audio_file_play_live },
1757        { "audio.file.record.open",                rx_audio_file_rec_open },
1758        { "audio.file.record.pause",               rx_audio_file_rec_pause },
1759        { "audio.file.record.stop",                rx_audio_file_rec_stop },
1760        { "audio.file.record.live",                rx_audio_file_rec_live },
1761        { "audio.device",                          rx_audio_device },
1762        { "audio.query",                           rx_audio_query },
1763        { "security.encryption.key",               rx_security_encryption_key },
1764        { "rtp.query",                             rx_rtp_query },
1765        { "rtp.addr.query",                        rx_rtp_addr_query },
1766        { "rtp.addr",                              rx_rtp_addr },
1767        { "rtp.source.name",                       rx_rtp_source_name },
1768        { "rtp.source.email",                      rx_rtp_source_email },
1769        { "rtp.source.phone",                      rx_rtp_source_phone },
1770        { "rtp.source.loc",                        rx_rtp_source_loc },
1771        { "rtp.source.note",                       rx_rtp_source_note },
1772        { "rtp.source.mute",                       rx_rtp_source_mute },
1773        { "rtp.source.gain",                       rx_rtp_source_gain },
1774        { "rtp.source.app.site",                   rx_rtp_source_app_site },
1775        { "mbus.quit",                             rx_mbus_quit },
1776        { "mbus.bye",                              rx_mbus_bye },
1777        { "mbus.waiting",                          rx_mbus_waiting },
1778        { "mbus.go",                               rx_mbus_go },
1779        { "mbus.hello",                            rx_mbus_hello },
1780};
1781
1782#define NUM_ENGINE_CMDS sizeof(engine_cmds)/sizeof(engine_cmds[0])
1783
1784void mbus_engine_rx(char *srce, char *cmnd, char *args, void *data)
1785{
1786        uint32_t i;
1787
1788        for (i = 0; i < NUM_ENGINE_CMDS; i++) {
1789                if (strcmp(engine_cmds[i].rxname, cmnd) == 0) {
1790                        engine_cmds[i].rxproc(srce, args, (session_t *) data);
1791                        return;
1792                }
1793        }
1794        debug_msg("Unknown mbus command: %s (%s)\n", cmnd, args);
1795#ifndef NDEBUG
1796        fprintf(stderr, "Unknown mbus command: %s (%s)\n", cmnd, args);
1797        abort();
1798#endif
1799}
Note: See TracBrowser for help on using the browser.