sox-devel@lists.sourceforge.net unofficial mirror
 help / color / mirror / code / Atom feed
From: Jan Stary <hans@stare.cz>
To: ole <ole.hellqvist@gmail.com>
Subject: Re: proposal,  funopen for libsox
Date: Mon, 20 May 2013 21:53:01 +0200	[thread overview]
Message-ID: <20130520195301.GA19524@www.stare.cz> (raw)
In-Reply-To: <20130520180724.a52ce49a.ole.hellqvist@gmail.com>

On May 20 18:07:24, ole.hellqvist@gmail.com wrote:
> Hi all
> For BSD's the the memstream functions don't work.

Can you elaborate please?

I can only see two "memstream functions":

./src/example5.c:  assert(out = sox_open_memstream_write(&buffer, &buffer_size, &in->signal, NULL, "sox", NULL));
./src/formats.c:        buffer_ptr? open_memstream(buffer_ptr, buffer_size_ptr) :
./src/formats.c:sox_format_t * sox_open_memstream_write( ./src/sox.h:Opens an encoding session for a memstream buffer. Returned handle must be closed with sox_close().
./src/sox.h:sox_open_memstream_write(

The sox_open_memstream_write() function
is defined in formats.c and used in example5.c

The use of open_memstream() in formats.c is #ifdef'd as

	ft->fp =
	#ifdef HAVE_FMEMOPEN
              buffer? fmemopen(buffer, buffer_size, "w+b") :
	              buffer_ptr? open_memstream(buffer_ptr,
		      buffer_size_ptr) :
	#endif


OpenBSD does have HAVE_FMEMOPEN
(indeed, config.log says so on my OpenBSD current/i386);

example5 works fine on this system, as in
./example5 monkey.wav out.wav && play out.wav

So what exactly does not work for you?

> I have made a patch for openbsd that seems to solve this.
> The files involved are formats.c and configure.ac.
> For configure.ac  it is only one line to change:
> "
>  dnl Checks for library functions.
> -AC_CHECK_FUNCS(strcasecmp strdup popen vsnprintf gettimeofday mkstemp fmemopen)
> +AC_CHECK_FUNCS(strcasecmp strdup popen vsnprintf gettimeofday mkstemp fmemopen funopen)
> "
> For formats.c the patch is larger, see below.
> So far I have verified this patch with "example5.c"
> in both modes.
> openbsd patch for  formats.c (sox version 14.4.0) :

What I wrote above uses 14.4.1; can you try with 14.4.1,
and preferably with the current git too?
Do you see the same problem that you have with 14.4.0?


	Jan

> $OpenBSD$
> --- src/formats.c.orig	Sun Mar  4 23:54:16 2012
> +++ src/formats.c	Mon May 20 15:48:34 2013
> @@ -36,7 +36,229 @@
>  #if HAVE_MAGIC
>    #include <magic.h>
>  #endif
> +#ifdef HAVE_FUNOPEN 
> +#include <stdio.h>
> +struct fmem {
> +    size_t pos;
> +    size_t size;
> +    char *buffer;
> +};
> +typedef struct fmem fmem_t;
>  
> +static int readfn(void *handler, char *buf, int size) {
> +  fmem_t *mem = handler;
> +  size_t available = mem->size - mem->pos;
> +
> +    if ((size > (int) (mem->size - mem->pos)) && ( mem->size >=  mem->pos))  {
> +    size = available;
> +  }
> +  memcpy(buf, mem->buffer + mem->pos, sizeof(char) * size);
> +  mem->pos += size;
> +  
> +  return size;
> +}
> +
> +static int writefn(void *handler, const char *buf, int size) {
> +  fmem_t *mem = handler;
> +  size_t available = mem->size - mem->pos;
> +
> +   if ((size > (int) (mem->size - mem->pos)) && ( mem->size >=  mem->pos))  {
> +    size = available;
> +  }
> +  memcpy(mem->buffer + mem->pos, buf, sizeof(char) * size);
> +  mem->pos += size;
> +
> +  return size;
> +}
> +
> +static fpos_t seekfn(void *handler, fpos_t offset, int whence) {
> +  size_t pos;
> +  fmem_t *mem = handler;
> +
> +  switch (whence) {
> +    case SEEK_SET: pos = offset; break;
> +    case SEEK_CUR: pos = mem->pos + offset; break;
> +    case SEEK_END: pos = mem->size + offset; break;
> +    default: return -1;
> +  }
> +
> +  if (pos > mem->size) {
> +    return -1;
> +  }
> +
> +  mem->pos = pos;
> +  return (fpos_t)pos;
> +}
> +
> +static int closefn(void *handler) {
> +  free(handler);
> +  return 0;
> +}
> +
> +
> +/*memstream :--------------------------------------- 
> +*extracted from: The Android Open Source Project
> +*
> +* Licensed under the Apache License, Version 2.0 
> +
> +* Definition of a seekable, write-only memory stream.
> +*/
> +typedef struct {
> +    char** bufp; /* pointer to buffer pointer */
> +    size_t* sizep; /* pointer to eof */
> +
> +    size_t allocSize; /* size of buffer */
> +    size_t eof; /* furthest point we've written to */
> +    size_t offset; /* current write offset */
> +    char saved; /* required by NUL handling */
> +} MemStream;
> +typedef struct MemStream  memstream_t;
> +#define kInitialSize 1024
> +
> +#if 0
> +# define DBUG(x) printf x
> +#else
> +# define DBUG(x) ((void)0)
> +#endif
> +/*
> +* Ensure that we have enough storage to write "size" bytes at the
> +* current offset. We also have to take into account the extra '\0'
> +* that we maintain just past EOF.
> +*
> +* Returns 0 on success.
> +*/
> +static int ensureCapacity(MemStream* stream, int writeSize)
> +{
> +    size_t newSize;
> +    size_t neededSize;
> +    char* newBuf;
> +    DBUG(("+++ ensureCap off=%d size=%d\n", stream->offset, writeSize));
> +
> +     neededSize = stream->offset + writeSize + 1;
> +    if (neededSize <= stream->allocSize)
> +        return 0;
> +
> +    if (stream->allocSize == 0) {
> +        newSize = kInitialSize;
> +    } else {
> +        newSize = stream->allocSize;
> +        newSize += newSize / 2; /* expand by 3/2 */
> +    }
> +
> +    if (newSize < neededSize)
> +        newSize = neededSize;
> +    DBUG(("+++ realloc %p->%p to size=%d\n",
> +        stream->bufp, *stream->bufp, newSize));
> +     newBuf = (char*) realloc(*stream->bufp, newSize);
> +    if (newBuf == NULL)
> +        return -1;
> +
> +    *stream->bufp = newBuf;
> +    stream->allocSize = newSize;
> +    return 0;
> +}
> +
> +/*
> +* Write data to a memstream, expanding the buffer if necessary.
> +*
> +* If we previously seeked beyond EOF, zero-fill the gap.
> +*
> +* Returns the number of bytes written.
> +*/
> +static int write_memstream(void* cookie, const char* buf, int size)
> +{
> +    MemStream* stream = (MemStream*) cookie;
> +
> +    if (ensureCapacity(stream, size) < 0)
> +        return -1;
> +
> +    /* seeked past EOF earlier? */
> +    if (stream->eof < stream->offset) {
> +        DBUG(("+++ zero-fill gap from %d to %d\n",
> +            stream->eof, stream->offset-1));
> +        memset(*stream->bufp + stream->eof, '\0',
> +            stream->offset - stream->eof);
> +    }
> +
> +    /* copy data, advance write pointer */
> +    memcpy(*stream->bufp + stream->offset, buf, (size_t) size);
> +    stream->offset += size;
> +
> +    if (stream->offset > stream->eof) {
> +        /* EOF has advanced, update it and append null byte */
> +        DBUG(("+++ EOF advanced to %d, appending nul\n", stream->offset));
> +        assert(stream->offset < stream->allocSize);
> +        stream->eof = stream->offset;
> +    } else {
> +        /* within previously-written area; save char we're about to stomp */
> +        DBUG(("+++ within written area, saving '%c' at %d\n",
> +            *(*stream->bufp + stream->offset), stream->offset));
> +        stream->saved = *(*stream->bufp + stream->offset);
> +    }
> +    *(*stream->bufp + stream->offset) = '\0';
> +    *stream->sizep = stream->offset;
> +
> +    return size;
> +}
> +
> +/*
> +* Seek within a memstream.
> +*
> +* Returns the new offset, or -1 on failure.
> +*/
> +static fpos_t seek_memstream(void* cookie, fpos_t offset, int whence)
> +{
> +    MemStream* stream = (MemStream*) cookie;
> +    off_t newPosn = (off_t) offset;
> +
> +    if (whence == SEEK_CUR) {
> +        newPosn += stream->offset;
> +    } else if (whence == SEEK_END) {
> +        newPosn += stream->eof;
> +    }
> +
> +    if (newPosn < 0 || ((fpos_t)((size_t) newPosn)) != newPosn) {
> +        /* bad offset - negative or huge */
> +        DBUG(("+++ bogus seek offset %ld\n", (long) newPosn));
> +        errno = EINVAL;
> +        return (fpos_t) -1;
> +    }
> +
> +    if (stream->offset < stream->eof) {
> +        /*
> +* We were pointing to an area we'd already written to, which means
> +* we stomped on a character and must now restore it.
> +*/
> +        DBUG(("+++ restoring char '%c' at %d\n",
> +            stream->saved, stream->offset));
> +        *(*stream->bufp + stream->offset) = stream->saved;
> +    }
> +
> +    stream->offset = (size_t) newPosn;
> +
> +    if (stream->offset < stream->eof) {
> +        /*
> +* We're seeked backward into the stream. Preserve the character
> +* at EOF and stomp it with a NUL.
> +*/
> +        stream->saved = *(*stream->bufp + stream->offset);
> +        *(*stream->bufp + stream->offset) = '\0';
> +        *stream->sizep = stream->offset;
> +    } else {
> +        /*
> +* We're positioned at, or possibly beyond, the EOF. We want to
> +* publish the current EOF, not the current position.
> +*/
> +        *stream->sizep = stream->eof;
> +    }
> +
> +    return newPosn;
> +}
> +
> +
> +
> +#endif
> +
>  #define AUTO_DETECT_SIZE 4096
>  
>  static char const * auto_detect_format(sox_format_t * ft, char const * ext)
> @@ -406,8 +628,14 @@ static void UNUSED rewind_pipe(FILE * fp)
>  /* _FSTDIO is for Torek stdio (i.e. most BSD-derived libc's)
>   * In theory, we no longer need to check _NEWLIB_VERSION or __APPLE__ */
>  #if defined _FSTDIO || defined _NEWLIB_VERSION || defined __APPLE__
> +#  ifdef __DragonFly__
> +  struct __FILE_public *fpp = (struct __FILE_public *)fp;
> +  fpp->_p -= AUTO_DETECT_SIZE;
> +  fpp->_r += AUTO_DETECT_SIZE;
> +#  else
>    fp->_p -= AUTO_DETECT_SIZE;
>    fp->_r += AUTO_DETECT_SIZE;
> +#  endif
>  #elif defined __GLIBC__
>    fp->_IO_read_ptr = fp->_IO_read_base;
>  #elif defined _MSC_VER || defined __MINGW_H || defined _ISO_STDIO_ISO_H
> @@ -456,16 +684,30 @@ static sox_format_t * open_read(
>        ft->fp = stdin;
>      }
>      else {
> -      ft->fp =
> +#ifdef HAVE_FUNOPEN
> +	fmem_t *memr = (fmem_t *) malloc(sizeof(fmem_t));
> +	memset(memr, 0, sizeof(fmem_t));
> +	memr->size = buffer_size ;
> +	memr->buffer = buffer;
> +#endif	
> +      ft->fp = 
>  #ifdef HAVE_FMEMOPEN
> -        buffer? fmemopen(buffer, buffer_size, "rb") :
> +        (buffer != NULL)? fmemopen(buffer, buffer_size, "rb") :
>  #endif
> -        xfopen(path, "rb", &ft->io_type);
> -      type = io_types[ft->io_type];
> +#ifdef HAVE_FUNOPEN
> +        (buffer != NULL)? funopen(memr, readfn, writefn, seekfn, closefn) :
> +#endif
> +		xfopen(path, "rb", &ft->io_type);
> +     	type = io_types[ft->io_type];
>        if (ft->fp == NULL) {
> +#ifdef HAVE_FUNOPEN
> +        lsx_fail("can't open FUNOPEN  %s `%s': %s", type, path, strerror(errno));
> +#else
>          lsx_fail("can't open input %s `%s': %s", type, path, strerror(errno));
> -        goto error;
> +#endif
> +	  goto error;
>        }
> +
>      }
>      if (setvbuf (ft->fp, NULL, _IOFBF, sizeof(char) * input_bufsiz)) {
>        lsx_fail("Can't set read buffer");
> @@ -825,7 +1067,26 @@ static sox_format_t * open_write(
>  {
>    sox_format_t * ft = lsx_calloc(sizeof(*ft), 1);
>    sox_format_handler_t const * handler;
> +#ifdef HAVE_FUNOPEN
> +  fmem_t *memw;
> +  MemStream*  ms;
> +    if (buffer != NULL)
> +    {
> +	memw = (fmem_t *) malloc(sizeof(fmem_t));
> +	memset(memw, 0, sizeof(fmem_t));
> +	memw->size = buffer_size ;
> +	memw->buffer = buffer ;
>  
> +    }
> +  else if  (buffer_ptr != NULL)
> +  { 
> +      ms = (MemStream*) calloc((size_t) 1, sizeof(MemStream));
> +
> +      ms->bufp = buffer_ptr;
> +      ms->sizep = &buffer_size;
> +  }
> +#endif
> +
>    if (!path || !signal) {
>      lsx_fail("must specify file name and signal parameters to write file");
>      goto error;
> @@ -853,12 +1114,17 @@ static sox_format_t * open_write(
>          lsx_fail("permission to overwrite `%s' denied", path);
>          goto error;
>        }
> +
>        ft->fp =
>  #ifdef HAVE_FMEMOPEN
> -        buffer? fmemopen(buffer, buffer_size, "w+b") :
> -        buffer_ptr? open_memstream(buffer_ptr, buffer_size_ptr) :
> +	    (buffer != NULL) ? fmemopen(buffer, buffer_size, "w+b") :
> +        (buffer_ptr != NULL) ? open_memstream(buffer_ptr, buffer_size_ptr) :
>  #endif
> -        fopen(path, "w+b");
> +#ifdef HAVE_FUNOPEN
> +        (buffer != NULL)? funopen(memw, readfn, writefn, seekfn, closefn) :
> +	(buffer_ptr != NULL) ? funopen(ms, NULL ,write_memstream, seek_memstream, closefn ):
> +#endif
> +	    fopen(path, "w+b");
>        if (ft->fp == NULL) {
>          lsx_fail("can't open output file `%s': %s", path, strerror(errno));
>          goto error;
> ----------------------------
> best regards /Ole
> 
> 
>  
> 
> 
> 
> 
> 
> 
> 
> 
> -- 

------------------------------------------------------------------------------
AlienVault Unified Security Management (USM) platform delivers complete
security visibility with the essential security capabilities. Easily and
efficiently configure, manage, and operate all of your security controls
from a single console and one unified framework. Download a free trial.
http://p.sf.net/sfu/alienvault_d2d

           reply	other threads:[~2013-05-20 20:33 UTC|newest]

Thread overview: expand[flat|nested]  mbox.gz  Atom feed
 [parent not found: <20130520180724.a52ce49a.ole.hellqvist@gmail.com>]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://lists.sourceforge.net/lists/listinfo/sox-devel

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20130520195301.GA19524@www.stare.cz \
    --to=sox-devel@lists.sourceforge.net \
    --cc=ole.hellqvist@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/sox.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).