void midi_engine_stop(void) { struct midi_provider *n, *p; struct midi_port *q; if (!_connected) return; if (!midi_mutex) return; SDL_mutexP(midi_mutex); for (n = port_providers; n;) { p = n->next; q = NULL; while (midi_port_foreach(p, &q)) { midi_port_unregister(q->num); } if (n->thread) { SDL_KillThread(n->thread); } free(n->name); free(n); n = p; } _connected = 0; SDL_mutexV(midi_mutex); }
void midi_send_flush(void) { struct midi_port *ptr = NULL; int need_explicit_flush = 0; if (!midi_record_mutex || !midi_play_mutex) return; while (midi_port_foreach(NULL, &ptr)) { if ((ptr->io & MIDI_OUTPUT)) { if (ptr->drain) ptr->drain(ptr); else if (ptr->send_now) need_explicit_flush=1; } } /* no need for midi sync huzzah; driver does it for us... */ if (!need_explicit_flush) return; if (!midi_queue_thread) { midi_queue_thread = SDL_CreateThread(_midi_queue_run, NULL); if (midi_queue_thread) { log_appendf(3, "Started MIDI queue thread"); } else { log_appendf(2, "ACK: Couldn't start MIDI thread; things are likely going to go boom!"); } } SDL_mutexP(midi_play_mutex); SDL_CondSignal(midi_play_cond); SDL_mutexV(midi_play_mutex); }
static int _midi_send_unlocked(const unsigned char *data, unsigned int len, unsigned int delay, int from) { struct midi_port *ptr = NULL; int need_timer = 0; #if 0 unsigned int i; printf("MIDI: "); for (i = 0; i < len; i++) { printf("%02x ", data[i]); } puts(""); fflush(stdout); #endif if (from == 0) { /* from == 0 means from immediate; everyone plays */ while (midi_port_foreach(NULL, &ptr)) { if ((ptr->io & MIDI_OUTPUT)) { if (ptr->send_now) ptr->send_now(ptr, data, len, 0); else if (ptr->send_later) ptr->send_later(ptr, data, len, 0); } } } else if (from == 1) { /* from == 1 means from buffer-flush; only "now" plays */ while (midi_port_foreach(NULL, &ptr)) { if ((ptr->io & MIDI_OUTPUT)) { if (ptr->send_now) ptr->send_now(ptr, data, len, 0); } } } else { /* from == 2 means from buffer-write; only "later" plays */ while (midi_port_foreach(NULL, &ptr)) { if ((ptr->io & MIDI_OUTPUT)) { if (ptr->send_later) ptr->send_later(ptr, data, len, delay); else if (ptr->send_now) need_timer = 1; } } } return need_timer; }
static void _readin(struct midi_provider *p, int en, int fd) { struct midi_port *ptr, *src; static unsigned char buffer[65536]; static struct sockaddr_in asin; unsigned slen = sizeof(asin); int r; r = recvfrom(fd, buffer, sizeof(buffer), 0, (struct sockaddr *)&asin, &slen); if (r > 0) { ptr = src = NULL; while (midi_port_foreach(p, &ptr)) { int n = INT_SHAPED_PTR(ptr->userdata); if (n == en) src = ptr; } midi_received_cb(src, buffer, r); } }
static void _ip_poll(struct midi_provider *p) { static int last_buildout = 0; struct midi_port *ptr; char *buffer; long i = 0; long m; SDL_mutexP(blocker); m = (volatile int)real_num_ports; if (m < last_buildout) { ptr = NULL; while (midi_port_foreach(p, &ptr)) { i = INT_SHAPED_PTR(ptr->userdata); if (i >= m) { midi_port_unregister(ptr->num); //port_top[i] (the address where ptr points to) is freed in midi_port_unregister. //So clear it to avoid midi_port_foreach crashing on next round ptr = NULL; } } last_buildout = m; } else if (m > last_buildout) { for (i = last_buildout; i < m; i++) { buffer = NULL; if (asprintf(&buffer, " Multicast/IP MIDI %lu", i+1) == -1) { perror("asprintf"); exit(255); } if (!buffer) { perror("asprintf"); exit(255); } midi_port_register(p, MIDI_INPUT | MIDI_OUTPUT, buffer, PTR_SHAPED_INT((intptr_t)i), 0); } last_buildout = m; } SDL_mutexV(blocker); }
int midi_need_flush(void) { struct midi_port *ptr; int need_explicit_flush = 0; int i; if (!midi_record_mutex || !midi_play_mutex) return 0; ptr = NULL; while (midi_port_foreach(NULL, &ptr)) { if ((ptr->io & MIDI_OUTPUT)) { if (!ptr->drain && ptr->send_now) need_explicit_flush = 1; } } if (!need_explicit_flush) return 0; for (i = 0; i < qlen; i++) { if (qq[i].used) return 1; } return 0; }
void cfg_save_midi(cfg_file_t *cfg) { struct cfg_section *c; struct midi_provider *p; struct midi_port *q; midi_config_t *md, *mc; char buf[33]; char *ss; int i, j; CFG_SET_MI(flags); CFG_SET_MI(pitch_depth); CFG_SET_MI(amplification); CFG_SET_MI(c5note); song_lock_audio(); md = &default_midi_config; /* overwrite default */ mc = ¤t_song->midi_config; memcpy(md, mc, sizeof(midi_config_t)); cfg_set_string(cfg,"MIDI","start", md->start); cfg_set_string(cfg,"MIDI","stop", md->stop); cfg_set_string(cfg,"MIDI","tick", md->tick); cfg_set_string(cfg,"MIDI","note_on", md->note_on); cfg_set_string(cfg,"MIDI","note_off", md->note_off); cfg_set_string(cfg,"MIDI","set_volume", md->set_volume); cfg_set_string(cfg,"MIDI","set_panning", md->set_panning); cfg_set_string(cfg,"MIDI","set_bank", md->set_bank); cfg_set_string(cfg,"MIDI","set_program", md->set_program); for (i = 0; i < 16; i++) { snprintf(buf, 32, "SF%X", i); cfg_set_string(cfg, "MIDI", buf, md->sfx[i]); } for (i = 0; i < 128; i++) { snprintf(buf, 32, "Z%02X", i + 0x80); cfg_set_string(cfg, "MIDI", buf, md->zxx[i]); } song_unlock_audio(); /* write out only enabled midi ports */ i = 1; SDL_mutexP(midi_mutex); q = NULL; for (p = port_providers; p; p = p->next) { while (midi_port_foreach(p, &q)) { ss = q->name; if (!ss) continue; while (isspace(*ss)) ss++; if (!*ss) continue; if (!q->io) continue; snprintf(buf, 32, "MIDI Port %d", i); i++; cfg_set_string(cfg, buf, "name", ss); ss = p->name; if (ss) { while (isspace(*ss)) ss++; if (*ss) { cfg_set_string(cfg, buf, "provider", ss); } } cfg_set_number(cfg, buf, "input", q->io & MIDI_INPUT ? 1 : 0); cfg_set_number(cfg, buf, "output", q->io & MIDI_OUTPUT ? 1 : 0); } } //TODO: Save number of MIDI-IP ports SDL_mutexV(midi_mutex); /* delete other MIDI port sections */ for (c = cfg->sections; c; c = c->next) { j = -1; sscanf(c->name, "MIDI Port %d", &j); if (j < i) continue; c->omit = 1; } }