void MidiAlsaDevice::close() { snd_seq_port_subscribe_t* subs; // Allocated on stack, no need to call snd_seq_port_subscribe_free() later. snd_seq_port_subscribe_alloca(&subs); // Changed by T356. This function appears to be called only by MidiPort::setMidiDevice(), // which closes then opens the device. // Because the open flags are set BEFORE setMidiDevice() is called, we must ignore the flags. // // NOTE: Tested: The read unsubscribe works ok but not the write. // As viewed in say, qjackctl, the connection is clearly lost, // but strangely the events are still accepted, ie, playback notes // are still heard etc. Tried an alsa midi device AND external fluidsynth inst. // // Also, jack running and with jack midi disabled, we get messages like // MidiAlsaDevice::0x84512c0 putEvent(): midi write error: No such device // dst 16:0 // only sometimes (not when playing notes), but with jack midi turned on, // we don't get the messages. With jack stopped we get the messages // no matter if jack midi is turned on or not. //if (_openFlags & 1) { //if (!(_openFlags & 1)) { snd_seq_port_subscribe_set_sender(subs, &losPort); snd_seq_port_subscribe_set_dest(subs, &adr); // Already subscribed? Then unsubscribe. if (!snd_seq_get_port_subscription(alsaSeq, subs)) { if (!snd_seq_unsubscribe_port(alsaSeq, subs)) _writeEnable = false; else printf("MidiAlsaDevice::close Error unsubscribing alsa midi port for writing\n"); } else _writeEnable = false; } //if (_openFlags & 2) { //if (!(_openFlags & 2)) { snd_seq_port_subscribe_set_dest(subs, &losPort); snd_seq_port_subscribe_set_sender(subs, &adr); // Already subscribed? Then unsubscribe. if (!snd_seq_get_port_subscription(alsaSeq, subs)) { if (!snd_seq_unsubscribe_port(alsaSeq, subs)) _readEnable = false; else printf("MidiAlsaDevice::close Error unsubscribing alsa midi port for reading\n"); } else _readEnable = false; } }
QString MidiAlsaDevice::open() { _openFlags &= _rwFlags; // restrict to available bits snd_seq_port_subscribe_t* subs; // Allocated on stack, no need to call snd_seq_port_subscribe_free() later. snd_seq_port_subscribe_alloca(&subs); QString estr; int wer = 0; int rer = 0; // subscribe for writing if (_openFlags & 1) { snd_seq_port_subscribe_set_sender(subs, &losPort); snd_seq_port_subscribe_set_dest(subs, &adr); // Not already subscribed (or error)? Then try subscribing. if (snd_seq_get_port_subscription(alsaSeq, subs) < 0) { wer = snd_seq_subscribe_port(alsaSeq, subs); if (wer < 0) estr += (QString("Play: ") + QString(snd_strerror(wer)) + QString(" ")); } if (!wer) _writeEnable = true; } // subscribe for reading if (_openFlags & 2) { snd_seq_port_subscribe_set_dest(subs, &losPort); snd_seq_port_subscribe_set_sender(subs, &adr); // Not already subscribed (or error)? Then try subscribing. if (snd_seq_get_port_subscription(alsaSeq, subs) < 0) { //int error = snd_seq_subscribe_port(alsaSeq, subs); rer = snd_seq_subscribe_port(alsaSeq, subs); if (rer < 0) estr += (QString("Rec: ") + QString(snd_strerror(rer))); } if (!rer) _readEnable = true; } if (wer < 0 || rer < 0) return estr; return QString("OK"); }
/* Set up ALSA MIDI subscription according to supplied parameter. */ static int subscribe(snd_seq_port_subscribe_t *sub) { if (snd_seq_get_port_subscription(seq, sub) == 0) { dprintf("Connection between editor and device already established\n"); return 0; } if (snd_seq_subscribe_port(seq, sub) < 0) { dprintf("Couldn't estabilsh connection between editor and device\n"); return -1; } return 0; }
int main(int argc, char **argv) { int c; snd_seq_t *seq; int queue = 0, convert_time = 0, convert_real = 0, exclusive = 0; int command = SUBSCRIBE; int list_perm = 0; int client; int list_subs = 0; snd_seq_port_subscribe_t *subs; snd_seq_addr_t sender, dest; #ifdef ENABLE_NLS setlocale(LC_ALL, ""); textdomain(PACKAGE); #endif while ((c = getopt_long(argc, argv, "dior:t:elx", long_option, NULL)) != -1) { switch (c) { case 'd': command = UNSUBSCRIBE; break; case 'i': command = LIST; list_perm |= LIST_INPUT; break; case 'o': command = LIST; list_perm |= LIST_OUTPUT; break; case 'e': exclusive = 1; break; case 'r': queue = atoi(optarg); convert_time = 1; convert_real = 1; break; case 't': queue = atoi(optarg); convert_time = 1; convert_real = 0; break; case 'l': list_subs = 1; break; case 'x': command = REMOVE_ALL; break; default: usage(); exit(1); } } if (snd_seq_open(&seq, "default", SND_SEQ_OPEN_DUPLEX, 0) < 0) { fprintf(stderr, _("can't open sequencer\n")); return 1; } snd_lib_error_set_handler(error_handler); switch (command) { case LIST: do_search_port(seq, list_perm, list_subs ? print_port_and_subs : print_port); snd_seq_close(seq); return 0; case REMOVE_ALL: remove_all_connections(seq); snd_seq_close(seq); return 0; } /* connection or disconnection */ if (optind + 2 > argc) { snd_seq_close(seq); usage(); exit(1); } if ((client = snd_seq_client_id(seq)) < 0) { snd_seq_close(seq); fprintf(stderr, _("can't get client id\n")); return 1; } /* set client info */ if (snd_seq_set_client_name(seq, "ALSA Connector") < 0) { snd_seq_close(seq); fprintf(stderr, _("can't set client info\n")); return 1; } /* set subscription */ if (snd_seq_parse_address(seq, &sender, argv[optind]) < 0) { snd_seq_close(seq); fprintf(stderr, _("invalid sender address %s\n"), argv[optind]); return 1; } if (snd_seq_parse_address(seq, &dest, argv[optind + 1]) < 0) { snd_seq_close(seq); fprintf(stderr, _("invalid destination address %s\n"), argv[optind + 1]); return 1; } snd_seq_port_subscribe_alloca(&subs); snd_seq_port_subscribe_set_sender(subs, &sender); snd_seq_port_subscribe_set_dest(subs, &dest); snd_seq_port_subscribe_set_queue(subs, queue); snd_seq_port_subscribe_set_exclusive(subs, exclusive); snd_seq_port_subscribe_set_time_update(subs, convert_time); snd_seq_port_subscribe_set_time_real(subs, convert_real); if (command == UNSUBSCRIBE) { if (snd_seq_get_port_subscription(seq, subs) < 0) { snd_seq_close(seq); fprintf(stderr, _("No subscription is found\n")); return 1; } if (snd_seq_unsubscribe_port(seq, subs) < 0) { snd_seq_close(seq); fprintf(stderr, _("Disconnection failed (%s)\n"), snd_strerror(errno)); return 1; } } else { if (snd_seq_get_port_subscription(seq, subs) == 0) { snd_seq_close(seq); fprintf(stderr, _("Connection is already subscribed\n")); return 1; } if (snd_seq_subscribe_port(seq, subs) < 0) { snd_seq_close(seq); fprintf(stderr, _("Connection failed (%s)\n"), snd_strerror(errno)); return 1; } } snd_seq_close(seq); return 0; }