Makefile.in: switch from git-tar-tree to git-archive
[paraslash.git] / afs.c
diff --git a/afs.c b/afs.c
index 6cc58bb..2d4184d 100644 (file)
--- a/afs.c
+++ b/afs.c
  * the current audio format, audio file selector and of the activated senders.
  */
 
+#include "server.h"
 #include <sys/time.h> /* gettimeofday */
 #include "server.cmdline.h"
 #include "db.h"
-#include "server.h"
+#include "afh.h"
 #include "afs.h"
 #include "send.h"
 #include "error.h"
@@ -36,26 +37,29 @@ extern const char *status_item_list[];
 static struct timeval announce_tv;
 static struct timeval data_send_barrier;
 static struct timeval eof_barrier;
+static struct timeval autoplay_barrier;
 
 extern struct misc_meta_data *mmd;
 extern struct audio_file_selector selectors[];
 extern struct sender senders[];
-extern struct gengetopt_args_info conf;
 
 static FILE *audio_file = NULL;
 
 #if 1
-       void mp3_init(void *);
+       void mp3_init(struct audio_format_handler *);
 #endif
 
 #ifdef HAVE_OGGVORBIS
-       void ogg_init(void *);
+       void ogg_init(struct audio_format_handler *);
+#endif
+#ifdef HAVE_FAAD
+       void aac_afh_init(struct audio_format_handler *);
 #endif
 
 /**
  * the list of supported  audio formats
  */
-struct audio_format afl[] = {
+static struct audio_format_handler afl[] = {
 #if 1
        {
                .name = "mp3",
@@ -67,12 +71,18 @@ struct audio_format afl[] = {
                .name = "ogg",
                .init = ogg_init,
        },
+#endif
+#ifdef HAVE_FAAD
+       {
+               .name = "aac",
+               .init = aac_afh_init,
+       },
 #endif
        {
                .name = NULL,
        }
 };
-
+#define FOR_EACH_AUDIO_FORMAT(i) for (i = 0; afl[i].name; i++)
 
 /**
  * check if audio file sender is playing
@@ -157,6 +167,14 @@ void afs_init(void)
        }
        free(hn);
        free(home);
+       if (conf.autoplay_given) {
+               struct timeval now, tmp;
+               mmd->afs_status_flags |= AFS_PLAYING;
+               mmd->new_afs_status_flags |= AFS_PLAYING;
+               gettimeofday(&now, NULL);
+               ms2tv(conf.autoplay_delay_arg, &tmp);
+               tv_add(&now, &tmp, &autoplay_barrier);
+       }
 }
 
 static int get_file_info(int i)
@@ -165,25 +183,30 @@ static int get_file_info(int i)
                &mmd->chunks_total, &mmd->seconds_total);
 }
 
-/*
+/**
  * guess the audio format judging from filename
+ *
  * \param name the filename
  *
  * \return This function returns -1 if it has no idea what kind of audio
  * file this might be. Otherwise the (non-negative) number of the audio format
  * is returned.
  */
-static int guess_audio_format(const char *name)
+int guess_audio_format(const char *name)
 {
-
-       int i, len1 = strlen(name), len2;
-
-       for (i = 0; afl[i].name; i++) {
-               len2 = strlen(afl[i].name);
-               if (len1 < len2)
-                       continue;
-               if (!strncasecmp(name + (len1 - len2), afl[i].name, len2)) {
-                       PARA_DEBUG_LOG("might be %s\n", afl[i].name);
+       int i,j, len = strlen(name);
+
+       FOR_EACH_AUDIO_FORMAT(i) {
+               for (j = 0; afl[i].suffixes[j]; j++) {
+                       const char *p = afl[i].suffixes[j];
+                       int plen = strlen(p);
+                       if (len < plen + 1)
+                               continue;
+                       if (name[len - plen - 1] != '.')
+                               continue;
+                       if (strcasecmp(name + len - plen, p))
+                               continue;
+//                     PARA_DEBUG_LOG("might be %s\n", audio_format_name(i));
                        return i;
                }
        }
@@ -194,7 +217,7 @@ static int get_audio_format(int omit)
 {
        int i;
 
-       for (i = 0; afl[i].name; i++) {
+       FOR_EACH_AUDIO_FORMAT(i) {
                if (i == omit || !afl[i].get_file_info)
                        continue;
                rewind(audio_file);
@@ -274,14 +297,15 @@ free:
 }
 
 static int chk_barrier(const char *bname, const struct timeval *now,
-               const struct timeval *barrier, struct timeval *diff, int log)
+               const struct timeval *barrier, struct timeval *diff,
+               int print_log)
 {
        long ms;
 
        if (tv_diff(now, barrier, diff) > 0)
                return 1;
        ms = tv2ms(diff);
-       if (log && ms)
+       if (print_log && ms)
                PARA_DEBUG_LOG("%s barrier: %lims left\n", bname, ms);
        return -1;
 }
@@ -310,6 +334,9 @@ static struct timeval *afs_compute_timeout(void)
                return &the_timeout;
        }
        gettimeofday(&now, NULL);
+       if (chk_barrier("autoplay_delay", &now, &autoplay_barrier,
+                       &the_timeout, 1) < 0)
+               return &the_timeout;
        if (chk_barrier("eof", &now, &eof_barrier, &the_timeout, 1) < 0)
                return &the_timeout;
        if (chk_barrier("data send", &now, &data_send_barrier,
@@ -327,7 +354,7 @@ static struct timeval *afs_compute_timeout(void)
        return &the_timeout;
 }
 
-static void afs_eof(struct audio_format *af)
+static void afs_eof(struct audio_format_handler *af)
 {
        struct timeval now;
        int i;
@@ -360,6 +387,43 @@ static void afs_eof(struct audio_format *af)
        mmd->events++;
 }
 
+/**
+ * get the header and of the current audio file
+ *
+ * \param header_len the length of the header is stored here
+ *
+ * \return a pointer to a buffer containing the header, or NULL, if no audio
+ * file is selected or if the current audio format does not need special header
+ * treamtment.
+ *
+ */
+char *afs_get_header(int *header_len)
+{
+       *header_len = 0;
+       if (mmd->audio_format < 0)
+               return NULL;
+       if (!afl[mmd->audio_format].get_header_info)
+               return NULL;
+       return afl[mmd->audio_format].get_header_info(header_len);
+}
+const char *supported_audio_formats(void)
+{
+       return SUPPORTED_AUDIO_FORMATS;
+}
+
+/**
+ * get the chunk time of the current audio file
+ *
+ * \return a pointer to a struct containing the chunk time, or NULL,
+ * if currently no audio file is selected.
+ */
+struct timeval *afs_chunk_time(void)
+{
+       if (mmd->audio_format < 0)
+               return NULL;
+       return &afl[mmd->audio_format].chunk_tv;
+}
+
 /**
  * compute the timeout for para_server's main select-loop
  *
@@ -370,16 +434,16 @@ static void afs_eof(struct audio_format *af)
  * and acted upon by calling appropriate functions from the lower layers.
  * Possible actions include
  *
- *     - request a new file list from the current dabase tool (audio file change)
+ *     - request a new file list from the current audio file selector
  *     - shutdown of all senders (stop/pause command)
- *     - repositioning of the stream (ff/jmp command)
+ *     - reposition the stream (ff/jmp command)
  *
  * \return A pointer to a struct timeval containing the timeout for the next
  * chunk of data to be sent, or NULL if we're not sending right now.
  */
 struct timeval *afs_preselect(void)
 {
-       struct audio_format *af = NULL;
+       struct audio_format_handler *af = NULL;
        int i, format;
        struct timeval *ret;
 again:
@@ -440,7 +504,7 @@ again:
 void afs_send_chunk(void)
 {
        int i;
-       struct audio_format *af;
+       struct audio_format_handler *af;
        char *buf;
        ssize_t ret;
        struct timeval now, due;
@@ -475,8 +539,7 @@ void afs_send_chunk(void)
                mmd->events++;
        }
        for (i = 0; senders[i].name; i++)
-               senders[i].send(af, mmd->current_chunk,
-                       mmd->chunks_sent, buf, ret);
+               senders[i].send(mmd->current_chunk, mmd->chunks_sent, buf, ret);
        mmd->new_afs_status_flags |= AFS_PLAYING;
        mmd->chunks_sent++;
        mmd->current_chunk++;