qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [PULL 0/3] Audio 20210316 patches
@ 2021-03-16 10:47 Gerd Hoffmann
  2021-03-16 10:47 ` [PULL 1/3] coreaudio: Drop support for macOS older than 10.6 Gerd Hoffmann
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Gerd Hoffmann @ 2021-03-16 10:47 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

The following changes since commit 2615a5e433aeb812c300d3a48e1a88e1303e2339:

  Merge remote-tracking branch 'remotes/stefanha-gitlab/tags/block-pull-reque=
st' into staging (2021-03-15 19:23:00 +0000)

are available in the Git repository at:

  git://git.kraxel.org/qemu tags/audio-20210316-pull-request

for you to fetch changes up to 3ba6e3f6888d2825709eba2f623f0615069c036c:

  coreaudio: Handle output device change (2021-03-16 07:17:50 +0100)

----------------------------------------------------------------
coreaudio fixes and cleanups.

----------------------------------------------------------------

Akihiko Odaki (3):
  coreaudio: Drop support for macOS older than 10.6
  coreaudio: Extract device operations
  coreaudio: Handle output device change

 audio/coreaudio.c | 428 +++++++++++++++++++++++++---------------------
 1 file changed, 235 insertions(+), 193 deletions(-)

--=20
2.30.2




^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PULL 1/3] coreaudio: Drop support for macOS older than 10.6
  2021-03-16 10:47 [PULL 0/3] Audio 20210316 patches Gerd Hoffmann
@ 2021-03-16 10:47 ` Gerd Hoffmann
  2021-03-16 10:47 ` [PULL 2/3] coreaudio: Extract device operations Gerd Hoffmann
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Gerd Hoffmann @ 2021-03-16 10:47 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, Gerd Hoffmann, Akihiko Odaki

From: Akihiko Odaki <akihiko.odaki@gmail.com>

Mac OS X 10.6 was released in 2009.

Signed-off-by: Akihiko Odaki <akihiko.odaki@gmail.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Message-Id: <20210311151512.22096-1-akihiko.odaki@gmail.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 audio/coreaudio.c | 103 ----------------------------------------------
 1 file changed, 103 deletions(-)

diff --git a/audio/coreaudio.c b/audio/coreaudio.c
index b7c02e0e516d..c5f0b615d643 100644
--- a/audio/coreaudio.c
+++ b/audio/coreaudio.c
@@ -32,10 +32,6 @@
 #define AUDIO_CAP "coreaudio"
 #include "audio_int.h"
 
-#ifndef MAC_OS_X_VERSION_10_6
-#define MAC_OS_X_VERSION_10_6 1060
-#endif
-
 typedef struct coreaudioVoiceOut {
     HWVoiceOut hw;
     pthread_mutex_t mutex;
@@ -45,9 +41,6 @@ typedef struct coreaudioVoiceOut {
     AudioDeviceIOProcID ioprocid;
 } coreaudioVoiceOut;
 
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
-/* The APIs used here only become available from 10.6 */
-
 static OSStatus coreaudio_get_voice(AudioDeviceID *id)
 {
     UInt32 size = sizeof(*id);
@@ -169,102 +162,6 @@ static OSStatus coreaudio_get_isrunning(AudioDeviceID id, UInt32 *result)
                                       &size,
                                       result);
 }
-#else
-/* Legacy versions of functions using deprecated APIs */
-
-static OSStatus coreaudio_get_voice(AudioDeviceID *id)
-{
-    UInt32 size = sizeof(*id);
-
-    return AudioHardwareGetProperty(
-        kAudioHardwarePropertyDefaultOutputDevice,
-        &size,
-        id);
-}
-
-static OSStatus coreaudio_get_framesizerange(AudioDeviceID id,
-                                             AudioValueRange *framerange)
-{
-    UInt32 size = sizeof(*framerange);
-
-    return AudioDeviceGetProperty(
-        id,
-        0,
-        0,
-        kAudioDevicePropertyBufferFrameSizeRange,
-        &size,
-        framerange);
-}
-
-static OSStatus coreaudio_get_framesize(AudioDeviceID id, UInt32 *framesize)
-{
-    UInt32 size = sizeof(*framesize);
-
-    return AudioDeviceGetProperty(
-        id,
-        0,
-        false,
-        kAudioDevicePropertyBufferFrameSize,
-        &size,
-        framesize);
-}
-
-static OSStatus coreaudio_set_framesize(AudioDeviceID id, UInt32 *framesize)
-{
-    UInt32 size = sizeof(*framesize);
-
-    return AudioDeviceSetProperty(
-        id,
-        NULL,
-        0,
-        false,
-        kAudioDevicePropertyBufferFrameSize,
-        size,
-        framesize);
-}
-
-static OSStatus coreaudio_get_streamformat(AudioDeviceID id,
-                                           AudioStreamBasicDescription *d)
-{
-    UInt32 size = sizeof(*d);
-
-    return AudioDeviceGetProperty(
-        id,
-        0,
-        false,
-        kAudioDevicePropertyStreamFormat,
-        &size,
-        d);
-}
-
-static OSStatus coreaudio_set_streamformat(AudioDeviceID id,
-                                           AudioStreamBasicDescription *d)
-{
-    UInt32 size = sizeof(*d);
-
-    return AudioDeviceSetProperty(
-        id,
-        0,
-        0,
-        0,
-        kAudioDevicePropertyStreamFormat,
-        size,
-        d);
-}
-
-static OSStatus coreaudio_get_isrunning(AudioDeviceID id, UInt32 *result)
-{
-    UInt32 size = sizeof(*result);
-
-    return AudioDeviceGetProperty(
-        id,
-        0,
-        0,
-        kAudioDevicePropertyDeviceIsRunning,
-        &size,
-        result);
-}
-#endif
 
 static void coreaudio_logstatus (OSStatus status)
 {
-- 
2.30.2



^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PULL 2/3] coreaudio: Extract device operations
  2021-03-16 10:47 [PULL 0/3] Audio 20210316 patches Gerd Hoffmann
  2021-03-16 10:47 ` [PULL 1/3] coreaudio: Drop support for macOS older than 10.6 Gerd Hoffmann
@ 2021-03-16 10:47 ` Gerd Hoffmann
  2021-03-16 10:47 ` [PULL 3/3] coreaudio: Handle output device change Gerd Hoffmann
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Gerd Hoffmann @ 2021-03-16 10:47 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann, Akihiko Odaki

From: Akihiko Odaki <akihiko.odaki@gmail.com>

This change prepare to support dynamic device changes, which requires to
perform device initialization/deinitialization multiple times.

Signed-off-by: Akihiko Odaki <akihiko.odaki@gmail.com>
Message-Id: <20210311151512.22096-2-akihiko.odaki@gmail.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 audio/coreaudio.c | 137 +++++++++++++++++++++++++++-------------------
 1 file changed, 80 insertions(+), 57 deletions(-)

diff --git a/audio/coreaudio.c b/audio/coreaudio.c
index c5f0b615d643..ab43cdcac199 100644
--- a/audio/coreaudio.c
+++ b/audio/coreaudio.c
@@ -36,6 +36,8 @@ typedef struct coreaudioVoiceOut {
     HWVoiceOut hw;
     pthread_mutex_t mutex;
     AudioDeviceID outputDeviceID;
+    int frameSizeSetting;
+    uint32_t bufferCount;
     UInt32 audioDevicePropertyBufferFrameSize;
     AudioStreamBasicDescription outputStreamBasicDescription;
     AudioDeviceIOProcID ioprocid;
@@ -253,6 +255,9 @@ static void GCC_FMT_ATTR (3, 4) coreaudio_logerr2 (
     coreaudio_logstatus (status);
 }
 
+#define coreaudio_playback_logerr(status, ...) \
+    coreaudio_logerr2(status, "playback", __VA_ARGS__)
+
 static inline UInt32 isPlaying (AudioDeviceID outputDeviceID)
 {
     OSStatus status;
@@ -368,126 +373,100 @@ static OSStatus audioDeviceIOProc(
     return 0;
 }
 
-static int coreaudio_init_out(HWVoiceOut *hw, struct audsettings *as,
-                              void *drv_opaque)
+static OSStatus init_out_device(coreaudioVoiceOut *core)
 {
     OSStatus status;
-    coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw;
-    int err;
-    const char *typ = "playback";
     AudioValueRange frameRange;
-    Audiodev *dev = drv_opaque;
-    AudiodevCoreaudioPerDirectionOptions *cpdo = dev->u.coreaudio.out;
-    int frames;
-    struct audsettings obt_as;
-
-    /* create mutex */
-    err = pthread_mutex_init(&core->mutex, NULL);
-    if (err) {
-        dolog("Could not create mutex\nReason: %s\n", strerror (err));
-        return -1;
-    }
-
-    obt_as = *as;
-    as = &obt_as;
-    as->fmt = AUDIO_FORMAT_F32;
-    audio_pcm_init_info (&hw->info, as);
 
     status = coreaudio_get_voice(&core->outputDeviceID);
     if (status != kAudioHardwareNoError) {
-        coreaudio_logerr2 (status, typ,
-                           "Could not get default output Device\n");
-        return -1;
+        coreaudio_playback_logerr (status,
+                                   "Could not get default output Device\n");
+        return status;
     }
     if (core->outputDeviceID == kAudioDeviceUnknown) {
-        dolog ("Could not initialize %s - Unknown Audiodevice\n", typ);
-        return -1;
+        dolog ("Could not initialize playback - Unknown Audiodevice\n");
+        return status;
     }
 
     /* get minimum and maximum buffer frame sizes */
     status = coreaudio_get_framesizerange(core->outputDeviceID,
                                           &frameRange);
     if (status != kAudioHardwareNoError) {
-        coreaudio_logerr2 (status, typ,
-                           "Could not get device buffer frame range\n");
-        return -1;
+        coreaudio_playback_logerr (status,
+                                    "Could not get device buffer frame range\n");
+        return status;
     }
 
-    frames = audio_buffer_frames(
-        qapi_AudiodevCoreaudioPerDirectionOptions_base(cpdo), as, 11610);
-    if (frameRange.mMinimum > frames) {
+    if (frameRange.mMinimum > core->frameSizeSetting) {
         core->audioDevicePropertyBufferFrameSize = (UInt32) frameRange.mMinimum;
         dolog ("warning: Upsizing Buffer Frames to %f\n", frameRange.mMinimum);
-    } else if (frameRange.mMaximum < frames) {
+    } else if (frameRange.mMaximum < core->frameSizeSetting) {
         core->audioDevicePropertyBufferFrameSize = (UInt32) frameRange.mMaximum;
         dolog ("warning: Downsizing Buffer Frames to %f\n", frameRange.mMaximum);
     } else {
-        core->audioDevicePropertyBufferFrameSize = frames;
+        core->audioDevicePropertyBufferFrameSize = core->frameSizeSetting;
     }
 
     /* set Buffer Frame Size */
     status = coreaudio_set_framesize(core->outputDeviceID,
                                      &core->audioDevicePropertyBufferFrameSize);
     if (status != kAudioHardwareNoError) {
-        coreaudio_logerr2 (status, typ,
-                           "Could not set device buffer frame size %" PRIu32 "\n",
-                           (uint32_t)core->audioDevicePropertyBufferFrameSize);
-        return -1;
+        coreaudio_playback_logerr (status,
+                                    "Could not set device buffer frame size %" PRIu32 "\n",
+                                    (uint32_t)core->audioDevicePropertyBufferFrameSize);
+        return status;
     }
 
     /* get Buffer Frame Size */
     status = coreaudio_get_framesize(core->outputDeviceID,
                                      &core->audioDevicePropertyBufferFrameSize);
     if (status != kAudioHardwareNoError) {
-        coreaudio_logerr2 (status, typ,
-                           "Could not get device buffer frame size\n");
-        return -1;
+        coreaudio_playback_logerr (status,
+                                    "Could not get device buffer frame size\n");
+        return status;
     }
-    hw->samples = (cpdo->has_buffer_count ? cpdo->buffer_count : 4) *
-        core->audioDevicePropertyBufferFrameSize;
+    core->hw.samples = core->bufferCount * core->audioDevicePropertyBufferFrameSize;
 
     /* get StreamFormat */
     status = coreaudio_get_streamformat(core->outputDeviceID,
                                         &core->outputStreamBasicDescription);
     if (status != kAudioHardwareNoError) {
-        coreaudio_logerr2 (status, typ,
-                           "Could not get Device Stream properties\n");
+        coreaudio_playback_logerr (status,
+                                    "Could not get Device Stream properties\n");
         core->outputDeviceID = kAudioDeviceUnknown;
-        return -1;
+        return status;
     }
 
     /* set Samplerate */
-    core->outputStreamBasicDescription.mSampleRate = (Float64) as->freq;
-
     status = coreaudio_set_streamformat(core->outputDeviceID,
                                         &core->outputStreamBasicDescription);
     if (status != kAudioHardwareNoError) {
-        coreaudio_logerr2 (status, typ, "Could not set samplerate %d\n",
-                           as->freq);
+        coreaudio_playback_logerr (status,
+                                   "Could not set samplerate %lf\n",
+                                   core->outputStreamBasicDescription.mSampleRate);
         core->outputDeviceID = kAudioDeviceUnknown;
-        return -1;
+        return status;
     }
 
     /* set Callback */
     core->ioprocid = NULL;
     status = AudioDeviceCreateIOProcID(core->outputDeviceID,
                                        audioDeviceIOProc,
-                                       hw,
+                                       &core->hw,
                                        &core->ioprocid);
     if (status != kAudioHardwareNoError || core->ioprocid == NULL) {
-        coreaudio_logerr2 (status, typ, "Could not set IOProc\n");
+        coreaudio_playback_logerr (status, "Could not set IOProc\n");
         core->outputDeviceID = kAudioDeviceUnknown;
-        return -1;
+        return status;
     }
 
     return 0;
 }
 
-static void coreaudio_fini_out (HWVoiceOut *hw)
+static void fini_out_device(coreaudioVoiceOut *core)
 {
     OSStatus status;
-    int err;
-    coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw;
 
     /* stop playback */
     if (isPlaying(core->outputDeviceID)) {
@@ -504,6 +483,50 @@ static void coreaudio_fini_out (HWVoiceOut *hw)
         coreaudio_logerr(status, "Could not remove IOProc\n");
     }
     core->outputDeviceID = kAudioDeviceUnknown;
+}
+
+static int coreaudio_init_out(HWVoiceOut *hw, struct audsettings *as,
+                              void *drv_opaque)
+{
+    OSStatus status;
+    coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw;
+    int err;
+    Audiodev *dev = drv_opaque;
+    AudiodevCoreaudioPerDirectionOptions *cpdo = dev->u.coreaudio.out;
+    struct audsettings obt_as;
+
+    /* create mutex */
+    err = pthread_mutex_init(&core->mutex, NULL);
+    if (err) {
+        dolog("Could not create mutex\nReason: %s\n", strerror (err));
+        return -1;
+    }
+
+    obt_as = *as;
+    as = &obt_as;
+    as->fmt = AUDIO_FORMAT_F32;
+    audio_pcm_init_info (&hw->info, as);
+
+    core->frameSizeSetting = audio_buffer_frames(
+        qapi_AudiodevCoreaudioPerDirectionOptions_base(cpdo), as, 11610);
+
+    core->bufferCount = cpdo->has_buffer_count ? cpdo->buffer_count : 4;
+    core->outputStreamBasicDescription.mSampleRate = (Float64) as->freq;
+
+    if (init_out_device(core)) {
+        return -1;
+    }
+
+    return 0;
+}
+
+static void coreaudio_fini_out (HWVoiceOut *hw)
+{
+    OSStatus status;
+    int err;
+    coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw;
+
+    fini_out_device(core);
 
     /* destroy mutex */
     err = pthread_mutex_destroy(&core->mutex);
-- 
2.30.2



^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PULL 3/3] coreaudio: Handle output device change
  2021-03-16 10:47 [PULL 0/3] Audio 20210316 patches Gerd Hoffmann
  2021-03-16 10:47 ` [PULL 1/3] coreaudio: Drop support for macOS older than 10.6 Gerd Hoffmann
  2021-03-16 10:47 ` [PULL 2/3] coreaudio: Extract device operations Gerd Hoffmann
@ 2021-03-16 10:47 ` Gerd Hoffmann
  2021-03-16 10:54 ` [PULL 0/3] Audio 20210316 patches no-reply
  2021-03-17 18:27 ` Peter Maydell
  4 siblings, 0 replies; 6+ messages in thread
From: Gerd Hoffmann @ 2021-03-16 10:47 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann, Akihiko Odaki

From: Akihiko Odaki <akihiko.odaki@gmail.com>

An output device change can occur when plugging or unplugging an
earphone.

Signed-off-by: Akihiko Odaki <akihiko.odaki@gmail.com>
Message-Id: <20210311151512.22096-3-akihiko.odaki@gmail.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 audio/coreaudio.c | 206 ++++++++++++++++++++++++++++++++++++----------
 1 file changed, 164 insertions(+), 42 deletions(-)

diff --git a/audio/coreaudio.c b/audio/coreaudio.c
index ab43cdcac199..578ec9b8b2e6 100644
--- a/audio/coreaudio.c
+++ b/audio/coreaudio.c
@@ -41,19 +41,21 @@ typedef struct coreaudioVoiceOut {
     UInt32 audioDevicePropertyBufferFrameSize;
     AudioStreamBasicDescription outputStreamBasicDescription;
     AudioDeviceIOProcID ioprocid;
+    bool enabled;
 } coreaudioVoiceOut;
 
+static const AudioObjectPropertyAddress voice_addr = {
+    kAudioHardwarePropertyDefaultOutputDevice,
+    kAudioObjectPropertyScopeGlobal,
+    kAudioObjectPropertyElementMaster
+};
+
 static OSStatus coreaudio_get_voice(AudioDeviceID *id)
 {
     UInt32 size = sizeof(*id);
-    AudioObjectPropertyAddress addr = {
-        kAudioHardwarePropertyDefaultOutputDevice,
-        kAudioObjectPropertyScopeGlobal,
-        kAudioObjectPropertyElementMaster
-    };
 
     return AudioObjectGetPropertyData(kAudioObjectSystemObject,
-                                      &addr,
+                                      &voice_addr,
                                       0,
                                       NULL,
                                       &size,
@@ -258,18 +260,6 @@ static void GCC_FMT_ATTR (3, 4) coreaudio_logerr2 (
 #define coreaudio_playback_logerr(status, ...) \
     coreaudio_logerr2(status, "playback", __VA_ARGS__)
 
-static inline UInt32 isPlaying (AudioDeviceID outputDeviceID)
-{
-    OSStatus status;
-    UInt32 result = 0;
-    status = coreaudio_get_isrunning(outputDeviceID, &result);
-    if (status != kAudioHardwareNoError) {
-        coreaudio_logerr(status,
-                         "Could not determine whether Device is playing\n");
-    }
-    return result;
-}
-
 static int coreaudio_lock (coreaudioVoiceOut *core, const char *fn_name)
 {
     int err;
@@ -341,6 +331,11 @@ static OSStatus audioDeviceIOProc(
         return 0;
     }
 
+    if (inDevice != core->outputDeviceID) {
+        coreaudio_unlock (core, "audioDeviceIOProc(old device)");
+        return 0;
+    }
+
     frameCount = core->audioDevicePropertyBufferFrameSize;
     pending_frames = hw->pending_emul / hw->info.bytes_per_frame;
 
@@ -392,6 +387,9 @@ static OSStatus init_out_device(coreaudioVoiceOut *core)
     /* get minimum and maximum buffer frame sizes */
     status = coreaudio_get_framesizerange(core->outputDeviceID,
                                           &frameRange);
+    if (status == kAudioHardwareBadObjectError) {
+        return 0;
+    }
     if (status != kAudioHardwareNoError) {
         coreaudio_playback_logerr (status,
                                     "Could not get device buffer frame range\n");
@@ -411,6 +409,9 @@ static OSStatus init_out_device(coreaudioVoiceOut *core)
     /* set Buffer Frame Size */
     status = coreaudio_set_framesize(core->outputDeviceID,
                                      &core->audioDevicePropertyBufferFrameSize);
+    if (status == kAudioHardwareBadObjectError) {
+        return 0;
+    }
     if (status != kAudioHardwareNoError) {
         coreaudio_playback_logerr (status,
                                     "Could not set device buffer frame size %" PRIu32 "\n",
@@ -421,6 +422,9 @@ static OSStatus init_out_device(coreaudioVoiceOut *core)
     /* get Buffer Frame Size */
     status = coreaudio_get_framesize(core->outputDeviceID,
                                      &core->audioDevicePropertyBufferFrameSize);
+    if (status == kAudioHardwareBadObjectError) {
+        return 0;
+    }
     if (status != kAudioHardwareNoError) {
         coreaudio_playback_logerr (status,
                                     "Could not get device buffer frame size\n");
@@ -431,6 +435,9 @@ static OSStatus init_out_device(coreaudioVoiceOut *core)
     /* get StreamFormat */
     status = coreaudio_get_streamformat(core->outputDeviceID,
                                         &core->outputStreamBasicDescription);
+    if (status == kAudioHardwareBadObjectError) {
+        return 0;
+    }
     if (status != kAudioHardwareNoError) {
         coreaudio_playback_logerr (status,
                                     "Could not get Device Stream properties\n");
@@ -441,6 +448,9 @@ static OSStatus init_out_device(coreaudioVoiceOut *core)
     /* set Samplerate */
     status = coreaudio_set_streamformat(core->outputDeviceID,
                                         &core->outputStreamBasicDescription);
+    if (status == kAudioHardwareBadObjectError) {
+        return 0;
+    }
     if (status != kAudioHardwareNoError) {
         coreaudio_playback_logerr (status,
                                    "Could not set samplerate %lf\n",
@@ -455,6 +465,9 @@ static OSStatus init_out_device(coreaudioVoiceOut *core)
                                        audioDeviceIOProc,
                                        &core->hw,
                                        &core->ioprocid);
+    if (status == kAudioHardwareBadDeviceError) {
+        return 0;
+    }
     if (status != kAudioHardwareNoError || core->ioprocid == NULL) {
         coreaudio_playback_logerr (status, "Could not set IOProc\n");
         core->outputDeviceID = kAudioDeviceUnknown;
@@ -467,24 +480,94 @@ static OSStatus init_out_device(coreaudioVoiceOut *core)
 static void fini_out_device(coreaudioVoiceOut *core)
 {
     OSStatus status;
+    UInt32 isrunning;
 
     /* stop playback */
-    if (isPlaying(core->outputDeviceID)) {
-        status = AudioDeviceStop(core->outputDeviceID, core->ioprocid);
+    status = coreaudio_get_isrunning(core->outputDeviceID, &isrunning);
+    if (status != kAudioHardwareBadObjectError) {
         if (status != kAudioHardwareNoError) {
-            coreaudio_logerr(status, "Could not stop playback\n");
+            coreaudio_logerr(status,
+                             "Could not determine whether Device is playing\n");
+        }
+
+        if (isrunning) {
+            status = AudioDeviceStop(core->outputDeviceID, core->ioprocid);
+            if (status != kAudioHardwareBadDeviceError && status != kAudioHardwareNoError) {
+                coreaudio_logerr(status, "Could not stop playback\n");
+            }
         }
     }
 
     /* remove callback */
     status = AudioDeviceDestroyIOProcID(core->outputDeviceID,
                                         core->ioprocid);
-    if (status != kAudioHardwareNoError) {
+    if (status != kAudioHardwareBadDeviceError && status != kAudioHardwareNoError) {
         coreaudio_logerr(status, "Could not remove IOProc\n");
     }
     core->outputDeviceID = kAudioDeviceUnknown;
 }
 
+static void update_device_playback_state(coreaudioVoiceOut *core)
+{
+    OSStatus status;
+    UInt32 isrunning;
+
+    status = coreaudio_get_isrunning(core->outputDeviceID, &isrunning);
+    if (status != kAudioHardwareNoError) {
+        if (status != kAudioHardwareBadObjectError) {
+            coreaudio_logerr(status,
+                             "Could not determine whether Device is playing\n");
+        }
+
+        return;
+    }
+
+    if (core->enabled) {
+        /* start playback */
+        if (!isrunning) {
+            status = AudioDeviceStart(core->outputDeviceID, core->ioprocid);
+            if (status != kAudioHardwareBadDeviceError && status != kAudioHardwareNoError) {
+                coreaudio_logerr (status, "Could not resume playback\n");
+            }
+        }
+    } else {
+        /* stop playback */
+        if (isrunning) {
+            status = AudioDeviceStop(core->outputDeviceID,
+                                     core->ioprocid);
+            if (status != kAudioHardwareBadDeviceError && status != kAudioHardwareNoError) {
+                coreaudio_logerr(status, "Could not pause playback\n");
+            }
+        }
+    }
+}
+
+static OSStatus handle_voice_change(
+    AudioObjectID in_object_id,
+    UInt32 in_number_addresses,
+    const AudioObjectPropertyAddress *in_addresses,
+    void *in_client_data)
+{
+    OSStatus status;
+    coreaudioVoiceOut *core = in_client_data;
+
+    if (coreaudio_lock(core, __func__)) {
+        abort();
+    }
+
+    if (core->outputDeviceID) {
+        fini_out_device(core);
+    }
+
+    status = init_out_device(core);
+    if (!status) {
+        update_device_playback_state(core);
+    }
+
+    coreaudio_unlock (core, __func__);
+    return status;
+}
+
 static int coreaudio_init_out(HWVoiceOut *hw, struct audsettings *as,
                               void *drv_opaque)
 {
@@ -499,7 +582,11 @@ static int coreaudio_init_out(HWVoiceOut *hw, struct audsettings *as,
     err = pthread_mutex_init(&core->mutex, NULL);
     if (err) {
         dolog("Could not create mutex\nReason: %s\n", strerror (err));
-        return -1;
+        goto mutex_error;
+    }
+
+    if (coreaudio_lock(core, __func__)) {
+        goto lock_error;
     }
 
     obt_as = *as;
@@ -513,11 +600,43 @@ static int coreaudio_init_out(HWVoiceOut *hw, struct audsettings *as,
     core->bufferCount = cpdo->has_buffer_count ? cpdo->buffer_count : 4;
     core->outputStreamBasicDescription.mSampleRate = (Float64) as->freq;
 
+    status = AudioObjectAddPropertyListener(kAudioObjectSystemObject,
+                                            &voice_addr, handle_voice_change,
+                                            core);
+    if (status != kAudioHardwareNoError) {
+        coreaudio_playback_logerr (status,
+                                   "Could not listen to voice property change\n");
+        goto listener_error;
+    }
+
     if (init_out_device(core)) {
-        return -1;
+        goto device_error;
     }
 
+    coreaudio_unlock(core, __func__);
     return 0;
+
+device_error:
+    status = AudioObjectRemovePropertyListener(kAudioObjectSystemObject,
+                                               &voice_addr,
+                                               handle_voice_change,
+                                               core);
+    if (status != kAudioHardwareNoError) {
+        coreaudio_playback_logerr(status,
+                                  "Could not remove voice property change listener\n");
+    }
+
+listener_error:
+    coreaudio_unlock(core, __func__);
+
+lock_error:
+    err = pthread_mutex_destroy(&core->mutex);
+    if (err) {
+        dolog("Could not destroy mutex\nReason: %s\n", strerror (err));
+    }
+
+mutex_error:
+    return -1;
 }
 
 static void coreaudio_fini_out (HWVoiceOut *hw)
@@ -526,8 +645,22 @@ static void coreaudio_fini_out (HWVoiceOut *hw)
     int err;
     coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw;
 
+    if (coreaudio_lock(core, __func__)) {
+        abort();
+    }
+
+    status = AudioObjectRemovePropertyListener(kAudioObjectSystemObject,
+                                               &voice_addr,
+                                               handle_voice_change,
+                                               core);
+    if (status != kAudioHardwareNoError) {
+        coreaudio_logerr(status, "Could not remove voice property change listener\n");
+    }
+
     fini_out_device(core);
 
+    coreaudio_unlock(core, __func__);
+
     /* destroy mutex */
     err = pthread_mutex_destroy(&core->mutex);
     if (err) {
@@ -537,27 +670,16 @@ static void coreaudio_fini_out (HWVoiceOut *hw)
 
 static void coreaudio_enable_out(HWVoiceOut *hw, bool enable)
 {
-    OSStatus status;
     coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw;
 
-    if (enable) {
-        /* start playback */
-        if (!isPlaying(core->outputDeviceID)) {
-            status = AudioDeviceStart(core->outputDeviceID, core->ioprocid);
-            if (status != kAudioHardwareNoError) {
-                coreaudio_logerr (status, "Could not resume playback\n");
-            }
-        }
-    } else {
-        /* stop playback */
-        if (isPlaying(core->outputDeviceID)) {
-            status = AudioDeviceStop(core->outputDeviceID,
-                                     core->ioprocid);
-            if (status != kAudioHardwareNoError) {
-                coreaudio_logerr(status, "Could not pause playback\n");
-            }
-        }
+    if (coreaudio_lock(core, __func__)) {
+        abort();
     }
+
+    core->enabled = enable;
+    update_device_playback_state(core);
+
+    coreaudio_unlock(core, __func__);
 }
 
 static void *coreaudio_audio_init(Audiodev *dev)
-- 
2.30.2



^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PULL 0/3] Audio 20210316 patches
  2021-03-16 10:47 [PULL 0/3] Audio 20210316 patches Gerd Hoffmann
                   ` (2 preceding siblings ...)
  2021-03-16 10:47 ` [PULL 3/3] coreaudio: Handle output device change Gerd Hoffmann
@ 2021-03-16 10:54 ` no-reply
  2021-03-17 18:27 ` Peter Maydell
  4 siblings, 0 replies; 6+ messages in thread
From: no-reply @ 2021-03-16 10:54 UTC (permalink / raw)
  To: kraxel; +Cc: qemu-devel, kraxel

Patchew URL: https://patchew.org/QEMU/20210316104745.2196286-1-kraxel@redhat.com/



Hi,

This series seems to have some coding style problems. See output below for
more information:

Type: series
Message-id: 20210316104745.2196286-1-kraxel@redhat.com
Subject: [PULL 0/3] Audio 20210316 patches

=== TEST SCRIPT BEGIN ===
#!/bin/bash
git rev-parse base > /dev/null || exit 0
git config --local diff.renamelimit 0
git config --local diff.renames True
git config --local diff.algorithm histogram
./scripts/checkpatch.pl --mailback base..
=== TEST SCRIPT END ===

Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
From https://github.com/patchew-project/qemu
 * [new tag]         patchew/20210316104745.2196286-1-kraxel@redhat.com -> patchew/20210316104745.2196286-1-kraxel@redhat.com
Switched to a new branch 'test'
54c97ba coreaudio: Handle output device change
3013a57 coreaudio: Extract device operations
45d1cb4 coreaudio: Drop support for macOS older than 10.6

=== OUTPUT BEGIN ===
1/3 Checking commit 45d1cb4bb7c7 (coreaudio: Drop support for macOS older than 10.6)
2/3 Checking commit 3013a5778d0a (coreaudio: Extract device operations)
ERROR: space prohibited between function name and open parenthesis '('
#76: FILE: audio/coreaudio.c:383:
+        coreaudio_playback_logerr (status,

ERROR: space prohibited between function name and open parenthesis '('
#83: FILE: audio/coreaudio.c:388:
+        dolog ("Could not initialize playback - Unknown Audiodevice\n");

ERROR: space prohibited between function name and open parenthesis '('
#94: FILE: audio/coreaudio.c:396:
+        coreaudio_playback_logerr (status,

ERROR: space prohibited between function name and open parenthesis '('
#122: FILE: audio/coreaudio.c:415:
+        coreaudio_playback_logerr (status,

ERROR: line over 90 characters
#123: FILE: audio/coreaudio.c:416:
+                                    "Could not set device buffer frame size %" PRIu32 "\n",

WARNING: line over 80 characters
#124: FILE: audio/coreaudio.c:417:
+                                    (uint32_t)core->audioDevicePropertyBufferFrameSize);

ERROR: space prohibited between function name and open parenthesis '('
#135: FILE: audio/coreaudio.c:425:
+        coreaudio_playback_logerr (status,

WARNING: line over 80 characters
#141: FILE: audio/coreaudio.c:429:
+    core->hw.samples = core->bufferCount * core->audioDevicePropertyBufferFrameSize;

ERROR: space prohibited between function name and open parenthesis '('
#149: FILE: audio/coreaudio.c:435:
+        coreaudio_playback_logerr (status,

ERROR: space prohibited between function name and open parenthesis '('
#164: FILE: audio/coreaudio.c:445:
+        coreaudio_playback_logerr (status,

WARNING: line over 80 characters
#166: FILE: audio/coreaudio.c:447:
+                                   core->outputStreamBasicDescription.mSampleRate);

ERROR: space prohibited between function name and open parenthesis '('
#181: FILE: audio/coreaudio.c:459:
+        coreaudio_playback_logerr (status, "Could not set IOProc\n");

ERROR: space prohibited between function name and open parenthesis '('
#218: FILE: audio/coreaudio.c:501:
+        dolog("Could not create mutex\nReason: %s\n", strerror (err));

ERROR: space prohibited between function name and open parenthesis '('
#225: FILE: audio/coreaudio.c:508:
+    audio_pcm_init_info (&hw->info, as);

ERROR: space prohibited between function name and open parenthesis '('
#240: FILE: audio/coreaudio.c:523:
+static void coreaudio_fini_out (HWVoiceOut *hw)

total: 12 errors, 3 warnings, 224 lines checked

Patch 2/3 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.

3/3 Checking commit 54c97bac0510 (coreaudio: Handle output device change)
ERROR: space prohibited between function name and open parenthesis '('
#74: FILE: audio/coreaudio.c:335:
+        coreaudio_unlock (core, "audioDeviceIOProc(old device)");

ERROR: line over 90 characters
#160: FILE: audio/coreaudio.c:495:
+            if (status != kAudioHardwareBadDeviceError && status != kAudioHardwareNoError) {

WARNING: line over 80 characters
#170: FILE: audio/coreaudio.c:504:
+    if (status != kAudioHardwareBadDeviceError && status != kAudioHardwareNoError) {

ERROR: line over 90 characters
#195: FILE: audio/coreaudio.c:529:
+            if (status != kAudioHardwareBadDeviceError && status != kAudioHardwareNoError) {

ERROR: space prohibited between function name and open parenthesis '('
#196: FILE: audio/coreaudio.c:530:
+                coreaudio_logerr (status, "Could not resume playback\n");

ERROR: line over 90 characters
#204: FILE: audio/coreaudio.c:538:
+            if (status != kAudioHardwareBadDeviceError && status != kAudioHardwareNoError) {

ERROR: space prohibited between function name and open parenthesis '('
#233: FILE: audio/coreaudio.c:567:
+    coreaudio_unlock (core, __func__);

ERROR: space prohibited between function name and open parenthesis '('
#263: FILE: audio/coreaudio.c:607:
+        coreaudio_playback_logerr (status,

ERROR: space prohibited between function name and open parenthesis '('
#291: FILE: audio/coreaudio.c:635:
+        dolog("Could not destroy mutex\nReason: %s\n", strerror (err));

WARNING: line over 80 characters
#312: FILE: audio/coreaudio.c:657:
+        coreaudio_logerr(status, "Could not remove voice property change listener\n");

total: 8 errors, 2 warnings, 321 lines checked

Patch 3/3 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.

=== OUTPUT END ===

Test command exited with code: 1


The full log is available at
http://patchew.org/logs/20210316104745.2196286-1-kraxel@redhat.com/testing.checkpatch/?type=message.
---
Email generated automatically by Patchew [https://patchew.org/].
Please send your feedback to patchew-devel@redhat.com

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PULL 0/3] Audio 20210316 patches
  2021-03-16 10:47 [PULL 0/3] Audio 20210316 patches Gerd Hoffmann
                   ` (3 preceding siblings ...)
  2021-03-16 10:54 ` [PULL 0/3] Audio 20210316 patches no-reply
@ 2021-03-17 18:27 ` Peter Maydell
  4 siblings, 0 replies; 6+ messages in thread
From: Peter Maydell @ 2021-03-17 18:27 UTC (permalink / raw)
  To: Gerd Hoffmann; +Cc: QEMU Developers

On Tue, 16 Mar 2021 at 10:50, Gerd Hoffmann <kraxel@redhat.com> wrote:
>
> The following changes since commit 2615a5e433aeb812c300d3a48e1a88e1303e2339:
>
>   Merge remote-tracking branch 'remotes/stefanha-gitlab/tags/block-pull-reque=
> st' into staging (2021-03-15 19:23:00 +0000)
>
> are available in the Git repository at:
>
>   git://git.kraxel.org/qemu tags/audio-20210316-pull-request
>
> for you to fetch changes up to 3ba6e3f6888d2825709eba2f623f0615069c036c:
>
>   coreaudio: Handle output device change (2021-03-16 07:17:50 +0100)
>
> ----------------------------------------------------------------
> coreaudio fixes and cleanups.
>
> ----------------------------------------------------------------
>
> Akihiko Odaki (3):
>   coreaudio: Drop support for macOS older than 10.6
>   coreaudio: Extract device operations
>   coreaudio: Handle output device change
>
>  audio/coreaudio.c | 428 +++++++++++++++++++++++++---------------------
>  1 file changed, 235 insertions(+), 193 deletions(-)


Applied, thanks.

Please update the changelog at https://wiki.qemu.org/ChangeLog/6.0
for any user-visible changes.

-- PMM


^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2021-03-17 18:29 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2021-03-16 10:47 [PULL 0/3] Audio 20210316 patches Gerd Hoffmann
2021-03-16 10:47 ` [PULL 1/3] coreaudio: Drop support for macOS older than 10.6 Gerd Hoffmann
2021-03-16 10:47 ` [PULL 2/3] coreaudio: Extract device operations Gerd Hoffmann
2021-03-16 10:47 ` [PULL 3/3] coreaudio: Handle output device change Gerd Hoffmann
2021-03-16 10:54 ` [PULL 0/3] Audio 20210316 patches no-reply
2021-03-17 18:27 ` Peter Maydell

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