diff options
Diffstat (limited to 'media-sound/mpg123/files/mpg123-osx.diff')
-rw-r--r-- | media-sound/mpg123/files/mpg123-osx.diff | 394 |
1 files changed, 394 insertions, 0 deletions
diff --git a/media-sound/mpg123/files/mpg123-osx.diff b/media-sound/mpg123/files/mpg123-osx.diff new file mode 100644 index 0000000..a58fffd --- /dev/null +++ b/media-sound/mpg123/files/mpg123-osx.diff @@ -0,0 +1,394 @@ +diff -Naur mpg123-orig/Makefile mpg123/Makefile +--- mpg123-orig/Makefile Sun Apr 10 13:35:56 2005 ++++ mpg123/Makefile Sun Apr 10 13:40:03 2005 +@@ -54,6 +54,7 @@ + @echo "make netbsd NetBSD" + @echo "make openbsd OpenBSD" + @echo "make mint MiNT on Atari" ++ @echo "make macos MacOSX + @echo "make generic try this one if your system isn't listed above" + @echo "" + @echo "Please read the file INSTALL for additional information." +@@ -149,6 +150,16 @@ + @echo "Please read the file INSTALL for additional information." + @echo "" + ++macos-help: ++ @echo "" ++ @echo "There are several Mac OS X flavours. Choose one:" ++ @echo "" ++ @echo "make macos" ++ @echo "make macos-esd" ++ @echo "" ++ @echo "Please read the file INSTALL for additional information." ++ @echo "" ++ + linux-devel: + $(MAKE) OBJECTS='decode_i386.o dct64_i386.o audio_oss.o' \ + LDFLAGS= \ +@@ -759,6 +770,24 @@ + -DI386_ASSEM -DREAL_IS_FLOAT -DUSE_MMAP -DOSS \ + -DDONT_CATCH_SIGNALS -DNAS' \ + mpg123-make ++ ++macos: ++ $(MAKE) CC=cc LDFLAGS='$(LDFLAGS)' AUDIO_LIB='-framework CoreAudio' \ ++ OBJECTS='decode.o dct64.o audio_macosx.o term.o' \ ++ CFLAGS='$(CFLAGS) -DINET6 -DTERM_CONTROL -DMAC_OS_X -Wall -O2 -DPPC_ENDIAN' \ ++ mpg123-make ++ ++macos-generic: ++ $(MAKE) CC=cc LDFLAGS='$(LDFLAGS)' AUDIO_LIB='-framework CoreAudio' \ ++ OBJECTS='decode.o dct64.o audio_macosx.o term.o' \ ++ CFLAGS='$(CFLAGS) -DINET6 -DTERM_CONTROL -DMAC_OS_X -Wall -O2 -DPPC_ENDIAN' \ ++ mpg123-make ++ ++macos-esd: ++ $(MAKE) CC=cc LDFLAGS='$(LDFLAGS)' AUDIO_LIB='-lesd -laudiofile' \ ++ OBJECTS='decode.o dct64.o audio_esd.o' \ ++ CFLAGS='$(CFLAGS) -O -DDARWIN -Wall -O2 -DPPC_ENDIAN -DUSE_ESD' \ ++ mpg123-make + + mint: + $(MAKE) LDFLAGS= \ +diff -Naur mpg123-orig/audio_macosx.c mpg123/audio_macosx.c +--- mpg123-orig/audio_macosx.c Wed Dec 31 19:00:00 1969 ++++ mpg123/audio_macosx.c Sun Apr 10 13:47:14 2005 +@@ -0,0 +1,337 @@ ++/*- This is a 80 chars line, to have pretty formatted comments ---------------*/ ++ ++/* audio_macosx.c, originally written by Guillaume Outters ++ * to contact the author, please mail to: guillaume.outters@free.fr ++ * ++ * This file is some quick pre-alpha patch to allow me to have some music for my ++ * long working days, and it does it well. But it surely isn't a final version; ++ * as Mac OS X requires at least a G3, I'm not sure it will be useful to ++ * implement downsampling. ++ * ++ * Mac OS X audio works by asking you to fill its buffer, and, to complicate a ++ * bit, you must provide it with floats. In order not to patch too much mpg123, ++ * we'll accept signed short (mpg123 "approved" format) and transform them into ++ * floats as soon as received. Let's say this way calculations are faster. ++ * ++ * As we don't have some /dev/audio device with blocking write, we'll have to ++ * stop mpg123 before it does too much work, while we are waiting our dump proc ++ * to be called. I wanted to use semaphores, but they still need an ++ * implementation from Apple before I can do anything. So we'll block using a ++ * sleep and wake up on SIGUSR2. ++ * Version 0.2: now I use named semaphores (which are implemented AND work). ++ * Preprocessor flag MOSX_USES_SEM (defined at the beginning of this file) ++ * enables this behaviour. ++ * ++ * In order always to have a ready buffer to be dumped when the routine gets ++ * called, we have a "buffer loop" of NUMBER_BUFFERS buffers. mpg123 fills it ++ * on one extremity ('to'), playProc reads it on another point ('from'). 'to' ++ * blocks when it arrives on 'from' (having filled the whole circle of buffers) ++ * and 'from' blocks when no data is available. As soon as it has emptied a ++ * buffer, if mpg123 is sleeping, it awakes it quite brutaly (SIGUSR2) to tell ++ * it to fill the buffer. */ ++ ++#ifndef MOSX_USES_SEM ++#define MOSX_USES_SEM 1 /* Semaphores or sleep()/kill()? I would say semaphores, but this is just my advice, after all */ ++#endif ++#ifndef MOSX_SEM_V2 ++#define MOSX_SEM_V2 1 ++#endif ++ ++#include "mpg123.h" ++#include <CoreAudio/AudioHardware.h> ++#include <stdio.h> ++#include <stdlib.h> ++#include <errno.h> ++#if MOSX_USES_SEM ++#include <semaphore.h> ++#endif ++ ++struct aBuffer ++{ ++ float * buffer; ++ long size; ++ ++ float * ptr; /* Where in the buffer are we? */ ++ long remaining; ++ ++ struct aBuffer * next; ++}; ++typedef struct aBuffer aBuffer; ++ ++struct anEnv ++{ ++ long size; ++ short * debut; ++ short * ptr; ++ AudioDeviceID device; ++ char play; ++ ++ /* Intermediate buffers */ ++ ++ #if MOSX_USES_SEM ++ sem_t * semaphore; ++ #else ++ char wait; /* mpg123 is waiting (due to the semaphore) to show the world its power; let's free him! */ ++ pid_t pid; ++ #endif ++ aBuffer * from; /* Current buffers */ ++ aBuffer * to; ++}; ++ ++static struct anEnv env; ++ ++#define ENV ((struct anEnv *)inClientData) ++#define NUMBER_BUFFERS 16 /* Tried with 3 buffers, but then any little window move is sufficient to stop the sound. Here we have 1.5 seconds music buffered */ ++ ++void destroyBuffers() ++{ ++ aBuffer * ptr; ++ aBuffer * ptr2; ++ ++ ptr = env.to->next; ++ env.to->next = NULL; ++ while(ptr) ++ { ++ ptr2 = ptr->next; ++ if(ptr->buffer) free(ptr->buffer); ++ free(ptr); ++ ptr = ptr2; ++ } ++} ++ ++void initBuffers() ++{ ++ long m; ++ aBuffer ** ptrptr; ++ ++ ptrptr = &env.to; ++ for(m = 0; m < NUMBER_BUFFERS; m++) ++ { ++ *ptrptr = malloc(sizeof(aBuffer)); ++ (*ptrptr)->size = 0; ++ (*ptrptr)->remaining = 0; ++ (*ptrptr)->buffer = NULL; ++ ptrptr = &(*ptrptr)->next; ++ #if MOSX_USES_SEM ++ sem_post(env.semaphore); /* This buffer is ready for filling (of course, it is empty!) */ ++ #endif ++ } ++ *ptrptr = env.from = env.to; ++} ++ ++int fillBuffer(aBuffer * b, short * source, long size) ++{ ++ float * dest; ++ ++ if(b->remaining) /* Non empty buffer, must still be playing */ ++ return(-1); ++ if(b->size != size) /* Hey! What's that? Coudn't this buffer size be fixed once (well, perhaps we just didn't allocate it yet) */ ++ { ++ if(b->buffer) free(b->buffer); ++ b->buffer = malloc(size * sizeof(float)); ++ b->size = size; ++ } ++ ++ dest = b->buffer; ++ while(size--) ++ //*dest++ = ((*source++) + 32768) / 65536.0; ++ *dest++ = (*source++) / 32768.0; ++ ++ b->ptr = b->buffer; ++ b->remaining = b->size; /* Do this at last; we shouldn't show the buffer is full before it is effectively */ ++ ++ #ifdef DEBUG_MOSX ++ printf("."); fflush(stdout); ++ #endif ++ ++ return(0); ++} ++ ++OSStatus playProc(AudioDeviceID inDevice, const AudioTimeStamp * inNow, const AudioBufferList * inInputData, const AudioTimeStamp * inInputTime, AudioBufferList * outOutputData, const AudioTimeStamp * inOutputTime, void * inClientData) ++{ ++ long m, n, o; ++ float * dest; ++ ++ for(o = 0; o < outOutputData->mNumberBuffers; o++) ++ { ++ m = outOutputData->mBuffers[o].mDataByteSize / sizeof(float); /* What we have to fill */ ++ dest = outOutputData->mBuffers[o].mData; ++ ++ while(m > 0) ++ { ++ if( (n = ENV->from->remaining) <= 0 ) /* No more bytes in the current read buffer! */ ++ { ++ while( (n = ENV->from->remaining) <= 0) ++ usleep(2000); /* Let's wait a bit for the results... */ ++ } ++ ++ /* We dump what we can */ ++ ++ if(n > m) n = m; /* In fact, just the necessary should be sufficient (I think) */ ++ ++ memcpy(dest, ENV->from->ptr, n * sizeof(float)); ++ ++ /* Let's remember all done work */ ++ ++ m -= n; ++ ENV->from->ptr += n; ++ if( (ENV->from->remaining -= n) <= 0) /* ... and tell mpg123 there's a buffer to fill */ ++ { ++ #if MOSX_USES_SEM ++ sem_post(ENV->semaphore); ++ #else ++ if(ENV->wait) ++ { ++ kill(ENV->pid, SIGUSR2); ++ ENV->wait = 0; ++ } ++ #endif ++ ENV->from = ENV->from->next; ++ } ++ } ++ } ++ ++ return (0); ++} ++ ++#if ! MOSX_USES_SEM ++void start(int n) ++{ ++ signal(SIGUSR2, start); ++} ++#endif ++ ++int audio_open(struct audio_info_struct *ai) ++{ ++ long size; ++ AudioStreamBasicDescription format; ++ #if MOSX_USES_SEM ++ char s[10]; ++ long m; ++ #endif ++ /*float vol; ++ OSStatus e;*/ ++ ++ /* Where did that default audio output go? */ ++ ++ size = sizeof(env.device); ++ if(AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &size, &env.device)) return(-1); ++ ++ /* Hmmm, let's choose PCM format */ ++ ++ size = sizeof(format); ++ if(AudioDeviceGetProperty(env.device, 0, 0, kAudioDevicePropertyStreamFormat, &size, &format)) return(-1); ++ if(format.mFormatID != kAudioFormatLinearPCM) return(-1); ++ ++ /* Let's test volume, which doesn't seem to work (but this is only an alpha, remember?) */ ++ ++ /*vol = 0.5; ++ size = sizeof(vol); ++ if(e = AudioDeviceSetProperty(env.device, NULL, 0, 0, 'volm', size, &vol)) { printf("Didn't your mother ever tell you not to hear music so loudly?\n"); return(-1); } */ ++ ++ /* Let's init our environment */ ++ ++ env.size = 0; ++ env.debut = NULL; ++ env.ptr = NULL; ++ env.play = 0; ++ ++ #if MOSX_USES_SEM ++ strcpy(s, "/mpg123-0000"); ++ do ++ { ++ for(m = 10;; m--) ++ if( (s[m]++) <= '9') ++ break; ++ else ++ s[m] = '0'; ++ } while( (env.semaphore = sem_open(s, O_CREAT | O_EXCL, 0644, 0)) == (sem_t *)SEM_FAILED); ++ #else ++ env.pid = getpid(); ++ env.wait = 0; ++ signal(SIGUSR2, start); ++ #endif ++ ++ initBuffers(); ++ ++ /* And prepare audio launching */ ++ ++ if(AudioDeviceAddIOProc(env.device, playProc, &env)) return(-1); ++ ++ return(0); ++} ++ ++int audio_reset_parameters(struct audio_info_struct *ai) ++{ ++ return 0; ++} ++ ++int audio_rate_best_match(struct audio_info_struct *ai) ++{ ++ return 0; ++} ++ ++int audio_set_rate(struct audio_info_struct *ai) ++{ ++ return 0; ++} ++ ++int audio_set_channels(struct audio_info_struct *ai) ++{ ++ return 0; ++} ++ ++int audio_set_format(struct audio_info_struct *ai) ++{ ++ return 0; ++} ++ ++int audio_get_formats(struct audio_info_struct *ai) ++{ ++ return AUDIO_FORMAT_SIGNED_16; ++} ++ ++int audio_play_samples(struct audio_info_struct *ai,unsigned char *buf,int len) ++{ ++ /* We have to calm down mpg123, else he wouldn't hesitate to drop us another buffer (which would be the same, in fact) */ ++ ++ #if MOSX_USES_SEM && MOSX_SEM_V2 /* Suddenly, I have some kind of doubt: HOW COULD IT WORK??? */ ++ while(sem_wait(env.semaphore)){} /* We just have to wait a buffer fill request */ ++ fillBuffer(env.to, (short *)buf, len / sizeof(short)); ++ #else ++ while(fillBuffer(env.to, (short *)buf, len / sizeof(short)) < 0) /* While the next buffer to write is not empty, we wait a bit... */ ++ { ++ #ifdef DEBUG_MOSX ++ printf("|"); fflush(stdout); ++ #endif ++ #if MOSX_USES_SEM ++ sem_wait(env.semaphore); /* This is a bug. I should wait for the semaphore once per empty buffer (and not each time fillBuffers() returns -1). See MOSX_SEM_V2; this was a too quickly modified part when I implemented MOSX_USES_SEM. */ ++ #else ++ env.wait = 1; ++ sleep(3600); /* This should be sufficient, shouldn't it? */ ++ #endif ++ } ++ #endif ++ env.to = env.to->next; ++ ++ /* And we lauch action if not already done */ ++ ++ if(!env.play) ++ { ++ if(AudioDeviceStart(env.device, playProc)) return(-1); ++ env.play = 1; ++ } ++ ++ return len; ++} ++ ++int audio_close(struct audio_info_struct *ai) ++{ ++ AudioDeviceStop(env.device, playProc); /* No matter the error code, we want to close it (by brute force if necessary) */ ++ AudioDeviceRemoveIOProc(env.device, playProc); ++ destroyBuffers(); ++ #if MOSX_USES_SEM ++ sem_close(env.semaphore); ++ #endif ++ return 0; ++} |