60
60
#include " debug.h"
61
61
#include " host.h" // for get_commandline_param, uv_argv
62
62
#include " lib_common.h"
63
+ #include " messaging.h"
63
64
#include " module.h"
64
65
#include " rtp/rtp.h"
65
66
#include " transmit.h"
66
67
#include " types.h" // for tx_media_type
67
68
#include " utils/audio_buffer.h"
69
+ #include " utils/macros.h"
68
70
#include " utils/net.h" // for get_sockaddr_addr_str
69
71
#include " utils/thread.h"
70
72
@@ -255,6 +257,8 @@ struct state_audio_mixer final {
255
257
state_audio_mixer (const struct audio_playback_opts *opts) {
256
258
parse_opts (opts);
257
259
260
+ only_sender.ss_family = AF_UNSPEC;
261
+
258
262
struct audio_codec_state *audio_coder =
259
263
audio_codec_init_cfg (audio_codec.c_str (), AUDIO_CODER);
260
264
if (!audio_coder) {
@@ -264,26 +268,83 @@ struct state_audio_mixer final {
264
268
audio_codec_done (audio_coder);
265
269
}
266
270
271
+ module_init_default (&mod);
272
+ mod.cls = MODULE_CLASS_DATA;
273
+ module_register (&mod, opts->parent );
274
+
267
275
thread_id = thread (&state_audio_mixer::worker, this );
268
276
}
269
277
~state_audio_mixer () {
270
278
thread_id.join ();
279
+ module_done (&mod);
271
280
}
272
281
bool should_exit = false ;
273
282
state_audio_mixer (state_audio_mixer const &) = delete ;
274
283
state_audio_mixer& operator =(state_audio_mixer const &) = delete ;
275
284
void worker ();
285
+ void check_messages ();
276
286
277
287
map<sockaddr_storage, am_participant, sockaddr_storage_less> participants;
278
288
mutex participants_lock;
279
289
280
290
struct socket_udp_local *recv_socket{};
281
291
string audio_codec{" PCM" };
292
+ sockaddr_storage
293
+ only_sender; // /< if !AF_UNSPEC, use stream just from this sender
282
294
private:
295
+ struct module mod;
283
296
thread thread_id;
284
297
unique_ptr<generic_mix_algo<sample_type_source, sample_type_mixed>> mixing_algorithm{new linear_mix_algo<sample_type_source, sample_type_mixed>()};
285
298
};
286
299
300
+ void
301
+ state_audio_mixer::check_messages ()
302
+ {
303
+ struct message *msg = nullptr ;
304
+ while ((msg = check_message (&mod))) {
305
+ auto *msg_univ = reinterpret_cast <struct msg_universal *>(msg);
306
+ MSG (VERBOSE, " Received message: %s\n " , msg_univ->text );
307
+ if (strcmp (msg_univ->text , " help" ) == 0 ) {
308
+ printf (" Syntax:\n "
309
+ " \t restrict <addr>\n "
310
+ " \t restrict flush\n "
311
+ " eg.:\n "
312
+ " \t restrict [::ffff:10.0.1.20]:65426\n " );
313
+ free_message (msg, new_response (RESPONSE_OK, nullptr ));
314
+ continue ;
315
+ }
316
+ if (strstr (msg_univ->text , " restrict " ) != msg_univ->text ) {
317
+ MSG (ERROR,
318
+ " Unknown message: %s!\n Send message \" help\" for "
319
+ " syntax.\n " ,
320
+ msg_univ->text );
321
+ char resp_msg[sizeof msg_univ->text + 20 ];
322
+ snprintf_ch (resp_msg, " unknown request: %s" ,
323
+ msg_univ->text );
324
+ free_message (
325
+ msg, new_response (RESPONSE_BAD_REQUEST, resp_msg));
326
+ continue ;
327
+ }
328
+ const char *val = msg_univ->text + strlen (" restrict " );
329
+ if (strcmp (val, " flush" ) == 0 ) {
330
+ MSG (INFO, " flushing the address restriction (defaulting to mix all)\n " );
331
+ only_sender.ss_family = AF_UNSPEC;
332
+ } else {
333
+ MSG (INFO, " restricting mixer to: %s\n " , val);
334
+ only_sender = get_sockaddr (val, 0 );
335
+ if (participants.find (only_sender) ==
336
+ participants.end ()) {
337
+ MSG (WARNING,
338
+ " The requested participant %s is not yet "
339
+ " present...\n " ,
340
+ val);
341
+ }
342
+ }
343
+
344
+ free_message (msg, new_response (RESPONSE_OK, nullptr ));
345
+ }
346
+ }
347
+
287
348
void state_audio_mixer::worker ()
288
349
{
289
350
set_thread_name (__func__);
@@ -304,6 +365,7 @@ void state_audio_mixer::worker()
304
365
}
305
366
306
367
unique_lock<mutex> plk (participants_lock);
368
+ check_messages ();
307
369
// check timeouts
308
370
for (auto it = participants.cbegin (); it != participants.cend (); )
309
371
{
@@ -433,8 +495,16 @@ static void audio_play_mixer_put_frame(void *state, const struct audio_frame *fr
433
495
s->participants .emplace (ss, am_participant{s->recv_socket , &ss, s->audio_codec });
434
496
}
435
497
436
- audio_buffer_write (s->participants .at (ss).m_buffer , frame->data , frame->data_len );
437
498
s->participants .at (ss).last_seen = chrono::steady_clock::now ();
499
+
500
+ // if mixer restricted to a single sender and this isn't me
501
+ if (s->only_sender .ss_family != AF_UNSPEC &&
502
+ sockaddr_compare ((const sockaddr *) &ss,
503
+ (const sockaddr *) &s->only_sender ) != 0 ) {
504
+ return ;
505
+ }
506
+
507
+ audio_buffer_write (s->participants .at (ss).m_buffer , frame->data , frame->data_len );
438
508
}
439
509
440
510
static void audio_play_mixer_done (void *state)
0 commit comments