root/rat/trunk/main_engine.c @ 3054

Revision 3054, 11.6 KB (checked in by ucaccsp, 15 years ago)

Lots of debugging code - don't even think of playing with this version...

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2 * FILE:    main-engine.c
3 * PROGRAM: RAT
4 * AUTHOR:  Colin Perkins
5 *
6 * $Revision$
7 * $Date$
8 *
9 * Copyright (c) 1995-2000 University College London
10 * All rights reserved.
11 *
12 */
13
14#include "config_unix.h"
15#include "config_win32.h"
16#include "debug.h"
17#include "memory.h"
18#include "audio_types.h"
19#include "codec_types.h"
20#include "codec.h"
21#include "channel_types.h"
22#include "session.h"
23#include "audio.h"
24#include "auddev.h"
25#include "cushion.h"
26#include "converter.h"
27#include "tcltk.h"
28#include "pdb.h"
29#include "ui.h"
30#include "net.h"
31#include "timers.h"
32#include "parameters.h"
33#include "transmit.h"
34#include "source.h"
35#include "mix.h"
36#include "sndfile.h"
37#include "mbus.h"
38#include "mbus_ui.h"
39#include "mbus_engine.h"
40#include "crypt_random.h"
41#include "net_udp.h"
42#include "settings.h"
43#include "rtp.h"
44#include "rtp_callback.h"
45
46int      should_exit = FALSE;
47char    *c_addr, *token, *token_e; /* These should be parameters of the session? */
48
49#ifndef WIN32
50static void
51signal_handler(int signal)
52{
53        debug_msg("Caught signal %d\n", signal);
54        exit(-1);
55}
56#endif
57
58#define MBUS_ADDR_ENGINE "(media:audio module:engine app:rat instance:%u)"
59
60static void parse_args(int argc, char *argv[])
61{
62        int     i;
63
64        if (argc != 5) {
65                printf("Usage: %s -ctrl <addr> -token <token>\n", argv[0]);
66                exit(1);
67        }
68        for (i = 1; i < argc; i++) {
69                if (strcmp(argv[i], "-ctrl") == 0) {
70                        c_addr = xstrdup(argv[++i]);
71                } else if (strcmp(argv[i], "-token") == 0) {
72                        token   = xstrdup(argv[++i]);
73                        token_e = mbus_encode_str(token);
74                } else {
75                        printf("Unknown argument \"%s\"\n", argv[i]);
76                        abort();
77                }
78        }
79}
80
81static void 
82mbus_error_handler(int seqnum, int reason)
83{
84        debug_msg("mbus message failed (%d:%d)\n", seqnum, reason);
85        if (should_exit == FALSE) {
86                abort();
87        }
88        UNUSED(seqnum);
89        UNUSED(reason);
90        /* Ignore error we're closing down anyway */
91}
92
93int main(int argc, char *argv[])
94{
95        uint32_t         cur_time = 0, ntp_time = 0;
96        int              seed, elapsed_time, alc = 0, scnt = 0;
97        session_t       *sp;
98        struct timeval   time;
99        struct timeval   timeout;
100        uint8_t          j;
101
102
103        Sleep(10000);
104
105#ifdef WIN32
106        SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
107#else
108        signal(SIGINT, signal_handler);
109        debug_set_core_dir(argv[0]);
110#endif
111
112        /* Setup things which are independent of the session. These should */
113        /* be create static data only, since it will be accessed by BOTH   */
114        /* instances when running as a transcoder.                         */
115        seed = (gethostid() << 8) | (getpid() & 0xff);
116        srand48(seed);
117        lbl_srandom(seed);
118        converters_init();
119        audio_init_interfaces();
120        parse_args(argc, argv);
121
122        /* Initialize the session structure, and all session specific data */
123        sp = (session_t *) xmalloc(sizeof(session_t));
124        session_init(sp);
125        audio_device_get_safe_config(&sp->new_config);
126        audio_device_reconfigure(sp);
127        sp->cur_ts = ts_seq32_in(&sp->decode_sequencer, get_freq(sp->device_clock), 0);
128        assert(audio_device_is_open(sp->audio_device));
129        settings_load_early(sp);
130
131        /* Initialise our mbus interface... once this is done we can talk to our controller */
132        sp->mbus_engine = mbus_init(mbus_engine_rx, mbus_error_handler);
133        sp->mbus_engine_addr = (char *) xmalloc(strlen(MBUS_ADDR_ENGINE) + 3);
134        sprintf(sp->mbus_engine_addr, MBUS_ADDR_ENGINE, (uint32_t) getpid());
135        mbus_addr(sp->mbus_engine, sp->mbus_engine_addr);
136
137        /* The first stage is to wait until we hear from our controller. The address of the */
138        /* controller is passed to us via a command line parameter, and we just wait until  */
139        /* we get an mbus.hello() from that address.                                        */
140        debug_msg("Waiting to validate address %s\n", c_addr);
141        while (!mbus_addr_valid(sp->mbus_engine, c_addr)) {
142                timeout.tv_sec  = 0;
143                timeout.tv_usec = 250000;
144                mbus_recv(sp->mbus_engine, NULL, &timeout);
145                mbus_send(sp->mbus_engine);
146                mbus_heartbeat(sp->mbus_engine, 1);
147                mbus_retransmit(sp->mbus_engine);
148        }
149        debug_msg("Address %s is valid\n", c_addr);
150
151        /* Next, we signal to the controller that we are ready to go. It should be sending  */
152        /* us an mbus.waiting(foo) where "foo" is the same as the "-token" argument we were */
153        /* passed on startup. We respond with mbus.go(foo) sent reliably to the controller. */
154        debug_msg("Waiting for mbus.waiting(%s) from controller...\n", token);
155        mbus_rendezvous_go(sp->mbus_engine, token, (void *) sp);
156        debug_msg("...got it\n");
157
158        /* At this point we know the mbus address of our controller, and have conducted */
159        /* a successful rendezvous with it. It will now send us configuration commands. */
160        debug_msg("Waiting for mbus.go(%s) from controller...\n", token);
161        mbus_rendezvous_waiting(sp->mbus_engine, c_addr, token, (void *) sp);
162        debug_msg("...got it\n");
163        assert(sp->rtp_session[0] != NULL);
164
165        if (pdb_create(&sp->pdb) == FALSE) {
166                debug_msg("Failed to create persistent database\n");
167                abort();
168        }
169        pdb_item_create(sp->pdb, sp->clock, (uint16_t)get_freq(sp->device_clock), rtp_my_ssrc(sp->rtp_session[0]));
170        settings_load_late(sp);
171
172        ui_initial_settings(sp);
173        ui_update(sp);
174        network_process_mbus(sp);
175       
176        audio_drain(sp->audio_device);
177        if (tx_is_sending(sp->tb)) {
178                tx_start(sp->tb);
179        }
180
181        session_validate(sp);
182        xdoneinit();
183
184        while (!should_exit) {
185                elapsed_time = 0;
186
187                /* Process audio */
188                elapsed_time = audio_rw_process(sp, sp, sp->ms);
189                cur_time = get_time(sp->device_clock);
190                ntp_time = ntp_time32();
191                sp->cur_ts   = ts_seq32_in(&sp->decode_sequencer, get_freq(sp->device_clock), cur_time);
192
193                if (tx_is_sending(sp->tb)) {
194                        tx_process_audio(sp->tb);
195                        tx_send(sp->tb);
196                }
197
198                /* Process RTP/RTCP packets */
199                timeout.tv_sec  = 0;
200                timeout.tv_usec = 0;
201                for (j = 0; j < sp->rtp_session_count; j++) {
202                        while(rtp_recv(sp->rtp_session[j], &timeout, cur_time));
203                        rtp_send_ctrl(sp->rtp_session[j], cur_time, NULL);
204                        rtp_update(sp->rtp_session[j]);
205                }
206
207                /* Process mbus */
208                timeout.tv_sec  = 0;
209                timeout.tv_usec = 0;
210                mbus_recv(sp->mbus_engine, (void *) sp, &timeout);
211                mbus_heartbeat(sp->mbus_engine, 1);
212                mbus_retransmit(sp->mbus_engine);
213                mbus_send(sp->mbus_engine);
214
215                /* Process audio */
216                elapsed_time += audio_rw_process(sp, sp, sp->ms);
217                cur_time      = get_time(sp->device_clock);
218                ntp_time      = ntp_time32();
219                sp->cur_ts    = ts_seq32_in(&sp->decode_sequencer, get_freq(sp->device_clock), cur_time);
220
221                if (tx_is_sending(sp->tb)) {
222                        tx_process_audio(sp->tb);
223                        tx_send(sp->tb);
224                }
225
226                /* Process and mix active sources */
227                if (sp->playing_audio) {
228                        struct s_source *s;
229                        int              sidx;
230                        ts_t             cush_ts;
231
232                        session_validate(sp);
233                        cush_ts = ts_map32(get_freq(sp->device_clock), cushion_get_size(sp->cushion));
234                        cush_ts = ts_add(sp->cur_ts, cush_ts);
235                        scnt = (int)source_list_source_count(sp->active_sources);
236                        for(sidx = 0; sidx < scnt; sidx++) {
237                                s = source_list_get_source_no(sp->active_sources, sidx);
238                                if (source_relevant(s, sp->cur_ts)) {
239                                        pdb_entry_t *e;
240                                        ts_t         two_secs, delta;
241                                        source_check_buffering(s);
242                                        source_process(sp, s, sp->ms, sp->render_3d, sp->repair, sp->cur_ts, cush_ts);
243                                        source_audit(s);
244                                        /* Check for UI update necessary, updating once per 2 secs */
245                                        pdb_item_get(sp->pdb, source_get_ssrc(s), &e);
246                                        delta    = ts_sub(sp->cur_ts, e->last_ui_update);
247                                        two_secs = ts_map32(8000, 16000);
248                                        if (ts_gt(delta, two_secs)) {
249                                                ui_update_stats(sp, e->ssrc);
250                                                e->last_ui_update = sp->cur_ts;
251                                        }
252                                } else {
253                                        /* Remove source as stopped */
254                                        uint32_t ssrc;
255                                        ssrc = source_get_ssrc(s);
256                                        ui_info_deactivate(sp, ssrc);
257                                        source_remove(sp->active_sources, s);
258                                        sidx--;
259                                        scnt--;
260                                }
261                        }
262                }
263
264                /* Echo Suppression - cut off transmitter when receiving     */
265                /* audio, enable when stop receiving.                        */
266                session_validate(sp);
267                if (sp->echo_suppress) {
268                        if (scnt > 0) {
269                                if (tx_is_sending(sp->tb)) {
270                                        tx_stop(sp->tb);
271                                        sp->echo_tx_active = TRUE;
272                                        debug_msg("Echo suppressor (disabling tx)\n");
273                                }
274                        } else if (sp->echo_tx_active) {
275                                /* Transmitter was stopped because we were   */
276                                /* playing out audio.  Restart it.           */
277                                if (tx_is_sending(sp->tb) == FALSE) {
278                                        tx_start(sp->tb);
279                                        debug_msg("Echo suppressor (enabling tx)\n");
280                                }
281                                sp->echo_tx_active = FALSE;
282                        }
283                }
284                /* Lecture Mode */
285                if (alc >= 50) {
286                        if (!sp->lecture && tx_is_sending(sp->tb) && sp->auto_lecture != 0) {
287                                gettimeofday(&time, NULL);
288                                if (time.tv_sec - sp->auto_lecture > 120) {
289                                        sp->auto_lecture = 0;
290                                        debug_msg("Dummy lecture mode\n");
291                                }
292                        }
293                        alc = 0;
294                } else {
295                        alc++;
296                }
297
298                if (sp->audio_device && elapsed_time != 0) {
299                        ui_periodic_updates(sp, elapsed_time);
300                }
301                if (sp->new_config != NULL) {
302                        /* wait for mbus messages - closing audio device    */
303                        /* can timeout unprocessed messages as some drivers */
304                        /* pause to drain before closing.                   */
305                        network_process_mbus(sp);
306                        if (audio_device_reconfigure(sp)) {
307                                /* Device reconfigured so decode paths of all sources */
308                                /* are misconfigured. Delete the source, and incoming */
309                                /* data will drive the correct new path.              */
310                                source_list_clear(sp->active_sources);
311                                ui_update(sp);
312                        }
313                }
314               
315                /* Choke CPU usage */
316                if (!audio_is_ready(sp->audio_device)) {
317                        audio_wait_for(sp->audio_device, 20);
318                }
319
320                /* Debugging sanity check of the session... */
321                session_validate(sp);
322        }
323
324        settings_save(sp);
325        tx_stop(sp->tb);
326        if (sp->in_file  != NULL) snd_read_close (&sp->in_file);
327        if (sp->out_file != NULL) snd_write_close(&sp->out_file);
328        audio_device_release(sp, sp->audio_device);
329        pdb_destroy(&sp->pdb);
330
331        /* Inform other processes that we're about to quit... */
332        mbus_qmsgf(sp->mbus_engine, "()", FALSE, "mbus.bye", "");
333        mbus_send(sp->mbus_engine);
334        do {
335                struct timeval   timeout;
336                mbus_send(sp->mbus_engine);
337                mbus_retransmit(sp->mbus_engine);
338                timeout.tv_sec  = 0;
339                timeout.tv_usec = 20000;
340                mbus_recv(sp->mbus_engine, sp, &timeout);
341        } while (!mbus_sent_all(sp->mbus_engine));
342        mbus_exit(sp->mbus_engine);
343
344        for (j = 0; j < sp->rtp_session_count; j++) {
345                rtp_send_bye(sp->rtp_session[j]);
346                rtp_done(sp->rtp_session[j]);
347                rtp_callback_exit(sp->rtp_session[j]);
348        }
349
350        session_validate(sp);
351        session_exit(sp);
352        converters_free();
353        audio_free_interfaces();
354        xmemdmp();
355        return 0;
356}
Note: See TracBrowser for help on using the browser.