]> git.alsa-project.org Git - alsa-lib.git/commitdiff
Added PCM timer selection for seq sender...
authorJaroslav Kysela <perex@perex.cz>
Wed, 7 Jul 1999 08:42:12 +0000 (08:42 +0000)
committerJaroslav Kysela <perex@perex.cz>
Wed, 7 Jul 1999 08:42:12 +0000 (08:42 +0000)
test/Makefile.am
test/seq-sender.c

index d2869c9dd3b86e9553965eadd58901bafc542745..97a52ea8f0b18451b0b82173fa9151960dfe0619 100644 (file)
@@ -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
index ffd8474f20319e3fd74f0c4e316f47fb080c7554..0e380607bded3dc17314a16abc34401008b354cd 100644 (file)
@@ -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;