Example #1
0
bool valtostr(const value_t * val, char *str, size_t n)
{
    char buf[128];
    int max_bytes = 0;
    bool print_as_unsigned = false;

#define FLAG_MACRO(bytes, string) (val->flags.u##bytes##b && val->flags.s##bytes##b) ? (string " ") : (val->flags.u##bytes##b) ? (string "u ") : (val->flags.s##bytes##b) ? (string "s ") : ""

    /* set the flags */
    snprintf(buf, sizeof(buf), "[%s%s%s%s%s%s%s]",
             FLAG_MACRO(64, "I64"),
             FLAG_MACRO(32, "I32"),
             FLAG_MACRO(16, "I16"),
             FLAG_MACRO(8,  "I8"),
             val->flags.f64b ? "F64 " : "",
             val->flags.f32b ? "F32 " : "",
             (val->flags.ineq_reverse && !val->flags.ineq_forwards) ? "(reversed inequality) " : "");

    if (val->flags.u64b) {
        max_bytes = 8;
        print_as_unsigned =  true;
    }
    else if (val->flags.s64b) {
        max_bytes = 8;
        print_as_unsigned = false;
    }
    else if (val->flags.u32b) {
        max_bytes = 4;
        print_as_unsigned =  true;
    }
    else if (val->flags.s32b) {
        max_bytes = 4;
        print_as_unsigned = false;
    }
    else if (val->flags.u16b) {
        max_bytes = 2;
        print_as_unsigned =  true;
    }
    else if (val->flags.s16b) {
        max_bytes = 2;
        print_as_unsigned = false;
    }
    else if (val->flags.u8b ) {
        max_bytes = 1;
        print_as_unsigned =  true;
    }
    else if (val->flags.s8b ) {
        max_bytes = 1;
        print_as_unsigned = false;
    }

    /* find the right format, considering different integer size implementations */
    if (max_bytes == sizeof(long long)) snprintf(str, n, print_as_unsigned ? "%llu, %s" : "%lld, %s", print_as_unsigned ? get_ulonglong(val) : get_slonglong(val), buf);
    else if (max_bytes == sizeof(long))      snprintf(str, n, print_as_unsigned ? "%lu, %s"  : "%ld, %s" , print_as_unsigned ? get_ulong(val) : get_slong(val), buf);
    else if (max_bytes == sizeof(int))       snprintf(str, n, print_as_unsigned ? "%u, %s"   : "%d, %s"  , print_as_unsigned ? get_uint(val) : get_sint(val), buf);
    else if (max_bytes == sizeof(short))     snprintf(str, n, print_as_unsigned ? "%hu, %s"  : "%hd, %s" , print_as_unsigned ? get_ushort(val) : get_sshort(val), buf);
    else if (max_bytes == sizeof(char))      snprintf(str, n, print_as_unsigned ? "%hhu, %s" : "%hhd, %s", print_as_unsigned ? get_uchar(val) : get_schar(val), buf);
    else if (val->flags.f64b) snprintf(str, n, "%lf, %s", get_f64b(val), buf);
    else if (val->flags.f32b) snprintf(str, n, "%f, %s", get_f32b(val), buf);
    else {
        snprintf(str, n, "%#llx?, %s", get_slonglong(val), buf);
        return false;
    }

    return true;
}
Example #2
0
File: ogg.c Project: 4nykey/rockbox
/* A simple parser to read vital metadata from an Ogg Vorbis file. 
 * Can also handle parsing Ogg Speex files for metadata. Returns
 * false if metadata needed by the codec couldn't be read.
 */
bool get_ogg_metadata(int fd, struct mp3entry* id3)
{
    /* An Ogg File is split into pages, each starting with the string 
     * "OggS". Each page has a timestamp (in PCM samples) referred to as
     * the "granule position".
     *
     * An Ogg Vorbis has the following structure:
     * 1) Identification header (containing samplerate, numchannels, etc)
     * 2) Comment header - containing the Vorbis Comments
     * 3) Setup header - containing codec setup information
     * 4) Many audio packets...
     *
     * An Ogg Speex has the following structure:
     * 1) Identification header (containing samplerate, numchannels, etc)
     *    Described in this page: (http://www.speex.org/manual2/node7.html)
     * 2) Comment header - containing the Vorbis Comments
     * 3) Many audio packets.
     */

    /* Use the path name of the id3 structure as a temporary buffer. */
    unsigned char* buf = (unsigned char *)id3->path;
    long comment_size;
    long remaining = 0;
    long last_serial = 0;
    long serial, r;
    int segments, header_size;
    int i;
    bool eof = false;

    /* 92 bytes is enough for both Vorbis and Speex headers */
    if ((lseek(fd, 0, SEEK_SET) < 0) || (read(fd, buf, 92) < 92))
    {
        return false;
    }

    /* All Ogg streams start with OggS */
    if (memcmp(buf, "OggS", 4) != 0)
    {
        return false;
    }

    /* Check for format magic and then get metadata */
    if (memcmp(&buf[29], "vorbis", 6) == 0)
    {
        id3->codectype = AFMT_OGG_VORBIS;
        id3->frequency = get_long_le(&buf[40]);
        id3->vbr = true;

        /* Comments are in second Ogg page (byte 58 onwards for Vorbis) */
        if (lseek(fd, 58, SEEK_SET) < 0)
        {
            return false;
        }
    }
    else if (memcmp(&buf[28], "Speex   ", 8) == 0)
    {
        id3->codectype = AFMT_SPEEX;
        id3->frequency = get_slong(&buf[64]);
        id3->vbr = get_long_le(&buf[88]);

        header_size = get_long_le(&buf[60]);

        /* Comments are in second Ogg page (byte 108 onwards for Speex) */
        if (lseek(fd, 28 + header_size, SEEK_SET) < 0)
        {
            return false;
        }
    }
    else if (memcmp(&buf[28], "OpusHead", 8) == 0)
    {
        id3->codectype = AFMT_OPUS;
        id3->frequency = 48000;
        id3->vbr = true;

// FIXME handle an actual channel mapping table
        /* Comments are in second Ogg page (byte 108 onwards for Speex) */
        if (lseek(fd, 47, SEEK_SET) < 0)
        {
            DEBUGF("Couldnotseektoogg");
            return false;
        }
    }
    else
    {
        /* Unsupported format, try to print the marker, catches Ogg/FLAC at least */
        DEBUGF("Usupported format in Ogg stream: %16s\n", &buf[28]);
        return false;
    }

    id3->filesize = filesize(fd);
    
    /* We need to ensure the serial number from this page is the same as the
     * one from the last page (since we only support a single bitstream).
     */
    serial = get_long_le(&buf[14]);
    comment_size = read_vorbis_tags(fd, id3, remaining);

    /* We now need to search for the last page in the file - identified by 
     * by ('O','g','g','S',0) and retrieve totalsamples.
     */

    /* A page is always < 64 kB */
    if (lseek(fd, -(MIN(64 * 1024, id3->filesize)), SEEK_END) < 0)
    {
        return false;
    }

    remaining = 0;

    while (!eof) 
    {
        r = read(fd, &buf[remaining], MAX_PATH - remaining);
        
        if (r <= 0) 
        {
            eof = true;
        } 
        else 
        {
            remaining += r;
        }
        
        /* Inefficient (but simple) search */
        i = 0;
        
        while (i < (remaining - 3)) 
        {
            if ((buf[i] == 'O') && (memcmp(&buf[i], "OggS", 4) == 0))
            {
                if (i < (remaining - 17)) 
                {
                    /* Note that this only reads the low 32 bits of a
                     * 64 bit value.
                     */
                     id3->samples = get_long_le(&buf[i + 6]);
                     last_serial = get_long_le(&buf[i + 14]);

                    /* If this page is very small the beginning of the next
                     * header could be in buffer. Jump near end of this header
                     * and continue */
                    i += 27;
                } 
                else 
                {
                    break;
                }
            } 
            else 
            {
                i++;
            }
        }

        if (i < remaining) 
        {
            /* Move the remaining bytes to start of buffer.
             * Reuse var 'segments' as it is no longer needed */
            segments = 0;
            while (i < remaining)
            {
                buf[segments++] = buf[i++];
            }
            remaining = segments;
        }
        else
        {
            /* Discard the rest of the buffer */
            remaining = 0;
        }
    }

    /* This file has mutiple vorbis bitstreams (or is corrupt). */
    /* FIXME we should display an error here. */
    if (serial != last_serial)
    {
        logf("serialno mismatch");
        logf("%ld", serial);
        logf("%ld", last_serial);
        return false;
    }

    id3->length = ((int64_t) id3->samples * 1000) / id3->frequency;
    if (id3->length <= 0)
    {
        logf("ogg length invalid!");
        return false;
    }
    
    id3->bitrate = (((int64_t) id3->filesize - comment_size) * 8) / id3->length;
    
    return true;
}