}
/**
+ * \brief Get the timer skew value of a queue_status container
+ * \param info queue_status container
+ * \return timer skew value
+ */
+unsigned int snd_seq_queue_tempo_get_skew(const snd_seq_queue_tempo_t *info)
+{
+ assert(info);
+ return info->skew_value;
+}
+
+/**
+ * \brief Get the timer skew base value of a queue_status container
+ * \param info queue_status container
+ * \return timer skew base value
+ */
+unsigned int snd_seq_queue_tempo_get_skew_base(const snd_seq_queue_tempo_t *info)
+{
+ assert(info);
+ return info->skew_base;
+}
+
+/**
* \brief Set the tempo of a queue_status container
* \param info queue_status container
* \param tempo tempo value
info->ppq = ppq;
}
+/**
+ * \brief Set the timer skew value of a queue_status container
+ * \param info queue_status container
+ * \param skew timer skew value
+ *
+ * The skew of timer is calculated as skew / base.
+ * For example, to play with double speed, pass base * 2 as the skew value.
+ */
+void snd_seq_queue_tempo_set_skew(snd_seq_queue_tempo_t *info, unsigned int skew)
+{
+ assert(info);
+ info->skew_value = skew;
+}
+
+/**
+ * \brief Set the timer skew base value of a queue_status container
+ * \param info queue_status container
+ * \param base timer skew base value
+ */
+void snd_seq_queue_tempo_set_skew_base(snd_seq_queue_tempo_t *info, unsigned int base)
+{
+ assert(info);
+ info->skew_base = base;
+}
/**
* \brief obtain the current tempo of the queue
static int local_tempo = 500000;
static int dest_queue = -1;
+static int shared_queue = 0;
+static int tick_offset = 0;
static int dest_client = DEST_CLIENT_NUMBER;
static int dest_port = DEST_PORT_NUMBER;
static int my_port = 0;
if (format != 0 || ntracks != 1) {
printf("This player does not support merging of tracks.\n");
- alsa_stop_timer();
+ if (! shared_queue)
+ alsa_stop_timer();
exit(1);
}
/* set ppq */
perror("get_queue_tempo");
exit(1);
}
- if (snd_seq_queue_tempo_get_ppq(tempo) != ppq) {
- slave_ppq = snd_seq_queue_tempo_get_ppq(tempo);
+ if ((slave_ppq = snd_seq_queue_tempo_get_ppq(tempo)) != ppq) {
snd_seq_queue_tempo_set_ppq(tempo, ppq);
if (snd_seq_set_queue_tempo(seq_handle, dest_queue, tempo) < 0) {
perror("set_queue_tempo");
- if (!slave)
+ if (!slave && !shared_queue)
exit(1);
else
printf("different PPQ %d in SMF from queue PPQ %d\n", ppq, slave_ppq);
wait_start();
if (verbose >= VERB_INFO)
printf("Go!\n");
- } else
+ } else if (shared_queue) {
+ snd_seq_queue_status_t *stat;
+ snd_seq_queue_status_alloca(&stat);
+ snd_seq_get_queue_status(seq_handle, dest_queue, stat);
+ tick_offset = snd_seq_queue_status_get_tick_time(stat);
+ fprintf(stderr, "tick offset = %d\n", tick_offset);
+ } else {
alsa_start_timer();
+ tick_offset = 0;
+ }
}
/* fill time */
} else {
if (ppq != slave_ppq)
currtime = (currtime * slave_ppq) / ppq;
+ currtime += tick_offset;
snd_seq_ev_schedule_tick(ev, dest_queue, 0, currtime);
}
}
snd_seq_event_t ev;
if (verbose >= VERB_EVENT)
- printf("NoteOn (%d) %d %d\n", chan, pitch, vol);
+ printf("%d: NoteOn (%d) %d %d\n", Mf_currtime, chan, pitch, vol);
set_event_header(&ev);
snd_seq_ev_set_noteon(&ev, chan, pitch, vol);
write_ev(&ev);
snd_seq_event_t ev;
if (verbose >= VERB_EVENT)
- printf("NoteOff (%d) %d %d\n", chan, pitch, vol);
+ printf("%d: NoteOff (%d) %d %d\n", Mf_currtime, chan, pitch, vol);
set_event_header(&ev);
snd_seq_ev_set_noteoff(&ev, chan, pitch, vol);
write_ev(&ev);
snd_seq_event_t ev;
if (verbose >= VERB_EVENT)
- printf("Program (%d) %d\n", chan, program);
+ printf("%d: Program (%d) %d\n", Mf_currtime, chan, program);
set_event_header(&ev);
snd_seq_ev_set_pgmchange(&ev, chan, program);
write_ev(&ev);
snd_seq_event_t ev;
if (verbose >= VERB_EVENT)
- printf("Control (%d) %d %d\n", chan, control, value);
+ printf("%d: Control (%d) %d %d\n", Mf_currtime, chan, control, value);
set_event_header(&ev);
snd_seq_ev_set_controller(&ev, chan, control, value);
write_ev(&ev);
snd_seq_event_t ev;
if (verbose >= VERB_EVENT)
- printf("Pitchbend (%d) %d %d\n", chan, lsb, msb);
+ printf("%d: Pitchbend (%d) %d %d\n", Mf_currtime, chan, lsb, msb);
set_event_header(&ev);
snd_seq_ev_set_pitchbend(&ev, chan, (lsb + (msb << 7)) - 8192);
write_ev(&ev);
snd_seq_event_t ev;
if (verbose >= VERB_EVENT)
- printf("KeyPress (%d) %d %d\n", chan, pitch, pressure);
+ printf("%d: KeyPress (%d) %d %d\n", Mf_currtime, chan, pitch, pressure);
set_event_header(&ev);
snd_seq_ev_set_keypress(&ev, chan, pitch, pressure);
write_ev(&ev);
snd_seq_event_t ev;
if (verbose >= VERB_EVENT)
- printf("ChanPress (%d) %d\n", chan, pressure);
+ printf("%d: ChanPress (%d) %d\n", Mf_currtime, chan, pressure);
set_event_header(&ev);
snd_seq_ev_set_chanpress(&ev, chan, pressure);
write_ev(&ev);
if (verbose >= VERB_MUCH) {
int c;
- printf("Sysex, len=%d\n", len);
+ printf("%d: Sysex, len=%d\n", Mf_currtime, len);
for (c = 0; c < len; c++) {
printf(" %02x", (unsigned char)msg[c]);
if (c % 16 == 15)
int tmp;
int c;
snd_seq_addr_t dest_addr;
- const char *addr = NULL;
+ const char *addr = "65:0";
while ((c = getopt(argc, argv, "s:a:p:q:vrb")) != -1) {
switch (c) {
/* setup queue */
if (dest_queue >= 0) {
+ shared_queue = 1;
if (snd_seq_set_queue_usage(seq_handle, dest_queue, 1) < 0) {
perror("use queue");
exit(1);
}
} else {
+ shared_queue = 0;
dest_queue = snd_seq_alloc_queue(seq_handle);
if (dest_queue < 0) {
perror("alloc queue");
mfread();
alsa_sync();
- alsa_stop_timer();
+ if (! shared_queue)
+ alsa_stop_timer();
snd_seq_close(seq_handle);