Skip to content

Commit

Permalink
Added "listannouncements" request to the AudioBridge (#3391)
Browse files Browse the repository at this point in the history
  • Loading branch information
keremcadirci authored Jul 1, 2024
1 parent 15edae8 commit 195bac0
Showing 1 changed file with 115 additions and 12 deletions.
127 changes: 115 additions & 12 deletions src/plugins/janus_audiobridge.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,23 +75,24 @@ room-<unique room ID>: {
* (invalid JSON, invalid request) which will always result in a
* synchronous error response even for asynchronous requests.
*
* \c create , \c edit , \c destroy , \c exists, \c allowed, \c kick, \c list,
* \c mute , \c unmute , \c mute_room , \c unmute_room , \c listparticipants ,
* \c resetdecoder , \c rtp_forward, \c stop_rtp_forward , \c list_forwarders ,
* \c play_file , \c is_playing and \c stop_file are synchronous requests,
* which means you'll get a response directly within the context of the
* transaction. \c create allows you to create a new audio conference bridge
* dynamically, as an alternative to using the configuration file; \c edit
* allows you to dynamically edit some room properties (e.g., the PIN);
* \c create, \c edit, \c destroy, \c exists, \c allowed, \c kick, \c list,
* \c mute, \c unmute, \c mute_room, \c unmute_room, \c listparticipants,
* \c listannouncements, \c resetdecoder, \c rtp_forward, \c stop_rtp_forward,
* \c list_forwarders, \c play_file, \c is_playing and \c stop_file are
* synchronous requests, which means you'll get a response directly within
* the context of the transaction. \c create allows you to create a new audio
* conference bridge dynamically, as an alternative to using the configuration file;
* \c edit allows you to dynamically edit some room properties (e.g., the PIN);
* \c destroy removes an audio conference bridge and destroys it, kicking
* all the users out as part of the process; \c exists allows you to
* check whether a specific audio conference exists; \c allowed allows
* you to edit who's allowed to join a room via ad-hoc tokens; \c list
* lists all the available rooms, while \c listparticipants lists all
* the participants of a specific room and their details; \c resetdecoder
* marks the Opus decoder for the participant as invalid, and forces it
* to be recreated (which might be needed if the audio for generated by
* the participant becomes garbled); \c rtp_forward allows you to forward
* the participants of a specific room and their details; \c listannouncements
* lists all playing announcements of a specific room and their details;
* \c resetdecoder marks the Opus decoder for the participant as invalid, and
* forces it to be recreated (which might be needed if the audio for generated
* by the participant becomes garbled); \c rtp_forward allows you to forward
* the mix of an AudioBridge room via RTP to a separate component (e.g.,
* for broadcasting it to a wider audience, or for processing/recording),
* whereas \c stop_rtp_forward can remove an existing forwarder; a list
Expand Down Expand Up @@ -750,6 +751,37 @@ room-<unique room ID>: {
"file_id" : "<unique string ID of the announcement>",
"playing" : <true|false>
}
\endverbatim
*
* To get a list of the announcements in a specific room, you
* can make use of the \c listannouncements request, which has to be
* formatted as follows:
*
\verbatim
{
"request" : "listannouncements",
"secret" : "<room secret, mandatory if configured>",
"room" : <unique numeric ID of the room>
}
\endverbatim
*
* A successful request will produce a list of announcements in a
* \c announcements response:
*
\verbatim
{
"audiobridge" : "announcements",
"room" : <unique numeric ID of the room>,
"announcements" : [ // Array of announcement objects
{ // Announcement #1
"file_id" : "<unique string ID of the announcement>",
"filename": "<path to the Opus file to play>",
"playing" : <true|false, whether or not the file is playing>,
"loop": <true|false, depending on whether or not the file is playing in a loop forever>
}
// Other announcements
]
}
\endverbatim
*
* As anticipated, when not looping a playback will automatically stop and
Expand Down Expand Up @@ -5449,6 +5481,77 @@ static json_t *janus_audiobridge_process_synchronous_request(janus_audiobridge_s
json_object_set_new(response, "playing", playing ? json_true() : json_false());
goto prepare_response;
#endif
} else if(!strcasecmp(request_text, "listannouncements")) {
/* List all announcements in a room */
if(!string_ids) {
JANUS_VALIDATE_JSON_OBJECT(root, room_parameters,
error_code, error_cause, TRUE,
JANUS_AUDIOBRIDGE_ERROR_MISSING_ELEMENT, JANUS_AUDIOBRIDGE_ERROR_INVALID_ELEMENT);
} else {
JANUS_VALIDATE_JSON_OBJECT(root, roomstr_parameters,
error_code, error_cause, TRUE,
JANUS_AUDIOBRIDGE_ERROR_MISSING_ELEMENT, JANUS_AUDIOBRIDGE_ERROR_INVALID_ELEMENT);
}
if(error_code != 0)
goto prepare_response;
json_t *room = json_object_get(root, "room");
guint64 room_id = 0;
char room_id_num[30], *room_id_str = NULL;
if(!string_ids) {
room_id = json_integer_value(room);
g_snprintf(room_id_num, sizeof(room_id_num), "%"SCNu64, room_id);
room_id_str = room_id_num;
} else {
room_id_str = (char *)json_string_value(room);
}
janus_mutex_lock(&rooms_mutex);
janus_audiobridge_room *audiobridge = g_hash_table_lookup(rooms,
string_ids ? (gpointer)room_id_str : (gpointer)&room_id);
if(audiobridge == NULL) {
janus_mutex_unlock(&rooms_mutex);
error_code = JANUS_AUDIOBRIDGE_ERROR_NO_SUCH_ROOM;
JANUS_LOG(LOG_ERR, "No such room (%s)\n", room_id_str);
g_snprintf(error_cause, 512, "No such room (%s)", room_id_str);
goto prepare_response;
}
if(audiobridge->destroyed) {
JANUS_LOG(LOG_ERR, "No such room (%s)\n", room_id_str);
error_code = JANUS_AUDIOBRIDGE_ERROR_NO_SUCH_ROOM;
g_snprintf(error_cause, 512, "No such room (%s)", room_id_str);
janus_mutex_unlock(&rooms_mutex);
goto prepare_response;
}
janus_refcount_increase(&audiobridge->ref);
/* A secret may be required for this action */
JANUS_CHECK_SECRET(audiobridge->room_secret, root, "secret", error_code, error_cause,
JANUS_AUDIOBRIDGE_ERROR_MISSING_ELEMENT, JANUS_AUDIOBRIDGE_ERROR_INVALID_ELEMENT, JANUS_AUDIOBRIDGE_ERROR_UNAUTHORIZED);
if(error_code != 0) {
janus_mutex_unlock(&rooms_mutex);
janus_refcount_decrease(&audiobridge->ref);
goto prepare_response;
}
/* Return a list of all announcements */
json_t *list = json_array();
GHashTableIter iter;
gpointer value;
g_hash_table_iter_init(&iter, audiobridge->anncs);
while(g_hash_table_iter_next(&iter, NULL, &value)) {
janus_audiobridge_participant *p = value;
json_t *pl = json_object();
json_object_set_new(pl, "file_id", json_string(p->annc->id));
if(p->annc->filename)
json_object_set_new(pl, "filename", json_string(p->annc->filename));
json_object_set_new(pl, "playing", p->annc->started ? json_true() : json_false());
json_object_set_new(pl, "loop", p->annc->loop ? json_true() : json_false());
json_array_append_new(list, pl);
}
janus_refcount_decrease(&audiobridge->ref);
janus_mutex_unlock(&rooms_mutex);
response = json_object();
json_object_set_new(response, "audiobridge", json_string("announcements"));
json_object_set_new(response, "room", string_ids ? json_string(room_id_str) : json_integer(room_id));
json_object_set_new(response, "announcements", list);
goto prepare_response;
} else if(!strcasecmp(request_text, "stop_file")) {
#ifndef HAVE_LIBOGG
JANUS_LOG(LOG_VERB, "Playing files unsupported in this instance\n");
Expand Down

0 comments on commit 195bac0

Please sign in to comment.