--- ./interface/server_c.c.ORIG Sun Jun 20 16:36:56 1999 +++ ./interface/server_c.c Sun Jun 20 16:36:15 1999 @@ -62,6 +62,7 @@ #ifdef HAVE_SYS_SOUNDCARD_H #include +#include #else #include "server_defs.h" #endif /* HAVE_SYS_SOUNDCARD_H */ @@ -87,6 +88,13 @@ #define SIG_TIMEOUT_SEC 3 +struct seq_context { + snd_seq_t *handle; /* The snd_seq handle to /dev/snd/seq */ + int client;/* The client associated with this context */ + int queue; /* The queue to use for all operations */ + int fd; /* The file descriptor */ +}; + static int cmd_help(int argc, char **argv); static int cmd_open(int argc, char **argv); static int cmd_close(int argc, char **argv); @@ -100,6 +108,8 @@ static int cmd_nop(int argc, char **argv); static int cmd_autoreduce(int argc, char **argv); static int cmd_setbuf(int argc, char **argv); +static void control_timer(int type); +static int subscribe_to(int client, int port); struct { @@ -359,13 +369,18 @@ static void compute_sample_increment(void); static void server_reset(void); +static struct seq_context alsactx; +static struct seq_context *ctxp = &alsactx; + static void ctl_pass_playing_list(int n, char *args[]) { - int sock; + snd_seq_port_info_t pinfo; - if(n != 2 && n != 1) + ctxp = &alsactx; + + if(n > 2) { - fprintf(stderr, "Usage: timidity -ir control-port [data-port]\n"); + fprintf(stderr, "Usage: timidity -ir [client [port]]\n"); return; } @@ -373,15 +388,26 @@ signal(SIGPIPE, SIG_IGN); /* Handle broken pipe */ #endif /* SIGPIPE */ - control_port = atoi(args[0]); - if(n == 2) - data_port = atoi(args[1]); - else - data_port = 0; + printf("Timidity starting in ALSA server mode\n"); + snd_seq_open(&ctxp->handle, SND_SEQ_OPEN); + ctxp->client = snd_seq_client_id(ctxp->handle); + ctxp->queue = snd_seq_alloc_queue(ctxp->handle); + ctxp->fd = snd_seq_file_descriptor(ctxp->handle); + memset(&pinfo, 0, sizeof(pinfo)); + strcpy(pinfo.name, "Timidity receive port"); + pinfo.capability = SND_SEQ_PORT_CAP_SUBSCRIPTION | SND_SEQ_PORT_CAP_OUT; + pinfo.type = SND_SEQ_PORT_TYPE_MIDI_GENERIC; + pinfo.midi_channels = 16; + pinfo.out_use = 1; + pinfo.in_use = 0; + pinfo.kernel = NULL; + snd_seq_create_port(ctxp->handle, &pinfo); + + if (n > 0) + subscribe_to(atoi(args[0]), (n>1)? atoi(args[1]):0); + + control_timer(SND_SEQ_EVENT_START); - sock = pasv_open(&control_port); - if(sock == -1) - return; opt_realtime_playing = 2; /* Enable loading patch while playing */ allocate_cache_size = 0; /* Don't use pre-calclated samples */ /* aq_set_soft_queue(-1.0, 0.0); */ @@ -391,22 +417,6 @@ play_mode->close_output(); while(1) { - int addrlen; - - addrlen = sizeof(control_client); - memset(&control_client, 0, addrlen); - - if((control_fd = accept(sock, - (struct sockaddr *)&control_client, - &addrlen)) < 0) - { - if(errno == EINTR) - continue; - perror("accept"); - close(sock); - return; - } - if(play_mode->open_output() < 0) { ctl.cmsg(CMSG_FATAL, VERB_NORMAL, @@ -592,103 +602,73 @@ static void doit(void) { - memset(&control_fd_buffer, 0, sizeof(control_fd_buffer)); - control_fd_buffer.fd = control_fd; send_status(220, "TiMidity++ v%s ready", timidity_version); -/* while(data_fd != -1 && control_fd != -1) */ - while(control_fd != -1) + while(1) { fd_set fds; int n, maxfd; + long usec = 1000; - if(data_fd == -1) - { - if(do_control_command()) - break; - } + FD_ZERO(&fds); + FD_SET(ctxp->fd, &fds); + maxfd = ctxp->fd; + + if(upper_voices == 0 || !IS_STREAM_TRACE) + usec = -1; else { - long usec; + double wait_time; + int32 filled; - FD_ZERO(&fds); - FD_SET(control_fd, &fds); - FD_SET(data_fd, &fds); - if(control_fd > data_fd) - maxfd = control_fd; + filled = aq_filled(); + if(tmr_running && filled <= 0) + usec = -1; else - maxfd = data_fd; - - if(data_fd != -1) { - if(upper_voices == 0 || !IS_STREAM_TRACE) - usec = -1; + wait_time = (double)filled / play_mode->rate + - low_time_at; + if(wait_time <= 0) + usec = 0; else - { - double wait_time; - int32 filled; - - filled = aq_filled(); - if(tmr_running && filled <= 0) - usec = -1; - else - { - wait_time = (double)filled / play_mode->rate - - low_time_at; - if(wait_time <= 0) - usec = 0; - else - usec = (long)(wait_time * 1000000); - } - } + usec = (long)(wait_time * 1000000); } - else - usec = -1; + } + if(usec >= 0) + { + struct timeval timeout; + timeout.tv_sec = usec / 1000000; + timeout.tv_usec = usec % 1000000; + n = select(maxfd + 1, &fds, NULL, NULL, &timeout); + } + else + n = select(maxfd + 1, &fds, NULL, NULL, NULL); - if(usec >= 0) - { - struct timeval timeout; - timeout.tv_sec = usec / 1000000; - timeout.tv_usec = usec % 1000000; - n = select(maxfd + 1, &fds, NULL, NULL, &timeout); - } - else - n = select(maxfd + 1, &fds, NULL, NULL, NULL); + if(n < 0) + { + perror("select"); + break; + } - if(n < 0) + if(n == 0) + { + if(ctl.verbosity >= VERB_DEBUG) { - perror("select"); - break; - } - - if(n == 0) - { - if(ctl.verbosity >= VERB_DEBUG) - { - putchar(','); - fflush(stdout); - } - do_timeout(); - continue; + putchar(','); + fflush(stdout); } + do_timeout(); + continue; + } - if(control_fd != -1 && FD_ISSET(control_fd, &fds)) - { - if(do_control_command()) - { - close(control_fd); - control_fd = -1; - } - } - else if(data_fd != -1 && FD_ISSET(data_fd, &fds)) + if(FD_ISSET(ctxp->fd, &fds)) + { + if(do_sequencer()) { - if(do_sequencer()) - { - close(data_fd); - data_fd = -1; - send_status(403, "Data connection is closed"); - } + close(data_fd); + data_fd = -1; + send_status(403, "Data connection is closed"); } } } @@ -701,10 +681,10 @@ { double fill_time; - if(data_fd == -1 || !IS_STREAM_TRACE) + if(!IS_STREAM_TRACE) return; aq_add(NULL, 0); - fill_time = high_time_at - (double)aq_filled() / play_mode->rate; + fill_time = high_time_at - (double)aq_filled() / play_mode->rate;/*XXX*/ if(fill_time <= 0) return; @@ -713,6 +693,8 @@ else { MidiEvent ev; + /* This is overridden from above */ + fill_time = 0.001; /* ADJUST */ event_time_offset += (int32)(fill_time * play_mode->rate); ev.time = curr_event_samples + event_time_offset; @@ -1120,11 +1102,10 @@ { int n, offset; MidiEvent ev; + snd_seq_event_t *aevp; + int events_done; - n = read(data_fd, data_buffer + data_buffer_len, - sizeof(data_buffer) - data_buffer_len); - - if(n <= 0) + if(0) { stop_playing(); return n; @@ -1139,17 +1120,66 @@ } #endif /* DEBUG_DUMP_SEQ */ - data_buffer_len += n; offset = 0; - while(offset < data_buffer_len) - { - int cmd; - cmd = data_buffer[offset]; + events_done = 0; + do { + n = snd_seq_event_input(ctxp->handle, &aevp); + if (aevp == NULL) + return 0; #define READ_NEEDBUF(x) if(offset + x > data_buffer_len) goto done; #define READ_ADVBUF(x) offset += x; - switch(cmd) + switch(aevp->type) { + case SND_SEQ_EVENT_NOTEON: + ev.channel = aevp->dest.channel; + 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 = aevp->dest.channel; + 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_PGMCHANGE: + ev.channel = aevp->dest.channel; + 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(aevp->dest.channel, + aevp->data.control.param, + aevp->data.control.value, + &ev)) + seq_play_event(&ev); + break; + + case SND_SEQ_EVENT_PITCHBEND: + ev.type = ME_PITCHWHEEL; + ev.channel = aevp->dest.channel; + 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 50: /* Active sensing */ + break; + default: + printf("Unknown event %d\n", aevp->type); + break; +#if 0 case EV_CHN_VOICE: READ_NEEDBUF(8); do_chn_voice(data_buffer + offset); @@ -1299,17 +1329,14 @@ cmd); stop_playing(); return 1; +#endif } #undef READ_NEEDBUF #undef READ_ADVBUF - } + + } while (n > 0); done: - if(offset) - { - data_buffer_len -= offset; - memmove(data_buffer, data_buffer + offset, data_buffer_len); - } return 0; } @@ -1591,4 +1618,51 @@ ControlMode *interface_r_loader(void) { return &ctl; +} + +static void control_timer(int type) +{ + snd_seq_event_t ev; + + ev.dest.queue = ctxp->queue; + ev.dest.client = SND_SEQ_CLIENT_SYSTEM; /* system */ + ev.dest.port = SND_SEQ_PORT_SYSTEM_TIMER; /* timer */ + ev.dest.channel = 0; /* don't care */ + + ev.flags = SND_SEQ_TIME_STAMP_REAL | SND_SEQ_TIME_MODE_REL; + ev.time.real.tv_sec = 0; + ev.time.real.tv_nsec = 0; + + ev.type = type; + + snd_seq_event_output(ctxp->handle, &ev); + snd_seq_flush_output(ctxp->handle); +} + +static int subscribe_to(int client, int port) +{ + snd_seq_port_subscribe_t subs; + snd_seq_addr_t addr; + snd_seq_addr_t source; + int ret; + + source.queue = ctxp->queue; + source.client = client; + source.port = port; + source.channel = 0; + + addr.queue = ctxp->queue; + addr.client = ctxp->client; + addr.port = 0; + + subs.sender = source; + subs.dest = addr; + subs.realtime = 0; /* XXX */ + subs.exclusive = 0; + ret = snd_seq_subscribe_port(ctxp->handle, &subs); + if (ret < 0) + printf("Could not subscribe %d:%d %s\n", client, port, + snd_strerror(ret)); + + return ret; } --- ./timidity/alsa_a.c.ORIG Mon Feb 22 09:31:48 1999 +++ ./timidity/alsa_a.c Sun Jun 20 16:09:06 1999 @@ -68,7 +68,7 @@ #define dpm alsa_play_mode PlayMode dpm = { - DEFAULT_RATE, PE_16BIT|PE_SIGNED, PF_PCM_STREAM|PF_CAN_TRACE, + DEFAULT_RATE, PE_16BIT|PE_SIGNED, PF_PCM_STREAM|PF_CAN_TRACE|PF_BUFF_FRAGM_OPT, -1, {0}, /* default: get all the buffer fragments you can */ "ALSA pcm device", 's', @@ -341,15 +341,17 @@ /* Set buffer fragments (in extra_param[0]) */ tmp = AUDIO_BUFFER_BITS; + tmp = 8; /* Adjust to taste */ +#if 0 if (!(*encoding__ & PE_MONO)) tmp++; if (*encoding__ & PE_16BIT) tmp++; -#if 0 - tmp++; +#endif +#if 1 playback_params.fragment_size = (1 << tmp); if (extra_param[0] == 0) - playback_params.fragments_max = 7;/*default value. What's value is apporpriate?*/ + playback_params.fragments_max = 32;/*default value. What's value is apporpriate?*/ else playback_params.fragments_max = extra_param[0]; #else