mysql_selector.c: introduce the myslq lock
[paraslash.git] / mp3_afh.c
index a3e3c5c330466e672aa80ab58a7a462443bdef7f..0eb1188eda0f578fbe2382a99514eec81737a9a4 100644 (file)
--- a/mp3_afh.c
+++ b/mp3_afh.c
@@ -1,19 +1,7 @@
 /*
  * Copyright (C) 2003-2007 Andre Noll <maan@systemlinux.org>
  *
- *     This program is free software; you can redistribute it and/or modify
- *     it under the terms of the GNU General Public License as published by
- *     the Free Software Foundation; either version 2 of the License, or
- *     (at your option) any later version.
- *
- *     This program is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public License
- *     along with this program; if not, write to the Free Software
- *     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ * Licensed under the GPL v2. For licencing details see COPYING.
  */
 
 /** \file mp3_afh.c para_server's mp3 audio format handler */
  *                      Johannes Overmann <overmann@iname.com>
  */
 
-#include "server.cmdline.h"
 #include "server.h"
-#include "vss.h"
 #include "error.h"
-#include "fd.h"
 #include "string.h"
 
 /** \cond some defines and structs which are only used in this file */
@@ -72,8 +57,6 @@ struct mp3info {
        int id3_isvalid;
        struct id3tag id3;
        int vbr;
-       long unsigned br_average;
-       int freq;
 };
 
 /** \endcond */
@@ -115,9 +98,19 @@ static const char *header_mode(struct mp3header *h)
                h->mode = 4; /* invalid */
        return mode_text[h->mode];
 }
+
+static int header_channels(struct mp3header *h)
+{
+       if (h->mode > 3)
+               return 0;
+       if (h->mode < 3)
+               return 2;
+       return 1;
+}
+
 static int header_bitrate(struct mp3header *h)
 {
-       if (h->layer > 3 || h->bitrate > 14)
+       if (!h->layer || h->layer > 3 || h->bitrate > 14 || !h->bitrate)
                return -E_HEADER_BITRATE;
        return mp3info_bitrate[h->version & 1][3 - h->layer][h->bitrate - 1];
 }
@@ -143,14 +136,14 @@ static void write_info_str(struct audio_format_info *afi)
        int v = mp3.id3_isvalid;
 
        snprintf(afi->info_string, MMD_INFO_SIZE,
-               "audio_file_info1:%lu x %lums, %lu kbit/s (%cbr) %i KHz %s\n"
+               "audio_file_info1:%lu x %lums, %u kbit/s (%cbr) %i KHz %s\n"
                "audio_file_info2:%s, by %s\n"
                "audio_file_info3:A: %s, Y: %s, C: %s\n",
                afi->chunks_total,
                tv2ms(&afi->chunk_tv),
-               mp3.br_average,
+               afi->bitrate,
                mp3.vbr? 'v' : 'c',
-               mp3.freq / 1000,
+               afi->frequency / 1000,
                header_mode(&mp3.header),
                v && *mp3.id3.title? mp3.id3.title : "(title tag not set)",
                v && *mp3.id3.artist? mp3.id3.artist : "(artist tag not set)",
@@ -187,17 +180,15 @@ static int compare_headers(struct mp3header *h1,struct mp3header *h2)
        return 0;
 }
 
-/**
+/*
  * get next MP3 frame header.
  *
- * \param stream to read the header from
- * \param header structure that gets filled in by get_header()
- *
- * \return On success, the header frame length is returned.  A return value of
- * zero means that we did not retrieve a valid frame header, and a negative
- * return value indicates an error.
+ * On success, the header frame length is returned and the given header
+ * structure that is filled in.  A return value of zero means that we did not
+ * retrieve a valid frame header, and a negative return value indicates an
+ * error.
  */
-static int get_header(unsigned char *map, off_t numbytes, off_t *fpos,
+static int get_header(unsigned char *map, size_t numbytes, off_t *fpos,
        struct mp3header *header)
 {
        int fl, ret;
@@ -230,25 +221,21 @@ out:
        return ret;
 }
 
-/**
+/*
  * find the next mp3 header
  *
- * \return On success, the length of the next frame header. If the end of the
- * file was reached, the function returns zero. On errors, a negative value is
- * returned.
- *
+ * Return the length of the next frame header or zero if the end of the file is
+ * reached.
  */
-static int mp3_seek_next_header(unsigned char *map, off_t numbytes, off_t *fpos)
+static int mp3_seek_next_header(unsigned char *map, size_t numbytes, off_t *fpos)
 {
        int k, l = 0, first_len;
        struct mp3header h, h2;
        long valid_start = 0;
 
-       while (1) {
-               while ((*fpos)++ < numbytes && map[*fpos] != 0xff)
-                       ;
-               if (*fpos >= numbytes)
-                       return 0;
+       for (; *fpos < numbytes; (*fpos)++) {
+               if (map[*fpos] != 0xff)
+                       continue;
                valid_start = *fpos;
                first_len = get_header(map, numbytes, fpos, &h);
                if (first_len <= 0)
@@ -267,9 +254,10 @@ static int mp3_seek_next_header(unsigned char *map, off_t numbytes, off_t *fpos)
                        return first_len;
                }
        }
+       return 0;
 }
 
-static void mp3_get_id3(unsigned char *map, off_t numbytes, off_t *fpos)
+static void mp3_get_id3(unsigned char *map, size_t numbytes, off_t *fpos)
 {
        mp3.id3_isvalid = 0;
        mp3.id3.title[0] = '\0';
@@ -280,7 +268,7 @@ static void mp3_get_id3(unsigned char *map, off_t numbytes, off_t *fpos)
        if (numbytes < 128)
                return;
        *fpos = numbytes - 128;
-       if (strncmp("TAG", map + *fpos, 3)) {
+       if (strncmp("TAG", (char *) map + *fpos, 3)) {
                PARA_INFO_LOG("%s", "no id3 tag\n");
                return;
        }
@@ -307,7 +295,7 @@ static void mp3_get_id3(unsigned char *map, off_t numbytes, off_t *fpos)
        unpad(mp3.id3.comment);
 }
 
-static int find_valid_start(unsigned char *map, off_t numbytes, off_t *fpos)
+static int find_valid_start(unsigned char *map, size_t numbytes, off_t *fpos)
 {
        int frame_len;
 
@@ -325,7 +313,7 @@ static int find_valid_start(unsigned char *map, off_t numbytes, off_t *fpos)
        return frame_len;
 }
 
-static int mp3_read_info(unsigned char *map, off_t numbytes,
+static int mp3_read_info(unsigned char *map, size_t numbytes,
                struct audio_format_info *afi)
 {
        long fl_avg = 0, freq_avg = 0, br_avg = 0;
@@ -339,19 +327,25 @@ static int mp3_read_info(unsigned char *map, off_t numbytes,
        mp3_get_id3(map, numbytes, &fpos);
        fpos = 0;
        mp3.vbr = 0;
-       mp3.freq = 0;
        while (1) {
-               int freq, br, fl;
+               unsigned long freq, br, fl;
                struct timeval tmp, cct; /* current chunk time */
                fpos += len;
                len = find_valid_start(map, numbytes, &fpos);
                if (len <= 0)
                        break;
-               freq = header_frequency(&mp3.header);
-               br = header_bitrate(&mp3.header);
-               fl = frame_length(&mp3.header);
-               if (freq < 0 || br < 0 || fl < 0)
+               ret = header_frequency(&mp3.header);
+               if (ret < 0)
+                       continue;
+               freq = ret;
+               ret = header_bitrate(&mp3.header);
+               if (ret < 0)
+                       continue;
+               br = ret;
+               ret = frame_length(&mp3.header);
+               if (ret < 0)
                        continue;
+               fl = ret;
                tmp.tv_sec = fl;
                tmp.tv_usec = 0;
                tv_divide(br * 125, &tmp, &cct);
@@ -375,9 +369,9 @@ static int mp3_read_info(unsigned char *map, off_t numbytes,
                        fl_avg = fl;
                        continue;
                }
-               freq_avg += (freq - freq_avg) / (afi->chunks_total + 1);
-               fl_avg += (fl - fl_avg) / (afi->chunks_total + 1);
-               br_avg += (br - br_avg) / ((long)afi->chunks_total + 1);
+               freq_avg += ((long)freq - freq_avg) / ((long)afi->chunks_total + 1);
+               fl_avg += ((long)fl - fl_avg) / ((long)afi->chunks_total + 1);
+               br_avg += ((long)br - br_avg) / ((long)afi->chunks_total + 1);
                if (old_br != br)
                        mp3.vbr = 1;
                old_br = br;
@@ -386,8 +380,9 @@ static int mp3_read_info(unsigned char *map, off_t numbytes,
        if (!afi->chunks_total || !freq_avg || !br_avg)
                goto err_out;
        afi->chunk_table[afi->chunks_total] = numbytes - 1;
-       mp3.br_average = br_avg;
-       mp3.freq = freq_avg;
+       afi->bitrate = br_avg;
+       afi->frequency = freq_avg;
+       afi->channels = header_channels(&mp3.header);
        afi->seconds_total = (tv2ms(&total_time) + 500) / 1000;
        tv_divide(afi->chunks_total, &total_time, &afi->chunk_tv);
        PARA_DEBUG_LOG("%lu chunks, each %lums\n", afi->chunks_total,
@@ -404,7 +399,7 @@ err_out:
 /*
  * Read mp3 information from audio file
  */
-static int mp3_get_file_info(FILE *file, char *map, off_t numbytes,
+static int mp3_get_file_info(char *map, size_t numbytes,
                struct audio_format_info *afi)
 {
        int ret;