arcam / CocoaUPnP

CocoaUPnP is a logical progression of upnpx; designed to be easy, modern and block-based.
MIT License
85 stars 40 forks source link

How to trap LastChange event? #48

Closed GINNOV closed 6 years ago

GINNOV commented 6 years ago

Hello there - Thank you for this project!

I work exclusively in Swift, I manage to get a few things done in ObjC but it is definitely not my cup of tea.

I would like to add to the Example attached at the project the ability to track events and then parse the dictionary.

I understand how to parse the dictionary but I can't figure out how to create In the sample attached in the code subscriptions for events.

I got this far: In the playbackManager.m I added: (a dummy method)

UPPAVTransportService *avTransport = [self.renderer avTransportService]; [[UPPEventSubscriptionManager sharedManager] subscribeObserver:avTransport.observationInfo toService:avTransport completion:nil];

To the same file I added UPPEventSubscriptionDelegate delegate and comformed at it with:

- (void)eventReceived:(NSDictionary *)event { NSLog(@"%@ Event: %@", event.observationInfo, event.allKeys); }

I understand (because that what I would do in Swift) that I need to provide an observer and delegation to trap the events but again I have no clue on how to accomplish that in swift. Any chance, someone can post a chunk of code to receive events (LastChange is enough) so that I can learn and expand on that?

Thank you!

squarefrog commented 6 years ago

Hi there. Unless you really need to, theres not a great need for you to do your playback manager in ObjC. Here is a Swift example that should work.

// Your class needs to inherit from NSObject in order to
// conform to Objective-C protocols
class PlaybackManager: NSObject {
    var transportService: UPPAVTransportService!

    func subscribe() {
        let manager = UPPEventSubscriptionManager.shared()
        manager.subscribeObserver(self, to: transportService, completion: nil)
    }

    func unsubscribe() {
        let manager = UPPEventSubscriptionManager.shared()
        manager.removeObserver(self, from: transportService, completion: nil)
    }
}

extension PlaybackManager: UPPEventSubscriptionDelegate {
    func eventRecieved(_ event: [AnyHashable: Any]) {
        guard
            let event = event as? [String: Any],
            let thisEvent = event["Event"] as? [String: String]
            else { return }

        if let transportState = thisEvent["TransportState"] {
            print("TransportState: \(transportState)")
        }
    }
}

In case you find it useful, here is an example event sent by a renderer:

{
    Event =     {
        AVTransportURI = "http://10.0.0.2:9790/minimserver/*/music/AAC/Black*20Sabbath/We*20Sold*20Our*20Soul*20For*20Rock*20*27N*27*20Roll/1-01*20Black*20Sabbath.m4a";
        AVTransportURIMetaData = "<UPPMediaItem: 0x60400010ac20, title: Black Sabbath>";
        CurrentMediaDuration = "0:06:22.061";
        CurrentPlayMode = NORMAL;
        CurrentRecordQualityMode = "NOT_IMPLEMENTED";
        CurrentTrack = 1;
        CurrentTrackDuration = "0:06:22.061";
        CurrentTrackMetaData = "<UPPMediaItem: 0x600000110620, title: Black Sabbath>";
        CurrentTrackURI = "http://10.0.0.2:9790/minimserver/*/music/AAC/Black*20Sabbath/We*20Sold*20Our*20Soul*20For*20Rock*20*27N*27*20Roll/1-01*20Black*20Sabbath.m4a";
        CurrentTransportActions = Play;
        NextAVTransportURI = "NOT_IMPLEMENTED";
        NumberOfTracks = 1;
        PlaybackStorageMedium = NETWORK;
        PossiblePlaybackStorageMedia = "NONE,NETWORK";
        PossibleRecordQualityModes = "NOT_IMPLEMENTED";
        PossibleRecordStorageMedia = "NOT_IMPLEMENTED";
        RecordMediumWriteStatus = "NOT_IMPLEMENTED";
        RecordStorageMedium = "NOT_IMPLEMENTED";
        TransportPlaySpeed = 1;
        TransportState = STOPPED;
        TransportStatus = OK;
    };
    SID = "uuid:140bccc0-8c66-153c-8767-e0bb44dae7bb";
}
GINNOV commented 6 years ago

thank you for the quick turnaround, much appreciated. I was aiming so much in trying to understand how to do that in ObjC and then create a bridge in Swift to continue my part that I completely missed the point that I could have simply taken a different approach. Thank you for your very complete answer, much appreciated.