2006-12-14 Stas Sergeev <stsp@aknet.ru>
* interface/server_c.c: extend midi protocol.
+ * timidity/midi_a.c: new file.
2006-12-13 URABE Shyouhei <shyouhei@ruby-lang.org>
fi
AC_CHECK_FUNC(getopt_long,
- AC_DEFINE([HAVE_GETOPT_LONG],1,[Define to 1 if you have `getopt_long function'])
+ AC_DEFINE([HAVE_GETOPT_LONG],1,[Define to 1 if you have `getopt_long' function])
tm_cv_needgetopt="no",
tm_cv_needgetopt="yes")
AM_CONDITIONAL([NEEDGETOPT], test "x$tm_cv_needgetopt" = "xyes")
-# Checks on cygnus and MYSYS
+AC_CHECK_FUNC(open_memstream, [
+ AC_DEFINE([HAVE_OPEN_MEMSTREAM],1,[Define to 1 if you have `open_memstream' function])
+ ])
+
+# Checks on cygnus and MSYS
if test "x$MSYS" = xyes ; then
case "$ac_cv_header_dirent_dirent_h$ac_cv_header_dirent_sys_ndir_h$ac_cv_header_dirent_sys_dir_h$ac_cv_header_dirent_ndir_h" in
*yes*)
AC_MSG_CHECKING(enable_audio=arts)
if test "x$au_enable_arts" = xyes; then
AC_MSG_RESULT([yes, configuring aRts])
- KEEPCFLAGS=$CFLAGS
- KEEPLIBS=$LIBS
- KEEPLDFLAGS=$LDFLAGS
- AM_PATH_ARTS()
- CFLAGS=$KEEPCFLAGS
- LIBS=$KEEPLIBS
- LDFLAGS=$KEEPLDFLAGS
- if test "x$no_arts" = x; then
+ dnl **** Check for aRts Sound Server ****
+ AC_PATH_PROG(ARTSCCONFIG, artsc-config)
+ if test x$ARTSCCONFIG != x -a x$ARTSCCONFIG != x'"$ARTSCCONFIG"';
+ then
+ ARTSC_CFLAGS=""
+ for i in `$ARTSCCONFIG --cflags`
+ do
+ case "$i" in
+ -I*) ARTSC_CFLAGS="$ARTSC_CFLAGS $i";;
+ esac
+ done
+ ARTSC_LIBS=`$ARTSCCONFIG --libs`
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $ARTSC_CFLAGS"
+ AC_TRY_COMPILE([#include <artsc.h>],[arts_stream_t stream;],
+ [AC_SUBST(ARTSLIBS, $ARTSC_LIBS)
+ AC_SUBST(ARTSINCL, $ARTSC_CFLAGS)
+ AC_DEFINE(HAVE_ARTS, 1, [Define if you have ARTS sound server])
+ have_arts="yes"
+ ])
+ CFLAGS="$save_CFLAGS"
+ fi
+
+ if test "$have_arts" = "yes"; then
dnl AC_MSG_RESULT(aRts: Enabled)
EXTRADEFS="$EXTRADEFS -DAU_ARTS"
SYSEXTRAS="$SYSEXTRAS aRts_a.c"
- EXTRACT_CPPFLAGS(CPPFLAGS,CFLAGS,$ARTS_CFLAGS)
- LIBS="$LIBS $ARTS_LIBS"
+ EXTRACT_CPPFLAGS(CPPFLAGS,CFLAGS,$ARTSC_CFLAGS)
+ LIBS="$LIBS $ARTSC_LIBS"
else
AC_MSG_WARN(aRts: Couldn't configure)
fi
AC_MSG_CHECKING(enable_audio=vorbis)
if test "x$au_enable_vorbis" = xyes; then
AC_MSG_RESULT([yes, configuring vorbis])
- AM_PATH_OGG([
- AM_PATH_VORBIS([
+ XIPH_PATH_OGG([
+ XIPH_PATH_VORBIS([
have_vorbis=yes
SYSEXTRAS="$SYSEXTRAS vorbis_a.c"
EXTRADEFS="$EXTRADEFS -DAU_VORBIS $OGG_CFLAGS $VORBIS_CFLAGS"
j += note_key_offset, j -= floor(j / 12.0) * 12;
current_freq_table = j;
- play_mode->close_output();
-
if (ctl.flags & CTLF_DAEMONIZE)
{
int pid = fork();
static int start_sequencer(struct seq_context *ctxp)
{
- if (play_mode->open_output() < 0) {
+ if (play_mode->acntl(PM_REQ_PLAY_START, NULL) < 0) {
ctl.cmsg(CMSG_FATAL, VERB_NORMAL,
- "Couldn't open %s (`%c')",
+ "Couldn't start %s (`%c')",
play_mode->id_name, play_mode->id_character);
return 0;
}
snd_seq_stop_queue(ctxp->handle, ctxp->queue, NULL);
snd_seq_drain_output(ctxp->handle);
}
- play_mode->close_output();
+ play_mode->acntl(PM_REQ_PLAY_END, NULL);
free_instruments(0);
free_global_mblock();
ctxp->used = 0;
alarm(0);
signal(SIGALRM, sig_timeout);
- play_mode->close_output();
while(1)
{
socklen_t addrlen;
}
else control_fd = 0;
- if(play_mode->open_output() < 0)
+ if (play_mode->acntl(PM_REQ_PLAY_START, NULL) < 0)
{
ctl.cmsg(CMSG_FATAL, VERB_NORMAL,
- "Couldn't open %s (`%c')",
+ "Couldn't start %s (`%c')",
play_mode->id_name, play_mode->id_character);
- send_status(510, "Couldn't open %s (`%c')",
+ send_status(510, "Couldn't start %s (`%c')",
play_mode->id_name, play_mode->id_character);
if (control_port) {
close(control_fd);
control_fd = -1;
}
- continue;
+ break;
}
server_reset();
doit();
ctl.cmsg(CMSG_INFO, VERB_NOISY, "Connection closed");
- play_mode->close_output();
+ play_mode->acntl(PM_REQ_PLAY_END, NULL);
if(control_fd != -1 && control_port)
{
if(data_fd != -1 && (tmr_running || notmr_running))
{
- double wait_time;
- int32 filled;
+ double wait_time, filled;
if (IS_STREAM_TRACE)
filled = aq_filled();
else
filled = high_time_at * play_mode->rate;
- wait_time = (double)filled / play_mode->rate - low_time_at;
+ wait_time = filled / play_mode->rate - low_time_at;
if(wait_time <= 0)
usec = 0;
else
aq.c \
aq.h \
au_a.c \
+ midi_a.c \
audio_cnv.c \
audio_cnv.h \
common.c \
case PM_REQ_FLUSH: /* Wait until playback is complete */
case PM_REQ_MIDI: /* Send MIDI event */
case PM_REQ_INST_NAME: /* Get instrument name */
+ return -1;
case PM_REQ_OUTPUT_FINISH: /* Sent after last output_data */
case PM_REQ_PLAY_START: /* Called just before playing */
case PM_REQ_PLAY_END: /* Called just after playing */
- return -1;
+ return 0;
}
return -1;
}
dpm.encoding = validate_encoding(dpm.encoding, include_enc, exclude_enc);
if(dpm.name == NULL) {
+ if (!current_file_info || !current_file_info->filename)
+ return -1;
dpm.flag |= PF_AUTO_SPLIT_FILE;
- dpm.name = NULL;
} else {
dpm.flag &= ~PF_AUTO_SPLIT_FILE;
if(aiff_output_open(dpm.name) == -1)
case PM_REQ_PLAY_START:
if(dpm.flag & PF_AUTO_SPLIT_FILE)
return auto_aiff_output_open(current_file_info->filename);
- break;
+ return 0;
case PM_REQ_PLAY_END:
- if(dpm.flag & PF_AUTO_SPLIT_FILE) {
+ if(dpm.flag & PF_AUTO_SPLIT_FILE)
close_output();
- return 0;
- }
- break;
+ return 0;
case PM_REQ_DISCARD:
return 0;
}
return -1;
output_counter = 0;
return 0;
+
+ case PM_REQ_PLAY_START: /* Called just before playing */
+ case PM_REQ_PLAY_END: /* Called just after playing */
+ return 0;
}
return -1;
}
{
switch(request) {
case PM_REQ_DISCARD:
- ;;
+ case PM_REQ_PLAY_START: /* Called just before playing */
+ case PM_REQ_PLAY_END: /* Called just after playing */
return 0;
}
return -1;
dpm.encoding = validate_encoding(dpm.encoding, include_enc, exclude_enc);
if(dpm.name == NULL) {
+ if (!current_file_info || !current_file_info->filename)
+ return -1;
dpm.flag |= PF_AUTO_SPLIT_FILE;
- dpm.name = NULL;
} else {
dpm.flag &= ~PF_AUTO_SPLIT_FILE;
if(au_output_open(dpm.name, NULL) == -1)
case PM_REQ_PLAY_START:
if(dpm.flag & PF_AUTO_SPLIT_FILE)
return auto_au_output_open(current_file_info->filename);
- break;
+ return 0;
case PM_REQ_PLAY_END:
- if(dpm.flag & PF_AUTO_SPLIT_FILE) {
+ if(dpm.flag & PF_AUTO_SPLIT_FILE)
close_output();
- return 0;
- }
- break;
+ return 0;
case PM_REQ_DISCARD:
return 0;
}
audriv_play_stop(); /* Reset audriv's sample counter */
Audio_On();
return 0;
+
+ case PM_REQ_PLAY_START: /* Called just before playing */
+ case PM_REQ_PLAY_END: /* Called just after playing */
+ return 0;
}
return -1;
}
{
case PM_REQ_DISCARD:
return ioctl(dpm.fd, DSP_IOCTL_RESET);
+
+ case PM_REQ_PLAY_START: /* Called just before playing */
+ case PM_REQ_PLAY_END: /* Called just after playing */
+ return 0;
}
return -1;
}
ControlMode *ctl=DEFAULT_CONTROL_MODE;
-int std_write(int fd, char *buffer, int size)
+int std_write(int fd, const char *buffer, int size)
{
/* redirect stdout writes */
if (fd == 1 && ctl->write)
extern ControlMode *ctl_list[], *ctl;
extern int dumb_error_count;
-extern int std_write(int fd, char *buffer, int size);
+extern int std_write(int fd, const char *buffer, int size);
#endif /* ___CONTROLS_H_ */
/* not implemented yet */
break;
}
+
+ case PM_REQ_PLAY_START: /* Called just before playing */
+ case PM_REQ_PLAY_END: /* Called just after playing */
+ return 0;
}
return -1;
}
#ifndef __W32G__
if(dpm.name == NULL) {
+ if (!current_file_info || !current_file_info->filename)
+ return -1;
dpm.flag |= PF_AUTO_SPLIT_FILE;
- dpm.name = NULL;
} else {
dpm.flag &= ~PF_AUTO_SPLIT_FILE;
if(flac_output_open(dpm.name, NULL) == -1)
case PM_REQ_PLAY_START:
if(dpm.flag & PF_AUTO_SPLIT_FILE)
return auto_flac_output_open(current_file_info->filename, current_file_info->seq_name);
- break;
+ return 0;
case PM_REQ_PLAY_END:
- if(dpm.flag & PF_AUTO_SPLIT_FILE) {
+ if(dpm.flag & PF_AUTO_SPLIT_FILE)
close_output();
- return 0;
- }
- break;
+ return 0;
case PM_REQ_DISCARD:
return 0;
}
#if !defined ( IA_W32GUI ) && !defined ( IA_W32G_SYN )
if(dpm.name == NULL) {
+ if (!current_file_info || !current_file_info->filename)
+ return -1;
dpm.flag |= PF_AUTO_SPLIT_FILE;
- dpm.name = NULL;
} else {
dpm.flag &= ~PF_AUTO_SPLIT_FILE;
if((dpm.fd = gogo_output_open(dpm.name)) == -1)
case PM_REQ_PLAY_START:
if(dpm.flag & PF_AUTO_SPLIT_FILE)
return auto_gogo_output_open(current_file_info->filename,current_file_info->seq_name);
- break;
+ return 0;
case PM_REQ_PLAY_END:
- if(dpm.flag & PF_AUTO_SPLIT_FILE) {
+ if(dpm.flag & PF_AUTO_SPLIT_FILE)
close_output();
- return 0;
- }
- break;
+ return 0;
case PM_REQ_DISCARD:
#if 1
gogo_buffer_reset();
switch(request)
{
case PM_REQ_DISCARD:
- /* Must be defined this request but I don't know how to do */
-/* fprintf(stderr,
- "hpux_a.c: acntl(): PM_REQ_DISCARD is not implemented.");
- */
- return -1;
+ case PM_REQ_PLAY_START: /* Called just before playing */
+ case PM_REQ_PLAY_END: /* Called just after playing */
+ return 0;
}
return -1;
}
{
case PM_REQ_DISCARD:
return ioctl(dpm.fd, AUDIO_RESET, RESET_TX_BUF);
+
+ case PM_REQ_PLAY_START: /* Called just before playing */
+ case PM_REQ_PLAY_END: /* Called just after playing */
+ return 0;
}
return -1;
}
--- /dev/null
+/*
+ TiMidity++ -- MIDI to WAVE converter and player
+ Copyright (C) 1999-2002 Masanao Izumo <mo@goice.co.jp>
+ Copyright (C) 1995 Tuukka Toivonen <tt@cgs.fi>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ midi_a.c - write midi file
+
+ Author: Stas Sergeev <stsp@users.sourceforge.net>
+ Based on midi-writer code by Rober Komar <rkomar@telus.net>
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* HAVE_CONFIG_H */
+
+#ifdef HAVE_OPEN_MEMSTREAM
+#define _GNU_SOURCE
+#endif
+
+#include <stdio.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+#ifndef NO_STRING_H
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#ifndef __WIN32__
+#include <arpa/inet.h>
+#else
+#include <winsock.h>
+#endif
+#ifdef HAVE_SYS_SOUNDCARD_H
+#include <sys/soundcard.h>
+#else
+#include "server_defs.h"
+#endif /* HAVE_SYS_SOUNDCARD_H */
+
+#include "timidity.h"
+#include "common.h"
+#include "instrum.h"
+#include "playmidi.h"
+#include "readmidi.h"
+#include "output.h"
+#include "controls.h"
+
+#define IGNORE_TEMPO_EVENTS 0
+
+static int open_output(void);
+static void close_output(void);
+static int acntl(int request, void *arg);
+
+static char *midibuf;
+static size_t midi_pos;
+#ifdef HAVE_OPEN_MEMSTREAM
+static FILE *fp;
+#else
+static size_t midibuf_size;
+#define fflush(x) do {} while (0)
+#define fclose(x) do {} while (0)
+#endif
+
+static long track_size_pos;
+static double last_time;
+
+static int tempo;
+static int ticks_per_quarter_note;
+#define TICKS_OFFSET 12
+
+#define dmp midi_play_mode
+
+PlayMode dmp = {
+ DEFAULT_RATE, 0, PF_MIDI_EVENT,
+ -1,
+ {0, 0, 0, 0, 0},
+ "Write MIDI file", 'm',
+ NULL,
+ open_output,
+ close_output,
+ NULL,
+ acntl
+};
+
+#define CARR(...) ((u_int8_t []) {__VA_ARGS__})
+#define M_FWRITE(...) m_fwrite(CARR(__VA_ARGS__), sizeof(CARR(__VA_ARGS__)))
+#define M_FWRITE_STR(s) m_fwrite((s), sizeof(s) - 1)
+
+static size_t m_fwrite(const void *ptr, size_t size)
+{
+#ifdef HAVE_OPEN_MEMSTREAM
+ return fwrite(ptr, size, 1, fp);
+#else
+ if (midi_pos + size > midibuf_size) {
+ size_t new_len = (midi_pos + size) * 2;
+ midibuf = safe_realloc(midibuf, new_len);
+ midibuf_size = new_len;
+ }
+ memcpy(midibuf + midi_pos, ptr, size);
+ midi_pos += size;
+ return 1;
+#endif
+}
+
+#ifndef HAVE_OPEN_MEMSTREAM
+static void my_open_memstream(void)
+{
+ midibuf_size = 1024;
+ midibuf = safe_malloc(midibuf_size);
+ midi_pos = 0;
+}
+#endif
+
+static void write_midi_header(void)
+{
+ /* Write out MID file header.
+ * The file will have a single track, with the configured number of
+ * ticks per quarter note.
+ */
+ M_FWRITE_STR("MThd");
+ M_FWRITE_STR("\0\0\0\6"); /* header size */
+ M_FWRITE_STR("\0\0"); /* single track format */
+ M_FWRITE_STR("\0\1"); /* #tracks = 1 */
+ M_FWRITE_STR("\0\0"); /* #ticks / quarter note written later */
+}
+
+static void finalize_midi_header(void)
+{
+ unsigned short tpqn = htons(ticks_per_quarter_note);
+
+ fflush(fp);
+ memcpy(midibuf + TICKS_OFFSET, &tpqn, 2); /* #ticks / quarter note */
+}
+
+static void set_tempo(void)
+{
+ M_FWRITE_STR("\xff\x51\3");
+ M_FWRITE(tempo >> 16, tempo >> 8, tempo);
+}
+
+static void set_time_sig(void)
+{
+ /* Set the time sig to 4/4 */
+ M_FWRITE_STR("\xff\x58\4\4\x2\x18\x08");
+}
+
+static void midout_write_delta_time(int32 time)
+{
+ int32 delta_time;
+ unsigned char c[4];
+ int idx;
+ int started_printing = 0;
+
+#if !IGNORE_TEMPO_EVENTS
+ double div;
+ delta_time = time - last_time;
+ div = (double)tempo * (double)play_mode->rate /
+ (double)(ticks_per_quarter_note * 1000000);
+ delta_time /= div;
+ last_time += delta_time * div;
+#else
+ delta_time = time - last_time;
+ last_time += delta_time;
+#endif
+
+ /* We have to divide the number of ticks into 7-bit segments, and only write
+ * the non-zero segments starting with the most significant (except for the
+ * least significant segment, which we always write). The most significant bit
+ * is set to 1 in all but the least significant segment.
+ */
+ c[0] = (delta_time >> 21) & 0x7f;
+ c[1] = (delta_time >> 14) & 0x7f;
+ c[2] = (delta_time >> 7) & 0x7f;
+ c[3] = (delta_time) & 0x7f;
+
+ for (idx = 0; idx < 3; idx++) {
+ if (started_printing || c[idx]) {
+ started_printing = 1;
+ M_FWRITE(c[idx] | 0x80);
+ }
+ }
+ M_FWRITE(c[3]);
+}
+
+static void start_midi_track(void)
+{
+ /* Write out track header.
+ * The track will have a large length (0x7fffffff) because we don't know at
+ * this time how big it will really be.
+ */
+ M_FWRITE_STR("MTrk");
+ fflush(fp);
+ track_size_pos = midi_pos;
+ M_FWRITE_STR("\x7f\xff\xff\xff"); /* #chunks */
+
+ last_time = 0;
+
+#if !IGNORE_TEMPO_EVENTS
+ tempo = 500000;
+#else
+ tempo = (ticks_per_quarter_note * 1000000) /
+ (double)play_mode->rate;
+#endif
+
+ midout_write_delta_time(0);
+ set_tempo();
+ midout_write_delta_time(0);
+ set_time_sig();
+}
+
+static void end_midi_track(void)
+{
+ int32 track_bytes;
+ /* Send (with delta-time of 0) "0xff 0x2f 0x0" to finish the track. */
+ M_FWRITE_STR("\0\xff\x2f\0");
+
+ fflush(fp);
+
+ track_bytes = htonl(midi_pos - track_size_pos - 4);
+ memcpy(midibuf + track_size_pos, &track_bytes, 4);
+}
+
+static int open_output(void)
+{
+#ifdef HAVE_OPEN_MEMSTREAM
+ fp = open_memstream(&midibuf, &midi_pos);
+#else
+ my_open_memstream();
+#endif
+
+ ticks_per_quarter_note = 144;
+ write_midi_header();
+
+ return 0;
+}
+
+static void close_output(void)
+{
+ finalize_midi_header();
+
+ fclose(fp);
+ if (dmp.name) {
+ if (strcmp(dmp.name, "-") == 0)
+ dmp.fd = STDOUT_FILENO;
+ else
+ dmp.fd = creat(dmp.name, 0666);
+ if (dmp.fd != -1) {
+ std_write(dmp.fd, midibuf, midi_pos);
+ if (strcmp(dmp.name, "-") != 0)
+ close(dmp.fd);
+ }
+ dmp.fd = -1;
+ }
+ free(midibuf);
+}
+
+static void midout_noteon(int chn, int note, int vel, int32 time)
+{
+ midout_write_delta_time(time);
+ M_FWRITE((chn & 0x0f) | MIDI_NOTEON, note & 0x7f, vel & 0x7f);
+}
+
+static void midout_noteoff(int chn, int note, int vel, int32 time)
+{
+ midout_write_delta_time(time);
+ M_FWRITE((chn & 0x0f) | MIDI_NOTEOFF, note & 0x7f, vel & 0x7f);
+}
+
+static void midout_control(int chn, int control, int value, int32 time)
+{
+ midout_write_delta_time(time);
+ M_FWRITE((chn & 0x0f) | MIDI_CTL_CHANGE, control & 0x7f, value & 0x7f);
+}
+
+static void midout_keypressure(int chn, int control, int value, int32 time)
+{
+ midout_write_delta_time(time);
+ M_FWRITE((chn & 0x0f) | MIDI_KEY_PRESSURE, control & 0x7f, value & 0x7f);
+}
+
+static void midout_channelpressure(int chn, int vel, int32 time)
+{
+ midout_write_delta_time(time);
+ M_FWRITE((chn & 0x0f) | MIDI_CHN_PRESSURE, vel & 0x7f);
+}
+
+static void midout_bender(int chn, int pitch, int32 time)
+{
+ midout_write_delta_time(time);
+ M_FWRITE((chn & 0x0f) | MIDI_PITCH_BEND, pitch & 0x7f, (pitch >> 7) & 0x7f);
+}
+
+static void midout_program(int chn, int pgm, int32 time)
+{
+ midout_write_delta_time(time);
+ M_FWRITE((chn & 0x0f) | MIDI_PGM_CHANGE, pgm & 0x7f);
+}
+
+static void midout_tempo(int chn, int a, int b, int32 time)
+{
+ midout_write_delta_time(time);
+ tempo = (a << 16) | (b << 8) | chn;
+ set_tempo();
+}
+
+static int find_bit(int val)
+{
+ int i = 0;
+ while (val) {
+ if (val & 1)
+ return i;
+ i++;
+ val >>= 1;
+ }
+ return -1;
+}
+
+static void midout_timesig(int chn, int a, int b, int32 time)
+{
+ if (chn == 0) {
+ if (!b)
+ return;
+ b = find_bit(b);
+ midout_write_delta_time(time);
+ M_FWRITE_STR("\xff\x58\4");
+ }
+ M_FWRITE(a, b);
+}
+
+static int do_event(MidiEvent * ev)
+{
+ int ch, co, va, type;
+
+ ch = ev->channel;
+
+ if ((type = unconvert_midi_control_change(ev)) != -1) {
+ midout_control(ch, type, ev->a, ev->time);
+ return RC_NONE;
+ }
+
+ switch (ev->type) {
+ case ME_NOTEON:
+ midout_noteon(ch, ev->a, ev->b, ev->time);
+ break;
+ case ME_NOTEOFF:
+ midout_noteoff(ch, ev->a, ev->b, ev->time);
+ break;
+ case ME_KEYPRESSURE:
+ midout_keypressure(ch, ev->a, ev->b, ev->time);
+ break;
+ case ME_PROGRAM:
+ midout_program(ch, ev->a, ev->time);
+ break;
+ case ME_CHANNEL_PRESSURE:
+ midout_channelpressure(ch, ev->a, ev->time);
+ break;
+ case ME_PITCHWHEEL:
+ midout_bender(ch, ev->a, ev->time);
+ break;
+ case ME_TEMPO:
+#if !IGNORE_TEMPO_EVENTS
+ midout_tempo(ch, ev->a, ev->b, ev->time);
+#endif
+ break;
+ case ME_TIMESIG:
+ midout_timesig(ch, ev->a, ev->b, ev->time);
+ break;
+ case ME_EOT:
+ return RC_TUNE_END;
+ }
+ return RC_NONE;
+}
+
+static int acntl(int request, void *arg)
+{
+ switch (request) {
+ case PM_REQ_MIDI:
+ return do_event((MidiEvent *) arg);
+ case PM_REQ_PLAY_START:
+ start_midi_track();
+ return 0;
+ case PM_REQ_PLAY_END:
+ end_midi_track();
+ return 0;
+ case PM_REQ_DIVISIONS:
+ ticks_per_quarter_note = *(int32 *) arg;
+ return 0;
+ }
+ return -1;
+}
switch(request)
{
case PM_REQ_DISCARD:
+ case PM_REQ_PLAY_START: /* Called just before playing */
+ case PM_REQ_PLAY_END: /* Called just after playing */
return 0;
}
return -1;
*((int *)arg) = i;
return 0;
#endif /* SNDCTL_DSP_GETODELAY */
+
+ case PM_REQ_PLAY_START: /* Called just before playing */
+ case PM_REQ_PLAY_END: /* Called just after playing */
+ return 0;
}
return -1;
}
#endif /* AU_GOGO */
#endif /* !__MACOS__ */
+extern PlayMode midi_play_mode;
extern PlayMode modmidi_play_mode;
PlayMode *play_mode_list[] = {
#endif /* AU_GOGO */
&list_play_mode,
#endif /* __MACOS__ */
+ &midi_play_mode,
&modmidi_play_mode,
0
};
* Get filled device queue size
*/
- PM_REQ_OUTPUT_FINISH /* ARG: not-used
+ PM_REQ_OUTPUT_FINISH, /* ARG: not-used
* PM_REQ_OUTPUT_FINISH calls just after the last
* output_data(), and TiMidity would into
* waiting to flush the audio buffer.
*/
+
+ PM_REQ_DIVISIONS, /* ARG: int32* - pointer to divisions number
+ */
};
buffer_pointer = common_buffer;
for(i = 0; i < MAX_CHANNELS; i++)
channel[i].lasttime = 0;
- play_mode->acntl(PM_REQ_PLAY_START, NULL);
}
void playmidi_stream_free(void)
}
}
//break;
+
+ case PM_REQ_PLAY_START: /* Called just before playing */
+ case PM_REQ_PLAY_END: /* Called just after playing */
+ return 0;
}
return -1;
}
dpm.encoding = validate_encoding(dpm.encoding, 0, 0);
if(dpm.name == NULL) {
+ if (!current_file_info || !current_file_info->filename)
+ return -1;
dpm.flag |= PF_AUTO_SPLIT_FILE;
- dpm.name = NULL;
} else {
dpm.flag &= ~PF_AUTO_SPLIT_FILE;
if((dpm.fd = raw_output_open(dpm.name)) == -1)
case PM_REQ_PLAY_START:
if(dpm.flag & PF_AUTO_SPLIT_FILE)
return auto_raw_output_open(current_file_info->filename);
- break;
+ return 0;
case PM_REQ_PLAY_END:
- if(dpm.flag & PF_AUTO_SPLIT_FILE) {
+ if(dpm.flag & PF_AUTO_SPLIT_FILE)
close_output();
- return 0;
- }
- break;
+ return 0;
case PM_REQ_DISCARD:
return 0;
}
}
}
+struct ctl_chg_types {
+ unsigned char mtype;
+ int ttype;
+} ctl_chg_list[] = {
+ { 0, ME_TONE_BANK_MSB },
+ { 1, ME_MODULATION_WHEEL },
+ { 2, ME_BREATH },
+ { 4, ME_FOOT },
+ { 5, ME_PORTAMENTO_TIME_MSB },
+ { 6, ME_DATA_ENTRY_MSB },
+ { 7, ME_MAINVOLUME },
+ { 8, ME_BALANCE },
+ { 10, ME_PAN },
+ { 11, ME_EXPRESSION },
+ { 32, ME_TONE_BANK_LSB },
+ { 37, ME_PORTAMENTO_TIME_LSB },
+ { 38, ME_DATA_ENTRY_LSB },
+ { 64, ME_SUSTAIN },
+ { 65, ME_PORTAMENTO },
+ { 66, ME_SOSTENUTO },
+ { 67, ME_SOFT_PEDAL },
+ { 68, ME_LEGATO_FOOTSWITCH },
+ { 69, ME_HOLD2 },
+ { 71, ME_HARMONIC_CONTENT },
+ { 72, ME_RELEASE_TIME },
+ { 73, ME_ATTACK_TIME },
+ { 74, ME_BRIGHTNESS },
+ { 84, ME_PORTAMENTO_CONTROL },
+ { 91, ME_REVERB_EFFECT },
+ { 92, ME_TREMOLO_EFFECT },
+ { 93, ME_CHORUS_EFFECT },
+ { 94, ME_CELESTE_EFFECT },
+ { 95, ME_PHASER_EFFECT },
+ { 96, ME_RPN_INC },
+ { 97, ME_RPN_DEC },
+ { 98, ME_NRPN_LSB },
+ { 99, ME_NRPN_MSB },
+ { 100, ME_RPN_LSB },
+ { 101, ME_RPN_MSB },
+ { 120, ME_ALL_SOUNDS_OFF },
+ { 121, ME_RESET_CONTROLLERS },
+ { 123, ME_ALL_NOTES_OFF },
+ { 126, ME_MONO },
+ { 127, ME_POLY },
+};
+
int convert_midi_control_change(int chn, int type, int val, MidiEvent *ev_ret)
{
- switch(type)
- {
- case 0: type = ME_TONE_BANK_MSB; break;
- case 1: type = ME_MODULATION_WHEEL; break;
- case 2: type = ME_BREATH; break;
- case 4: type = ME_FOOT; break;
- case 5: type = ME_PORTAMENTO_TIME_MSB; break;
- case 6: type = ME_DATA_ENTRY_MSB; break;
- case 7: type = ME_MAINVOLUME; break;
- case 8: type = ME_BALANCE; break;
- case 10: type = ME_PAN; break;
- case 11: type = ME_EXPRESSION; break;
- case 32: type = ME_TONE_BANK_LSB; break;
- case 37: type = ME_PORTAMENTO_TIME_LSB; break;
- case 38: type = ME_DATA_ENTRY_LSB; break;
- case 64: type = ME_SUSTAIN; break;
- case 65: type = ME_PORTAMENTO; break;
- case 66: type = ME_SOSTENUTO; break;
- case 67: type = ME_SOFT_PEDAL; break;
- case 68: type = ME_LEGATO_FOOTSWITCH; break;
- case 69: type = ME_HOLD2; break;
- case 71: type = ME_HARMONIC_CONTENT; break;
- case 72: type = ME_RELEASE_TIME; break;
- case 73: type = ME_ATTACK_TIME; break;
- case 74: type = ME_BRIGHTNESS; break;
- case 84: type = ME_PORTAMENTO_CONTROL; break;
- case 91: type = ME_REVERB_EFFECT; break;
- case 92: type = ME_TREMOLO_EFFECT; break;
- case 93: type = ME_CHORUS_EFFECT; break;
- case 94: type = ME_CELESTE_EFFECT; break;
- case 95: type = ME_PHASER_EFFECT; break;
- case 96: type = ME_RPN_INC; break;
- case 97: type = ME_RPN_DEC; break;
- case 98: type = ME_NRPN_LSB; break;
- case 99: type = ME_NRPN_MSB; break;
- case 100: type = ME_RPN_LSB; break;
- case 101: type = ME_RPN_MSB; break;
- case 120: type = ME_ALL_SOUNDS_OFF; break;
- case 121: type = ME_RESET_CONTROLLERS; break;
- case 123: type = ME_ALL_NOTES_OFF; break;
- case 126: type = ME_MONO; break;
- case 127: type = ME_POLY; break;
- default: type = -1; break;
+ int i;
+ for (i = 0; i < ARRAY_SIZE(ctl_chg_list); i++) {
+ if (ctl_chg_list[i].mtype == type) {
+ type = ctl_chg_list[i].ttype;
+ break;
+ }
}
+ if (i >= ARRAY_SIZE(ctl_chg_list))
+ type = -1;
if(type != -1)
{
return 0;
}
+int unconvert_midi_control_change(MidiEvent *ev)
+{
+ int i;
+ for (i = 0; i < ARRAY_SIZE(ctl_chg_list); i++) {
+ if (ctl_chg_list[i].ttype == ev->type)
+ break;
+ }
+ if (i >= ARRAY_SIZE(ctl_chg_list))
+ return -1;
+
+ return ctl_chg_list[i].mtype;
+}
+
static int block_to_part(int block, int port)
{
int p;
else
divisions = (int32)divisions_tmp;
+ if(play_mode->flag & PF_MIDI_EVENT)
+ play_mode->acntl(PM_REQ_DIVISIONS, &divisions);
+
if(len > 6)
{
ctl->cmsg(CMSG_WARNING, VERB_NORMAL,
extern int parse_sysex_event_multi(uint8 *data, int32 datalen, MidiEvent *ev_ret);
extern int convert_midi_control_change(int chn, int type, int val,
MidiEvent *ev_ret);
+extern int unconvert_midi_control_change(MidiEvent *ev);
extern char *readmidi_make_string_event(int type, char *string, MidiEvent *ev,
int cnv);
extern MidiEvent *read_midi_file(struct timidity_file *mtf,
extern void free_readmidi(void);
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
#endif /* ___READMIDI_H_ */
#if !defined (IA_W32GUI) && !defined (IA_W32G_SYN)
if (dpm.name == NULL) {
+ if (!current_file_info || !current_file_info->filename)
+ return -1;
dpm.flag |= PF_AUTO_SPLIT_FILE;
- dpm.name = NULL;
}
else {
dpm.flag &= ~PF_AUTO_SPLIT_FILE;
case PM_REQ_PLAY_START:
if(dpm.flag & PF_AUTO_SPLIT_FILE)
return auto_speex_output_open(current_file_info->filename,current_file_info->seq_name);
- break;
+ return 0;
case PM_REQ_PLAY_END:
- if(dpm.flag & PF_AUTO_SPLIT_FILE) {
+ if(dpm.flag & PF_AUTO_SPLIT_FILE)
close_output();
- return 0;
- }
- break;
+ return 0;
case PM_REQ_DISCARD:
return 0;
}
play_mode->rate = rate;
return 0;
}
+
+ case PM_REQ_PLAY_START: /* Called just before playing */
+ case PM_REQ_PLAY_END: /* Called just after playing */
+ return 0;
}
return -1;
}
#if !defined ( IA_W32GUI ) && !defined ( IA_W32G_SYN )
if(dpm.name == NULL) {
+ if (!current_file_info || !current_file_info->filename)
+ return -1;
dpm.flag |= PF_AUTO_SPLIT_FILE;
- dpm.name = NULL;
} else {
dpm.flag &= ~PF_AUTO_SPLIT_FILE;
if((dpm.fd = ogg_output_open(dpm.name, NULL)) == -1)
case PM_REQ_PLAY_START:
if(dpm.flag & PF_AUTO_SPLIT_FILE)
return auto_ogg_output_open(current_file_info->filename,current_file_info->seq_name);
- break;
+ return 0;
case PM_REQ_PLAY_END:
- if(dpm.flag & PF_AUTO_SPLIT_FILE) {
+ if(dpm.flag & PF_AUTO_SPLIT_FILE)
close_output();
- return 0;
- }
- break;
+ return 0;
case PM_REQ_DISCARD:
return 0;
}
open_output();
return 0;
}
+
+ case PM_REQ_PLAY_START: /* Called just before playing */
+ case PM_REQ_PLAY_END: /* Called just after playing */
+ return 0;
}
return -1;
#ifndef __W32G__
if(dpm.name == NULL) {
+ if (!current_file_info || !current_file_info->filename)
+ return -1;
dpm.flag |= PF_AUTO_SPLIT_FILE;
- dpm.name = NULL;
} else {
dpm.flag &= ~PF_AUTO_SPLIT_FILE;
if((dpm.fd = wav_output_open(dpm.name)) == -1)
case PM_REQ_PLAY_START:
if(dpm.flag & PF_AUTO_SPLIT_FILE)
return auto_wav_output_open(current_file_info->filename);
- break;
+ return 0;
case PM_REQ_PLAY_END:
- if(dpm.flag & PF_AUTO_SPLIT_FILE) {
+ if(dpm.flag & PF_AUTO_SPLIT_FILE)
close_output();
- return 0;
- }
- break;
+ return 0;
case PM_REQ_DISCARD:
return 0;
}