Fix --device bug
[paraslash.git] / play.c
diff --git a/play.c b/play.c
index 99c231697c76707008326ce2b587d4f5558b177f..c7289c020d5114629b066d401c8158a429a02df2 100644 (file)
--- a/play.c
+++ b/play.c
@@ -57,7 +57,7 @@ enum {        E_BROKEN_CONF,          /* Broken configuration for this PCM */
 
 #define EXIT(EXP) \
 do { if (EXP) \
-        fprintf (stderr, "error: " #EXP "\n"); exit(EXP);} \
+       fprintf (stderr, "error: " #EXP "\n"); exit(EXP);} \
 while (0)
 
 static snd_pcm_t *handle;
@@ -151,25 +151,19 @@ static void set_alsa_params(void)
 
 /*
  * pcm_write - push out pcm frames
- * @data: pointer do data to be written
- * @count: number of frames
+ * \param data pointer do data to be written
+ * \param count number of frames
  *
- * Return value: Number of bytes written. Exit on errors.
+ * \return Number of bytes written. Exit on errors.
  */
 static snd_pcm_sframes_t pcm_write(u_char *data, size_t count)
 {
        snd_pcm_sframes_t r, result = 0;
-#if 0
-       if (count < chunk_size) {
-               snd_pcm_format_set_silence(FORMAT, data
-                       + count * bytes_per_frame,
-                       (chunk_size - count) * conf.channels_arg);
-               count = chunk_size;
-       }
-#endif
        while (count > 0) {
                /* write interleaved frames */
                r = snd_pcm_writei(handle, data, count);
+               if (r < 0)
+                       fprintf(stderr, "write error: %s\n", snd_strerror(r));
                if (r == -EAGAIN || (r >= 0 && r < count))
                        snd_pcm_wait(handle, 1);
                else if (r == -EPIPE)
@@ -187,7 +181,7 @@ static snd_pcm_sframes_t pcm_write(u_char *data, size_t count)
 
 /*
  * start_time_in_future - check if current time is later than start_time
- * @diff: pointer to write remaining time to
+ * \param diff pointer to write remaining time to
  *
  * If start_time was not given, or current time is later than given
  * start_time, return 0. Otherwise, return 1 and write the time
@@ -213,79 +207,69 @@ static int start_time_in_future(struct timeval *diff)
  * or if the given start time is in the past.
  *
  */
-static void do_initial_delay(void)
+static void do_initial_delay(struct timeval *delay)
 {
-       struct timeval diff;
-       int ret;
-
-       fprintf(stderr, "initial delay\n");
-       if (!conf.start_time_given)
-               return;
-again:
-       if (!start_time_in_future(&diff))
-               return;
-       ret = select(1, NULL, NULL, NULL, &diff);
-       if (ret < 0 && errno == EINTR)
-               goto again;
+       fprintf(stderr, "sleeping %lums\n", tv2ms(delay));
+       do
+               select(1, NULL, NULL, NULL, delay);
+       while (start_time_in_future(delay));
 }
 
-
 /*
  * play_pcm - play raw pcm data
- * @l: number of bytes already loaded
+ * \param loaded number of bytes already loaded
  *
  * If start_time was given, prebuffer data until buffer is full or
  * start_time is reached. In any case, do not start playing before
  * start_time.
  */
-static void play_pcm(size_t l)
+static void play_pcm(size_t loaded)
 {
-       ssize_t r, w;
-       unsigned long written = 0;
-       size_t chunk_bytes;
+       size_t chunk_bytes, bufsize, written = 0;
+       ssize_t ret;
+       unsigned char *p;
+       int dont_write;
+       struct timeval delay;
 
        set_alsa_params();
        chunk_bytes = chunk_size * bytes_per_frame;
-       audiobuf = realloc(audiobuf, BUFFER_SIZE);
-//     fprintf(stderr, "loaded: %d, chunk_bytes: %d\n", l, chunk_bytes);
+       bufsize = chunk_bytes * 1024;
+       audiobuf = realloc(audiobuf, bufsize);
        if (!audiobuf)
                EXIT(E_MEM);
-       for (;;) {
-               for (;;) {
-                       if (l >= chunk_bytes) {
-                               if (written)
-                                       break;
-                               if (!start_time)
-                                       break;
-                               if (!start_time_in_future(NULL))
-                                       break;
-                               if (l > BUFFER_SIZE) {
-                                       do_initial_delay();
-                                       break;
-                               }
+again:
+       dont_write = 0;
+       if (!written && start_time)
+               dont_write = start_time_in_future(&delay);
+       if (!dont_write) {
+               p = audiobuf;
+               while (loaded >= chunk_bytes) {
+                       ret = (ssize_t) pcm_write(p, chunk_size) * bytes_per_frame;
+                       if (ret <= 0) {
+                               fprintf(stderr, "write error: %d\n", ret);
+                               EXIT(E_WRITE);
                        }
-//                     fprintf(stderr, "l = %d, chunk_Bytes = %d\n", l, chunk_bytes);
-                       r = read(STDIN_FILENO, audiobuf + l, BUFFER_SIZE -l);
-                       if (r < 0)
-                               EXIT(E_READ);
-                       l += r;
-//                     fprintf(stderr, "loaded: %d, r= %d\n", l, r);
-                       if (!r)
-                               goto out;;
+                       p += ret;
+                       written += ret;
+                       loaded -= ret;
                }
-               w = MIN(chunk_bytes, l);
-//             fprintf(stderr, "play: writing %d\n", w);
-               r = (ssize_t) pcm_write(audiobuf, w / bytes_per_frame) * bytes_per_frame;
-//             fprintf(stderr, "wrote %d\n", r);
-               if (r < 0)
-                       EXIT(E_WRITE);
-               written += r;
-               l -= r;
-               if (l)
-                       memmove(audiobuf, audiobuf + r, l);
-//             fprintf(stderr, "written %lu, loaded : %d\n", written, l);
+               if (loaded && p != audiobuf) {
+                       fprintf(stderr, "memcpy: %d\n", loaded);
+                       memcpy(audiobuf, p, loaded);
+               }
+       }
+       if (dont_write && loaded >= bufsize) {
+               do_initial_delay(&delay);
+               start_time = NULL;
+               goto again;
+       }
+       ret = read(STDIN_FILENO, audiobuf, bufsize - loaded);
+       if (ret < 0)
+               EXIT(E_READ);
+       if (ret) {
+               loaded += ret;
+               goto again;
        }
-out:
        snd_pcm_drain(handle);
 }
 
@@ -325,7 +309,7 @@ int main(int argc, char *argv[])
        snd_pcm_info_alloca(&info);
        if (snd_output_stdio_attach(&log, stderr, 0) < 0)
                EXIT(E_LOG);
-       err = snd_pcm_open(&handle, "plug:swmix",
+       err = snd_pcm_open(&handle, conf.device_arg,
                SND_PCM_STREAM_PLAYBACK, 0);
        if (err < 0)
                EXIT(E_PCM_OPEN);
@@ -336,7 +320,7 @@ int main(int argc, char *argv[])
        play_pcm(check_wave());
        snd_pcm_close(handle);
        free(audiobuf);
-       snd_output_close(log);
+//     snd_output_close(log);
        snd_config_update_free_global();
        return EXIT_SUCCESS;
 }