📄 alsaseq_c.c
字号:
break; case -1: // error status return exit(7); default: // no error, doing well if ((pidf = fopen( "/var/run/timidity.pid", "w" )) != NULL ) fprintf( pidf, "%d\n", pid ); exit(0); } } for (;;) { server_reset(); doit(&alsactx); }}/* * get the current time in usec from gettimeofday() */static long get_current_time(void){ struct timeval tv; long t; gettimeofday(&tv, NULL); t = tv.tv_sec * 1000000L + tv.tv_usec; return t - start_time_base;} /* * convert from snd_seq_real_time_t to sample count */inline static long queue_time_to_position(const snd_seq_real_time_t *t){ return (long)t->tv_sec * play_mode->rate + (long)(t->tv_nsec * rate_frac_nsec);}/* * get the current queue position in sample count */static long get_current_queue_position(struct seq_context *ctxp){#if HAVE_SND_SEQ_PORT_INFO_SET_TIMESTAMPING snd_seq_get_queue_status(ctxp->handle, ctxp->queue, ctxp->q_status); return queue_time_to_position(snd_seq_queue_status_get_real_time(ctxp->q_status));#else return 0;#endif}/* * update the current position from the event timestamp */static void update_timestamp_from_event(snd_seq_event_t *ev){ long t = queue_time_to_position(&ev->time.time) - last_queue_offset; if (t < 0) { // fprintf(stderr, "timestamp underflow! (delta=%d)\n", (int)t); t = 0; } else if (buffer_time_advance > 0 && t >= buffer_time_advance) { // fprintf(stderr, "timestamp overflow! (delta=%d)\n", (int)t); t = buffer_time_advance - 1; } t += buffer_time_offset; if (t >= cur_time_offset) cur_time_offset = t;}/* * update the current position from system time */static void update_timestamp(void){ cur_time_offset = (long)(get_current_time() * rate_frac);}static void seq_play_event(MidiEvent *ev){ //JAVE make channel -Q channels quiet, modified some code from readmidi.c int gch; gch = GLOBAL_CHANNEL_EVENT_TYPE(ev->type); if (gch || !IS_SET_CHANNELMASK(quietchannels, ev->channel)){ //if its a global event or not a masked event ev->time = cur_time_offset; play_event(ev); }}static void stop_playing(void){ if(upper_voices) { MidiEvent ev; ev.type = ME_EOT; ev.a = 0; ev.b = 0; seq_play_event(&ev); aq_flush(0); }}static void doit(struct seq_context *ctxp){ for (;;) { while (snd_seq_event_input_pending(ctxp->handle, 1)) { if (do_sequencer(ctxp)) goto __done; } if (ctxp->active) { MidiEvent ev; if (IS_STREAM_TRACE) { /* remember the last update position */ if (ctxp->queue >= 0) last_queue_offset = get_current_queue_position(ctxp); /* advance the buffer position */ buffer_time_offset += buffer_time_advance; ev.time = buffer_time_offset; } else { /* update the current position */ if (ctxp->queue >= 0) cur_time_offset = get_current_queue_position(ctxp); else update_timestamp(); ev.time = cur_time_offset; } ev.type = ME_NONE; play_event(&ev); aq_fill_nonblocking(); } if (! ctxp->active || ! IS_STREAM_TRACE) { fd_set rfds; struct timeval timeout; FD_ZERO(&rfds); FD_SET(ctxp->fd, &rfds); timeout.tv_sec = 0; timeout.tv_usec = 10000; /* 10ms */ if (select(ctxp->fd + 1, &rfds, NULL, NULL, &timeout) < 0) goto __done; } }__done: if (ctxp->active) { stop_sequencer(ctxp); }}static void server_reset(void){ readmidi_read_init(); playmidi_stream_init(); if (free_instruments_afterwards) free_instruments(0); reduce_voice_threshold = 0; /* Disable auto reduction voice */ buffer_time_offset = 0;}static int start_sequencer(struct seq_context *ctxp){ if (play_mode->open_output() < 0) { ctl.cmsg(CMSG_FATAL, VERB_NORMAL, "Couldn't open %s (`%c')", play_mode->id_name, play_mode->id_character); return 0; } ctxp->active = 1; buffer_time_offset = 0; last_queue_offset = 0; cur_time_offset = 0; if (ctxp->queue >= 0) { if (snd_seq_start_queue(ctxp->handle, ctxp->queue, NULL) < 0) ctxp->queue = -1; else snd_seq_drain_output(ctxp->handle); } if (ctxp->queue < 0) { start_time_base = 0; start_time_base = get_current_time(); } return 1;}static void stop_sequencer(struct seq_context *ctxp){ stop_playing(); if (ctxp->queue >= 0) { snd_seq_stop_queue(ctxp->handle, ctxp->queue, NULL); snd_seq_drain_output(ctxp->handle); } play_mode->close_output(); free_instruments(0); free_global_mblock(); ctxp->used = 0; ctxp->active = 0;}#define NOTE_CHAN(ev) ((ev)->dest.port * 16 + (ev)->data.note.channel)#define CTRL_CHAN(ev) ((ev)->dest.port * 16 + (ev)->data.control.channel)static int do_sequencer(struct seq_context *ctxp){ int n, ne, i; MidiEvent ev, evm[260]; snd_seq_event_t *aevp; n = snd_seq_event_input(ctxp->handle, &aevp); if (n < 0 || aevp == NULL) return 0; if (ctxp->active && ctxp->queue >= 0) update_timestamp_from_event(aevp); else if (IS_STREAM_TRACE) cur_time_offset = buffer_time_offset; else update_timestamp(); switch(aevp->type) { case SND_SEQ_EVENT_NOTEON: ev.channel = NOTE_CHAN(aevp); ev.a = aevp->data.note.note; ev.b = aevp->data.note.velocity; if (ev.b == 0) ev.type = ME_NOTEOFF; else ev.type = ME_NOTEON; seq_play_event(&ev); break; case SND_SEQ_EVENT_NOTEOFF: ev.channel = NOTE_CHAN(aevp); ev.a = aevp->data.note.note; ev.b = aevp->data.note.velocity; ev.type = ME_NOTEOFF; seq_play_event(&ev); break; case SND_SEQ_EVENT_KEYPRESS: ev.channel = NOTE_CHAN(aevp); ev.a = aevp->data.note.note; ev.b = aevp->data.note.velocity; ev.type = ME_KEYPRESSURE; seq_play_event(&ev); break; case SND_SEQ_EVENT_PGMCHANGE: ev.channel = CTRL_CHAN(aevp); ev.a = aevp->data.control.value; ev.type = ME_PROGRAM; seq_play_event(&ev); break; case SND_SEQ_EVENT_CONTROLLER: if(convert_midi_control_change(CTRL_CHAN(aevp), aevp->data.control.param, aevp->data.control.value, &ev)) seq_play_event(&ev); break; case SND_SEQ_EVENT_CONTROL14: if (aevp->data.control.param < 0 || aevp->data.control.param >= 32) break; if (! convert_midi_control_change(CTRL_CHAN(aevp), aevp->data.control.param, (aevp->data.control.value >> 7) & 0x7f, &ev)) break; seq_play_event(&ev); if (! convert_midi_control_change(CTRL_CHAN(aevp), aevp->data.control.param + 32, aevp->data.control.value & 0x7f, &ev)) break; seq_play_event(&ev); break; case SND_SEQ_EVENT_PITCHBEND: ev.type = ME_PITCHWHEEL; ev.channel = CTRL_CHAN(aevp); aevp->data.control.value += 0x2000; ev.a = (aevp->data.control.value) & 0x7f; ev.b = (aevp->data.control.value>>7) & 0x7f; seq_play_event(&ev); break; case SND_SEQ_EVENT_CHANPRESS: ev.type = ME_CHANNEL_PRESSURE; ev.channel = CTRL_CHAN(aevp); ev.a = aevp->data.control.value; seq_play_event(&ev); break; case SND_SEQ_EVENT_NONREGPARAM: /* Break it back into its controler values */ ev.type = ME_NRPN_MSB; ev.channel = CTRL_CHAN(aevp); ev.a = (aevp->data.control.param >> 7) & 0x7f; seq_play_event(&ev); ev.type = ME_NRPN_LSB; ev.channel = CTRL_CHAN(aevp); ev.a = aevp->data.control.param & 0x7f; seq_play_event(&ev); ev.type = ME_DATA_ENTRY_MSB; ev.channel = CTRL_CHAN(aevp); ev.a = (aevp->data.control.value >> 7) & 0x7f; seq_play_event(&ev); ev.type = ME_DATA_ENTRY_LSB; ev.channel = CTRL_CHAN(aevp); ev.a = aevp->data.control.value & 0x7f; seq_play_event(&ev); break; case SND_SEQ_EVENT_REGPARAM: /* Break it back into its controler values */ ev.type = ME_RPN_MSB; ev.channel = CTRL_CHAN(aevp); ev.a = (aevp->data.control.param >> 7) & 0x7f; seq_play_event(&ev); ev.type = ME_RPN_LSB; ev.channel = CTRL_CHAN(aevp); ev.a = aevp->data.control.param & 0x7f; seq_play_event(&ev); ev.type = ME_DATA_ENTRY_MSB; ev.channel = CTRL_CHAN(aevp); ev.a = (aevp->data.control.value >> 7) & 0x7f; seq_play_event(&ev); ev.type = ME_DATA_ENTRY_LSB; ev.channel = CTRL_CHAN(aevp); ev.a = aevp->data.control.value & 0x7f; seq_play_event(&ev); break; case SND_SEQ_EVENT_SYSEX: if (parse_sysex_event(aevp->data.ext.ptr + 1, aevp->data.ext.len - 1, &ev)) seq_play_event(&ev); if ((ne = parse_sysex_event_multi(aevp->data.ext.ptr + 1, aevp->data.ext.len - 1, evm)) > 0) for (i = 0; i < ne; i++) seq_play_event(&evm[i]); break;#if SND_LIB_MAJOR > 0 || SND_LIB_MINOR >= 6#define snd_seq_addr_equal(a,b) ((a)->client == (b)->client && (a)->port == (b)->port) case SND_SEQ_EVENT_PORT_SUBSCRIBED: if (snd_seq_addr_equal(&aevp->data.connect.dest, &aevp->dest)) { if (! ctxp->active) { if (! start_sequencer(ctxp)) { snd_seq_free_event(aevp); return 0; } } ctxp->used++; } break; case SND_SEQ_EVENT_PORT_UNSUBSCRIBED: if (snd_seq_addr_equal(&aevp->data.connect.dest, &aevp->dest)) { if (ctxp->active) { ctxp->used--; if (ctxp->used <= 0) { snd_seq_free_event(aevp); return 1; /* quit now */ } } } break;#else case SND_SEQ_EVENT_PORT_USED: if (! ctxp->active) { if (! start_sequencer(ctxp)) { snd_seq_free_event(aevp); return 0; } } ctxp->used++; break; case SND_SEQ_EVENT_PORT_UNUSED: if (ctxp->active) { ctxp->used--; if (ctxp->used <= 0) { snd_seq_free_event(aevp); return 1; /* quit now */ } } break;#endif default: /*printf("Unsupported event %d\n", aevp->type);*/ break; } snd_seq_free_event(aevp); return 0;}/* * interface_<id>_loader(); */ControlMode *interface_A_loader(void){ return &ctl;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -