зеркало из https://github.com/mozilla/gecko-dev.git
Backed out 8 changesets (bug 1023947, bug 1027713) for frequent Cppunit test failures
Backed out changeset 03edb1ab3182 (bug 1027713) Backed out changeset ad05dc816fa0 (bug 1023947) Backed out changeset a56aad94c7c9 (bug 1023947) Backed out changeset 63af4528bd9c (bug 1023947) Backed out changeset b6bb38846333 (bug 1027713) Backed out changeset c0045bb1849e (bug 1027713) Backed out changeset 274b2b25d167 (bug 1027713) Backed out changeset e0bba6f4966f (bug 1027713)
This commit is contained in:
Родитель
ef05e77439
Коммит
04a9c3cb26
|
@ -5,7 +5,6 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include "prlog.h"
|
||||
#include "prdtoa.h"
|
||||
#include "AudioStream.h"
|
||||
|
@ -17,9 +16,6 @@
|
|||
#include "mozilla/Telemetry.h"
|
||||
#include "soundtouch/SoundTouch.h"
|
||||
#include "Latency.h"
|
||||
#ifdef XP_MACOSX
|
||||
#include <sys/sysctl.h>
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
@ -250,10 +246,10 @@ AudioStream::AudioStream()
|
|||
, mLatencyRequest(HighLatency)
|
||||
, mReadPoint(0)
|
||||
, mDumpFile(nullptr)
|
||||
, mVolume(1.0)
|
||||
, mBytesPerFrame(0)
|
||||
, mState(INITIALIZED)
|
||||
, mNeedsStart(false)
|
||||
, mShouldDropFrames(false)
|
||||
{
|
||||
// keep a ref in case we shut down later than nsLayoutStatics
|
||||
mLatencyLog = AsyncLatencyLogger::Get(true);
|
||||
|
@ -502,10 +498,8 @@ AudioStream::Init(int32_t aNumChannels, int32_t aRate,
|
|||
params.channels = mOutChannels;
|
||||
#if defined(__ANDROID__)
|
||||
#if defined(MOZ_B2G)
|
||||
mAudioChannel = aAudioChannel;
|
||||
params.stream_type = ConvertChannelToCubebType(aAudioChannel);
|
||||
#else
|
||||
mAudioChannel = dom::AudioChannel::Content;
|
||||
params.stream_type = CUBEB_STREAM_TYPE_MUSIC;
|
||||
#endif
|
||||
|
||||
|
@ -550,62 +544,6 @@ AudioStream::Init(int32_t aNumChannels, int32_t aRate,
|
|||
return rv;
|
||||
}
|
||||
|
||||
// On certain MacBookPro, the microphone is located near the left speaker.
|
||||
// We need to pan the sound output to the right speaker if we are using the mic
|
||||
// and the built-in speaker, or we will have terrible echo.
|
||||
void AudioStream::PanOutputIfNeeded(bool aMicrophoneActive)
|
||||
{
|
||||
#ifdef XP_MACOSX
|
||||
cubeb_device* device;
|
||||
int rv;
|
||||
char name[128];
|
||||
size_t length = sizeof(name);
|
||||
bool panCenter = false;
|
||||
|
||||
rv = sysctlbyname("hw.model", name, &length, NULL, 0);
|
||||
if (rv) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!strncmp(name, "MacBookPro", 10)) {
|
||||
if (cubeb_stream_get_current_device(mCubebStream, &device) == CUBEB_OK) {
|
||||
// Check if we are currently outputing sound on external speakers.
|
||||
if (!strcmp(device->output_name, "ispk")) {
|
||||
// Pan everything to the right speaker.
|
||||
if (aMicrophoneActive) {
|
||||
LOG(("%p Panning audio output to the right.", this));
|
||||
if (cubeb_stream_set_panning(mCubebStream, 1.0) != CUBEB_OK) {
|
||||
NS_WARNING("Could not pan audio output to the right.");
|
||||
}
|
||||
} else {
|
||||
panCenter = true;
|
||||
}
|
||||
} else {
|
||||
panCenter = true;
|
||||
}
|
||||
if (panCenter) {
|
||||
LOG(("%p Panning audio output to the center.", this));
|
||||
if (cubeb_stream_set_panning(mCubebStream, 0.0) != CUBEB_OK) {
|
||||
NS_WARNING("Could not pan audio output to the center.");
|
||||
}
|
||||
// This a microphone that goes through the headphone plug, reset the
|
||||
// output to prevent echo building up.
|
||||
if (strcmp(device->input_name, "emic") == 0) {
|
||||
Reset();
|
||||
}
|
||||
}
|
||||
cubeb_stream_device_destroy(mCubebStream, device);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void AudioStream::DeviceChangedCallback() {
|
||||
MonitorAutoLock mon(mMonitor);
|
||||
PanOutputIfNeeded(mMicrophoneActive);
|
||||
mShouldDropFrames = true;
|
||||
}
|
||||
|
||||
// This code used to live inside AudioStream::Init(), but on Mac (others?)
|
||||
// it has been known to take 300-800 (or even 8500) ms to execute(!)
|
||||
nsresult
|
||||
|
@ -662,17 +600,12 @@ AudioStream::OpenCubeb(cubeb_stream_params &aParams,
|
|||
}
|
||||
}
|
||||
|
||||
cubeb_stream_register_device_changed_callback(mCubebStream,
|
||||
AudioStream::DeviceChangedCallback_s);
|
||||
|
||||
mState = INITIALIZED;
|
||||
|
||||
if (!mStartTime.IsNull()) {
|
||||
TimeDuration timeDelta = TimeStamp::Now() - mStartTime;
|
||||
TimeDuration timeDelta = TimeStamp::Now() - mStartTime;
|
||||
LOG(("AudioStream creation time %sfirst: %u ms", mIsFirst ? "" : "not ",
|
||||
(uint32_t) timeDelta.ToMilliseconds()));
|
||||
Telemetry::Accumulate(mIsFirst ? Telemetry::AUDIOSTREAM_FIRST_OPEN_MS :
|
||||
Telemetry::AUDIOSTREAM_LATER_OPEN_MS, timeDelta.ToMilliseconds());
|
||||
(uint32_t) timeDelta.ToMilliseconds()));
|
||||
Telemetry::Accumulate(mIsFirst ? Telemetry::AUDIOSTREAM_FIRST_OPEN_MS :
|
||||
Telemetry::AUDIOSTREAM_LATER_OPEN_MS, timeDelta.ToMilliseconds());
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -727,20 +660,15 @@ nsresult
|
|||
AudioStream::Write(const AudioDataValue* aBuf, uint32_t aFrames, TimeStamp *aTime)
|
||||
{
|
||||
MonitorAutoLock mon(mMonitor);
|
||||
|
||||
// See if we need to start() the stream, since we must do that from this thread
|
||||
CheckForStart();
|
||||
|
||||
if (mShouldDropFrames) {
|
||||
mBuffer.ContractTo(0);
|
||||
return NS_OK;
|
||||
}
|
||||
if (mState == ERRORED) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
NS_ASSERTION(mState == INITIALIZED || mState == STARTED || mState == RUNNING,
|
||||
"Stream write in unexpected state.");
|
||||
|
||||
// See if we need to start() the stream, since we must do that from this thread
|
||||
CheckForStart();
|
||||
|
||||
// Downmix to Stereo.
|
||||
if (mChannels > 2 && mChannels <= 8) {
|
||||
DownmixAudioToStereo(const_cast<AudioDataValue*> (aBuf), mChannels, aFrames);
|
||||
|
@ -822,22 +750,10 @@ AudioStream::Available()
|
|||
|
||||
void
|
||||
AudioStream::SetVolume(double aVolume)
|
||||
{
|
||||
NS_ABORT_IF_FALSE(aVolume >= 0.0 && aVolume <= 1.0, "Invalid volume");
|
||||
|
||||
if (cubeb_stream_set_volume(mCubebStream, aVolume * GetVolumeScale()) != CUBEB_OK) {
|
||||
NS_WARNING("Could not change volume on cubeb stream.");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AudioStream::SetMicrophoneActive(bool aActive)
|
||||
{
|
||||
MonitorAutoLock mon(mMonitor);
|
||||
|
||||
mMicrophoneActive = aActive;
|
||||
|
||||
PanOutputIfNeeded(mMicrophoneActive);
|
||||
NS_ABORT_IF_FALSE(aVolume >= 0.0 && aVolume <= 1.0, "Invalid volume");
|
||||
mVolume = aVolume;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -878,14 +794,11 @@ AudioStream::StartUnlocked()
|
|||
mNeedsStart = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (mState == INITIALIZED) {
|
||||
int r;
|
||||
{
|
||||
MonitorAutoUnlock mon(mMonitor);
|
||||
r = cubeb_stream_start(mCubebStream);
|
||||
|
||||
PanOutputIfNeeded(mMicrophoneActive);
|
||||
}
|
||||
mState = r == CUBEB_OK ? STARTED : ERRORED;
|
||||
LOG(("AudioStream: started %p, state %s", this, mState == STARTED ? "STARTED" : "ERRORED"));
|
||||
|
@ -1124,59 +1037,6 @@ AudioStream::GetTimeStretched(void* aBuffer, long aFrames, int64_t &aTimeMs)
|
|||
return processedFrames;
|
||||
}
|
||||
|
||||
void
|
||||
AudioStream::Reset()
|
||||
{
|
||||
mShouldDropFrames = true;
|
||||
mNeedsStart = true;
|
||||
|
||||
cubeb_stream_params params;
|
||||
params.rate = mInRate;
|
||||
params.channels = mOutChannels;
|
||||
#if defined(__ANDROID__)
|
||||
#if defined(MOZ_B2G)
|
||||
params.stream_type = ConvertChannelToCubebType(mAudioChannel);
|
||||
#else
|
||||
params.stream_type = CUBEB_STREAM_TYPE_MUSIC;
|
||||
#endif
|
||||
|
||||
if (params.stream_type == CUBEB_STREAM_TYPE_MAX) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (AUDIO_OUTPUT_FORMAT == AUDIO_FORMAT_S16) {
|
||||
params.format = CUBEB_SAMPLE_S16NE;
|
||||
} else {
|
||||
params.format = CUBEB_SAMPLE_FLOAT32NE;
|
||||
}
|
||||
mBytesPerFrame = sizeof(AudioDataValue) * mOutChannels;
|
||||
|
||||
// Size mBuffer for one second of audio. This value is arbitrary, and was
|
||||
// selected based on the observed behaviour of the existing AudioStream
|
||||
// implementations.
|
||||
uint32_t bufferLimit = FramesToBytes(mInRate);
|
||||
NS_ABORT_IF_FALSE(bufferLimit % mBytesPerFrame == 0, "Must buffer complete frames");
|
||||
mBuffer.Reset();
|
||||
mBuffer.SetCapacity(bufferLimit);
|
||||
|
||||
|
||||
if (mLatencyRequest == LowLatency) {
|
||||
// Don't block this thread to initialize a cubeb stream.
|
||||
// When this is done, it will start callbacks from Cubeb. Those will
|
||||
// cause us to move from INITIALIZED to RUNNING. Until then, we
|
||||
// can't access any cubeb functions.
|
||||
// Use a RefPtr to avoid leaks if Dispatch fails
|
||||
RefPtr<AudioInitTask> init = new AudioInitTask(this, mLatencyRequest, params);
|
||||
init->Dispatch();
|
||||
return;
|
||||
}
|
||||
// High latency - open synchronously
|
||||
OpenCubeb(params, mLatencyRequest);
|
||||
|
||||
CheckForStart();
|
||||
}
|
||||
|
||||
long
|
||||
AudioStream::DataCallback(void* aBuffer, long aFrames)
|
||||
{
|
||||
|
@ -1189,8 +1049,6 @@ AudioStream::DataCallback(void* aBuffer, long aFrames)
|
|||
uint32_t servicedFrames = 0;
|
||||
int64_t insertTime;
|
||||
|
||||
mShouldDropFrames = false;
|
||||
|
||||
// NOTE: wasapi (others?) can call us back *after* stop()/Shutdown() (mState == SHUTDOWN)
|
||||
// Bug 996162
|
||||
|
||||
|
@ -1241,6 +1099,9 @@ AudioStream::DataCallback(void* aBuffer, long aFrames)
|
|||
} else {
|
||||
servicedFrames = GetTimeStretched(output, aFrames, insertTime);
|
||||
}
|
||||
float scaled_volume = float(GetVolumeScale() * mVolume);
|
||||
|
||||
ScaleAudioSamples(output, aFrames * mOutChannels, scaled_volume);
|
||||
|
||||
NS_ABORT_IF_FALSE(mBuffer.Length() % mBytesPerFrame == 0, "Must copy complete frames");
|
||||
|
||||
|
|
|
@ -158,14 +158,6 @@ public:
|
|||
return amount;
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
mBuffer = nullptr;
|
||||
mCapacity = 0;
|
||||
mStart = 0;
|
||||
mCount = 0;
|
||||
}
|
||||
|
||||
private:
|
||||
nsAutoArrayPtr<uint8_t> mBuffer;
|
||||
uint32_t mCapacity;
|
||||
|
@ -177,8 +169,8 @@ class AudioInitTask;
|
|||
|
||||
// Access to a single instance of this class must be synchronized by
|
||||
// callers, or made from a single thread. One exception is that access to
|
||||
// GetPosition, GetPositionInFrames, SetVolume, and Get{Rate,Channels},
|
||||
// SetMicrophoneActive is thread-safe without external synchronization.
|
||||
// GetPosition, GetPositionInFrames, SetVolume, and Get{Rate,Channels}
|
||||
// is thread-safe without external synchronization.
|
||||
class AudioStream MOZ_FINAL
|
||||
{
|
||||
virtual ~AudioStream();
|
||||
|
@ -220,8 +212,6 @@ public:
|
|||
// Closes the stream. All future use of the stream is an error.
|
||||
void Shutdown();
|
||||
|
||||
void Reset();
|
||||
|
||||
// Write audio data to the audio hardware. aBuf is an array of AudioDataValues
|
||||
// AudioDataValue of length aFrames*mChannels. If aFrames is larger
|
||||
// than the result of Available(), the write will block until sufficient
|
||||
|
@ -236,11 +226,6 @@ public:
|
|||
// 0 (meaning muted) to 1 (meaning full volume). Thread-safe.
|
||||
void SetVolume(double aVolume);
|
||||
|
||||
// Informs the AudioStream that a microphone is being used by someone in the
|
||||
// application.
|
||||
void SetMicrophoneActive(bool aActive);
|
||||
void PanOutputIfNeeded(bool aMicrophoneActive);
|
||||
|
||||
// Block until buffered audio data has been consumed.
|
||||
void Drain();
|
||||
|
||||
|
@ -319,14 +304,8 @@ private:
|
|||
static_cast<AudioStream*>(aThis)->StateCallback(aState);
|
||||
}
|
||||
|
||||
|
||||
static void DeviceChangedCallback_s(void * aThis) {
|
||||
static_cast<AudioStream*>(aThis)->DeviceChangedCallback();
|
||||
}
|
||||
|
||||
long DataCallback(void* aBuffer, long aFrames);
|
||||
void StateCallback(cubeb_state aState);
|
||||
void DeviceChangedCallback();
|
||||
|
||||
nsresult EnsureTimeStretcherInitializedUnlocked();
|
||||
|
||||
|
@ -352,9 +331,6 @@ private:
|
|||
int mOutRate;
|
||||
int mChannels;
|
||||
int mOutChannels;
|
||||
#if defined(__ANDROID__)
|
||||
dom::AudioChannel mAudioChannel;
|
||||
#endif
|
||||
// Number of frames written to the buffers.
|
||||
int64_t mWritten;
|
||||
AudioClock mAudioClock;
|
||||
|
@ -385,6 +361,9 @@ private:
|
|||
// frames.
|
||||
CircularByteBuffer mBuffer;
|
||||
|
||||
// Software volume level. Applied during the servicing of DataCallback().
|
||||
double mVolume;
|
||||
|
||||
// Owning reference to a cubeb_stream. cubeb_stream_destroy is called by
|
||||
// nsAutoRef's destructor.
|
||||
nsAutoRef<cubeb_stream> mCubebStream;
|
||||
|
@ -418,12 +397,6 @@ private:
|
|||
StreamState mState;
|
||||
bool mNeedsStart; // needed in case Start() is called before cubeb is open
|
||||
bool mIsFirst;
|
||||
// True if a microphone is active.
|
||||
bool mMicrophoneActive;
|
||||
// When we are in the process of changing the output device, and the callback
|
||||
// is not going to be called for a little while, simply drop incoming frames.
|
||||
// This is only on OSX for now, because other systems handle this gracefully.
|
||||
bool mShouldDropFrames;
|
||||
|
||||
// This mutex protects the static members below.
|
||||
static StaticMutex sMutex;
|
||||
|
|
|
@ -568,18 +568,8 @@ MediaStreamGraphImpl::UpdateStreamOrder()
|
|||
|
||||
if (!mMixer && shouldMix) {
|
||||
mMixer = new AudioMixer(AudioMixerCallback);
|
||||
for (uint32_t i = 0; i < mStreams.Length(); ++i) {
|
||||
for (uint32_t i = 0; i < mStreams[i]->mAudioOutputStreams.Length(); ++i) {
|
||||
mStreams[i]->mAudioOutputStreams[i].mStream->SetMicrophoneActive(true);
|
||||
}
|
||||
}
|
||||
} else if (mMixer && !shouldMix) {
|
||||
mMixer = nullptr;
|
||||
for (uint32_t i = 0; i < mStreams.Length(); ++i) {
|
||||
for (uint32_t i = 0; i < mStreams[i]->mAudioOutputStreams.Length(); ++i) {
|
||||
mStreams[i]->mAudioOutputStreams[i].mStream->SetMicrophoneActive(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The algorithm for finding cycles is based on Tim Leslie's iterative
|
||||
|
@ -960,9 +950,6 @@ MediaStreamGraphImpl::CreateOrDestroyAudioStreams(GraphTime aAudioOutputStartTim
|
|||
AudioStream::LowLatency);
|
||||
audioOutputStream->mTrackID = tracks->GetID();
|
||||
|
||||
// If there is a mixer, there is a micrphone active.
|
||||
audioOutputStream->mStream->SetMicrophoneActive(mMixer);
|
||||
|
||||
LogLatency(AsyncLatencyLogger::AudioStreamCreate,
|
||||
reinterpret_cast<uint64_t>(aStream),
|
||||
reinterpret_cast<int64_t>(audioOutputStream->mStream.get()));
|
||||
|
|
|
@ -8,7 +8,7 @@ var gSmallTests = [
|
|||
{ name:"small-shot.ogg", type:"audio/ogg", duration:0.276 },
|
||||
{ name:"small-shot.m4a", type:"audio/mp4", duration:0.29 },
|
||||
{ name:"small-shot.mp3", type:"audio/mpeg", duration:0.27 },
|
||||
// { name:"small-shot-mp3.mp4", type:"audio/mp4; codecs=mp3", duration:0.34 },
|
||||
{ name:"small-shot-mp3.mp4", type:"audio/mp4; codecs=mp3", duration:0.34 },
|
||||
{ name:"r11025_s16_c1.wav", type:"audio/x-wav", duration:1.0 },
|
||||
{ name:"320x240.ogv", type:"video/ogg", width:320, height:240, duration:0.266 },
|
||||
{ name:"seek.webm", type:"video/webm", width:320, height:240, duration:3.966 },
|
||||
|
|
|
@ -135,11 +135,6 @@ cubeb_stream_init
|
|||
cubeb_stream_start
|
||||
cubeb_stream_stop
|
||||
cubeb_stream_get_latency
|
||||
cubeb_stream_set_volume
|
||||
cubeb_stream_set_panning
|
||||
cubeb_stream_get_current_device
|
||||
cubeb_stream_device_destroy
|
||||
cubeb_stream_register_device_changed_callback
|
||||
th_comment_clear
|
||||
th_comment_init
|
||||
th_decode_alloc
|
||||
|
|
|
@ -129,12 +129,6 @@ typedef struct {
|
|||
#endif
|
||||
} cubeb_stream_params;
|
||||
|
||||
/** Output device description */
|
||||
typedef struct {
|
||||
char * output_name; /**< The name of the output device */
|
||||
char * input_name; /**< The name of the input device */
|
||||
} cubeb_device;
|
||||
|
||||
/** Stream states signaled via state_callback. */
|
||||
typedef enum {
|
||||
CUBEB_STATE_STARTED, /**< Stream started. */
|
||||
|
@ -172,11 +166,6 @@ typedef void (* cubeb_state_callback)(cubeb_stream * stream,
|
|||
void * user_ptr,
|
||||
cubeb_state state);
|
||||
|
||||
/**
|
||||
* User supplied callback called when the underlying device changed.
|
||||
* @param user */
|
||||
typedef void (* cubeb_device_changed_callback)(void * user_ptr);
|
||||
|
||||
/** Initialize an application context. This will perform any library or
|
||||
application scoped initialization.
|
||||
@param context
|
||||
|
@ -272,63 +261,6 @@ int cubeb_stream_get_position(cubeb_stream * stream, uint64_t * position);
|
|||
@retval CUBEB_ERROR */
|
||||
int cubeb_stream_get_latency(cubeb_stream * stream, uint32_t * latency);
|
||||
|
||||
/**
|
||||
* Set the volume for a stream.
|
||||
* @param stream the stream for which to adjust the volume.
|
||||
* @param volumes a float between 0.0 (muted) and 1.0 (maximum volumes)
|
||||
* @return CUBEB_ERROR_INVALID_PARAMETER if volume is outside [0.0; 1.0]
|
||||
* @return CUBEB_ERROR_INVALID_PARAMETER if stream is an invalid pointer
|
||||
* @return CUBEB_OK otherwise
|
||||
*/
|
||||
int cubeb_stream_set_volume(cubeb_stream * stream, float volume);
|
||||
|
||||
/**
|
||||
* If the stream is stereo, set the left/right panning. If the stream is mono,
|
||||
* this has no effect.
|
||||
* @param stream the stream for which to change the panning
|
||||
* @param panning a number from -1.0 to 1.0. -1.0 means that the stream is fully
|
||||
* mixed in the left channel, 1.0 means the stream is fully mixed in the right
|
||||
* channel. 0.0 is equal power in the right and left channel (default).
|
||||
* @return CUBEB_ERROR_INVALID_PARAMETER if stream is null or if panning is outside
|
||||
* the [-1.0; 1.0] range.
|
||||
* @return CUBEB_ERROR if this stream is not mono nor stereo.
|
||||
* @return CUBEB_OK otherwise.
|
||||
*/
|
||||
int cubeb_stream_set_panning(cubeb_stream * stream, float panning);
|
||||
|
||||
/**
|
||||
* Get the current output device for this stream.
|
||||
* @param stm the stream for which to query the current output device
|
||||
* @param device a pointer in which the current output device will be stored.
|
||||
* @return CUBEB_OK in case of success
|
||||
* @return CUBEB_ERROR_INVALID_PARAMETER if either stm, device or count are
|
||||
* invalid pointers
|
||||
*/
|
||||
int cubeb_stream_get_current_device(cubeb_stream * stm,
|
||||
cubeb_device ** const device);
|
||||
|
||||
/**
|
||||
* Destroy a cubeb_device structure.
|
||||
* @param stream the stream passed in cubeb_stream_get_current_device
|
||||
* @param devices the devices to destroy
|
||||
* @return CUBEB_OK in case of success
|
||||
* @return CUBEB_ERROR_INVALID_PARAMETER if devices is an invalid pointer
|
||||
*/
|
||||
int cubeb_stream_device_destroy(cubeb_stream * stream,
|
||||
cubeb_device * devices);
|
||||
|
||||
/**
|
||||
* Set a callback to be notified when the output device changes.
|
||||
* @param stream the stream for which to set the callback.
|
||||
* @param device_changed_callback a function called whenever the device has
|
||||
* changed. Passing NULL allow to unregister a function
|
||||
* @return CUBEB_ERROR_INVALID_PARAMETER if either stream or
|
||||
* device_changed_callback are invalid pointers.
|
||||
* @return CUBEB_OK
|
||||
*/
|
||||
int cubeb_stream_register_device_changed_callback(cubeb_stream * stream,
|
||||
cubeb_device_changed_callback device_changed_callback);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -28,16 +28,6 @@ struct cubeb_ops {
|
|||
int (* stream_stop)(cubeb_stream * stream);
|
||||
int (* stream_get_position)(cubeb_stream * stream, uint64_t * position);
|
||||
int (* stream_get_latency)(cubeb_stream * stream, uint32_t * latency);
|
||||
int (* stream_set_volume)(cubeb_stream * stream, float volumes);
|
||||
int (* stream_set_panning)(cubeb_stream * stream, float panning);
|
||||
int (* stream_get_current_device)(cubeb_stream * stream,
|
||||
cubeb_device ** const device);
|
||||
int (* stream_device_destroy)(cubeb_stream * stream,
|
||||
cubeb_device * device);
|
||||
int (*stream_register_device_changed_callback)(cubeb_stream * stream,
|
||||
cubeb_device_changed_callback device_changed_callback);
|
||||
|
||||
};
|
||||
|
||||
#endif /* CUBEB_INTERNAL_0eb56756_4e20_4404_a76d_42bf88cd15a5 */
|
||||
|
||||
|
|
|
@ -258,71 +258,3 @@ cubeb_stream_get_latency(cubeb_stream * stream, uint32_t * latency)
|
|||
|
||||
return stream->context->ops->stream_get_latency(stream, latency);
|
||||
}
|
||||
|
||||
int
|
||||
cubeb_stream_set_volume(cubeb_stream * stream, float volume)
|
||||
{
|
||||
if (!stream || volume > 1.0 || volume < 0.0) {
|
||||
return CUBEB_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
return stream->context->ops->stream_set_volume(stream, volume);
|
||||
}
|
||||
|
||||
int cubeb_stream_set_panning(cubeb_stream * stream, float panning)
|
||||
{
|
||||
if (!stream || panning < -1.0 || panning > 1.0) {
|
||||
return CUBEB_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
return stream->context->ops->stream_set_panning(stream, panning);
|
||||
}
|
||||
|
||||
int cubeb_stream_get_current_device(cubeb_stream * stream,
|
||||
cubeb_device ** const device)
|
||||
{
|
||||
if (!stream || !device) {
|
||||
return CUBEB_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
// If we find an implementation, call the function, it might not be available
|
||||
// on some platforms.
|
||||
if (stream->context->ops->stream_get_current_device) {
|
||||
return stream->context->ops->stream_get_current_device(stream,
|
||||
device);
|
||||
}
|
||||
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
|
||||
int cubeb_stream_device_destroy(cubeb_stream * stream,
|
||||
cubeb_device * device)
|
||||
{
|
||||
if (!stream || !device) {
|
||||
return CUBEB_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
// If we find an implementation, call the function, it might not be available
|
||||
// on some platforms.
|
||||
if (stream->context->ops->stream_device_destroy) {
|
||||
return stream->context->ops->stream_device_destroy(stream, device);
|
||||
}
|
||||
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
|
||||
int cubeb_stream_register_device_changed_callback(cubeb_stream * stream,
|
||||
cubeb_device_changed_callback device_changed_callback)
|
||||
{
|
||||
if (!stream || !device_changed_callback) {
|
||||
return CUBEB_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (stream->context->ops->stream_register_device_changed_callback) {
|
||||
return stream->context->ops->
|
||||
stream_register_device_changed_callback(stream,
|
||||
device_changed_callback);
|
||||
}
|
||||
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
|
|
|
@ -106,7 +106,6 @@ struct cubeb_stream {
|
|||
PulseAudio where streams would stop requesting new data despite still
|
||||
being logically active and playing. */
|
||||
struct timeval last_activity;
|
||||
float volume;
|
||||
};
|
||||
|
||||
static int
|
||||
|
@ -314,20 +313,7 @@ alsa_refill_stream(cubeb_stream * stm)
|
|||
return ERROR;
|
||||
}
|
||||
if (got > 0) {
|
||||
snd_pcm_sframes_t wrote;
|
||||
|
||||
if (stm->params.format == CUBEB_SAMPLE_FLOAT32NE) {
|
||||
float * b = (float *) p;
|
||||
for (uint32_t i = 0; i < got * stm->params.channels; i++) {
|
||||
b[i] *= stm->volume;
|
||||
}
|
||||
} else {
|
||||
short * b = (short *) p;
|
||||
for (uint32_t i = 0; i < got * stm->params.channels; i++) {
|
||||
b[i] *= stm->volume;
|
||||
}
|
||||
}
|
||||
wrote = snd_pcm_writei(stm->pcm, p, got);
|
||||
snd_pcm_sframes_t wrote = snd_pcm_writei(stm->pcm, p, got);
|
||||
if (wrote == -EPIPE) {
|
||||
snd_pcm_recover(stm->pcm, wrote, 1);
|
||||
wrote = snd_pcm_writei(stm->pcm, p, got);
|
||||
|
@ -827,7 +813,6 @@ alsa_stream_init(cubeb * ctx, cubeb_stream ** stream, char const * stream_name,
|
|||
stm->user_ptr = user_ptr;
|
||||
stm->params = stream_params;
|
||||
stm->state = INACTIVE;
|
||||
stm->volume = 1.0;
|
||||
|
||||
r = pthread_mutex_init(&stm->mutex, NULL);
|
||||
assert(r == 0);
|
||||
|
@ -1098,24 +1083,6 @@ alsa_stream_get_latency(cubeb_stream * stm, uint32_t * latency)
|
|||
return CUBEB_OK;
|
||||
}
|
||||
|
||||
int
|
||||
alsa_stream_set_volume(cubeb_stream * stm, float volume)
|
||||
{
|
||||
/* setting the volume using an API call does not seem very stable/supported */
|
||||
pthread_mutex_lock(&stm->mutex);
|
||||
stm->volume = volume;
|
||||
pthread_mutex_unlock(&stm->mutex);
|
||||
|
||||
return CUBEB_OK;
|
||||
}
|
||||
|
||||
int
|
||||
alsa_stream_set_panning(cubeb_stream * stream, float panning)
|
||||
{
|
||||
assert(0 && "not implemented");
|
||||
return CUBEB_OK;
|
||||
}
|
||||
|
||||
static struct cubeb_ops const alsa_ops = {
|
||||
.init = alsa_init,
|
||||
.get_backend_id = alsa_get_backend_id,
|
||||
|
@ -1128,10 +1095,5 @@ static struct cubeb_ops const alsa_ops = {
|
|||
.stream_start = alsa_stream_start,
|
||||
.stream_stop = alsa_stream_stop,
|
||||
.stream_get_position = alsa_stream_get_position,
|
||||
.stream_get_latency = alsa_stream_get_latency,
|
||||
.stream_set_volume = alsa_stream_set_volume,
|
||||
.stream_set_panning = alsa_stream_set_panning,
|
||||
.stream_get_current_device = NULL,
|
||||
.stream_device_destroy = NULL,
|
||||
.stream_register_device_changed_callback = NULL
|
||||
.stream_get_latency = alsa_stream_get_latency
|
||||
};
|
||||
|
|
|
@ -71,7 +71,7 @@ struct AudioTrack {
|
|||
/* static */ int (*get_output_latency)(uint32_t* latency, int stream);
|
||||
/* static */ int (*get_output_samplingrate)(int* samplerate, int stream);
|
||||
status_t (*set_marker_position)(void* instance, unsigned int);
|
||||
status_t (*set_volume)(void* instance, float left, float right);
|
||||
|
||||
};
|
||||
|
||||
struct cubeb {
|
||||
|
@ -251,7 +251,6 @@ audiotrack_init(cubeb ** context, char const * context_name)
|
|||
DLSYM_DLERROR("_ZN7android10AudioTrack5pauseEv", ctx->klass.pause, ctx->library);
|
||||
DLSYM_DLERROR("_ZN7android10AudioTrack11getPositionEPj", ctx->klass.get_position, ctx->library);
|
||||
DLSYM_DLERROR("_ZN7android10AudioTrack17setMarkerPositionEj", ctx->klass.set_marker_position, ctx->library);
|
||||
DLSYM_DLERROR("_ZN7android10AudioTrack9setVolumeEff", ctx->klass.set_volume, ctx->library);
|
||||
|
||||
/* check that we have a combination of symbol that makes sense */
|
||||
c = &ctx->klass;
|
||||
|
@ -469,27 +468,6 @@ audiotrack_stream_get_latency(cubeb_stream * stream, uint32_t * latency)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
audiotrack_stream_set_volume(cubeb_stream * stream, float volume)
|
||||
{
|
||||
status_t status;
|
||||
|
||||
status = stream->context->klass.set_volume(stream->instance, volume, volume);
|
||||
|
||||
if (status) {
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
|
||||
return CUBEB_OK;
|
||||
}
|
||||
|
||||
int
|
||||
audiotrack_stream_set_panning(cubeb_stream * stream, float panning)
|
||||
{
|
||||
assert(false && "not implemented.");
|
||||
return CUBEB_OK;
|
||||
}
|
||||
|
||||
static struct cubeb_ops const audiotrack_ops = {
|
||||
.init = audiotrack_init,
|
||||
.get_backend_id = audiotrack_get_backend_id,
|
||||
|
@ -502,10 +480,5 @@ static struct cubeb_ops const audiotrack_ops = {
|
|||
.stream_start = audiotrack_stream_start,
|
||||
.stream_stop = audiotrack_stream_stop,
|
||||
.stream_get_position = audiotrack_stream_get_position,
|
||||
.stream_get_latency = audiotrack_stream_get_latency,
|
||||
.stream_set_volume = audiotrack_stream_set_volume,
|
||||
.stream_set_panning = audiotrack_stream_set_panning,
|
||||
.stream_get_current_device = NULL,
|
||||
.stream_device_destroy = NULL,
|
||||
.stream_register_device_changed_callback = NULL
|
||||
.stream_get_latency = audiotrack_stream_get_latency
|
||||
};
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include "cubeb/cubeb.h"
|
||||
#include "cubeb-internal.h"
|
||||
#include "cubeb_panner.h"
|
||||
|
||||
#if !defined(kCFCoreFoundationVersionNumber10_7)
|
||||
/* From CoreFoundation CFBase.h */
|
||||
|
@ -38,7 +37,6 @@ struct cubeb_stream {
|
|||
AudioUnit unit;
|
||||
cubeb_data_callback data_callback;
|
||||
cubeb_state_callback state_callback;
|
||||
cubeb_device_changed_callback device_changed_callback;
|
||||
void * user_ptr;
|
||||
AudioStreamBasicDescription sample_spec;
|
||||
pthread_mutex_t mutex;
|
||||
|
@ -48,7 +46,6 @@ struct cubeb_stream {
|
|||
int draining;
|
||||
uint64_t current_latency_frames;
|
||||
uint64_t hw_latency_frames;
|
||||
float panning;
|
||||
};
|
||||
|
||||
static int64_t
|
||||
|
@ -73,7 +70,6 @@ audiounit_output_callback(void * user_ptr, AudioUnitRenderActionFlags * flags,
|
|||
unsigned char * buf;
|
||||
long got;
|
||||
OSStatus r;
|
||||
float panning;
|
||||
|
||||
assert(bufs->mNumberBuffers == 1);
|
||||
buf = bufs->mBuffers[0].mData;
|
||||
|
@ -83,7 +79,6 @@ audiounit_output_callback(void * user_ptr, AudioUnitRenderActionFlags * flags,
|
|||
pthread_mutex_lock(&stm->mutex);
|
||||
|
||||
stm->current_latency_frames = audiotimestamp_to_latency(tstamp, stm);
|
||||
panning = stm->panning;
|
||||
|
||||
if (stm->draining || stm->shutdown) {
|
||||
pthread_mutex_unlock(&stm->mutex);
|
||||
|
@ -118,10 +113,6 @@ audiounit_output_callback(void * user_ptr, AudioUnitRenderActionFlags * flags,
|
|||
stm->frames_queued += got;
|
||||
pthread_mutex_unlock(&stm->mutex);
|
||||
|
||||
if (stm->sample_spec.mChannelsPerFrame == 2) {
|
||||
cubeb_pan_stereo_buffer_float((float*)buf, got, panning);
|
||||
}
|
||||
|
||||
return noErr;
|
||||
}
|
||||
|
||||
|
@ -182,146 +173,6 @@ audiounit_get_output_device_id(AudioDeviceID * device_id)
|
|||
return CUBEB_OK;
|
||||
}
|
||||
|
||||
static int
|
||||
audiounit_get_input_device_id(AudioDeviceID * device_id)
|
||||
{
|
||||
UInt32 size;
|
||||
OSStatus r;
|
||||
AudioObjectPropertyAddress input_device_address = {
|
||||
kAudioHardwarePropertyDefaultInputDevice,
|
||||
kAudioObjectPropertyScopeGlobal,
|
||||
kAudioObjectPropertyElementMaster
|
||||
};
|
||||
|
||||
size = sizeof(*device_id);
|
||||
|
||||
r = AudioObjectGetPropertyData(kAudioObjectSystemObject,
|
||||
&input_device_address,
|
||||
0,
|
||||
NULL,
|
||||
&size,
|
||||
device_id);
|
||||
if (r != noErr) {
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
|
||||
return CUBEB_OK;
|
||||
}
|
||||
|
||||
static int audiounit_install_device_changed_callback(cubeb_stream * stm);
|
||||
static int audiounit_uninstall_device_changed_callback();
|
||||
|
||||
static OSStatus
|
||||
audiounit_property_listener_callback(AudioObjectID id, UInt32 address_count,
|
||||
const AudioObjectPropertyAddress * addresses,
|
||||
void * user)
|
||||
{
|
||||
cubeb_stream * stm = (cubeb_stream*) user;
|
||||
|
||||
for (UInt32 i = 0; i < address_count; i++) {
|
||||
switch(addresses[i].mSelector) {
|
||||
case kAudioHardwarePropertyDefaultOutputDevice:
|
||||
/* fall through */
|
||||
case kAudioDevicePropertyDataSource:
|
||||
pthread_mutex_lock(&stm->mutex);
|
||||
if (stm->device_changed_callback) {
|
||||
stm->device_changed_callback(stm->user_ptr);
|
||||
}
|
||||
pthread_mutex_unlock(&stm->mutex);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return noErr;
|
||||
}
|
||||
|
||||
static int
|
||||
audiounit_install_device_changed_callback(cubeb_stream * stm)
|
||||
{
|
||||
OSStatus r;
|
||||
AudioDeviceID id;
|
||||
|
||||
/* This event will notify us when the data source on the same device changes,
|
||||
* for example when the user plugs in a normal (non-usb) headset in the
|
||||
* headphone jack. */
|
||||
AudioObjectPropertyAddress alive_address = {
|
||||
kAudioDevicePropertyDataSource,
|
||||
kAudioObjectPropertyScopeGlobal,
|
||||
kAudioObjectPropertyElementMaster
|
||||
};
|
||||
|
||||
if (audiounit_get_output_device_id(&id) != noErr) {
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
|
||||
r = AudioObjectAddPropertyListener(id, &alive_address,
|
||||
&audiounit_property_listener_callback,
|
||||
stm);
|
||||
if (r != noErr) {
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
|
||||
/* This event will notify us when the default audio device changes,
|
||||
* for example when the user plugs in a USB headset and the system chooses it
|
||||
* automatically as the default, or when another device is chosen in the
|
||||
* dropdown list. */
|
||||
AudioObjectPropertyAddress default_device_address = {
|
||||
kAudioHardwarePropertyDefaultOutputDevice,
|
||||
kAudioObjectPropertyScopeGlobal,
|
||||
kAudioObjectPropertyElementMaster
|
||||
};
|
||||
|
||||
r = AudioObjectAddPropertyListener(kAudioObjectSystemObject,
|
||||
&default_device_address,
|
||||
&audiounit_property_listener_callback,
|
||||
stm);
|
||||
if (r != noErr) {
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
|
||||
return CUBEB_OK;
|
||||
}
|
||||
|
||||
static int
|
||||
audiounit_uninstall_device_changed_callback()
|
||||
{
|
||||
OSStatus r;
|
||||
AudioDeviceID id;
|
||||
|
||||
AudioObjectPropertyAddress datasource_address = {
|
||||
kAudioDevicePropertyDataSource,
|
||||
kAudioObjectPropertyScopeGlobal,
|
||||
kAudioObjectPropertyElementMaster
|
||||
};
|
||||
|
||||
if (audiounit_get_output_device_id(&id) != noErr) {
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
|
||||
r = AudioObjectRemovePropertyListener(id, &datasource_address,
|
||||
&audiounit_property_listener_callback,
|
||||
NULL);
|
||||
if (r != noErr) {
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
|
||||
AudioObjectPropertyAddress default_device_address = {
|
||||
kAudioHardwarePropertyDefaultOutputDevice,
|
||||
kAudioObjectPropertyScopeGlobal,
|
||||
kAudioObjectPropertyElementMaster
|
||||
};
|
||||
|
||||
r = AudioObjectRemovePropertyListener(kAudioObjectSystemObject,
|
||||
&default_device_address,
|
||||
&audiounit_property_listener_callback,
|
||||
NULL);
|
||||
if (r != noErr) {
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
|
||||
return CUBEB_OK;
|
||||
}
|
||||
|
||||
/* Get the acceptable buffer size (in frames) that this device can work with. */
|
||||
static int
|
||||
audiounit_get_acceptable_latency_range(AudioValueRange * latency_range)
|
||||
|
@ -541,15 +392,10 @@ audiounit_stream_init(cubeb * context, cubeb_stream ** stream, char const * stre
|
|||
stm->data_callback = data_callback;
|
||||
stm->state_callback = state_callback;
|
||||
stm->user_ptr = user_ptr;
|
||||
stm->device_changed_callback = NULL;
|
||||
|
||||
stm->sample_spec = ss;
|
||||
|
||||
pthread_mutexattr_t attr;
|
||||
pthread_mutexattr_init(&attr);
|
||||
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
|
||||
r = pthread_mutex_init(&stm->mutex, &attr);
|
||||
pthread_mutexattr_destroy(&attr);
|
||||
r = pthread_mutex_init(&stm->mutex, NULL);
|
||||
assert(r == 0);
|
||||
|
||||
stm->frames_played = 0;
|
||||
|
@ -634,24 +480,6 @@ audiounit_stream_init(cubeb * context, cubeb_stream ** stream, char const * stre
|
|||
|
||||
*stream = stm;
|
||||
|
||||
/* This is needed so that AudioUnit listeners get called on this thread, and
|
||||
* not the main thread. If we don't do that, they are not called, or a crash
|
||||
* occur, depending on the OSX version. */
|
||||
AudioObjectPropertyAddress runloop_address = {
|
||||
kAudioHardwarePropertyRunLoop,
|
||||
kAudioObjectPropertyScopeGlobal,
|
||||
kAudioObjectPropertyElementMaster
|
||||
};
|
||||
|
||||
CFRunLoopRef run_loop = NULL;
|
||||
r = AudioObjectSetPropertyData(kAudioObjectSystemObject,
|
||||
&runloop_address,
|
||||
0, NULL, sizeof(CFRunLoopRef), &run_loop);
|
||||
|
||||
/* we dont' check the return value here, because we want to be able to play
|
||||
* even if we can't detect device changes. */
|
||||
audiounit_install_device_changed_callback(stm);
|
||||
|
||||
return CUBEB_OK;
|
||||
}
|
||||
|
||||
|
@ -672,8 +500,6 @@ audiounit_stream_destroy(cubeb_stream * stm)
|
|||
#endif
|
||||
}
|
||||
|
||||
audiounit_uninstall_device_changed_callback();
|
||||
|
||||
r = pthread_mutex_destroy(&stm->mutex);
|
||||
assert(r == 0);
|
||||
|
||||
|
@ -791,145 +617,6 @@ audiounit_stream_get_latency(cubeb_stream * stm, uint32_t * latency)
|
|||
return CUBEB_OK;
|
||||
}
|
||||
|
||||
int audiounit_stream_set_volume(cubeb_stream * stm, float volume)
|
||||
{
|
||||
AudioDeviceID id;
|
||||
OSStatus r;
|
||||
|
||||
r = AudioUnitSetParameter(stm->unit,
|
||||
kHALOutputParam_Volume,
|
||||
kAudioUnitScope_Global,
|
||||
0, volume, 0);
|
||||
|
||||
if (r != noErr) {
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
return CUBEB_OK;
|
||||
}
|
||||
|
||||
int audiounit_stream_set_panning(cubeb_stream * stm, float panning)
|
||||
{
|
||||
if (stm->sample_spec.mChannelsPerFrame > 2) {
|
||||
return CUBEB_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&stm->mutex);
|
||||
stm->panning = panning;
|
||||
pthread_mutex_unlock(&stm->mutex);
|
||||
|
||||
return CUBEB_OK;
|
||||
}
|
||||
|
||||
int audiounit_stream_get_current_device(cubeb_stream * stm,
|
||||
cubeb_device ** const device)
|
||||
{
|
||||
OSStatus r;
|
||||
UInt32 size;
|
||||
UInt32 data;
|
||||
char strdata[4];
|
||||
AudioDeviceID output_device_id;
|
||||
AudioDeviceID input_device_id;
|
||||
|
||||
AudioObjectPropertyAddress datasource_address = {
|
||||
kAudioDevicePropertyDataSource,
|
||||
kAudioDevicePropertyScopeOutput,
|
||||
kAudioObjectPropertyElementMaster
|
||||
};
|
||||
|
||||
AudioObjectPropertyAddress datasource_address_input = {
|
||||
kAudioDevicePropertyDataSource,
|
||||
kAudioDevicePropertyScopeInput,
|
||||
kAudioObjectPropertyElementMaster
|
||||
};
|
||||
|
||||
*device = NULL;
|
||||
|
||||
if (audiounit_get_output_device_id(&output_device_id) != CUBEB_OK) {
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
|
||||
*device = malloc(sizeof(cubeb_device));
|
||||
if (!*device) {
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
|
||||
size = sizeof(UInt32);
|
||||
/* This fails with some USB headset, so simply return an empty string. */
|
||||
r = AudioObjectGetPropertyData(output_device_id,
|
||||
&datasource_address,
|
||||
0, NULL, &size, &data);
|
||||
if (r != noErr) {
|
||||
size = 0;
|
||||
data = 0;
|
||||
}
|
||||
|
||||
(*device)->output_name = malloc(size + 1);
|
||||
if (!(*device)->output_name) {
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
|
||||
(*device)->output_name = malloc(size + 1);
|
||||
if (!(*device)->output_name) {
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
|
||||
// Turn the four chars packed into a uint32 into a string
|
||||
strdata[0] = (char)(data >> 24);
|
||||
strdata[1] = (char)(data >> 16);
|
||||
strdata[2] = (char)(data >> 8);
|
||||
strdata[3] = (char)(data);
|
||||
|
||||
memcpy((*device)->output_name, strdata, size);
|
||||
(*device)->output_name[size] = '\0';
|
||||
|
||||
if (audiounit_get_input_device_id(&input_device_id) != CUBEB_OK) {
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
|
||||
size = sizeof(UInt32);
|
||||
r = AudioObjectGetPropertyData(input_device_id, &datasource_address_input, 0, NULL, &size, &data);
|
||||
if (r != noErr) {
|
||||
printf("Error when getting device !\n");
|
||||
size = 0;
|
||||
data = 0;
|
||||
}
|
||||
|
||||
(*device)->input_name = malloc(size + 1);
|
||||
if (!(*device)->input_name) {
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
|
||||
// Turn the four chars packed into a uint32 into a string
|
||||
strdata[0] = (char)(data >> 24);
|
||||
strdata[1] = (char)(data >> 16);
|
||||
strdata[2] = (char)(data >> 8);
|
||||
strdata[3] = (char)(data);
|
||||
|
||||
memcpy((*device)->input_name, strdata, size);
|
||||
(*device)->input_name[size] = '\0';
|
||||
|
||||
return CUBEB_OK;
|
||||
}
|
||||
|
||||
int audiounit_stream_device_destroy(cubeb_stream * stream,
|
||||
cubeb_device * device)
|
||||
{
|
||||
free(device->output_name);
|
||||
free(device->input_name);
|
||||
free(device);
|
||||
return CUBEB_OK;
|
||||
}
|
||||
|
||||
int audiounit_stream_register_device_changed_callback(cubeb_stream * stream,
|
||||
cubeb_device_changed_callback device_changed_callback)
|
||||
{
|
||||
pthread_mutex_lock(&stream->mutex);
|
||||
stream->device_changed_callback = device_changed_callback;
|
||||
pthread_mutex_unlock(&stream->mutex);
|
||||
|
||||
return CUBEB_OK;
|
||||
}
|
||||
|
||||
static struct cubeb_ops const audiounit_ops = {
|
||||
.init = audiounit_init,
|
||||
.get_backend_id = audiounit_get_backend_id,
|
||||
|
@ -942,10 +629,5 @@ static struct cubeb_ops const audiounit_ops = {
|
|||
.stream_start = audiounit_stream_start,
|
||||
.stream_stop = audiounit_stream_stop,
|
||||
.stream_get_position = audiounit_stream_get_position,
|
||||
.stream_get_latency = audiounit_stream_get_latency,
|
||||
.stream_set_volume = audiounit_stream_set_volume,
|
||||
.stream_set_panning = audiounit_stream_set_panning,
|
||||
.stream_get_current_device = audiounit_stream_get_current_device,
|
||||
.stream_device_destroy = audiounit_stream_device_destroy,
|
||||
.stream_register_device_changed_callback = audiounit_stream_register_device_changed_callback
|
||||
.stream_get_latency = audiounit_stream_get_latency
|
||||
};
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <SLES/OpenSLES.h>
|
||||
#include <math.h>
|
||||
#if defined(__ANDROID__)
|
||||
#include <sys/system_properties.h>
|
||||
#include "android/sles_definitions.h"
|
||||
|
@ -35,7 +34,6 @@ struct cubeb {
|
|||
#if defined(__ANDROID__)
|
||||
SLInterfaceID SL_IID_ANDROIDCONFIGURATION;
|
||||
#endif
|
||||
SLInterfaceID SL_IID_VOLUME;
|
||||
SLObjectItf engObj;
|
||||
SLEngineItf eng;
|
||||
SLObjectItf outmixObj;
|
||||
|
@ -51,7 +49,6 @@ struct cubeb_stream {
|
|||
SLObjectItf playerObj;
|
||||
SLPlayItf play;
|
||||
SLBufferQueueItf bufq;
|
||||
SLVolumeItf volume;
|
||||
uint8_t *queuebuf[NBUFS];
|
||||
int queuebuf_idx;
|
||||
long queuebuf_len;
|
||||
|
@ -246,7 +243,6 @@ opensl_init(cubeb ** context, char const * context_name)
|
|||
(slCreateEngine_t)dlsym(ctx->lib, "slCreateEngine");
|
||||
SLInterfaceID SL_IID_ENGINE = *(SLInterfaceID *)dlsym(ctx->lib, "SL_IID_ENGINE");
|
||||
SLInterfaceID SL_IID_OUTPUTMIX = *(SLInterfaceID *)dlsym(ctx->lib, "SL_IID_OUTPUTMIX");
|
||||
ctx->SL_IID_VOLUME = *(SLInterfaceID *)dlsym(ctx->lib, "SL_IID_VOLUME");
|
||||
ctx->SL_IID_BUFFERQUEUE = *(SLInterfaceID *)dlsym(ctx->lib, "SL_IID_BUFFERQUEUE");
|
||||
#if defined(__ANDROID__)
|
||||
ctx->SL_IID_ANDROIDCONFIGURATION = *(SLInterfaceID *)dlsym(ctx->lib, "SL_IID_ANDROIDCONFIGURATION");
|
||||
|
@ -525,13 +521,11 @@ opensl_stream_init(cubeb * ctx, cubeb_stream ** stream, char const * stream_name
|
|||
sink.pFormat = NULL;
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
const SLInterfaceID ids[] = {ctx->SL_IID_BUFFERQUEUE,
|
||||
ctx->SL_IID_VOLUME,
|
||||
ctx->SL_IID_ANDROIDCONFIGURATION};
|
||||
const SLboolean req[] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
|
||||
#else
|
||||
const SLInterfaceID ids[] = {ctx->SL_IID_BUFFERQUEUE, ctx->SL_IID_VOLUME};
|
||||
const SLInterfaceID ids[] = {ctx->SL_IID_BUFFERQUEUE, ctx->SL_IID_ANDROIDCONFIGURATION};
|
||||
const SLboolean req[] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
|
||||
#else
|
||||
const SLInterfaceID ids[] = {ctx->SL_IID_BUFFERQUEUE};
|
||||
const SLboolean req[] = {SL_BOOLEAN_TRUE};
|
||||
#endif
|
||||
assert(NELEMS(ids) == NELEMS(req));
|
||||
SLresult res = (*ctx->eng)->CreateAudioPlayer(ctx->eng, &stm->playerObj,
|
||||
|
@ -615,14 +609,6 @@ opensl_stream_init(cubeb * ctx, cubeb_stream ** stream, char const * stream_name
|
|||
return CUBEB_ERROR;
|
||||
}
|
||||
|
||||
res = (*stm->playerObj)->GetInterface(stm->playerObj, ctx->SL_IID_VOLUME,
|
||||
&stm->volume);
|
||||
|
||||
if (res != SL_RESULT_SUCCESS) {
|
||||
opensl_stream_destroy(stm);
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
|
||||
res = (*stm->play)->RegisterCallback(stm->play, play_callback, stm);
|
||||
if (res != SL_RESULT_SUCCESS) {
|
||||
opensl_stream_destroy(stm);
|
||||
|
@ -738,41 +724,6 @@ opensl_stream_get_latency(cubeb_stream * stm, uint32_t * latency)
|
|||
return CUBEB_OK;
|
||||
}
|
||||
|
||||
int
|
||||
opensl_stream_set_volume(cubeb_stream * stm, float volume)
|
||||
{
|
||||
SLresult res;
|
||||
SLmillibel max_level, millibels;
|
||||
|
||||
res = (*stm->volume)->GetMaxVolumeLevel(stm->volume, &max_level);
|
||||
|
||||
if (res != SL_RESULT_SUCCESS) {
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
|
||||
/* convert to millibels */
|
||||
millibels = lroundf(2000.f * log10f(volume));
|
||||
/* clamp to supported range */
|
||||
if (millibels > max_level) {
|
||||
millibels = max_level;
|
||||
}
|
||||
|
||||
res = (*stm->volume)->SetVolumeLevel(stm->volume, millibels);
|
||||
|
||||
if (res != SL_RESULT_SUCCESS) {
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
return CUBEB_OK;
|
||||
}
|
||||
|
||||
int
|
||||
opensl_stream_set_panning(cubeb_stream * stream, float panning)
|
||||
{
|
||||
assert(0 && "not implemented.");
|
||||
|
||||
return CUBEB_OK;
|
||||
}
|
||||
|
||||
static struct cubeb_ops const opensl_ops = {
|
||||
.init = opensl_init,
|
||||
.get_backend_id = opensl_get_backend_id,
|
||||
|
@ -785,10 +736,5 @@ static struct cubeb_ops const opensl_ops = {
|
|||
.stream_start = opensl_stream_start,
|
||||
.stream_stop = opensl_stream_stop,
|
||||
.stream_get_position = opensl_stream_get_position,
|
||||
.stream_get_latency = opensl_stream_get_latency,
|
||||
.stream_set_volume = opensl_stream_set_volume,
|
||||
.stream_set_panning = opensl_stream_set_panning,
|
||||
.stream_get_current_device = NULL,
|
||||
.stream_device_destroy = NULL,
|
||||
.stream_register_device_changed_callback = NULL
|
||||
.stream_get_latency = opensl_stream_get_latency
|
||||
};
|
||||
|
|
|
@ -1,56 +0,0 @@
|
|||
/*
|
||||
* Copyright © 2014 Mozilla Foundation
|
||||
*
|
||||
* This program is made available under an ISC-style license. See the
|
||||
* accompanying file LICENSE for details.
|
||||
*/
|
||||
|
||||
#define _USE_MATH_DEFINES
|
||||
#include <math.h>
|
||||
#include <cubeb/cubeb-stdint.h>
|
||||
|
||||
#include "cubeb_panner.h"
|
||||
|
||||
/**
|
||||
* We use a cos/sin law.
|
||||
*/
|
||||
|
||||
namespace {
|
||||
template<typename T>
|
||||
void cubeb_pan_stereo_buffer(T * buf, uint32_t frames, float pan)
|
||||
{
|
||||
if (pan == 0.0) {
|
||||
return;
|
||||
}
|
||||
/* rescale in [0; 1] */
|
||||
pan += 1;
|
||||
pan /= 2;
|
||||
float left_gain = cos(pan * M_PI * 0.5);
|
||||
float right_gain = sin(pan * M_PI * 0.5);
|
||||
|
||||
/* In we are panning on the left, pan the right channel into the left one and
|
||||
* vice-versa. */
|
||||
if (pan < 0.5) {
|
||||
for (uint32_t i = 0; i < frames * 2; i+=2) {
|
||||
buf[i] = buf[i] + buf[i + 1] * left_gain;
|
||||
buf[i + 1] = buf[i + 1] * right_gain;
|
||||
}
|
||||
} else {
|
||||
for (uint32_t i = 0; i < frames * 2; i+=2) {
|
||||
buf[i] = buf[i] * left_gain;
|
||||
buf[i + 1] = buf[i + 1] + buf[i] * right_gain;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cubeb_pan_stereo_buffer_float(float * buf, uint32_t frames, float pan)
|
||||
{
|
||||
cubeb_pan_stereo_buffer(reinterpret_cast<float*>(buf), frames, pan);
|
||||
}
|
||||
|
||||
void cubeb_pan_stereo_buffer_int(short * buf, uint32_t frames, float pan)
|
||||
{
|
||||
cubeb_pan_stereo_buffer(reinterpret_cast<short*>(buf), frames, pan);
|
||||
}
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
/*
|
||||
* Copyright © 2014 Mozilla Foundation
|
||||
*
|
||||
* This program is made available under an ISC-style license. See the
|
||||
* accompanying file LICENSE for details.
|
||||
*/
|
||||
|
||||
#if !defined(CUBEB_PANNER)
|
||||
#define CUBEB_PANNER
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Pan an integer or an float stereo buffer according to a cos/sin pan law
|
||||
* @param buf the buffer to pan
|
||||
* @param frames the number of frames in `buf`
|
||||
* @param pan a float in [-1.0; 1.0]
|
||||
*/
|
||||
void cubeb_pan_stereo_buffer_float(float * buf, uint32_t frames, float pan);
|
||||
void cubeb_pan_stereo_buffer_int(short* buf, uint32_t frames, float pan);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -12,28 +12,23 @@
|
|||
#include <string.h>
|
||||
#include "cubeb/cubeb.h"
|
||||
#include "cubeb-internal.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef DISABLE_LIBPULSE_DLOPEN
|
||||
#define WRAP(x) x
|
||||
#else
|
||||
#define WRAP(x) cubeb_##x
|
||||
#define MAKE_TYPEDEF(x) static typeof(x) * cubeb_##x
|
||||
MAKE_TYPEDEF(pa_channel_map_can_balance);
|
||||
MAKE_TYPEDEF(pa_channel_map_init_auto);
|
||||
MAKE_TYPEDEF(pa_context_connect);
|
||||
MAKE_TYPEDEF(pa_context_disconnect);
|
||||
MAKE_TYPEDEF(pa_context_drain);
|
||||
MAKE_TYPEDEF(pa_context_get_server_info);
|
||||
MAKE_TYPEDEF(pa_context_get_sink_info_by_name);
|
||||
MAKE_TYPEDEF(pa_context_get_state);
|
||||
MAKE_TYPEDEF(pa_context_new);
|
||||
MAKE_TYPEDEF(pa_context_rttime_new);
|
||||
MAKE_TYPEDEF(pa_context_set_sink_input_volume);
|
||||
MAKE_TYPEDEF(pa_context_set_state_callback);
|
||||
MAKE_TYPEDEF(pa_context_unref);
|
||||
MAKE_TYPEDEF(pa_cvolume_set);
|
||||
MAKE_TYPEDEF(pa_cvolume_set_balance);
|
||||
MAKE_TYPEDEF(pa_context_get_sink_info_by_name);
|
||||
MAKE_TYPEDEF(pa_context_get_server_info);
|
||||
MAKE_TYPEDEF(pa_frame_size);
|
||||
MAKE_TYPEDEF(pa_operation_get_state);
|
||||
MAKE_TYPEDEF(pa_operation_unref);
|
||||
|
@ -43,10 +38,7 @@ MAKE_TYPEDEF(pa_stream_cancel_write);
|
|||
MAKE_TYPEDEF(pa_stream_connect_playback);
|
||||
MAKE_TYPEDEF(pa_stream_cork);
|
||||
MAKE_TYPEDEF(pa_stream_disconnect);
|
||||
MAKE_TYPEDEF(pa_stream_get_channel_map);
|
||||
MAKE_TYPEDEF(pa_stream_get_index);
|
||||
MAKE_TYPEDEF(pa_stream_get_latency);
|
||||
MAKE_TYPEDEF(pa_stream_get_sample_spec);
|
||||
MAKE_TYPEDEF(pa_stream_get_state);
|
||||
MAKE_TYPEDEF(pa_stream_get_time);
|
||||
MAKE_TYPEDEF(pa_stream_new);
|
||||
|
@ -55,11 +47,10 @@ MAKE_TYPEDEF(pa_stream_set_write_callback);
|
|||
MAKE_TYPEDEF(pa_stream_unref);
|
||||
MAKE_TYPEDEF(pa_stream_update_timing_info);
|
||||
MAKE_TYPEDEF(pa_stream_write);
|
||||
MAKE_TYPEDEF(pa_sw_volume_from_linear);
|
||||
MAKE_TYPEDEF(pa_threaded_mainloop_free);
|
||||
MAKE_TYPEDEF(pa_threaded_mainloop_get_api);
|
||||
MAKE_TYPEDEF(pa_threaded_mainloop_in_thread);
|
||||
MAKE_TYPEDEF(pa_threaded_mainloop_lock);
|
||||
MAKE_TYPEDEF(pa_threaded_mainloop_in_thread);
|
||||
MAKE_TYPEDEF(pa_threaded_mainloop_new);
|
||||
MAKE_TYPEDEF(pa_threaded_mainloop_signal);
|
||||
MAKE_TYPEDEF(pa_threaded_mainloop_start);
|
||||
|
@ -253,12 +244,10 @@ operation_wait(cubeb * ctx, pa_stream * stream, pa_operation * o)
|
|||
{
|
||||
while (WRAP(pa_operation_get_state)(o) == PA_OPERATION_RUNNING) {
|
||||
WRAP(pa_threaded_mainloop_wait)(ctx->mainloop);
|
||||
if (!PA_CONTEXT_IS_GOOD(WRAP(pa_context_get_state)(ctx->context))) {
|
||||
if (!PA_CONTEXT_IS_GOOD(WRAP(pa_context_get_state)(ctx->context)))
|
||||
return -1;
|
||||
}
|
||||
if (stream && !PA_STREAM_IS_GOOD(WRAP(pa_stream_get_state)(stream))) {
|
||||
if (stream && !PA_STREAM_IS_GOOD(WRAP(pa_stream_get_state)(stream)))
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -335,21 +324,17 @@ pulse_init(cubeb ** context, char const * context_name)
|
|||
return CUBEB_ERROR; \
|
||||
} \
|
||||
} while(0)
|
||||
LOAD(pa_channel_map_can_balance);
|
||||
LOAD(pa_channel_map_init_auto);
|
||||
LOAD(pa_context_connect);
|
||||
LOAD(pa_context_disconnect);
|
||||
LOAD(pa_context_drain);
|
||||
LOAD(pa_context_get_server_info);
|
||||
LOAD(pa_context_get_sink_info_by_name);
|
||||
LOAD(pa_context_get_state);
|
||||
LOAD(pa_context_new);
|
||||
LOAD(pa_context_rttime_new);
|
||||
LOAD(pa_context_set_sink_input_volume);
|
||||
LOAD(pa_context_set_state_callback);
|
||||
LOAD(pa_context_get_sink_info_by_name);
|
||||
LOAD(pa_context_get_server_info);
|
||||
LOAD(pa_context_unref);
|
||||
LOAD(pa_cvolume_set);
|
||||
LOAD(pa_cvolume_set_balance);
|
||||
LOAD(pa_frame_size);
|
||||
LOAD(pa_operation_get_state);
|
||||
LOAD(pa_operation_unref);
|
||||
|
@ -359,10 +344,7 @@ pulse_init(cubeb ** context, char const * context_name)
|
|||
LOAD(pa_stream_connect_playback);
|
||||
LOAD(pa_stream_cork);
|
||||
LOAD(pa_stream_disconnect);
|
||||
LOAD(pa_stream_get_channel_map);
|
||||
LOAD(pa_stream_get_index);
|
||||
LOAD(pa_stream_get_latency);
|
||||
LOAD(pa_stream_get_sample_spec);
|
||||
LOAD(pa_stream_get_state);
|
||||
LOAD(pa_stream_get_time);
|
||||
LOAD(pa_stream_new);
|
||||
|
@ -371,11 +353,10 @@ pulse_init(cubeb ** context, char const * context_name)
|
|||
LOAD(pa_stream_unref);
|
||||
LOAD(pa_stream_update_timing_info);
|
||||
LOAD(pa_stream_write);
|
||||
LOAD(pa_sw_volume_from_linear);
|
||||
LOAD(pa_threaded_mainloop_free);
|
||||
LOAD(pa_threaded_mainloop_get_api);
|
||||
LOAD(pa_threaded_mainloop_in_thread);
|
||||
LOAD(pa_threaded_mainloop_lock);
|
||||
LOAD(pa_threaded_mainloop_in_thread);
|
||||
LOAD(pa_threaded_mainloop_new);
|
||||
LOAD(pa_threaded_mainloop_signal);
|
||||
LOAD(pa_threaded_mainloop_start);
|
||||
|
@ -680,60 +661,6 @@ pulse_stream_get_latency(cubeb_stream * stm, uint32_t * latency)
|
|||
return CUBEB_OK;
|
||||
}
|
||||
|
||||
void volume_success(pa_context *c, int success, void *userdata)
|
||||
{
|
||||
cubeb_stream * stream = userdata;
|
||||
assert(success);
|
||||
WRAP(pa_threaded_mainloop_signal)(stream->context->mainloop, 0);
|
||||
}
|
||||
|
||||
int
|
||||
pulse_stream_set_volume(cubeb_stream * stm, float volume)
|
||||
{
|
||||
uint32_t index;
|
||||
pa_operation * op;
|
||||
pa_volume_t vol;
|
||||
pa_cvolume cvol;
|
||||
const pa_sample_spec * ss;
|
||||
|
||||
WRAP(pa_threaded_mainloop_lock)(stm->context->mainloop);
|
||||
|
||||
ss = WRAP(pa_stream_get_sample_spec)(stm->stream);
|
||||
|
||||
vol = WRAP(pa_sw_volume_from_linear)(volume);
|
||||
WRAP(pa_cvolume_set)(&cvol, ss->channels, vol);
|
||||
|
||||
index = WRAP(pa_stream_get_index)(stm->stream);
|
||||
|
||||
op = WRAP(pa_context_set_sink_input_volume)(stm->context->context,
|
||||
index, &cvol, volume_success,
|
||||
stm);
|
||||
if (op) {
|
||||
operation_wait(stm->context, stm->stream, op);
|
||||
WRAP(pa_operation_unref)(op);
|
||||
}
|
||||
WRAP(pa_threaded_mainloop_unlock)(stm->context->mainloop);
|
||||
|
||||
return CUBEB_OK;
|
||||
}
|
||||
|
||||
int
|
||||
pulse_stream_set_panning(cubeb_stream * stream, float panning)
|
||||
{
|
||||
const pa_channel_map * map;
|
||||
pa_cvolume vol;
|
||||
|
||||
map = WRAP(pa_stream_get_channel_map)(stream->stream);
|
||||
|
||||
if (!WRAP(pa_channel_map_can_balance)(map)) {
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
|
||||
WRAP(pa_cvolume_set_balance)(&vol, map, panning);
|
||||
|
||||
return CUBEB_OK;
|
||||
}
|
||||
|
||||
static struct cubeb_ops const pulse_ops = {
|
||||
.init = pulse_init,
|
||||
.get_backend_id = pulse_get_backend_id,
|
||||
|
@ -746,10 +673,5 @@ static struct cubeb_ops const pulse_ops = {
|
|||
.stream_start = pulse_stream_start,
|
||||
.stream_stop = pulse_stream_stop,
|
||||
.stream_get_position = pulse_stream_get_position,
|
||||
.stream_get_latency = pulse_stream_get_latency,
|
||||
.stream_set_volume = pulse_stream_set_volume,
|
||||
.stream_set_panning = pulse_stream_set_panning,
|
||||
.stream_get_current_device = NULL,
|
||||
.stream_device_destroy = NULL,
|
||||
.stream_register_device_changed_callback = NULL
|
||||
.stream_get_latency = pulse_stream_get_latency
|
||||
};
|
||||
|
|
|
@ -341,12 +341,6 @@ sndio_stream_get_latency(cubeb_stream * stm, uint32_t * latency)
|
|||
return CUBEB_OK;
|
||||
}
|
||||
|
||||
int
|
||||
sndio_stream_set_volume(cubeb_stream * stm, float panning)
|
||||
{
|
||||
assert(0 && "not implemented");
|
||||
}
|
||||
|
||||
static struct cubeb_ops const sndio_ops = {
|
||||
.init = sndio_init,
|
||||
.get_backend_id = sndio_get_backend_id,
|
||||
|
@ -359,10 +353,5 @@ static struct cubeb_ops const sndio_ops = {
|
|||
.stream_start = sndio_stream_start,
|
||||
.stream_stop = sndio_stream_stop,
|
||||
.stream_get_position = sndio_stream_get_position,
|
||||
.stream_get_latency = sndio_stream_get_latency,
|
||||
.stream_set_volume = sndio_stream_set_volume,
|
||||
.stream_set_panning = sndio_stream_set_panning,
|
||||
.stream_get_current_device = NULL,
|
||||
.stream_device_destroy = NULL,
|
||||
.stream_register_device_changed_callback = NULL
|
||||
.stream_get_latency = sndio_stream_get_latency
|
||||
};
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
#include "cubeb_resampler.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#if 1
|
||||
#if 0
|
||||
# define LOG(...) do { \
|
||||
fprintf(stderr, __VA_ARGS__); \
|
||||
fprintf(stderr, "\n"); \
|
||||
|
@ -102,8 +102,6 @@ struct cubeb_stream
|
|||
IAudioRenderClient * render_client;
|
||||
/* Interface pointer to use the clock facilities. */
|
||||
IAudioClock * audio_clock;
|
||||
/* Interface pointer to use the volume facilities. */
|
||||
IAudioStreamVolume * audio_stream_volume;
|
||||
/* This event is set by the stream_stop and stream_destroy
|
||||
* function, so the render loop can exit properly. */
|
||||
HANDLE shutdown_event;
|
||||
|
@ -750,14 +748,6 @@ wasapi_stream_init(cubeb * context, cubeb_stream ** stream,
|
|||
return CUBEB_ERROR;
|
||||
}
|
||||
|
||||
hr = stm->client->GetService(__uuidof(IAudioStreamVolume),
|
||||
(void **)&stm->audio_stream_volume);
|
||||
if (FAILED(hr)) {
|
||||
LOG("Could not get the IAudioStreamVolume %x.", hr);
|
||||
wasapi_stream_destroy(stm);
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
|
||||
hr = stm->audio_clock->GetFrequency(&stm->clock_freq);
|
||||
if (FAILED(hr)) {
|
||||
LOG("failed to get audio clock frequency, %x", hr);
|
||||
|
@ -892,39 +882,6 @@ int wasapi_stream_get_latency(cubeb_stream * stm, uint32_t * latency)
|
|||
return CUBEB_OK;
|
||||
}
|
||||
|
||||
int wasapi_stream_set_volume(cubeb_stream * stm, float volume)
|
||||
{
|
||||
HRESULT hr;
|
||||
uint32_t channels;
|
||||
/* up to 9.1 for now */
|
||||
float volumes[10];
|
||||
|
||||
hr = stm->audio_stream_volume->GetChannelCount(&channels);
|
||||
if (hr != S_OK) {
|
||||
LOG("could not get the channel count: %x", hr);
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
|
||||
assert(channels <= 10 && "bump the array size");
|
||||
|
||||
for (uint32_t i = 0; i < channels; i++) {
|
||||
volumes[i] = volume;
|
||||
}
|
||||
|
||||
hr = stm->audio_stream_volume->SetAllVolumes(channels, volumes);
|
||||
if (hr != S_OK) {
|
||||
LOG("coult not set the channels volume: %x", hr);
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
return CUBEB_OK;
|
||||
}
|
||||
|
||||
int wasapi_stream_set_panning(cubeb_stream * stream, float panning)
|
||||
{
|
||||
assert(false && "not implemented");
|
||||
return CUBEB_OK;
|
||||
}
|
||||
|
||||
cubeb_ops const wasapi_ops = {
|
||||
/*.init =*/ wasapi_init,
|
||||
/*.get_backend_id =*/ wasapi_get_backend_id,
|
||||
|
@ -937,12 +894,7 @@ cubeb_ops const wasapi_ops = {
|
|||
/*.stream_start =*/ wasapi_stream_start,
|
||||
/*.stream_stop =*/ wasapi_stream_stop,
|
||||
/*.stream_get_position =*/ wasapi_stream_get_position,
|
||||
/*.stream_get_latency =*/ wasapi_stream_get_latency,
|
||||
/*.stream_set_volume =*/ wasapi_stream_set_volume,
|
||||
/*.stream_set_panning =*/ wasapi_stream_set_panning,
|
||||
/*.stream_get_current_device =*/ NULL,
|
||||
/*.stream_device_destroy =*/ NULL,
|
||||
/*.stream_register_device_changed_callback =*/ NULL
|
||||
/*.stream_get_latency =*/ wasapi_stream_get_latency
|
||||
};
|
||||
} // namespace anonymous
|
||||
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
#include <mmsystem.h>
|
||||
#include <process.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include "cubeb/cubeb.h"
|
||||
#include "cubeb-internal.h"
|
||||
|
||||
|
@ -29,9 +28,6 @@
|
|||
|
||||
#define CUBEB_STREAM_MAX 32
|
||||
#define NBUFS 4
|
||||
/* When cubeb_stream.soft_volume is set to this value, the device supports
|
||||
* setting the volume. Otherwise, a gain will be applied manually. */
|
||||
#define SETTING_VOLUME_SUPPORTED -1.0
|
||||
|
||||
const GUID KSDATAFORMAT_SUBTYPE_PCM =
|
||||
{ 0x00000001, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 } };
|
||||
|
@ -72,7 +68,6 @@ struct cubeb_stream {
|
|||
HWAVEOUT waveout;
|
||||
CRITICAL_SECTION lock;
|
||||
uint64_t written;
|
||||
float soft_volume;
|
||||
};
|
||||
|
||||
static size_t
|
||||
|
@ -160,22 +155,6 @@ winmm_refill_stream(cubeb_stream * stm)
|
|||
hdr->dwBufferLength = got * bytes_per_frame(stm->params);
|
||||
assert(hdr->dwBufferLength <= stm->buffer_size);
|
||||
|
||||
if (stm->soft_volume != SETTING_VOLUME_SUPPORTED) {
|
||||
if (stm->params.format == CUBEB_SAMPLE_FLOAT32NE) {
|
||||
short * b = (short *) hdr->lpData;
|
||||
uint32_t i;
|
||||
for (i = 0; i < got * stm->params.channels; i++) {
|
||||
b[i] *= stm->soft_volume;
|
||||
}
|
||||
} else {
|
||||
short * b = (short *) hdr->lpData;
|
||||
uint32_t i;
|
||||
for (i = 0; i < got * stm->params.channels; i++) {
|
||||
b[i] *= stm->soft_volume;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
r = waveOutWrite(stm->waveout, hdr, sizeof(*hdr));
|
||||
if (r != MMSYSERR_NOERROR) {
|
||||
LeaveCriticalSection(&stm->lock);
|
||||
|
@ -351,7 +330,6 @@ winmm_stream_init(cubeb * context, cubeb_stream ** stream, char const * stream_n
|
|||
{
|
||||
MMRESULT r;
|
||||
WAVEFORMATEXTENSIBLE wfx;
|
||||
WAVEOUTCAPS waveoutcaps;
|
||||
cubeb_stream * stm;
|
||||
int i;
|
||||
size_t bufsz;
|
||||
|
@ -438,20 +416,6 @@ winmm_stream_init(cubeb * context, cubeb_stream ** stream, char const * stream_n
|
|||
return CUBEB_ERROR;
|
||||
}
|
||||
|
||||
r = waveOutGetDevCaps(WAVE_MAPPER, &waveoutcaps, sizeof(WAVEOUTCAPS));
|
||||
if(r != MMSYSERR_NOERROR) {
|
||||
winmm_stream_destroy(stm);
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
|
||||
stm->soft_volume = SETTING_VOLUME_SUPPORTED;
|
||||
|
||||
/* if this device does not support setting the volume, do it manually. */
|
||||
if(!(waveoutcaps.dwSupport & WAVECAPS_VOLUME)) {
|
||||
stm->soft_volume = 1.0;
|
||||
}
|
||||
|
||||
|
||||
/* winmm_buffer_callback will be called during waveOutOpen, so all
|
||||
other initialization must be complete before calling it. */
|
||||
r = waveOutOpen(&stm->waveout, WAVE_MAPPER, &wfx.Format,
|
||||
|
@ -468,7 +432,6 @@ winmm_stream_init(cubeb * context, cubeb_stream ** stream, char const * stream_n
|
|||
return CUBEB_ERROR;
|
||||
}
|
||||
|
||||
|
||||
for (i = 0; i < NBUFS; ++i) {
|
||||
WAVEHDR * hdr = &stm->buffers[i];
|
||||
|
||||
|
@ -665,41 +628,6 @@ winmm_stream_get_latency(cubeb_stream * stm, uint32_t * latency)
|
|||
return CUBEB_OK;
|
||||
}
|
||||
|
||||
static int
|
||||
winmm_stream_set_volume(cubeb_stream * stm, float volume)
|
||||
{
|
||||
MMRESULT r;
|
||||
DWORD vol;
|
||||
|
||||
if (stm->soft_volume != SETTING_VOLUME_SUPPORTED) {
|
||||
stm->soft_volume = volume;
|
||||
return CUBEB_OK;
|
||||
}
|
||||
|
||||
// lower order word is the left channel, higher order
|
||||
// word is the right channel. Full volume on a channel is 0xffff.
|
||||
vol = volume * 0xffff;
|
||||
vol |= vol << 16;
|
||||
|
||||
EnterCriticalSection(&stm->lock);
|
||||
r = waveOutSetVolume(stm->waveout, vol);
|
||||
if (r != MMSYSERR_NOERROR) {
|
||||
stm->soft_volume = volume;
|
||||
LeaveCriticalSection(&stm->lock);
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
LeaveCriticalSection(&stm->lock);
|
||||
|
||||
return CUBEB_OK;
|
||||
}
|
||||
|
||||
static int
|
||||
winmm_stream_set_panning(cubeb_stream * stream, float panning)
|
||||
{
|
||||
assert(0 && "not implemented");
|
||||
return CUBEB_OK;
|
||||
}
|
||||
|
||||
static struct cubeb_ops const winmm_ops = {
|
||||
/*.init =*/ winmm_init,
|
||||
/*.get_backend_id =*/ winmm_get_backend_id,
|
||||
|
@ -712,10 +640,5 @@ static struct cubeb_ops const winmm_ops = {
|
|||
/*.stream_start =*/ winmm_stream_start,
|
||||
/*.stream_stop =*/ winmm_stream_stop,
|
||||
/*.stream_get_position =*/ winmm_stream_get_position,
|
||||
/*.stream_get_latency = */ winmm_stream_get_latency,
|
||||
/*.stream_set_volume =*/ winmm_stream_set_volume,
|
||||
/*.stream_set_panning =*/ winmm_stream_set_panning,
|
||||
/*.stream_get_current_device =*/ NULL,
|
||||
/*.stream_device_destroy =*/ NULL,
|
||||
/*.stream_register_device_changed_callback=*/ NULL
|
||||
/*.stream_get_latency = */ winmm_stream_get_latency
|
||||
};
|
||||
|
|
|
@ -8,7 +8,6 @@ LIBRARY_NAME = 'cubeb'
|
|||
|
||||
SOURCES += [
|
||||
'cubeb.c',
|
||||
'cubeb_panner.cpp'
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_ALSA']:
|
||||
|
|
Загрузка…
Ссылка в новой задаче