objc2-avf-audio 0.3.2

Bindings to the AVFAudio framework
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
//! This file has been automatically generated by `objc2`'s `header-translator`.
//! DO NOT EDIT
use core::ffi::*;
use core::ptr::NonNull;
use objc2::__framework_prelude::*;

use crate::*;

/// Options controlling buffer scheduling.
///
///
/// The buffer loops indefinitely.
///
/// The buffer interrupts any buffer already playing.
///
/// The buffer interrupts any buffer already playing, at its loop point.
///
/// API_AVAILABLE(macos(10.10), ios(8.0), watchos(2.0), tvos(9.0))
///
/// See also [Apple's documentation](https://developer.apple.com/documentation/avfaudio/avaudioplayernodebufferoptions?language=objc)
// NS_OPTIONS
#[repr(transparent)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct AVAudioPlayerNodeBufferOptions(pub NSUInteger);
bitflags::bitflags! {
    impl AVAudioPlayerNodeBufferOptions: NSUInteger {
        #[doc(alias = "AVAudioPlayerNodeBufferLoops")]
        const Loops = 1<<0;
        #[doc(alias = "AVAudioPlayerNodeBufferInterrupts")]
        const Interrupts = 1<<1;
        #[doc(alias = "AVAudioPlayerNodeBufferInterruptsAtLoop")]
        const InterruptsAtLoop = 1<<2;
    }
}

unsafe impl Encode for AVAudioPlayerNodeBufferOptions {
    const ENCODING: Encoding = NSUInteger::ENCODING;
}

unsafe impl RefEncode for AVAudioPlayerNodeBufferOptions {
    const ENCODING_REF: Encoding = Encoding::Pointer(&Self::ENCODING);
}

/// Specifies when the completion handler must be invoked.
///
///
/// The buffer or file data has been consumed by the player.
///
/// The buffer or file data has been rendered (i.e. output) by the player. This
/// does not account for any signal processing latencies downstream of the player
/// in the engine (see `AVAudioNode(outputPresentationLatency)`).
///
/// Applicable only when the engine is rendering to/from an audio device.
/// The buffer or file has finished playing. This accounts for both (small) signal
/// processing latencies downstream of the player in the engine, as well as
/// (possibly significant) latency in the audio playback device.
///
/// API_AVAILABLE(macos(10.13), ios(11.0), watchos(4.0), tvos(11.0));
///
/// See also [Apple's documentation](https://developer.apple.com/documentation/avfaudio/avaudioplayernodecompletioncallbacktype?language=objc)
// NS_ENUM
#[repr(transparent)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct AVAudioPlayerNodeCompletionCallbackType(pub NSInteger);
impl AVAudioPlayerNodeCompletionCallbackType {
    #[doc(alias = "AVAudioPlayerNodeCompletionDataConsumed")]
    pub const DataConsumed: Self = Self(0);
    #[doc(alias = "AVAudioPlayerNodeCompletionDataRendered")]
    pub const DataRendered: Self = Self(1);
    #[doc(alias = "AVAudioPlayerNodeCompletionDataPlayedBack")]
    pub const DataPlayedBack: Self = Self(2);
}

unsafe impl Encode for AVAudioPlayerNodeCompletionCallbackType {
    const ENCODING: Encoding = NSInteger::ENCODING;
}

unsafe impl RefEncode for AVAudioPlayerNodeCompletionCallbackType {
    const ENCODING_REF: Encoding = Encoding::Pointer(&Self::ENCODING);
}

/// Buffer or file completion callback handler.
///
/// Parameter `callbackType`: Indicates the type of buffer or file completion when the callback is invoked.
///
/// AVAudioPlayerNode issues this callback to inform the client about the specific type of
/// buffer or file completion. See `AVAudioPlayerNodeCompletionCallbackType` for more details.
///
/// Note that the `AVAudioNodeCompletionHandler` callback from some of the player's scheduling
/// methods (e.g. `scheduleBuffer:completionHandler:`) is equivalent to the
/// AVAudioPlayerNodeCompletionHandler callback for `AVAudioPlayerNodeCompletionDataConsumed`.
///
/// In general the callbacks arrive on a non-main thread and it is the client's responsibility
/// to handle them in a thread-safe manner.
///
/// Setting or getting properties on an AVAudioPlayerNode while the AVAudioEngine is running requires
/// some synchronisation between the calling threads internally. If you want to call player node API within this
/// completion handler block, calls should be synchronised to the same thread/queue.
///
/// See also [Apple's documentation](https://developer.apple.com/documentation/avfaudio/avaudioplayernodecompletionhandler?language=objc)
#[cfg(feature = "block2")]
pub type AVAudioPlayerNodeCompletionHandler =
    *mut block2::DynBlock<dyn Fn(AVAudioPlayerNodeCompletionCallbackType)>;

extern_class!(
    /// Play buffers or segments of audio files.
    ///
    /// AVAudioPlayerNode supports scheduling the playback of `AVAudioBuffer` instances,
    /// or segments of audio files opened via `AVAudioFile`. Buffers and segments may be
    /// scheduled at specific points in time, or to play immediately following preceding segments.
    ///
    /// FORMATS
    ///
    /// Normally, you will want to configure the node's output format with the same number of
    /// channels as are in the files and buffers to be played. Otherwise, channels will be dropped
    /// or added as required. It is usually better to use an `AVAudioMixerNode` to
    /// do this.
    ///
    /// Similarly, when playing file segments, the node will sample rate convert if necessary, but
    /// it is often preferable to configure the node's output sample rate to match that of the file(s)
    /// and use a mixer to perform the rate conversion.
    ///
    /// When playing buffers, there is an implicit assumption that the buffers are at the same
    /// sample rate as the node's output format.
    ///
    /// TIMELINES
    ///
    /// The usual `AVAudioNode` sample times (as observed by `lastRenderTime`)
    /// have an arbitrary zero point. AVAudioPlayerNode superimposes a second "player timeline" on
    /// top of this, to reflect when the player was started, and intervals during which it was
    /// paused. The methods `nodeTimeForPlayerTime:` and `playerTimeForNodeTime:`
    /// convert between the two.
    ///
    /// This class' `stop` method unschedules all previously scheduled buffers and
    /// file segments, and returns the player timeline to sample time 0.
    ///
    /// TIMESTAMPS
    ///
    /// The "schedule" methods all take an `AVAudioTime` "when" parameter. This is
    /// interpreted as follows:
    ///
    /// 1. nil:
    /// - if there have been previous commands, the new one is played immediately following the
    /// last one.
    /// - otherwise, if the node is playing, the event is played in the very near future.
    /// - otherwise, the command is played at sample time 0.
    /// 2. sample time:
    /// - relative to the node's start time (which begins at 0 when the node is started).
    /// 3. host time:
    /// - ignored unless the sample time is invalid when the engine is rendering to an audio
    /// device.
    /// - ignored in manual rendering mode.
    ///
    /// ERRORS
    ///
    /// The "schedule" methods can fail if:
    ///
    /// 1. a buffer's channel count does not match that of the node's output format.
    /// 2. a file can't be accessed.
    /// 3. an AVAudioTime specifies neither a valid sample time or host time.
    /// 4. a segment's start frame or frame count is negative.
    ///
    /// BUFFER/FILE COMPLETION HANDLERS
    ///
    /// The buffer or file completion handlers (see scheduling methods) are a means to schedule
    /// more data if available on the player node. See `AVAudioPlayerNodeCompletionCallbackType`
    /// for details on the different buffer/file completion callback types.
    ///
    /// Note that a player should not be stopped from within a completion handler callback because
    /// it can deadlock while trying to unschedule previously scheduled buffers.
    ///
    /// OFFLINE RENDERING
    ///
    /// When a player node is used with the engine operating in the manual rendering mode, the
    /// buffer/file completion handlers, `lastRenderTime` and the latencies (`latency` and
    /// `outputPresentationLatency`) can be used to track how much data the player has rendered and
    /// how much more data is left to render.
    ///
    /// See also [Apple's documentation](https://developer.apple.com/documentation/avfaudio/avaudioplayernode?language=objc)
    #[unsafe(super(AVAudioNode, NSObject))]
    #[derive(Debug, PartialEq, Eq, Hash)]
    #[cfg(feature = "AVAudioNode")]
    pub struct AVAudioPlayerNode;
);

#[cfg(all(feature = "AVAudioMixing", feature = "AVAudioNode"))]
extern_conformance!(
    unsafe impl AVAudio3DMixing for AVAudioPlayerNode {}
);

#[cfg(all(feature = "AVAudioMixing", feature = "AVAudioNode"))]
extern_conformance!(
    unsafe impl AVAudioMixing for AVAudioPlayerNode {}
);

#[cfg(all(feature = "AVAudioMixing", feature = "AVAudioNode"))]
extern_conformance!(
    unsafe impl AVAudioStereoMixing for AVAudioPlayerNode {}
);

#[cfg(feature = "AVAudioNode")]
extern_conformance!(
    unsafe impl NSObjectProtocol for AVAudioPlayerNode {}
);

#[cfg(feature = "AVAudioNode")]
impl AVAudioPlayerNode {
    extern_methods!(
        #[unsafe(method(init))]
        #[unsafe(method_family = init)]
        pub unsafe fn init(this: Allocated<Self>) -> Retained<Self>;

        #[cfg(all(
            feature = "AVAudioBuffer",
            feature = "AVAudioTypes",
            feature = "block2"
        ))]
        /// Schedule playing samples from an AVAudioBuffer.
        ///
        /// Parameter `buffer`: the buffer to play
        ///
        /// Parameter `completionHandler`: called after the buffer has been consumed by the player or the player is stopped. may be nil.
        ///
        /// Schedules the buffer to be played following any previously scheduled commands.
        ///
        /// It is possible for the completionHandler to be called before rendering begins
        /// or before the buffer is played completely.
        ///
        /// # Safety
        ///
        /// `completion_handler` must be a valid pointer or null.
        #[unsafe(method(scheduleBuffer:completionHandler:))]
        #[unsafe(method_family = none)]
        pub unsafe fn scheduleBuffer_completionHandler(
            &self,
            buffer: &AVAudioPCMBuffer,
            completion_handler: AVAudioNodeCompletionHandler,
        );

        #[cfg(all(feature = "AVAudioBuffer", feature = "block2"))]
        /// Schedule playing samples from an AVAudioBuffer.
        ///
        /// Parameter `buffer`: the buffer to play
        ///
        /// Parameter `callbackType`: option to specify when the completion handler must be called
        ///
        /// Parameter `completionHandler`: called after the buffer has been consumed by the player or has finished playing back or
        /// the player is stopped. may be nil.
        ///
        /// Schedules the buffer to be played following any previously scheduled commands.
        ///
        /// # Safety
        ///
        /// `completion_handler` must be a valid pointer or null.
        #[unsafe(method(scheduleBuffer:completionCallbackType:completionHandler:))]
        #[unsafe(method_family = none)]
        pub unsafe fn scheduleBuffer_completionCallbackType_completionHandler(
            &self,
            buffer: &AVAudioPCMBuffer,
            callback_type: AVAudioPlayerNodeCompletionCallbackType,
            completion_handler: AVAudioPlayerNodeCompletionHandler,
        );

        #[cfg(all(
            feature = "AVAudioBuffer",
            feature = "AVAudioTime",
            feature = "AVAudioTypes",
            feature = "block2"
        ))]
        /// Schedule playing samples from an AVAudioBuffer.
        ///
        /// Parameter `buffer`: the buffer to play
        ///
        /// Parameter `when`: the time at which to play the buffer. see the discussion of timestamps, above.
        ///
        /// Parameter `options`: options for looping, interrupting other buffers, etc.
        ///
        /// Parameter `completionHandler`: called after the buffer has been consumed by the player or the player is stopped. may be nil.
        ///
        /// It is possible for the completionHandler to be called before rendering begins
        /// or before the buffer is played completely.
        ///
        /// # Safety
        ///
        /// `completion_handler` must be a valid pointer or null.
        #[unsafe(method(scheduleBuffer:atTime:options:completionHandler:))]
        #[unsafe(method_family = none)]
        pub unsafe fn scheduleBuffer_atTime_options_completionHandler(
            &self,
            buffer: &AVAudioPCMBuffer,
            when: Option<&AVAudioTime>,
            options: AVAudioPlayerNodeBufferOptions,
            completion_handler: AVAudioNodeCompletionHandler,
        );

        #[cfg(all(feature = "AVAudioBuffer", feature = "AVAudioTime", feature = "block2"))]
        /// Schedule playing samples from an AVAudioBuffer.
        ///
        /// Parameter `buffer`: the buffer to play
        ///
        /// Parameter `when`: the time at which to play the buffer. see the discussion of timestamps, above.
        ///
        /// Parameter `options`: options for looping, interrupting other buffers, etc.
        ///
        /// Parameter `callbackType`: option to specify when the completion handler must be called
        ///
        /// Parameter `completionHandler`: called after the buffer has been consumed by the player or has finished playing back or
        /// the player is stopped. may be nil.
        ///
        /// # Safety
        ///
        /// `completion_handler` must be a valid pointer or null.
        #[unsafe(method(scheduleBuffer:atTime:options:completionCallbackType:completionHandler:))]
        #[unsafe(method_family = none)]
        pub unsafe fn scheduleBuffer_atTime_options_completionCallbackType_completionHandler(
            &self,
            buffer: &AVAudioPCMBuffer,
            when: Option<&AVAudioTime>,
            options: AVAudioPlayerNodeBufferOptions,
            callback_type: AVAudioPlayerNodeCompletionCallbackType,
            completion_handler: AVAudioPlayerNodeCompletionHandler,
        );

        #[cfg(all(
            feature = "AVAudioFile",
            feature = "AVAudioTime",
            feature = "AVAudioTypes",
            feature = "block2"
        ))]
        /// Schedule playing of an entire audio file.
        ///
        /// Parameter `file`: the file to play
        ///
        /// Parameter `when`: the time at which to play the file. see the discussion of timestamps, above.
        ///
        /// Parameter `completionHandler`: called after the file has been consumed by the player or the player is stopped. may be nil.
        ///
        /// It is possible for the completionHandler to be called before rendering begins
        /// or before the file is played completely.
        ///
        /// # Safety
        ///
        /// `completion_handler` must be a valid pointer or null.
        #[unsafe(method(scheduleFile:atTime:completionHandler:))]
        #[unsafe(method_family = none)]
        pub unsafe fn scheduleFile_atTime_completionHandler(
            &self,
            file: &AVAudioFile,
            when: Option<&AVAudioTime>,
            completion_handler: AVAudioNodeCompletionHandler,
        );

        #[cfg(all(feature = "AVAudioFile", feature = "AVAudioTime", feature = "block2"))]
        /// Schedule playing of an entire audio file.
        ///
        /// Parameter `file`: the file to play
        ///
        /// Parameter `when`: the time at which to play the file. see the discussion of timestamps, above.
        ///
        /// Parameter `callbackType`: option to specify when the completion handler must be called
        ///
        /// Parameter `completionHandler`: called after the file has been consumed by the player or has finished playing back or
        /// the player is stopped. may be nil.
        ///
        /// # Safety
        ///
        /// `completion_handler` must be a valid pointer or null.
        #[unsafe(method(scheduleFile:atTime:completionCallbackType:completionHandler:))]
        #[unsafe(method_family = none)]
        pub unsafe fn scheduleFile_atTime_completionCallbackType_completionHandler(
            &self,
            file: &AVAudioFile,
            when: Option<&AVAudioTime>,
            callback_type: AVAudioPlayerNodeCompletionCallbackType,
            completion_handler: AVAudioPlayerNodeCompletionHandler,
        );

        #[cfg(all(
            feature = "AVAudioFile",
            feature = "AVAudioTime",
            feature = "AVAudioTypes",
            feature = "block2"
        ))]
        /// Schedule playing a segment of an audio file.
        ///
        /// Parameter `file`: the file to play
        ///
        /// Parameter `startFrame`: the starting frame position in the stream
        ///
        /// Parameter `numberFrames`: the number of frames to play
        ///
        /// Parameter `when`: the time at which to play the region. see the discussion of timestamps, above.
        ///
        /// Parameter `completionHandler`: called after the segment has been consumed by the player or the player is stopped. may be nil.
        ///
        /// It is possible for the completionHandler to be called before rendering begins
        /// or before the segment is played completely.
        ///
        /// # Safety
        ///
        /// `completion_handler` must be a valid pointer or null.
        #[unsafe(method(scheduleSegment:startingFrame:frameCount:atTime:completionHandler:))]
        #[unsafe(method_family = none)]
        pub unsafe fn scheduleSegment_startingFrame_frameCount_atTime_completionHandler(
            &self,
            file: &AVAudioFile,
            start_frame: AVAudioFramePosition,
            number_frames: AVAudioFrameCount,
            when: Option<&AVAudioTime>,
            completion_handler: AVAudioNodeCompletionHandler,
        );

        #[cfg(all(
            feature = "AVAudioFile",
            feature = "AVAudioTime",
            feature = "AVAudioTypes",
            feature = "block2"
        ))]
        /// Schedule playing a segment of an audio file.
        ///
        /// Parameter `file`: the file to play
        ///
        /// Parameter `startFrame`: the starting frame position in the stream
        ///
        /// Parameter `numberFrames`: the number of frames to play
        ///
        /// Parameter `when`: the time at which to play the region. see the discussion of timestamps, above.
        ///
        /// Parameter `callbackType`: option to specify when the completion handler must be called
        ///
        /// Parameter `completionHandler`: called after the segment has been consumed by the player or has finished playing back or
        /// the player is stopped. may be nil.
        ///
        /// # Safety
        ///
        /// `completion_handler` must be a valid pointer or null.
        #[unsafe(method(scheduleSegment:startingFrame:frameCount:atTime:completionCallbackType:completionHandler:))]
        #[unsafe(method_family = none)]
        pub unsafe fn scheduleSegment_startingFrame_frameCount_atTime_completionCallbackType_completionHandler(
            &self,
            file: &AVAudioFile,
            start_frame: AVAudioFramePosition,
            number_frames: AVAudioFrameCount,
            when: Option<&AVAudioTime>,
            callback_type: AVAudioPlayerNodeCompletionCallbackType,
            completion_handler: AVAudioPlayerNodeCompletionHandler,
        );

        /// Clear all of the node's previously scheduled events and stop playback.
        ///
        /// All of the node's previously scheduled events are cleared, including any that are in the
        /// middle of playing. The node's sample time (and therefore the times to which new events are
        /// to be scheduled) is reset to 0, and will not proceed until the node is started again (via
        /// play or playAtTime).
        ///
        /// Note that pausing or stopping all the players connected to an engine does not pause or stop
        /// the engine or the underlying hardware. The engine must be explicitly paused or stopped for
        /// the hardware to stop.
        #[unsafe(method(stop))]
        #[unsafe(method_family = none)]
        pub unsafe fn stop(&self);

        #[cfg(feature = "AVAudioTypes")]
        /// Prepares previously scheduled file regions or buffers for playback.
        ///
        /// Parameter `frameCount`: The number of sample frames of data to be prepared before returning.
        #[unsafe(method(prepareWithFrameCount:))]
        #[unsafe(method_family = none)]
        pub unsafe fn prepareWithFrameCount(&self, frame_count: AVAudioFrameCount);

        /// Start or resume playback immediately.
        ///
        /// equivalent to playAtTime:nil
        #[unsafe(method(play))]
        #[unsafe(method_family = none)]
        pub unsafe fn play(&self);

        #[cfg(feature = "AVAudioTime")]
        /// Start or resume playback at a specific time.
        ///
        /// Parameter `when`: the node time at which to start or resume playback. nil signifies "now".
        ///
        /// This node is initially paused. Requests to play buffers or file segments are enqueued, and
        /// any necessary decoding begins immediately. Playback does not begin, however, until the player
        /// has started playing, via this method.
        ///
        /// Note that providing an AVAudioTime which is past (before lastRenderTime) will cause the
        /// player to begin playback immediately.
        ///
        /// E.g. To start a player X seconds in future:
        /// <pre>
        /// // start engine and player
        /// NSError *nsErr = nil;
        /// [_engine startAndReturnError:
        /// &nsErr
        /// ];
        /// if (!nsErr) {
        /// const float kStartDelayTime = 0.5; // sec
        /// AVAudioFormat *outputFormat = [_player outputFormatForBus:0];
        /// AVAudioFramePosition startSampleTime = _player.lastRenderTime.sampleTime + kStartDelayTime * outputFormat.sampleRate;
        /// AVAudioTime *startTime = [AVAudioTime timeWithSampleTime:startSampleTime atRate:outputFormat.sampleRate];
        /// [_player playAtTime:startTime];
        /// }
        /// </pre>
        #[unsafe(method(playAtTime:))]
        #[unsafe(method_family = none)]
        pub unsafe fn playAtTime(&self, when: Option<&AVAudioTime>);

        /// Pause playback.
        ///
        /// The player's sample time does not advance while the node is paused.
        ///
        /// Note that pausing or stopping all the players connected to an engine does not pause or stop
        /// the engine or the underlying hardware. The engine must be explicitly paused or stopped for
        /// the hardware to stop.
        #[unsafe(method(pause))]
        #[unsafe(method_family = none)]
        pub unsafe fn pause(&self);

        #[cfg(feature = "AVAudioTime")]
        /// Convert from player time to node time.
        ///
        /// Parameter `playerTime`: a time relative to the player's start time
        ///
        /// Returns: a node time
        ///
        /// This method and its inverse `playerTimeForNodeTime:` are discussed in the
        /// introduction to this class.
        ///
        /// If the player is not playing when this method is called, nil is returned.
        #[unsafe(method(nodeTimeForPlayerTime:))]
        #[unsafe(method_family = none)]
        pub unsafe fn nodeTimeForPlayerTime(
            &self,
            player_time: &AVAudioTime,
        ) -> Option<Retained<AVAudioTime>>;

        #[cfg(feature = "AVAudioTime")]
        /// Convert from node time to player time.
        ///
        /// Parameter `nodeTime`: a node time
        ///
        /// Returns: a time relative to the player's start time
        ///
        /// This method and its inverse `nodeTimeForPlayerTime:` are discussed in the
        /// introduction to this class.
        ///
        /// If the player is not playing when this method is called, nil is returned.
        #[unsafe(method(playerTimeForNodeTime:))]
        #[unsafe(method_family = none)]
        pub unsafe fn playerTimeForNodeTime(
            &self,
            node_time: &AVAudioTime,
        ) -> Option<Retained<AVAudioTime>>;

        /// Indicates whether or not the player is playing.
        #[unsafe(method(isPlaying))]
        #[unsafe(method_family = none)]
        pub unsafe fn isPlaying(&self) -> bool;
    );
}

/// Methods declared on superclass `NSObject`.
#[cfg(feature = "AVAudioNode")]
impl AVAudioPlayerNode {
    extern_methods!(
        #[unsafe(method(new))]
        #[unsafe(method_family = new)]
        pub unsafe fn new() -> Retained<Self>;
    );
}