use the random dbtool as default
[paraslash.git] / afs.c
1 /*
2  * Copyright (C) 1997-2006 Andre Noll <maan@systemlinux.org>
3  *
4  *     This program is free software; you can redistribute it and/or modify
5  *     it under the terms of the GNU General Public License as published by
6  *     the Free Software Foundation; either version 2 of the License, or
7  *     (at your option) any later version.
8  *
9  *     This program is distributed in the hope that it will be useful,
10  *     but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *     GNU General Public License for more details.
13  *
14  *     You should have received a copy of the GNU General Public License
15  *     along with this program; if not, write to the Free Software
16  *     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
17  */
18
19 /** \file afs.c audio file sending functions
20  *
21  * This contains the audio sending part of para_server which is independent
22  * of the current audio format, database tool and of the activated senders.
23  */
24
25 #include <sys/time.h> /* gettimeofday */
26 #include "server.cmdline.h"
27 #include "db.h"
28 #include "server.h"
29 #include "afs.h"
30 #include "send.h"
31 #include "error.h"
32 #include "string.h"
33
34 extern const char *status_item_list[];
35
36 static struct timeval announce_tv;
37 static struct timeval data_send_barrier;
38 static struct timeval eof_barrier;
39
40 extern struct misc_meta_data *mmd;
41 extern struct dbtool dblist[];
42 extern struct sender senders[];
43 extern struct gengetopt_args_info conf;
44
45 static FILE *audio_file = NULL;
46
47 #if 1
48         void mp3_init(void *);
49 #endif
50
51 #ifdef HAVE_OGGVORBIS
52         void ogg_init(void *);
53 #endif
54
55 /**
56  * the list of supported  audio formats
57  */
58 struct audio_format afl[] = {
59 #if 1
60         {
61                 .name = "mp3",
62                 .init = mp3_init,
63         },
64 #endif
65 #ifdef HAVE_OGGVORBIS
66         {
67                 .name = "ogg",
68                 .init = ogg_init,
69         },
70 #endif
71         {
72                 .name = NULL,
73         }
74 };
75
76
77 /**
78  * check if audio file sender is playing
79  *
80  * \return greater than zero if playing, zero otherwise.
81  *
82  */
83 unsigned int afs_playing(void)
84 {
85         return mmd->new_afs_status_flags & AFS_PLAYING;
86 }
87
88 /**
89  * check if 'next' flag is set afs_status_flags
90  *
91  * \return greater than zero if set, zero if not.
92  *
93  */
94 unsigned int afs_next(void)
95 {
96         return mmd->new_afs_status_flags & AFS_NEXT;
97 }
98
99 /**
100  * check if a reposition request is pending
101  *
102  * \return greater than zero if true, zero otherwise.
103  *
104  */
105 unsigned int afs_repos(void)
106 {
107         return mmd->new_afs_status_flags & AFS_REPOS;
108 }
109
110 /**
111  * check if audio file sender is paused
112  *
113  * \return greater than zero if paused, zero otherwise.
114  *
115  */
116 unsigned int afs_paused(void)
117 {
118         return !(mmd->new_afs_status_flags & AFS_NEXT)
119                 && !(mmd->new_afs_status_flags & AFS_PLAYING);
120 }
121
122 /**
123  * get the name of the given audio format
124  * \param i the audio format number
125  *
126  * This returns a pointer to statically allocated memory so it
127  * must not be freed by the caller.
128  */
129 const char *audio_format_name(int i)
130 {
131         return i >= 0?  afl[i].name : "(none)";
132 }
133
134 /**
135  * initialize the audio file sender
136  *
137  * Call the init functions of all supported audio format handlers and
138  * initialize all supported senders.
139  */
140 void afs_init(void)
141 {
142         int i;
143         char *hn = para_hostname(), *home = para_homedir();
144
145         PARA_DEBUG_LOG("supported audio formats: %s\n",
146                 SUPPORTED_AUDIO_FORMATS);
147         for (i = 0; afl[i].name; i++) {
148                 PARA_NOTICE_LOG("initializing %s handler\n",
149                         afl[i].name);
150                 afl[i].init(&afl[i]);
151         }
152         ms2tv(conf.announce_time_arg, &announce_tv);
153         PARA_INFO_LOG("announce timeval: %lu:%lu\n", announce_tv.tv_sec, announce_tv.tv_usec);
154         for (i = 0; senders[i].name; i++) {
155                 PARA_NOTICE_LOG("initializing %s sender\n", senders[i].name);
156                 senders[i].init(&senders[i]);
157         }
158         free(hn);
159         free(home);
160 }
161
162 static int get_file_info(int i)
163 {
164         return  afl[i].get_file_info(audio_file, mmd->audio_file_info,
165                 &mmd->chunks_total, &mmd->seconds_total);
166 }
167
168 /*
169  * guess the audio format judging from filename
170  * \param name the filename
171  *
172  * \return This function returns -1 if it has no idea what kind of audio
173  * file this might be. Otherwise the (non-negative) number of the audio format
174  * is returned.
175  */
176 static int guess_audio_format(const char *name)
177 {
178
179         int i, len1 = strlen(name), len2;
180
181         for (i = 0; afl[i].name; i++) {
182                 len2 = strlen(afl[i].name);
183                 if (len1 < len2)
184                         continue;
185                 if (!strncasecmp(name + (len1 - len2), afl[i].name, len2)) {
186                         PARA_DEBUG_LOG("might be %s\n", afl[i].name);
187                         return i;
188                 }
189         }
190         return -1;
191 }
192
193 static int get_audio_format(int omit)
194 {
195         int i;
196
197         for (i = 0; afl[i].name; i++) {
198                 if (i == omit || !afl[i].get_file_info)
199                         continue;
200                 rewind(audio_file);
201                 if (get_file_info(i) > 0)
202                         return i;
203                 rewind(audio_file);
204         }
205         return -E_AUDIO_FORMAT;
206 }
207
208 /*
209  * upddate shared mem
210  */
211 static int update_mmd(void)
212 {
213         int i;
214         struct stat file_status;
215
216         i = guess_audio_format(mmd->filename);
217         if (i < 0 || get_file_info(i) < 0)
218                 i = get_audio_format(i);
219         if (i < 0)
220                 return i;
221         mmd->audio_format = i;
222         mmd->chunks_sent = 0;
223         mmd->current_chunk = 0;
224         mmd->offset = 0;
225         if (fstat(fileno(audio_file), &file_status) == -1)
226                 return -E_FSTAT;
227         mmd->size = file_status.st_size;
228         mmd->mtime = file_status.st_mtime;
229         mmd->events++;
230         PARA_NOTICE_LOG("next audio file: %s\n", mmd->filename);
231         return 1;
232 }
233
234 static void get_song(void)
235 {
236         char **sl = dblist[mmd->dbt_num].get_audio_file_list(10);
237         int i;
238
239         if (!sl)
240                 goto err_out;
241         for (i = 0; sl[i]; i++) {
242                 struct timeval now;
243                 PARA_INFO_LOG("trying %s\n", sl[i]);
244                 if (strlen(sl[i]) >= _POSIX_PATH_MAX)
245                         continue;
246                 audio_file = fopen(sl[i], "r");
247                 if (!audio_file)
248                         continue;
249                 strcpy(mmd->filename, sl[i]);
250                 if (update_mmd() < 0) {
251                         fclose(audio_file);
252                         audio_file = NULL;
253                         continue;
254                 }
255                 mmd->num_played++;
256                 if (dblist[mmd->dbt_num].update_audio_file)
257                         dblist[mmd->dbt_num].update_audio_file(sl[i]);
258                 PARA_DEBUG_LOG("%s", "success\n");
259                 mmd->new_afs_status_flags &= (~AFS_NEXT);
260                 gettimeofday(&now, NULL);
261                 tv_add(&now, &announce_tv, &data_send_barrier);
262
263                 goto free;
264         }
265         PARA_ERROR_LOG("%s", "no valid files found\n");
266 err_out:
267         mmd->new_afs_status_flags = AFS_NEXT;
268 free:
269         if (sl) {
270                 for (i = 0; sl[i]; i++)
271                         free(sl[i]);
272                 free(sl);
273         }
274 }
275
276 static int chk_barrier(const char *bname, const struct timeval *now,
277                 const struct timeval *barrier, struct timeval *diff, int log)
278 {
279         long ms;
280
281         if (tv_diff(now, barrier, diff) > 0)
282                 return 1;
283         ms = tv2ms(diff);
284         if (log && ms)
285                 PARA_DEBUG_LOG("%s barrier: %lims left\n", bname, ms);
286         return -1;
287 }
288
289 static void afs_next_chunk_time(struct timeval *due)
290 {
291         struct timeval tmp;
292
293         tv_scale(mmd->chunks_sent, &afl[mmd->audio_format].chunk_tv, &tmp);
294         tv_add(&tmp, &mmd->stream_start, due);
295 }
296
297 /*
298  * != NULL: timeout for next chunk
299  * NULL: nothing to do
300  */
301 static struct timeval *afs_compute_timeout(void)
302 {
303         static struct timeval the_timeout;
304         struct timeval now, next_chunk;
305
306         if (afs_next() && mmd->audio_format >= 0) {
307                 /* only sleep a bit, nec*/
308                 the_timeout.tv_sec = 0;
309                 the_timeout.tv_usec = 100;
310                 return &the_timeout;
311         }
312         gettimeofday(&now, NULL);
313         if (chk_barrier("eof", &now, &eof_barrier, &the_timeout, 1) < 0)
314                 return &the_timeout;
315         if (chk_barrier("data send", &now, &data_send_barrier,
316                          &the_timeout, 1) < 0)
317                 return &the_timeout;
318         if (mmd->audio_format < 0 || !afs_playing() || !audio_file)
319                 return NULL;
320         afs_next_chunk_time(&next_chunk);
321         if (chk_barrier(afl[mmd->audio_format].name, &now, &next_chunk,
322                         &the_timeout, 0) < 0)
323                 return &the_timeout;
324         /* chunk is due or bof */
325         the_timeout.tv_sec = 0;
326         the_timeout.tv_usec = 0;
327         return &the_timeout;
328 }
329
330 static void afs_eof(struct audio_format *af)
331 {
332         struct timeval now;
333         int i;
334         char *tmp;
335
336         if (!af || !audio_file) {
337                 for (i = 0; senders[i].name; i++)
338                         senders[i].shutdown_clients();
339                 return;
340         }
341         gettimeofday(&now, NULL);
342         tv_add(&af->eof_tv, &now, &eof_barrier);
343         af->close_audio_file();
344         audio_file = NULL;
345         mmd->audio_format = -1;
346         af = NULL;
347         mmd->chunks_sent = 0;
348         mmd->offset = 0;
349         mmd->seconds_total = 0;
350         tmp  = make_message("%s:\n%s:\n%s:\n", status_item_list[SI_AUDIO_INFO1],
351                 status_item_list[SI_AUDIO_INFO2], status_item_list[SI_AUDIO_INFO3]);
352         strcpy(mmd->audio_file_info, tmp);
353         free(tmp);
354         tmp  = make_message("%s:\n%s:\n%s:\n", status_item_list[SI_DBINFO1],
355                 status_item_list[SI_DBINFO2], status_item_list[SI_DBINFO3]);
356         strcpy(mmd->dbinfo, tmp);
357         free(tmp);
358         mmd->filename[0] = '\0';
359         mmd->size = 0;
360         mmd->events++;
361 }
362
363 /**
364  * compute the timeout for para_server's main select-loop
365  *
366  * This function gets called from para_server to determine the timeout value
367  * for its main select loop.
368  *
369  * Before the timeout is computed, the current afs status flags are evaluated
370  * and acted upon by calling appropriate functions from the lower layers.
371  * Possible actions include
372  *
373  *      - request a new file list from the current dabase tool (audio file change)
374  *      - shutdown of all senders (stop/pause command)
375  *      - repositioning of the stream (ff/jmp command)
376  *
377  * \return A pointer to a struct timeval containing the timeout for the next
378  * chunk of data to be sent, or NULL if we're not sending right now.
379  */
380 struct timeval *afs_preselect(void)
381 {
382         struct audio_format *af = NULL;
383         int i, format;
384         struct timeval *ret;
385 again:
386         format = mmd->audio_format;
387         if (format >= 0)
388                 af = afl + format;
389         else
390                 for (i = 0; senders[i].name; i++)
391                         senders[i].shutdown_clients();
392         if (afs_next() && af) {
393                 afs_eof(af);
394                 return afs_compute_timeout();
395         }
396         if (afs_paused() || afs_repos()) {
397                 for (i = 0; senders[i].name; i++)
398                         senders[i].shutdown_clients();
399                 if (af) {
400                         struct timeval now;
401                         if (!afs_paused() || mmd->chunks_sent) {
402                                 gettimeofday(&now, NULL);
403                                 tv_add(&af->eof_tv, &now, &eof_barrier);
404                         }
405                         if (afs_repos())
406                                 tv_add(&now, &announce_tv, &data_send_barrier);
407                         if (mmd->new_afs_status_flags & AFS_NOMORE)
408                                 mmd->new_afs_status_flags = AFS_NEXT;
409                 }
410                 mmd->chunks_sent = 0;
411         }
412         if (af && afs_repos() && mmd->current_chunk != mmd->repos_request)
413                 af->reposition_stream(mmd->repos_request);
414         if (afs_repos()) {
415                 mmd->new_afs_status_flags &= ~(AFS_REPOS);
416                 mmd->current_chunk = mmd->repos_request;
417         }
418         ret = afs_compute_timeout(); 
419         if (!ret && !audio_file && afs_playing() &&
420                         !(mmd->new_afs_status_flags & AFS_NOMORE)) {
421                 PARA_DEBUG_LOG("%s", "ready and playing, but no audio file\n");
422                 get_song();
423                 goto again;
424         }
425         return ret;
426 }
427
428 /**
429  * afs_send_chunk - paraslash's main sending function
430  *
431  * This function gets called from para_server as soon as the next chunk of
432  * data should be pushed out. It first calls the read_chunk() function of
433  * the current audio format handler to obtain a pointer to the data to be
434  * sent out as well as its length. This information is then passed to each
435  * supported sender's send() function which does the actual sending.
436  *
437  * Return value: Positive return value on success, zero on eof and negative
438  * on errors.
439  */
440
441 void afs_send_chunk(void)
442 {
443         int i;
444         struct audio_format *af;
445         char *buf;
446         ssize_t ret;
447         struct timeval now, due;
448
449         if (mmd->audio_format < 0 || !audio_file || !afs_playing())
450                 return;
451         af = &afl[mmd->audio_format];
452         gettimeofday(&now, NULL);
453         afs_next_chunk_time(&due);
454         if (tv_diff(&due, &now, NULL) > 0)
455                 return;
456         buf = af->read_chunk(mmd->current_chunk, &ret);
457         mmd->new_afs_status_flags &= ~(AFS_NEXT | AFS_REPOS);
458         if (!buf) {
459                 if (ret < 0)
460                         mmd->new_afs_status_flags = AFS_NEXT;
461                 else
462                         mmd->new_afs_status_flags |= AFS_NEXT;
463                 afs_eof(af);
464                 return;
465         }
466         if (!mmd->chunks_sent) {
467                 struct timeval tmp;
468                 gettimeofday(&mmd->stream_start, NULL);
469                 tv_scale(mmd->current_chunk, &af->chunk_tv, &tmp);
470                 mmd->offset = tv2ms(&tmp);
471                 mmd->events++;
472         }
473         for (i = 0; senders[i].name; i++)
474                 senders[i].send(af, mmd->current_chunk,
475                         mmd->chunks_sent, buf, ret);
476         mmd->new_afs_status_flags |= AFS_PLAYING;
477         mmd->chunks_sent++;
478         mmd->current_chunk++;
479 }