diff --git a/audacity-1.3.7-audiodevdefaults.patch b/audacity-1.3.7-audiodevdefaults.patch new file mode 100644 index 0000000..1a493a5 --- /dev/null +++ b/audacity-1.3.7-audiodevdefaults.patch @@ -0,0 +1,77 @@ +diff -Nur audacity-src-1.3.7-orig/src/prefs/AudioIOPrefs.cpp audacity-src-1.3.7/src/prefs/AudioIOPrefs.cpp +--- audacity-src-1.3.7-orig/src/prefs/AudioIOPrefs.cpp 2009-01-27 21:50:58.000000000 +0100 ++++ audacity-src-1.3.7/src/prefs/AudioIOPrefs.cpp 2009-03-02 17:25:17.000000000 +0100 +@@ -71,6 +71,25 @@ + wxString Name; + wxString Label; + ++ mDefaultPlayDeviceName = gPrefs->Read(wxT("/AudioIO/PlaybackDevice"), wxT("")); ++ int playDeviceNum = -1; // use device name from gPrefs ++ if ( mDefaultPlayDeviceName == wxT("") ) { ++#if USE_PORTAUDIO_V19 ++ playDeviceNum = Pa_GetDefaultOutputDevice(); ++#else ++ playDeviceNum = Pa_GetDefaultOutputDeviceID(); ++#endif ++ } ++ mDefaultRecDeviceName = gPrefs->Read(wxT("/AudioIO/RecordingDevice"), wxT("")); ++ int recDeviceNum = -1; // use device name from gPrefs ++ if ( mDefaultRecDeviceName == wxT("") ) { ++#if USE_PORTAUDIO_V19 ++ recDeviceNum = Pa_GetDefaultInputDevice(); ++#else ++ recDeviceNum = Pa_GetDefaultInputDeviceID(); ++#endif ++ } ++ + #if USE_PORTAUDIO_V19 + int nDevices = Pa_GetDeviceCount(); + #else +@@ -85,10 +104,16 @@ + if (info->maxOutputChannels > 0) { + mmPlayNames.Add( Name ); + mmPlayLabels.Add( Label ); ++ if ( playDeviceNum == j ) { ++ mDefaultPlayDeviceName = Name; ++ } + } + if (info->maxInputChannels > 0) { + mmRecordNames.Add( Name ); + mmRecordLabels.Add( Label ); ++ if ( recDeviceNum == j ) { ++ mDefaultRecDeviceName = Name; ++ } + // if (info->maxInputChannels > numChannels) + // numChannels = info->maxInputChannels; + } +@@ -121,7 +146,7 @@ + S.StartMultiColumn(2, wxEXPAND); + S.SetStretchyCol(1); + mPlay = S.TieChoice( _("Device") + wxString(wxT(":")), wxT("PlaybackDevice"), +- wxT(""), mmPlayNames, mmPlayLabels ); ++ mDefaultPlayDeviceName, mmPlayNames, mmPlayLabels ); + + S.AddPrompt( _("Using:") ); + wxString ver = _("Portaudio v"); +@@ -139,7 +164,7 @@ + S.StartMultiColumn(2, wxEXPAND); + S.SetStretchyCol(1); + mRec = S.TieChoice( _("Device") + wxString(wxT(":")), wxT("RecordingDevice"), +- wxT(""), mmRecordNames, mmRecordLabels ); ++ mDefaultRecDeviceName, mmRecordNames, mmRecordLabels ); + S.TieChoice( _("Channels") + wxString(wxT(":")), wxT("RecordChannels"), + 2, mmChannelNames, mmChannelLabels ); + S.EndMultiColumn(); +diff -Nur audacity-src-1.3.7-orig/src/prefs/AudioIOPrefs.h audacity-src-1.3.7/src/prefs/AudioIOPrefs.h +--- audacity-src-1.3.7-orig/src/prefs/AudioIOPrefs.h 2009-01-27 21:50:58.000000000 +0100 ++++ audacity-src-1.3.7/src/prefs/AudioIOPrefs.h 2009-03-02 17:25:16.000000000 +0100 +@@ -48,6 +48,9 @@ + + wxChoice *mPlay; + wxChoice *mRec; ++ ++ wxString mDefaultPlayDeviceName; ++ wxString mDefaultRecDeviceName; + }; + + #endif diff --git a/audacity-1.3.7-portaudio-non-mmap-alsa.patch b/audacity-1.3.7-portaudio-non-mmap-alsa.patch new file mode 100644 index 0000000..3f146b6 --- /dev/null +++ b/audacity-1.3.7-portaudio-non-mmap-alsa.patch @@ -0,0 +1,369 @@ +diff -Nur audacity-src-1.3.7-orig/lib-src/portaudio-v19/src/hostapi/alsa/pa_linux_alsa.c audacity-src-1.3.7/lib-src/portaudio-v19/src/hostapi/alsa/pa_linux_alsa.c +--- audacity-src-1.3.7-orig/lib-src/portaudio-v19/src/hostapi/alsa/pa_linux_alsa.c 2009-01-27 21:51:40.000000000 +0100 ++++ audacity-src-1.3.7/lib-src/portaudio-v19/src/hostapi/alsa/pa_linux_alsa.c 2009-02-02 19:08:22.000000000 +0100 +@@ -6,6 +6,7 @@ + * + * Copyright (c) 2002 Joshua Haberman + * Copyright (c) 2005-2007 Arve Knudsen ++ * Copyright (c) 2008 Kevin Kofler + * + * Based on the Open Source API proposed by Ross Bencina + * Copyright (c) 1999-2002 Ross Bencina, Phil Burk +@@ -118,6 +119,8 @@ + unsigned long framesPerBuffer; + int numUserChannels, numHostChannels; + int userInterleaved, hostInterleaved; ++ int canMmap; ++ void *nonMmapBuffer; + PaDeviceIndex device; /* Keep the device index */ + + snd_pcm_t *pcm; +@@ -321,7 +324,7 @@ + * and a suitable result returned. The device is closed before returning. + */ + static PaError GropeDevice( snd_pcm_t* pcm, int isPlug, StreamDirection mode, int openBlocking, +- PaAlsaDeviceInfo* devInfo, int* canMmap ) ++ PaAlsaDeviceInfo* devInfo ) + { + PaError result = paNoError; + snd_pcm_hw_params_t *hwParams; +@@ -354,9 +357,6 @@ + snd_pcm_hw_params_alloca( &hwParams ); + snd_pcm_hw_params_any( pcm, hwParams ); + +- *canMmap = snd_pcm_hw_params_test_access( pcm, hwParams, SND_PCM_ACCESS_MMAP_INTERLEAVED ) >= 0 || +- snd_pcm_hw_params_test_access( pcm, hwParams, SND_PCM_ACCESS_MMAP_NONINTERLEAVED ) >= 0; +- + if( defaultSr >= 0 ) + { + /* Could be that the device opened in one mode supports samplerates that the other mode wont have, +@@ -566,7 +566,6 @@ + PaError result = 0; + PaDeviceInfo *baseDeviceInfo = &devInfo->baseDeviceInfo; + snd_pcm_t *pcm; +- int canMmap = -1; + PaUtilHostApiRepresentation *baseApi = &alsaApi->baseHostApiRep; + + /* Zero fields */ +@@ -580,8 +579,7 @@ + OpenPcm( &pcm, deviceName->alsaName, SND_PCM_STREAM_CAPTURE, blocking, 0 ) + >= 0 ) + { +- if( GropeDevice( pcm, deviceName->isPlug, StreamDirection_In, blocking, devInfo, +- &canMmap ) != paNoError ) ++ if( GropeDevice( pcm, deviceName->isPlug, StreamDirection_In, blocking, devInfo ) != paNoError ) + { + /* Error */ + PA_DEBUG(("%s: Failed groping %s for capture\n", __FUNCTION__, deviceName->alsaName)); +@@ -594,8 +592,7 @@ + OpenPcm( &pcm, deviceName->alsaName, SND_PCM_STREAM_PLAYBACK, blocking, 0 ) + >= 0 ) + { +- if( GropeDevice( pcm, deviceName->isPlug, StreamDirection_Out, blocking, devInfo, +- &canMmap ) != paNoError ) ++ if( GropeDevice( pcm, deviceName->isPlug, StreamDirection_Out, blocking, devInfo ) != paNoError ) + { + /* Error */ + PA_DEBUG(("%s: Failed groping %s for playback\n", __FUNCTION__, deviceName->alsaName)); +@@ -603,12 +600,6 @@ + } + } + +- if( 0 == canMmap ) +- { +- PA_DEBUG(("%s: Device %s doesn't support mmap\n", __FUNCTION__, deviceName->alsaName)); +- goto end; +- } +- + baseDeviceInfo->structVersion = 2; + baseDeviceInfo->hostApi = alsaApi->hostApiIndex; + baseDeviceInfo->name = deviceName->name; +@@ -1197,6 +1188,8 @@ + self->hostInterleaved = self->userInterleaved = !(userSampleFormat & paNonInterleaved); + self->numUserChannels = params->channelCount; + self->streamDir = streamDir; ++ self->canMmap = 0; ++ self->nonMmapBuffer = NULL; + + if( !callbackMode && !self->userInterleaved ) + { +@@ -1239,6 +1232,7 @@ + + PaError result = paNoError; + snd_pcm_access_t accessMode, alternateAccessMode; ++ snd_pcm_access_t rwAccessMode, alternateRwAccessMode; + int dir = 0; + snd_pcm_t *pcm = self->pcm; + double sr = *sampleRate; +@@ -1258,32 +1252,40 @@ + if( self->userInterleaved ) + { + accessMode = SND_PCM_ACCESS_MMAP_INTERLEAVED; ++ rwAccessMode = SND_PCM_ACCESS_RW_INTERLEAVED; + alternateAccessMode = SND_PCM_ACCESS_MMAP_NONINTERLEAVED; ++ alternateRwAccessMode = SND_PCM_ACCESS_RW_NONINTERLEAVED; + } + else + { + accessMode = SND_PCM_ACCESS_MMAP_NONINTERLEAVED; ++ rwAccessMode = SND_PCM_ACCESS_RW_NONINTERLEAVED; + alternateAccessMode = SND_PCM_ACCESS_MMAP_INTERLEAVED; ++ alternateRwAccessMode = SND_PCM_ACCESS_RW_INTERLEAVED; + } + /* If requested access mode fails, try alternate mode */ ++ self->canMmap = 1; + if( snd_pcm_hw_params_set_access( pcm, hwParams, accessMode ) < 0 ) + { +- int err = 0; +- if( (err = snd_pcm_hw_params_set_access( pcm, hwParams, alternateAccessMode )) < 0) ++ if( snd_pcm_hw_params_set_access( pcm, hwParams, rwAccessMode ) >= 0 ) ++ self->canMmap = 0; ++ else + { +- result = paUnanticipatedHostError; +- if( -EINVAL == err ) ++ if( snd_pcm_hw_params_set_access( pcm, hwParams, alternateAccessMode ) < 0 ) + { +- PaUtil_SetLastHostErrorInfo( paALSA, err, "PA ALSA requires that a device supports mmap access" ); +- } +- else +- { +- PaUtil_SetLastHostErrorInfo( paALSA, err, snd_strerror( err ) ); ++ int err = 0; ++ if( (err = snd_pcm_hw_params_set_access( pcm, hwParams, alternateRwAccessMode )) >= 0) ++ self->canMmap = 0; ++ else ++ { ++ result = paUnanticipatedHostError; ++ PaUtil_SetLastHostErrorInfo( paALSA, err, snd_strerror( err ) ); ++ goto error; ++ } + } +- goto error; ++ /* Flip mode */ ++ self->hostInterleaved = !self->userInterleaved; + } +- /* Flip mode */ +- self->hostInterleaved = !self->userInterleaved; + } + + ENSURE_( snd_pcm_hw_params_set_format( pcm, hwParams, self->nativeFormat ), paUnanticipatedHostError ); +@@ -1361,7 +1363,7 @@ + + ENSURE_( snd_pcm_sw_params_set_avail_min( self->pcm, swParams, self->framesPerBuffer ), paUnanticipatedHostError ); + ENSURE_( snd_pcm_sw_params_set_xfer_align( self->pcm, swParams, 1 ), paUnanticipatedHostError ); +- ENSURE_( snd_pcm_sw_params_set_tstamp_mode( self->pcm, swParams, SND_PCM_TSTAMP_MMAP ), paUnanticipatedHostError ); ++ ENSURE_( snd_pcm_sw_params_set_tstamp_mode( self->pcm, swParams, SND_PCM_TSTAMP_ENABLE ), paUnanticipatedHostError ); + + /* Set the parameters! */ + ENSURE_( snd_pcm_sw_params( self->pcm, swParams ), paUnanticipatedHostError ); +@@ -1589,6 +1591,10 @@ + } + } + ++ /* non-mmap mode needs a reasonably-sized buffer or it'll stutter */ ++ if( !self->canMmap && framesPerHostBuffer < 2048 ) ++ framesPerHostBuffer = 2048; ++ + assert( framesPerHostBuffer > 0 ); + { + snd_pcm_uframes_t min = 0, max = 0; +@@ -1831,12 +1837,13 @@ + PA_UNLESS( framesPerHostBuffer != 0, paInternalError ); + self->maxFramesPerHostBuffer = framesPerHostBuffer; + +- if( !accurate ) ++ if( !self->playback.canMmap || !accurate ) + { + /* Don't know the exact size per host buffer */ + *hostBufferSizeMode = paUtilBoundedHostBufferSize; + /* Raise upper bound */ +- ++self->maxFramesPerHostBuffer; ++ if( !accurate ) ++ ++self->maxFramesPerHostBuffer; + } + + error: +@@ -2059,9 +2066,11 @@ + { + /* Buffer isn't primed, so prepare and silence */ + ENSURE_( snd_pcm_prepare( stream->playback.pcm ), paUnanticipatedHostError ); +- SilenceBuffer( stream ); ++ if( stream->playback.canMmap ) ++ SilenceBuffer( stream ); + } +- ENSURE_( snd_pcm_start( stream->playback.pcm ), paUnanticipatedHostError ); ++ if( stream->playback.canMmap ) ++ ENSURE_( snd_pcm_start( stream->playback.pcm ), paUnanticipatedHostError ); + } + else + ENSURE_( snd_pcm_prepare( stream->playback.pcm ), paUnanticipatedHostError ); +@@ -2390,6 +2399,7 @@ + snd_pcm_status_t *st; + PaTime now = PaUtil_GetTime(); + snd_timestamp_t t; ++ int errplayback = 0, errcapture = 0; + + snd_pcm_status_alloca( &st ); + +@@ -2400,6 +2410,7 @@ + { + snd_pcm_status_get_trigger_tstamp( st, &t ); + self->underrun = now * 1000 - ((PaTime) t.tv_sec * 1000 + (PaTime) t.tv_usec / 1000); ++ errplayback = snd_pcm_recover( self->playback.pcm, -EPIPE, 0 ); + } + } + if( self->capture.pcm ) +@@ -2409,10 +2420,12 @@ + { + snd_pcm_status_get_trigger_tstamp( st, &t ); + self->overrun = now * 1000 - ((PaTime) t.tv_sec * 1000 + (PaTime) t.tv_usec / 1000); ++ errcapture = snd_pcm_recover( self->capture.pcm, -EPIPE, 0 ); + } + } + +- PA_ENSURE( AlsaRestart( self ) ); ++ if( errplayback || errcapture ) ++ PA_ENSURE( AlsaRestart( self ) ); + + end: + return result; +@@ -2563,7 +2576,7 @@ + static PaError PaAlsaStreamComponent_EndProcessing( PaAlsaStreamComponent *self, unsigned long numFrames, int *xrun ) + { + PaError result = paNoError; +- int res; ++ int res = 0; + + /* @concern FullDuplex It is possible that only one direction is marked ready after polling, and processed + * afterwards +@@ -2571,7 +2584,34 @@ + if( !self->ready ) + goto end; + +- res = snd_pcm_mmap_commit( self->pcm, self->offset, numFrames ); ++ if( !self->canMmap && StreamDirection_Out == self->streamDir ) ++ { ++ /* Play sound */ ++ if( self->hostInterleaved ) ++ res = snd_pcm_writei( self->pcm, self->nonMmapBuffer, numFrames ); ++ else ++ { ++ void *bufs[self->numHostChannels]; ++ int bufsize = snd_pcm_format_size( self->nativeFormat, self->framesPerBuffer + 1 ); ++ unsigned char *buffer = self->nonMmapBuffer; ++ int i; ++ for( i = 0; i < self->numHostChannels; ++i ) ++ { ++ bufs[i] = buffer; ++ buffer += bufsize; ++ } ++ res = snd_pcm_writen( self->pcm, bufs, numFrames ); ++ } ++ } ++ ++ if( self->canMmap ) ++ res = snd_pcm_mmap_commit( self->pcm, self->offset, numFrames ); ++ else ++ { ++ free( self->nonMmapBuffer ); ++ self->nonMmapBuffer = NULL; ++ } ++ + if( res == -EPIPE || res == -ESTRPIPE ) + { + *xrun = 1; +@@ -2611,7 +2651,7 @@ + if( self->hostInterleaved ) + { + int swidth = snd_pcm_format_size( self->nativeFormat, 1 ); +- unsigned char *buffer = ExtractAddress( self->channelAreas, self->offset ); ++ unsigned char *buffer = self->canMmap ? ExtractAddress( self->channelAreas, self->offset ) : self->nonMmapBuffer; + + /* Start after the last user channel */ + p = buffer + self->numUserChannels * swidth; +@@ -2991,13 +3031,23 @@ + goto end; + } + +- ENSURE_( snd_pcm_mmap_begin( self->pcm, &areas, &self->offset, numFrames ), paUnanticipatedHostError ); ++ if( self->canMmap ) ++ { ++ ENSURE_( snd_pcm_mmap_begin( self->pcm, &areas, &self->offset, numFrames ), paUnanticipatedHostError ); ++ /* @concern ChannelAdaption Buffer address is recorded so we can do some channel adaption later */ ++ self->channelAreas = (snd_pcm_channel_area_t *)areas; ++ } ++ else ++ { ++ free( self->nonMmapBuffer ); ++ self->nonMmapBuffer = calloc( self->numHostChannels, snd_pcm_format_size( self->nativeFormat, self->framesPerBuffer + 1 ) ); ++ } + + if( self->hostInterleaved ) + { + int swidth = snd_pcm_format_size( self->nativeFormat, 1 ); + +- p = buffer = ExtractAddress( areas, self->offset ); ++ p = buffer = self->canMmap ? ExtractAddress( areas, self->offset ) : self->nonMmapBuffer; + for( i = 0; i < self->numUserChannels; ++i ) + { + /* We're setting the channels up to userChannels, but the stride will be hostChannels samples */ +@@ -3007,16 +3057,52 @@ + } + else + { +- for( i = 0; i < self->numUserChannels; ++i ) ++ if( self->canMmap ) ++ for( i = 0; i < self->numUserChannels; ++i ) ++ { ++ area = areas + i; ++ buffer = ExtractAddress( area, self->offset ); ++ setChannel( bp, i, buffer, 1 ); ++ } ++ else + { +- area = areas + i; +- buffer = ExtractAddress( area, self->offset ); +- setChannel( bp, i, buffer, 1 ); ++ int bufsize = snd_pcm_format_size( self->nativeFormat, self->framesPerBuffer + 1 ); ++ buffer = self->nonMmapBuffer; ++ for( i = 0; i < self->numUserChannels; ++i ) ++ { ++ setChannel( bp, i, buffer, 1 ); ++ buffer += bufsize; ++ } + } + } + +- /* @concern ChannelAdaption Buffer address is recorded so we can do some channel adaption later */ +- self->channelAreas = (snd_pcm_channel_area_t *)areas; ++ if( !self->canMmap && StreamDirection_In == self->streamDir ) ++ { ++ /* Read sound */ ++ int res; ++ if( self->hostInterleaved ) ++ res = snd_pcm_readi( self->pcm, self->nonMmapBuffer, *numFrames ); ++ else ++ { ++ void *bufs[self->numHostChannels]; ++ int bufsize = snd_pcm_format_size( self->nativeFormat, self->framesPerBuffer + 1 ); ++ unsigned char *buffer = self->nonMmapBuffer; ++ int i; ++ for( i = 0; i < self->numHostChannels; ++i ) ++ { ++ bufs[i] = buffer; ++ buffer += bufsize; ++ } ++ res = snd_pcm_readn( self->pcm, bufs, *numFrames ); ++ } ++ if( res == -EPIPE || res == -ESTRPIPE ) ++ { ++ *xrun = 1; ++ *numFrames = 0; ++ free( self->nonMmapBuffer ); ++ self->nonMmapBuffer = NULL; ++ } ++ } + + end: + error: diff --git a/audacity.changes b/audacity.changes index bf0b0d4..4f9cb87 100644 --- a/audacity.changes +++ b/audacity.changes @@ -1,3 +1,9 @@ +------------------------------------------------------------------- +Thu May 21 23:00:52 CEST 2009 - cmorve69@yahoo.es + +- Got portaudio-non-mmap-alsa.patch and audiodevdefaults.patch from + Fedora to allow it to work with PulseAudio + ------------------------------------------------------------------- Tue May 19 16:18:43 CEST 2009 - cmorve69@yahoo.es diff --git a/audacity.spec b/audacity.spec index dc0d584..5e1870b 100644 --- a/audacity.spec +++ b/audacity.spec @@ -38,7 +38,7 @@ BuildRequires: libtwolame-devel %endif Summary: A Free, Cross-Platform Digital Audio Editor Version: 1.3.7 -Release: 4 +Release: 5 License: GPL v2 or later Group: Productivity/Multimedia/Sound/Editors and Convertors BuildRoot: %{_tmppath}/%{name}-%{version}-build @@ -55,6 +55,8 @@ Patch6: %{name}-%{version}-strict-aliasing.patch Patch8: %{name}-%{version}-wxGTK_with_stl.patch Patch9: %{name}-%{version}-modal-help-dialog.patch Patch10: %{name}-%{version}-desktop_file.patch +Patch11: %{name}-%{version}-portaudio-non-mmap-alsa.patch +Patch12: %{name}-%{version}-audiodevdefaults.patch %description Audacity is a program that manipulates digital audio wave forms. In @@ -91,6 +93,8 @@ Authors: %patch8 %patch9 %patch10 +%patch11 -p1 +%patch12 -p1 %build %{?suse_update_config:%{suse_update_config -f . lib-src/*/.}} @@ -143,6 +147,9 @@ rm -rf $RPM_BUILD_ROOT %{_datadir}/mime/packages/audacity.xml %changelog +* Thu May 21 2009 cmorve69@yahoo.es +- Got portaudio-non-mmap-alsa.patch and audiodevdefaults.patch from + Fedora to allow it to work with PulseAudio * Tue May 19 2009 cmorve69@yahoo.es - Add alsa-devel BR to allow ALSA output * Mon May 11 2009 cmorve69@yahoo.es