From 452d7704e1cfbf77fc64a69876a2fd5b0441ac10 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Wed, 7 Jul 1999 08:42:12 +0000 Subject: [PATCH] Added PCM timer selection for seq sender... --- test/Makefile.am | 4 +- test/seq-sender.c | 121 +++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 115 insertions(+), 10 deletions(-) diff --git a/test/Makefile.am b/test/Makefile.am index d2869c9d..97a52ea8 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -1,5 +1,5 @@ -check_PROGRAMS=control mixer switches pause pcm latency seq playmidi1 timer \ - loopback +check_PROGRAMS=control mixer switches pause pcm latency seq \ + playmidi1 timer loopback control_LDADD=../src/libasound.la mixer_LDADD=../src/libasound.la diff --git a/test/seq-sender.c b/test/seq-sender.c index ffd8474f..0e380607 100644 --- a/test/seq-sender.c +++ b/test/seq-sender.c @@ -1,12 +1,83 @@ +/* + * PCM timer layer + */ + +int pcard = 0; +int pdevice = 0; +int pfragment_size = 4096; + +void set_format(snd_pcm_t *phandle) +{ + int err; + snd_pcm_format_t format; + + bzero(&format, sizeof(format)); + format.format = SND_PCM_SFMT_S16_LE; + format.channels = 2; + format.rate = 44100; + if ((err = snd_pcm_playback_format(phandle, &format)) < 0) { + fprintf(stderr, "Playback format error: %s\n", snd_strerror(err)); + exit(0); + } +} + +void set_fragment(snd_pcm_t *phandle) +{ + int err; + snd_pcm_playback_params_t pparams; + + bzero(&pparams, sizeof(pparams)); + pparams.fragment_size = pfragment_size; + pparams.fragments_max = -1; /* maximum */ + pparams.fragments_room = 1; + if ((err = snd_pcm_playback_params(phandle, &pparams)) < 0) { + fprintf(stderr, "Fragment setup error: %s\n", snd_strerror(err)); + exit(0); + } +} + +void show_playback_status(snd_pcm_t *phandle) +{ + int err; + snd_pcm_playback_status_t pstatus; + + if ((err = snd_pcm_playback_status(phandle, &pstatus)) < 0) { + fprintf(stderr, "Playback status error: %s\n", snd_strerror(err)); + exit(0); + } + printf("Playback status\n"); + printf(" Real rate : %u\n", pstatus.rate); + printf(" Fragments : %i\n", pstatus.fragments); + printf(" Fragment size : %i\n", pstatus.fragment_size); +} + /* * Simple event sender */ -void event_sender_start_timer(snd_seq_t *handle, int client, int queue) +void event_sender_start_timer(snd_seq_t *handle, int client, int queue, snd_pcm_t *phandle) { int err; snd_seq_event_t ev; + if (phandle) { + snd_pcm_playback_info_t pinfo; + snd_seq_queue_timer_t qtimer; + + if ((err = snd_pcm_playback_info(phandle, &pinfo)) < 0) { + fprintf(stderr, "Playback info error: %s\n", snd_strerror(err)); + exit(0); + } + bzero(&qtimer, sizeof(qtimer)); + qtimer.type = SND_SEQ_TIMER_MASTER; + /* note: last bit from subdevices specifies playback */ + /* or capture direction for the timer specification */ + qtimer.number = SND_TIMER_PCM(pcard, pdevice, pinfo.subdevice << 1); + if ((err = snd_seq_set_queue_timer(handle, queue, &qtimer)) < 0) { + fprintf(stderr, "Sequencer PCM timer setup failed: %s\n", snd_strerror(err)); + exit(0); + } + } bzero(&ev, sizeof(ev)); ev.source.queue = queue; ev.source.client = client; @@ -18,6 +89,7 @@ void event_sender_start_timer(snd_seq_t *handle, int client, int queue) ev.type = SND_SEQ_EVENT_START; if ((err = snd_seq_event_output(handle, &ev))<0) fprintf(stderr, "Timer event output error: %s\n", snd_strerror(err)); + /* ugly, but working */ while (snd_seq_flush_output(handle)>0) sleep(1); } @@ -74,10 +146,12 @@ void event_sender(snd_seq_t *handle, int argc, char *argv[]) snd_seq_port_info_t port; snd_seq_port_subscribe_t sub; fd_set out, in; - int client, queue, max, err, v1, v2, time = 0, first; + int client, queue, max, err, v1, v2, time = 0, first, pcm_flag = 0; char *ptr; + snd_pcm_t *phandle = NULL; + char *pbuf = NULL; - if (argc != 1) { + if (argc < 1) { fprintf(stderr, "Invalid destonation...\n"); return; } @@ -95,7 +169,6 @@ void event_sender(snd_seq_t *handle, int argc, char *argv[]) event_sender_filter(handle); if ((err = snd_seq_block_mode(handle, 0))<0) fprintf(stderr, "Cannot set nonblock mode: %s\n", snd_strerror(err)); - event_sender_start_timer(handle, client, queue); bzero(&port, sizeof(port)); strcpy(port.name, "Output"); if ((err = snd_seq_create_port(handle, &port)) < 0) { @@ -114,6 +187,10 @@ void event_sender(snd_seq_t *handle, int argc, char *argv[]) ptr = argv[max]; if (!ptr) continue; + if (!strcmp(ptr, "pcm")) { + pcm_flag = 1; + continue; + } if (sscanf(ptr, "%i.%i", &v1, &v2) != 2) { fprintf(stderr, "Wrong argument '%s'...\n", argv[max]); return; @@ -127,22 +204,50 @@ void event_sender(snd_seq_t *handle, int argc, char *argv[]) } printf("Destonation client = %i, port = %i\n", sub.dest.client, sub.dest.port); + + if (pcm_flag) { + if ((err = snd_pcm_open(&phandle, pcard, pdevice, SND_PCM_OPEN_PLAYBACK)) < 0) { + fprintf(stderr, "Playback open error: %s\n", snd_strerror(err)); + exit(0); + } + set_format(phandle); + set_fragment(phandle); + show_playback_status(phandle); + pbuf = calloc(1, pfragment_size); + if (pbuf == NULL) { + fprintf(stderr, "No enough memory...\n"); + exit(0); + } + } + event_sender_start_timer(handle, client, queue, phandle); first = 1; while (1) { FD_ZERO(&out); FD_ZERO(&in); - FD_SET(max = snd_seq_file_descriptor(handle), &out); - FD_SET(max = snd_seq_file_descriptor(handle), &in); + max = snd_seq_file_descriptor(handle); + FD_SET(snd_seq_file_descriptor(handle), &out); + FD_SET(snd_seq_file_descriptor(handle), &in); + if (phandle) { + if (snd_pcm_file_descriptor(phandle) > max) + max = snd_pcm_file_descriptor(phandle); + FD_SET(snd_pcm_file_descriptor(phandle), &out); + } if (select(max + 1, &in, &out, NULL, NULL) < 0) break; - if (FD_ISSET(max, &out)) { + if (phandle && FD_ISSET(snd_pcm_file_descriptor(phandle), &out)) { + if (snd_pcm_write(phandle, pbuf, pfragment_size) != pfragment_size) { + fprintf(stderr, "Playback write error!!\n"); + exit(0); + } + } + if (FD_ISSET(snd_seq_file_descriptor(handle), &out)) { if (first) { send_event(handle, queue, client, port.port, &sub, &time); first = 0; } } - if (FD_ISSET(max, &in)) { + if (FD_ISSET(snd_seq_file_descriptor(handle), &in)) { do { if ((err = snd_seq_event_input(handle, &ev))<0) break; -- 2.47.1