void JVlibForm::init_seq() { if (seq) return; int err = snd_seq_open(&seq, "default", SND_SEQ_OPEN_OUTPUT, 0); check_snd("open sequencer", err); err = snd_seq_set_client_name(seq, "midi_player"); check_snd("set client name", err); int client = snd_seq_client_id(seq); // client # is 128 by default check_snd("get client id", client); }
static void init_seq(void) { int err; /* open sequencer */ err = snd_seq_open(&seq, "default", SND_SEQ_OPEN_DUPLEX, 0); check_snd("open sequencer", err); /* set our client's name */ err = snd_seq_set_client_name(seq, "aseqdump"); check_snd("set client name", err); }
// SLOTS void JVlibForm::on_System_OpenMidi_button_clicked() { disconnect_port(); // close_seq(); System_PlayMidi_button->setChecked(false); System_PlayMidi_button->setEnabled(false); System_PauseMidi_button->setEnabled(false); SysFilePlaying->clear(); System_MIDI_Transpose->setValue(0); System_MIDI_KeySig->clear(); MIDI_length_display->setText("00:00"); QString fn = QFileDialog::getOpenFileName(this,"Open MIDI File",MIDI_dir,"Midi files (*.mid, *.MID);;Any (*.*)"); if (fn.isEmpty()) return; strcpy(playfile, fn.toAscii().data()); SysFilePlaying->setText(fn); init_seq(); if (!queue) queue = snd_seq_alloc_named_queue(seq, "midi_play"); check_snd("create queue", queue); connect_port(); all_events.clear(); if (!parseFile(playfile)) { QMessageBox::critical(this, "MIDI Player", QString("Error parsing input file")); return; } // parseFile System_MIDI_progressBar->setRange(0,all_events.back().tick); System_MIDI_progressBar->setTickInterval(song_length_seconds<240? all_events.back().tick/song_length_seconds*10 : all_events.back().tick/song_length_seconds*30); System_MIDI_progressBar->setTickPosition(QSlider::TicksAbove); MIDI_length_display->setText(QString::number(static_cast<int>(song_length_seconds/60)).rightJustified(2,'0') + ":" + QString::number(static_cast<int>(song_length_seconds)%60).rightJustified(2,'0')); System_PlayMidi_button->setEnabled(true); System_MIDI_Transpose->setEnabled(true); } // end on_System_OpenMidi_button_clicked
void JVlibForm::connect_port() { if (seq && strlen(SEQ_dev)) { // create_source_port snd_seq_port_info_t *pinfo; snd_seq_port_info_alloca(&pinfo); // the first created port is 0 anyway, but let's make sure ... snd_seq_port_info_set_port(pinfo, 0); snd_seq_port_info_set_port_specified(pinfo, 1); snd_seq_port_info_set_name(pinfo, "midi_player"); snd_seq_port_info_set_capability(pinfo, 0); snd_seq_port_info_set_type(pinfo, SND_SEQ_PORT_TYPE_MIDI_GENERIC | SND_SEQ_PORT_TYPE_APPLICATION); int err = snd_seq_create_port(seq, pinfo); check_snd("create port", err); ports = (snd_seq_addr_t *)realloc(ports, sizeof(snd_seq_addr_t)); err = snd_seq_parse_address(seq, &ports[0], SEQ_dev); if (err < 0) { QMessageBox::critical(this, "MIDI Player", QString("Invalid port%1\n%2") .arg(SEQ_dev) .arg(snd_strerror(err))); return; } err = snd_seq_connect_to(seq, 0, ports[0].client, ports[0].port); if (err < 0 && err!= -16) QMessageBox::critical(this, "MIDI Player", QString("%4 Cannot connect to port %1:%2 - %3") .arg(ports[0].client) .arg(ports[0].port) .arg(strerror(errno)) .arg(err)); } } // end connect_port
static int init_seq(ClientData clientData, Tcl_Interp *interp) { if (seq == NULL) { int err; /* open sequencer */ err = snd_seq_open(&seq, "default", SND_SEQ_OPEN_DUPLEX, 0); if (check_snd(clientData, interp, "open sequencer", err) < 0) { return TCL_ERROR; } /* set our client's name */ err = snd_seq_set_client_name(seq, "awtcl"); if (check_snd(clientData, interp, "set client name", err) != TCL_OK) { return TCL_ERROR; } } return TCL_OK; }
static void create_port(void) { int err; err = snd_seq_create_simple_port(seq, "aseqdump", SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE, SND_SEQ_PORT_TYPE_MIDI_GENERIC | SND_SEQ_PORT_TYPE_APPLICATION); check_snd("create port", err); }
void JVlibForm::on_System_PlayMidi_button_toggled(bool checked) { if (checked) { seqTimer = new QTimer(this); System_PauseMidi_button->setEnabled(true); System_OpenMidi_button->setEnabled(false); System_PlayMidi_button->setText("Stop"); System_MIDI_progressBar->setEnabled(true); connect_port(); // queue won't actually start until it is drained int err = snd_seq_start_queue(seq, queue, NULL); check_snd("start queue", err); System_PlayMidi_status->on(); connect(JVlibForm::seqTimer, SIGNAL(timeout()), this, SLOT(tickDisplay())); seqTimer->start(100); startPlayer(0); } else { if (seqTimer->isActive()) { disconnect(JVlibForm::seqTimer, SIGNAL(timeout()), this, SLOT(tickDisplay())); seqTimer->stop(); delete seqTimer; } snd_seq_stop_queue(seq,queue,NULL); snd_seq_drain_output(seq); stopPlayer(); stop_sound(); disconnect_port(); System_PlayMidi_status->off(); System_MIDI_progressBar->blockSignals(true); System_MIDI_progressBar->setValue(0); System_MIDI_progressBar->blockSignals(false); MIDI_time_display->setText("00:00"); if (System_PauseMidi_button->isChecked()) { System_PauseMidi_button->blockSignals(true); System_PauseMidi_button->setChecked(false); System_PauseMidi_button->blockSignals(false); System_PauseMidi_button->setText("Pause"); } System_PauseMidi_button->setEnabled(false); System_PlayMidi_button->setText("Play"); System_OpenMidi_button->setEnabled(true); System_MIDI_Transpose->setEnabled(true); System_MIDI_progressBar->setEnabled(false); event_num=0; } } // end on_System_PlayMidi_button_toggled
int main(int argc, char *argv[]) { static const char short_options[] = "hVlp:"; static const struct option long_options[] = { {"help", 0, NULL, 'h'}, {"version", 0, NULL, 'V'}, {"list", 0, NULL, 'l'}, {"port", 1, NULL, 'p'}, { } }; int do_list = 0; struct pollfd *pfds; int npfds; int c, err; init_seq(); while ((c = getopt_long(argc, argv, short_options, long_options, NULL)) != -1) { switch (c) { case 'h': help(argv[0]); return 0; case 'V': version(); return 0; case 'l': do_list = 1; break; case 'p': parse_ports(optarg); break; default: help(argv[0]); return 1; } } if (optind < argc) { help(argv[0]); return 1; } if (do_list) { list_ports(); return 0; } create_port(); connect_ports(); err = snd_seq_nonblock(seq, 1); check_snd("set nonblock mode", err); if (port_count > 0) printf("Waiting for data."); else printf("Waiting for data at port %d:0.", snd_seq_client_id(seq)); printf(" Press Ctrl+C to end.\n"); printf("Source Event Ch Data\n"); signal(SIGINT, sighandler); signal(SIGTERM, sighandler); npfds = snd_seq_poll_descriptors_count(seq, POLLIN); pfds = alloca(sizeof(*pfds) * npfds); for (;;) { snd_seq_poll_descriptors(seq, pfds, npfds, POLLIN); if (poll(pfds, npfds, -1) < 0) break; do { snd_seq_event_t *event; err = snd_seq_event_input(seq, &event); if (err < 0) break; if (event) dump_event(event); } while (err > 0); fflush(stdout); if (stop) break; } snd_seq_close(seq); return 0; }
void MIDI_PLAYER::play_midi(unsigned int startTick) { int end_delay = 2; int err; // set data in (snd_seq_event_t ev) and output the event // common settings for all events snd_seq_event_t ev; snd_seq_ev_clear(&ev); ev.queue = queue; ev.source.port = 0; ev.flags = SND_SEQ_TIME_STAMP_TICK; // parse each event, already in sort order by 'tick' from parse_file for (std::vector<event>::iterator Event=all_events.begin(); Event!=all_events.end(); ++Event) { // skip over everything except TEMPO, CONTROLLER, PROGRAM, ChannelPressure and SysEx changes until startTick is reached. if (Event->tick<startTick && (Event->type!=SND_SEQ_EVENT_TEMPO || Event->type!=SND_SEQ_EVENT_CONTROLLER || Event->type!=SND_SEQ_EVENT_PGMCHANGE || Event->type!=SND_SEQ_EVENT_CHANPRESS || Event->type!=SND_SEQ_EVENT_SYSEX)) { continue; } ev.time.tick = Event->tick; ev.type = Event->type; // ev.dest = ports[Event->port]; ev.dest = ports[0]; switch (ev.type) { case SND_SEQ_EVENT_NOTEON: case SND_SEQ_EVENT_NOTEOFF: case SND_SEQ_EVENT_KEYPRESS: snd_seq_ev_set_fixed(&ev); ev.data.note.channel = Event->data.d[0]; ev.data.note.note = Event->data.d[1]; ev.data.note.velocity = Event->data.d[2]; break; case SND_SEQ_EVENT_CONTROLLER: snd_seq_ev_set_fixed(&ev); ev.data.control.channel = Event->data.d[0]; ev.data.control.param = Event->data.d[1]; ev.data.control.value = Event->data.d[2]; break; case SND_SEQ_EVENT_PGMCHANGE: case SND_SEQ_EVENT_CHANPRESS: snd_seq_ev_set_fixed(&ev); ev.data.control.channel = Event->data.d[0]; ev.data.control.value = Event->data.d[1]; break; case SND_SEQ_EVENT_PITCHBEND: snd_seq_ev_set_fixed(&ev); ev.data.control.channel = Event->data.d[0]; ev.data.control.value = ((Event->data.d[1]) | ((Event->data.d[2]) << 7)) - 0x2000; break; case SND_SEQ_EVENT_SYSEX: snd_seq_ev_set_variable(&ev, Event->data.length, &Event->sysex); break; case SND_SEQ_EVENT_TEMPO: snd_seq_ev_set_fixed(&ev); ev.dest.client = SND_SEQ_CLIENT_SYSTEM; ev.dest.port = SND_SEQ_PORT_SYSTEM_TIMER; ev.data.queue.queue = queue; ev.data.queue.param.value = Event->data.tempo; break; default: QMessageBox::critical(this, "MIDI Player", QString("Invalid event type %1") .arg(ev.type)); } // end SWITCH ev.type // do the actual output of the event to the MIDI queue // this blocks when the output pool has been filled err = snd_seq_event_output(seq, &ev); check_snd("output event", err); } // end for all_events iterator // schedule queue stop at end of song snd_seq_ev_set_fixed(&ev); ev.type = SND_SEQ_EVENT_STOP; ev.time.tick = all_events.back().tick; ev.dest.client = SND_SEQ_CLIENT_SYSTEM; ev.dest.port = SND_SEQ_PORT_SYSTEM_TIMER; ev.data.queue.queue = queue; err = snd_seq_event_output(seq, &ev); check_snd("output event", err); // make sure that the sequencer sees all our events err = snd_seq_drain_output(seq); check_snd("drain output", err); // There are three possibilities for how to wait until all events have been played: // 1) send an event back to us (like pmidi does), and wait for it; // 2) wait for the EVENT_STOP notification for our queue which is sent // by the system timer port (this would require a subscription); // 3) wait until the output pool is empty. // The last is the simplest. err = snd_seq_sync_output_queue(seq); check_snd("sync output", err); // give the last notes time to die away if (end_delay > 0) sleep(end_delay); } // end play_midi