kmikiy / SpotMenu

Spotify and iTunes in your menu bar
https://kmikiy.github.io/SpotMenu
MIT License
2.93k stars 183 forks source link

Request: YouTube #232

Open daudadu opened 4 years ago

daudadu commented 4 years ago

First of all, thank you for making my life a hundred times better and easier with SpotMenu! I would love if it could be functional in the same way for music playing on Chrome though, specifically YouTube as it's frustrating to keep having to switch to Chrome while I'm on another app to change my music.

flightmansam commented 3 years ago

I would also love to see this feature! Let's have a look at seeing if we can hook into chrome / a playing browser and scraping the audio metadata. I know it should be theoretically possible. I have an airplay capable TV, if I select it as an audio sink when playing music from my laptop (through chrome) all of the metadata comes up on the TV, including album artwork. Note: I'm not talking about chromecast, which of course is just sharing the URL.

flightmansam commented 3 years ago

Check this out from our favorite source, stackoverflow: https://stackoverflow.com/questions/61003379/how-to-get-currently-playing-song-on-mac-swift

> // Load framework
> let bundle = CFBundleCreate(kCFAllocatorDefault, NSURL(fileURLWithPath: "/System/Library/PrivateFrameworks/MediaRemote.framework"))
> 
> // Get a Swift function for MRMediaRemoteGetNowPlayingInfo
> guard let MRMediaRemoteGetNowPlayingInfoPointer = CFBundleGetFunctionPointerForName(bundle, "MRMediaRemoteGetNowPlayingInfo" as CFString) else { return }
> typealias MRMediaRemoteGetNowPlayingInfoFunction = @convention(c) (DispatchQueue, @escaping ([String: Any]) -> Void) -> Void
> let MRMediaRemoteGetNowPlayingInfo = unsafeBitCast(MRMediaRemoteGetNowPlayingInfoPointer, to: MRMediaRemoteGetNowPlayingInfoFunction.self)
> 
> // Get a Swift function for MRNowPlayingClientGetBundleIdentifier
> guard let MRNowPlayingClientGetBundleIdentifierPointer = CFBundleGetFunctionPointerForName(bundle, "MRNowPlayingClientGetBundleIdentifier" as CFString) else { return }
> typealias MRNowPlayingClientGetBundleIdentifierFunction = @convention(c) (AnyObject?) -> String
> let MRNowPlayingClientGetBundleIdentifier = unsafeBitCast(MRNowPlayingClientGetBundleIdentifierPointer, to: MRNowPlayingClientGetBundleIdentifierFunction.self)
> 
> // Get song info
> MRMediaRemoteGetNowPlayingInfo(DispatchQueue.main, { (information) in
>     NSLog("%@", information["kMRMediaRemoteNowPlayingInfoArtist"] as! String)
>     NSLog("%@", information["kMRMediaRemoteNowPlayingInfoTitle"] as! String)
>     NSLog("%@", information["kMRMediaRemoteNowPlayingInfoAlbum"] as! String)
>     NSLog("%@", information["kMRMediaRemoteNowPlayingInfoDuration"] as! String)
>     let artwork = NSImage(data: information["kMRMediaRemoteNowPlayingInfoArtworkData"] as! Data)
> 
>     // Get bundle identifier
>     let _MRNowPlayingClientProtobuf: AnyClass? = NSClassFromString("_MRNowPlayingClientProtobuf")
>     let handle : UnsafeMutableRawPointer! = dlopen("/usr/lib/libobjc.A.dylib", RTLD_NOW)
>     let object = unsafeBitCast(dlsym(handle, "objc_msgSend"), to:(@convention(c)(AnyClass?,Selector?)->AnyObject).self)(_MRNowPlayingClientProtobuf,Selector("a"+"lloc"))
>     unsafeBitCast(dlsym(handle, "objc_msgSend"), to:(@convention(c)(AnyObject?,Selector?,Any?)->Void).self)(object,Selector("i"+"nitWithData:"),information["kMRMediaRemoteNowPlayingInfoClientPropertiesData"] as AnyObject?)
>     NSLog("%@", MRNowPlayingClientGetBundleIdentifier(object))
>     dlclose(handle)
> })

This could be along the lines of what we're looking for. I suggest we could write a new MusicPlayer entity -- NewPlayer (not sure if that's the right word), under: SpotMenu/MusicPlayer/Player/NewPlayer/ SpotMenu/MusicPlayer/Bridges/NewPlayerBridge/ SpotMenu/MusicPlayer/Model/Enumeration.swift, add a NewPlayer name at the enum at line 40 SpotMenu/MusicPlayer/Manager/MusicPlayerFactory.swift, add a new cace for the NewPlayer class SpotMenu/PopOver/PopOverVC.swift, create a player icon

And then appropriate inclusions in the xcode project and AppDelegate for SpotMenu and SpotMenuToday. If I didn't have an honours thesis to complete I'd be keen to give it a crack. Otherwise it will have to wait until after May. How good is your coding @daudadu? What do you think about this @kmikiy? I guess there is the possibility for SpotMenu to conflict with iTunes or Spotify when they are playing so some code should be included to prefer the iTunes and Spotify classes when they are the audio source. I haven't looked far enough into the code to see if this isn't already implemented.

Also NewPlayer is a terrible name, just a placeholder. Maybe SystemPlayer? NowPlaying? MediaRemote?