Move struct senders[] from server.c to vss.c.
[paraslash.git] / vss.c
diff --git a/vss.c b/vss.c
index 1be4cd15d1db262dd5f79a43b19e7bba09f2087a..e21a1ff4fd13a715fc465c2c2758f72961856aa3 100644 (file)
--- a/vss.c
+++ b/vss.c
@@ -36,7 +36,33 @@ static struct timeval eof_barrier;
 static struct timeval autoplay_barrier;
 
 extern struct misc_meta_data *mmd;
-extern struct sender senders[];
+
+extern void dccp_send_init(struct sender *);
+extern void http_send_init(struct sender *);
+extern void ortp_send_init(struct sender *);
+
+/** the list of supported senders */
+struct sender senders[] = {
+       {
+               .name = "http",
+               .init = http_send_init,
+       },
+       {
+               .name = "dccp",
+               .init = dccp_send_init,
+       },
+#ifdef HAVE_ORTP
+       {
+               .name = "ortp",
+               .init = ortp_send_init,
+       },
+#endif
+       {
+               .name = NULL,
+       }
+};
+
+
 
 static char *map;
 
@@ -97,6 +123,25 @@ unsigned int vss_stopped(void)
                && !(mmd->new_vss_status_flags & VSS_PLAYING);
 }
 
+/**
+ * Get the data of the given chunk.
+ *
+ * \param chunk_num The number of the desired chunk.
+ * \param buf Chunk data.
+ * \param len Chunk length in bytes.
+ *
+ * \return Standard.
+ */
+int vss_get_chunk(long unsigned chunk_num, char **buf, size_t *len)
+{
+       if (!map || !vss_playing())
+               return -E_CHUNK;
+       if (chunk_num >= mmd->afd.afhi.chunks_total)
+               return -E_CHUNK;
+       afh_get_chunk(chunk_num, &mmd->afd.afhi, map, buf, len);
+       return 1;
+}
+
 /**
  * Initialize the virtual streaming system.
  *
@@ -119,6 +164,7 @@ void vss_init(void)
        }
        free(hn);
        free(home);
+       mmd->sender_cmd_data.cmd_num = -1;
        if (conf.autoplay_given) {
                struct timeval now, tmp;
                mmd->vss_status_flags |= VSS_PLAYING;
@@ -182,14 +228,8 @@ static struct timeval *vss_compute_timeout(void)
 static void vss_eof(void)
 {
        struct timeval now;
-       int i;
        char *tmp;
 
-       if (!map) {
-               for (i = 0; senders[i].name; i++)
-                       senders[i].shutdown_clients();
-               return;
-       }
        if (mmd->new_vss_status_flags & VSS_NOMORE)
                mmd->new_vss_status_flags = VSS_NEXT;
        gettimeofday(&now, NULL);
@@ -262,6 +302,19 @@ enum afs_socket_status {
 
 static enum afs_socket_status afsss;
 
+static int need_to_request_new_audio_file(void)
+{
+       if (map) /* have audio file */
+               return 0;
+       if (!vss_playing()) /* don't need one */
+               return 0;
+       if (mmd->new_vss_status_flags & VSS_NOMORE)
+               return 0;
+       if (afsss == AFS_SOCKET_AFD_PENDING) /* already requested one */
+               return 0;
+       return 1;
+}
+
 /**
  * Compute the timeout for para_server's main select-loop.
  *
@@ -286,48 +339,40 @@ static enum afs_socket_status afsss;
 struct timeval *vss_preselect(fd_set *rfds, fd_set *wfds, int *max_fileno)
 {
        int i;
-       struct timeval *tv;
+       struct timeval now;
 
-       para_fd_set(afs_socket, rfds, max_fileno);
-       if (!map)
+       if (!map || vss_next() || vss_paused() || vss_repos())
                for (i = 0; senders[i].name; i++)
                        senders[i].shutdown_clients();
-       else {
-               if (vss_next()) {
-                       vss_eof();
-                       return vss_compute_timeout();
-               }
-       }
-       if (vss_paused() || vss_repos()) {
-               for (i = 0; senders[i].name; i++)
-                       senders[i].shutdown_clients();
-               if (map) {
-                       struct timeval now;
+       if (vss_next())
+               vss_eof();
+       else if (vss_paused()) {
+               if (mmd->chunks_sent) {
                        gettimeofday(&now, NULL);
-                       if (!vss_paused() || mmd->chunks_sent)
-                               tv_add(&mmd->afd.afhi.eof_tv, &now, &eof_barrier);
-                       if (vss_repos())
-                               tv_add(&now, &announce_tv, &data_send_barrier);
+                       tv_add(&mmd->afd.afhi.eof_tv, &now, &eof_barrier);
                }
                mmd->chunks_sent = 0;
-       }
-       if (vss_repos()) {
-               mmd->new_vss_status_flags &= ~(VSS_REPOS);
+       } else if (vss_repos()) {
+               gettimeofday(&now, NULL);
+               tv_add(&now, &announce_tv, &data_send_barrier);
+               tv_add(&mmd->afd.afhi.eof_tv, &now, &eof_barrier);
+               mmd->chunks_sent = 0;
                mmd->current_chunk = mmd->repos_request;
+               mmd->new_vss_status_flags &= ~VSS_REPOS;
        }
-       tv = vss_compute_timeout();
-       if (tv)
-               return tv;
-       if (!map && vss_playing() &&
-                       !(mmd->new_vss_status_flags & VSS_NOMORE)) {
-               if (afsss == AFS_SOCKET_READY ||
-                               afsss == AFS_SOCKET_CHECK_FOR_WRITE) {
-                       PARA_DEBUG_LOG("ready and playing, but no audio file\n");
-                       para_fd_set(afs_socket, wfds, max_fileno);
-                       afsss = AFS_SOCKET_CHECK_FOR_WRITE;
-               }
+
+       if (need_to_request_new_audio_file()) {
+               PARA_DEBUG_LOG("ready and playing, but no audio file\n");
+               para_fd_set(afs_socket, wfds, max_fileno);
+               afsss = AFS_SOCKET_CHECK_FOR_WRITE;
+       } else
+               para_fd_set(afs_socket, rfds, max_fileno);
+       for (i = 0; senders[i].name; i++) {
+               if (!senders[i].pre_select)
+                       continue;
+               senders[i].pre_select(max_fileno, rfds, wfds);
        }
-       return tv;
+       return vss_compute_timeout();
 }
 
 static int recv_afs_msg(int *fd, uint32_t *code, uint32_t *data)
@@ -416,37 +461,6 @@ err:
        mmd->new_vss_status_flags = VSS_NEXT;
 }
 
-void vss_post_select(fd_set *rfds, fd_set *wfds)
-{
-       int ret;
-
-       if (FD_ISSET(afs_socket, rfds))
-               recv_afs_result();
-       if (afsss != AFS_SOCKET_CHECK_FOR_WRITE || !FD_ISSET(afs_socket, wfds))
-               return;
-       PARA_NOTICE_LOG("requesting new fd from afs\n");
-       ret = send_buffer(afs_socket, "new");
-       afsss = AFS_SOCKET_AFD_PENDING;
-}
-/**
- * Get the data of the given chunk.
- *
- * \param chunk_num The number of the desired chunk.
- * \param buf Chunk data.
- * \param len Chunk length in bytes.
- *
- * \return Standard.
- */
-int vss_get_chunk(long unsigned chunk_num, char **buf, size_t *len)
-{
-       if (!map || !vss_playing())
-               return -E_CHUNK;
-       if (chunk_num >= mmd->afd.afhi.chunks_total)
-               return -E_CHUNK;
-       afh_get_chunk(chunk_num, &mmd->afd.afhi, map, buf, len);
-       return 1;
-}
-
 /**
  * Main sending function.
  *
@@ -456,7 +470,7 @@ int vss_get_chunk(long unsigned chunk_num, char **buf, size_t *len)
  * each supported sender's send() function which is supposed to send out the data
  * to all connected clients.
  */
-void vss_send_chunk(void)
+static void vss_send_chunk(void)
 {
        int i;
        struct timeval now, due;
@@ -478,7 +492,7 @@ void vss_send_chunk(void)
        mmd->new_vss_status_flags &= ~VSS_REPOS;
        if (mmd->current_chunk >= mmd->afd.afhi.chunks_total) { /* eof */
                mmd->new_vss_status_flags |= VSS_NEXT;
-               return vss_eof();
+               return;
        }
        /*
         * We call the send function also in case of empty chunks as they
@@ -498,3 +512,31 @@ void vss_send_chunk(void)
        mmd->chunks_sent++;
        mmd->current_chunk++;
 }
+
+void vss_post_select(fd_set *rfds, fd_set *wfds)
+{
+       int ret, i;
+
+       if (mmd->sender_cmd_data.cmd_num >= 0) {
+               int num = mmd->sender_cmd_data.cmd_num,
+                       s = mmd->sender_cmd_data.sender_num;
+
+               if (senders[s].client_cmds[num])
+                       senders[s].client_cmds[num](&mmd->sender_cmd_data);
+               mmd->sender_cmd_data.cmd_num = -1;
+       }
+       if (afsss != AFS_SOCKET_CHECK_FOR_WRITE) {
+               if (FD_ISSET(afs_socket, rfds))
+                       recv_afs_result();
+       } else if (FD_ISSET(afs_socket, wfds)) {
+               PARA_NOTICE_LOG("requesting new fd from afs\n");
+               ret = send_buffer(afs_socket, "new");
+               afsss = AFS_SOCKET_AFD_PENDING;
+       }
+       for (i = 0; senders[i].name; i++) {
+               if (!senders[i].post_select)
+                       continue;
+               senders[i].post_select(rfds, wfds);
+       }
+       vss_send_chunk();
+}