From b5d5f26835ea8840fc3aedd38780f3025d2959b3 Mon Sep 17 00:00:00 2001 From: cbdev Date: Mon, 16 Dec 2019 22:47:52 +0100 Subject: Move active invitations to global scope --- backends/rtpmidi.c | 85 ++++++++++++++++++++++++++++++++++++++++++----------- backends/rtpmidi.h | 9 ++++-- backends/rtpmidi.md | 6 ++-- 3 files changed, 78 insertions(+), 22 deletions(-) (limited to 'backends') diff --git a/backends/rtpmidi.c b/backends/rtpmidi.c index 780e517..719f823 100644 --- a/backends/rtpmidi.c +++ b/backends/rtpmidi.c @@ -13,10 +13,15 @@ static struct /*_rtpmidi_global*/ { int mdns_fd; char* mdns_name; uint8_t detect; + + size_t announces; + rtpmidi_announce* announce; } cfg = { .mdns_fd = -1, .mdns_name = NULL, - .detect = 0 + .detect = 0, + .announces = 0, + .announce = NULL }; MM_PLUGIN_API int init(){ @@ -137,6 +142,7 @@ static int rtpmidi_push_peer(rtpmidi_instance_data* data, struct sockaddr_storag data->peer = realloc(data->peer, (data->peers + 1) * sizeof(rtpmidi_peer)); if(!data->peer){ fprintf(stderr, "Failed to allocate memory\n"); + data->peers = 0; return 1; } @@ -147,6 +153,58 @@ static int rtpmidi_push_peer(rtpmidi_instance_data* data, struct sockaddr_storag return 0; } +static int rtpmidi_push_invite(instance* inst, char* peer){ + size_t u, p; + + //check whether the instance is already in the announce list + for(u = 0; u < cfg.announces; u++){ + if(cfg.announce[u].inst == inst){ + break; + } + } + + //add to the announce list + if(u == cfg.announces){ + cfg.announce = realloc(cfg.announce, (cfg.announces + 1) * sizeof(rtpmidi_announce)); + if(!cfg.announce){ + fprintf(stderr, "Failed to allocate memory\n"); + cfg.announces = 0; + return 1; + } + + cfg.announce[u].inst = inst; + cfg.announce[u].invites = 0; + cfg.announce[u].invite = NULL; + + cfg.announces++; + } + + //check whether the peer is already in the invite list + for(p = 0; p < cfg.announce[u].invites; p++){ + if(!strcmp(cfg.announce[u].invite[p], peer)){ + return 0; + } + } + + //extend the invite list + cfg.announce[u].invite = realloc(cfg.announce[u].invite, (cfg.announce[u].invites + 1) * sizeof(char*)); + if(!cfg.announce[u].invite){ + fprintf(stderr, "Failed to allocate memory\n"); + cfg.announce[u].invites = 0; + return 1; + } + + //append the new invitee + cfg.announce[u].invite[p] = strdup(peer); + if(!cfg.announce[u].invite[p]){ + fprintf(stderr, "Failed to allocate memory\n"); + return 1; + } + + cfg.announce[u].invites++; + return 0; +} + static int rtpmidi_configure_instance(instance* inst, char* option, char* value){ rtpmidi_instance_data* data = (rtpmidi_instance_data*) inst->impl; char* host = NULL, *port = NULL; @@ -230,22 +288,17 @@ static int rtpmidi_configure_instance(instance* inst, char* option, char* value) fprintf(stderr, "The rtpmidi 'invite' option is only valid for apple mode instances\n"); return 1; } - free(data->invite_peers); - data->invite_peers = strdup(value); - if(!data->invite_peers){ - fprintf(stderr, "Failed to allocate memory\n"); - return 1; - } - return 0; + + return rtpmidi_push_invite(inst, value); } else if(!strcmp(option, "join")){ if(data->mode != apple){ fprintf(stderr, "The rtpmidi 'join' option is only valid for apple mode instances\n"); return 1; } - free(data->invite_accept); - data->invite_accept = strdup(value); - if(!data->invite_accept){ + free(data->accept); + data->accept = strdup(value); + if(!data->accept){ fprintf(stderr, "Failed to allocate memory\n"); return 1; } @@ -350,7 +403,7 @@ static int rtpmidi_set(instance* inst, size_t num, channel** c, channel_value* v //some receivers seem to have problems reading rfcs and interpreting the marker bit correctly rtp_header->mpt = (data->mode == apple ? 0 : 0x80) | RTPMIDI_HEADER_TYPE; rtp_header->sequence = htobe16(data->sequence++); - rtp_header->timestamp = 0; //TODO calculate appropriate timestamps + rtp_header->timestamp = mm_timestamp() * 10; //just assume 100msec resolution because rfc4695 handwaves it rtp_header->ssrc = htobe32(data->ssrc); //midi command section header @@ -617,11 +670,8 @@ static int rtpmidi_shutdown(size_t n, instance** inst){ free(data->session_name); data->session_name = NULL; - free(data->invite_peers); - data->invite_peers = NULL; - - free(data->invite_accept); - data->invite_accept = NULL; + free(data->accept); + data->accept = NULL; free(data->peer); data->peer = NULL; @@ -631,6 +681,7 @@ static int rtpmidi_shutdown(size_t n, instance** inst){ inst[u]->impl = NULL; } + //TODO free announces free(cfg.mdns_name); if(cfg.mdns_fd >= 0){ close(cfg.mdns_fd); diff --git a/backends/rtpmidi.h b/backends/rtpmidi.h index d4ca044..2652db7 100644 --- a/backends/rtpmidi.h +++ b/backends/rtpmidi.h @@ -71,13 +71,18 @@ typedef struct /*_rtmidi_instance_data*/ { //apple-midi config char* session_name; - char* invite_peers; - char* invite_accept; + char* accept; //direct mode config uint8_t learn_peers; } rtpmidi_instance_data; +typedef struct /*rtpmidi_announced_instance*/ { + instance* inst; + size_t invites; + char** invite; +} rtpmidi_announce; + #pragma pack(push, 1) typedef struct /*_apple_session_command*/ { uint16_t res1; diff --git a/backends/rtpmidi.md b/backends/rtpmidi.md index d8e3b63..d42df6f 100644 --- a/backends/rtpmidi.md +++ b/backends/rtpmidi.md @@ -34,6 +34,7 @@ Common instance configuration parameters |---------------|-----------------------|-----------------------|-----------------------| | `ssrc` | `0xDEADBEEF` | Randomly generated | 32-bit synchronization source identifier | | `mode` | `direct` | none | Instance session management mode (`direct` or `apple`) | +| `peer` | `10.1.2.3 9001` | none | MIDI session peer, may be specified multiple times. Bypasses session discovery protocols | `direct` mode instance configuration parameters @@ -41,7 +42,6 @@ Common instance configuration parameters |---------------|-----------------------|-----------------------|-----------------------| | `bind` | `10.1.2.1 9001` | `:: ` | Local network address to bind to | | `learn` | `true` | `false` | Accept new peers for data exchange at runtime | -| `peer` | `10.1.2.3 9001` | none | MIDI session peer, may be specified multiple times | `apple` mode instance configuration parameters @@ -49,8 +49,8 @@ Common instance configuration parameters |---------------|-----------------------|-----------------------|-----------------------| | `bind` | `10.1.2.1 9001` | `:: ` | Local network address to bind to (note that AppleMIDI requires two consecutive port numbers to be allocated) | | `session` | `Just Jamming` | `MIDIMonster` | Session name to announce via mDNS | -| `invite` | `pad,piano` | none | Devices to send invitations to when discovered (the special value `*` invites all discovered peers). Setting this option makes the instance a session initiator | -| `join` | `Just Jamming` | none | Sessions for which to accept invitations (the special value `*` accepts all invitations). Setting this option makes the instance a session participant | +| `invite` | `pad` | none | Devices to send invitations to when discovered (the special value `*` invites all discovered peers). Setting this option makes the instance a session initiator. May be specified multiple times | +| `join` | `Just Jamming` | none | Session for which to accept invitations (the special value `*` accepts all invitations). Setting this option makes the instance a session participant | | `peer` | `10.1.2.3 9001` | none | Configure a direct session peer, bypassing AppleMIDI discovery. May be specified multiple times | Note that AppleMIDI session discovery requires mDNS functionality, thus the `mdns-name` global parameter -- cgit v1.2.3