view src/xs_support.c @ 732:8312acdb7b15

Bump autotools version requirement.
author Matti Hamalainen <ccr@tnsp.org>
date Mon, 05 Nov 2012 12:06:05 +0200
parents 82be5d6b70ab
children d9d769b5dbe2
line wrap: on
line source

/*  
   XMMS-SID - SIDPlay input plugin for X MultiMedia System (XMMS)

   Miscellaneous support functions
   
   Programmed and designed by Matti 'ccr' Hamalainen <ccr@tnsp.org>
   (C) Copyright 1999-2009 Tecnic Software productions (TNSP)

   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.,
   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "xs_support.h"
#include <ctype.h>


guint16 xs_fread_be16(xs_file_t *f)
{
    return (((guint16) xs_fgetc(f)) << 8) | ((guint16) xs_fgetc(f));
}


guint32 xs_fread_be32(xs_file_t *f)
{
    return (((guint32) xs_fgetc(f)) << 24) |
        (((guint32) xs_fgetc(f)) << 16) |
        (((guint32) xs_fgetc(f)) << 8) |
        ((guint32) xs_fgetc(f));
}


/* Load a file to a buffer, return 0 on success, negative value on error
 */
gint xs_fload_buffer(const gchar *filename, guint8 **buf, size_t *bufSize)
{
    xs_file_t *f;
    glong seekPos;
    
    /* Open file, get file size */
    if ((f = xs_fopen(filename, "rb")) == NULL)
        return -1;

    xs_fseek(f, 0, SEEK_END);
    seekPos = xs_ftell(f);
    
    if (seekPos > 0) {
        size_t readSize = seekPos;
        if (readSize >= *bufSize || *buf == NULL) {
            /* Only re-allocate if the required size > current */
            if (*buf != NULL) {
                g_free(*buf);
                *buf = NULL;
            }
    
            *bufSize = seekPos;
            
            *buf = (guint8 *) g_malloc(*bufSize * sizeof(guint8));
            if (*buf == NULL) {
                xs_fclose(f);
                return -2;
            }
        }
        
        /* Read data */    
        xs_fseek(f, 0, SEEK_SET);
        readSize = xs_fread(*buf, sizeof(guint8), *bufSize, f);
        xs_fclose(f);
        
        if (readSize != *bufSize)
            return -3;
        else
            return 0;
    } else {
        xs_fclose(f);
        return -4;
    }
}


/* Copy a given string over in *result.
 */
gint xs_pstrcpy(gchar **result, const gchar *str)
{
    /* Check the string pointers */
    if (!result || !str)
        return -1;

    /* Allocate memory for destination */
    if (*result)
        g_free(*result);
    *result = (gchar *) g_malloc(strlen(str) + 1);
    if (!*result)
        return -2;

    /* Copy to the destination */
    strcpy(*result, str);

    return 0;
}


/* Concatenates a given string into string pointed by *result.
 */
gint xs_pstrcat(gchar **result, const gchar *str)
{
    /* Check the string pointers */
    if (!result || !str)
        return -1;

    if (*result != NULL) {
        *result = (gchar *) g_realloc(*result, strlen(*result) + strlen(str) + 1);
        if (*result == NULL)
            return -1;
        strcat(*result, str);
    } else {
        *result = (gchar *) g_malloc(strlen(str) + 1);
        if (*result == NULL)
            return -1;
        strcpy(*result, str);
    }

    return 0;
}


/* Concatenate a given string up to given dest size or \n.
 * If size max is reached, change the end to "..."
 */
void xs_pnstrcat(gchar *dest, size_t iSize, const gchar *str)
{
    size_t i, n;
    const gchar *s;
    gchar *d;

    d = dest;
    i = 0;
    while (*d && (i < iSize)) {
        i++;
        d++;
    }

    s = str;
    while (*s && (*s != '\n') && (i < iSize)) {
        *d = *s;
        d++;
        s++;
        i++;
    }

    *d = 0;

    if (i >= iSize) {
        i--;
        d--;
        n = 3;
        while ((i > 0) && (n > 0)) {
            *d = '.';
            d--;
            i--;
            n--;
        }
    }
}


/* Locate character in string
 */
gchar *xs_strrchr(gchar *str, const gchar ch)
{
    gchar *lastPos = NULL;

    while (*str) {
        if (*str == ch)
            lastPos = str;
        str++;
    }

    return lastPos;
}


void xs_findnext(const gchar *str, size_t *pos)
{
    while (str[*pos] && isspace(str[*pos]))
        (*pos)++;
}


void xs_findeol(const gchar *str, size_t *pos)
{
    while (str[*pos] && (str[*pos] != '\n') && (str[*pos] != '\r'))
        (*pos)++;
}


void xs_findnum(const gchar *str, size_t *pos)
{
    while (str[*pos] && isdigit(str[*pos]))
        (*pos)++;
}


/* Let's do some preprocessor magic :) */
#define XS_FVAR(T, P, K) g ## K ## int ## P *sp_ ## T ## P , *dp_ ## T ## P

#define XS_FILTER1(T, P, K, Q)                            \
    dataSize /= sizeof(g ## K ## int ## P);                 \
    sp_ ## T ## P = (g ## K ## int ## P *) srcBuf;                \
    dp_ ## T ## P = (g ## K ## int ## P *) destBuf;                \
    while (dataSize-- > 0) {                        \
        for (tmp = 0, i = 0; i < oversampleFactor; i++)            \
            tmp += (gint32) ((gint ## P) (*(sp_ ## T ## P ++) Q));    \
        xs_filter_mbn = (tmp + xs_filter_mbn) / (oversampleFactor + 1);    \
        *(dp_ ## T ## P ++) = ((g ## K ## int ## P) xs_filter_mbn) Q ;    \
        }


static gint32 xs_filter_mbn = 0;


gint xs_filter_rateconv(void *destBuf, void *srcBuf, const AFormat audioFormat,
            const gint oversampleFactor, const gint bufSize)
{
    static gint32 tmp;
    XS_FVAR(s, 8,);
    XS_FVAR(u, 8, u);
    XS_FVAR(s, 16,);
    XS_FVAR(u, 16, u);
    gint i;
    gint dataSize = bufSize;

    if (dataSize <= 0)
        return dataSize;

    switch (audioFormat) {
    case FMT_U8:
        XS_FILTER1(u, 8, u, ^0x80)
            break;

    case FMT_S8:
        XS_FILTER1(s, 8,,)
            break;


    case FMT_U16_BE:
    case FMT_U16_LE:
    case FMT_U16_NE:
        XS_FILTER1(u, 16, u, ^0x8000)
            break;

    case FMT_S16_BE:
    case FMT_S16_LE:
    case FMT_S16_NE:
        XS_FILTER1(s, 16,,)
            break;

    default:
        return -1;
    }

    return 0;
}