Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow inheritance from AudioPlayer and QueuedAudioPlayer #109

Open
curiousdustin opened this issue Apr 21, 2020 · 1 comment
Open

Allow inheritance from AudioPlayer and QueuedAudioPlayer #109

curiousdustin opened this issue Apr 21, 2020 · 1 comment

Comments

@curiousdustin
Copy link

Is your feature request related to a problem? Please describe.
In my project I would like to override some portions of QueuedAudioPlayer. I cannot because is it marked as public, and not open.

I want to override because I want to send events to react native when certain things happen. Most of these can be achieved alternatively by listening to the events emitted by SwiftAudio, however, these are asynchronous, and I have had a lot of trouble getting the proper data to pass on in my events to react because things like the currentItem have changed by the time the SwiftAudio event is handled. Hope that makes sense.

Describe alternatives you've considered
I do not know swift well enough yet to know if there is a better alternative. Any guidance would be greatly appreciated.

Additional context
Here is an example of what I would like to do. This works if I include SwiftAudio codebase directly in my Xcode project. But I would like to achieve similar by installing SwiftAudio via CocoaPods.

import Foundation
import MediaPlayer
import SwiftAudio

public class MyAudioPlayer: QueuedAudioPlayer {

  public var reactEventEmitter: RCTEventEmitter

  // Override _currentItem so that we can send an event when it changes.
  override var _currentItem: AudioItem? {
    willSet(newCurrentItem) {
      if ((newCurrentItem as? Track) === (_currentItem as? Track)) {
        return
      }

      self.reactEventEmitter.sendEvent(withName: "playback-track-changed", body: [
        "track": (_currentItem as? Track)?.id ?? nil,
        "position": self.currentTime,
        "nextTrack": (newCurrentItem as? Track)?.id ?? nil,
        ])
    }
  }

  // Override init to include a reference to the React Event Emitter.
  public init(reactEventEmitter: RCTEventEmitter) {
        self.reactEventEmitter = reactEventEmitter
    super.init()
    }

  // MARK: - Player Actions
    
  public override func load(item: AudioItem, playWhenReady: Bool = true) throws {
        let url: URL
        switch item.getSourceType() {
        case .stream:
            if let itemUrl = URL(string: item.getSourceUrl()) {
                url = itemUrl
            }
            else {
                throw APError.LoadError.invalidSourceUrl(item.getSourceUrl())
            }
        case .file:
            url = URL(fileURLWithPath: item.getSourceUrl())
        }
        
        wrapper.load(from: url,
                     playWhenReady: playWhenReady,
                     initialTime: (item as? InitialTiming)?.getInitialTime(),
                     options:(item as? AssetOptionsProviding)?.getAssetOptions())
        
        self._currentItem = item
        
        if (automaticallyUpdateNowPlayingInfo) {
            self.loadNowPlayingMetaValues()
        }

    // This is the only change from the original AudioPlayer
        if (item is RemoteCommandable) {
            enableRemoteCommands(forItem: item)
        }
    }

  // MARK: - AVPlayerWrapperDelegate
    
    override func AVWrapper(didChangeState state: AVPlayerWrapperState) {
        super.AVWrapper(didChangeState: state)
    self.reactEventEmitter.sendEvent(withName: "playback-state", body: ["state": state.rawValue])
    }
    
    override func AVWrapper(failedWithError error: Error?) {
        super.AVWrapper(failedWithError: error)
        self.reactEventEmitter.sendEvent(withName: "playback-error", body: ["error": error?.localizedDescription])
    }
    
    override func AVWrapperItemDidPlayToEndTime() {
        if self.nextItems.count == 0 {
      // For consistency sake, send an event for the track changing to nothing
      self.reactEventEmitter.sendEvent(withName: "playback-track-changed", body: [
        "track": (self.currentItem as? Track)?.id ?? nil,
        "position": self.currentTime,
        "nextTrack": nil,
        ])

      // fire an event for the queue ending
      self.reactEventEmitter.sendEvent(withName: "playback-queue-ended", body: [
        "track": (self.currentItem as? Track)?.id,
        "position": self.currentTime,
        ])
    } 
    super.AVWrapperItemDidPlayToEndTime()
    }
}
@curiousdustin
Copy link
Author

I should have included the error:

Cannot inherit from non-open class 'QueuedAudioPlayer' outside of its defining module

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant