Need a way to retrieve the current playing song from Zune and Windows Media Player with Python

↘锁芯ラ 提交于 2019-12-18 21:53:27

问题


An Application of mine retrieves the current playing song from a multitude of music players. However, I'm having great trouble implementing Zune and Windows Media Player.

I've done a lot of googling on the subject, unfortunately it's only confusing me more and more.

What I would normally do for my other applications:

  1. Iterate over all open windows every 4 seconds
  2. Get the title of all windows
  3. Check title for a pattern (Ie, " - Spotify ")
  4. If it's there, adjust the title for output.

WMP Does not have the current playing song in the title.

Zune does, but it's rotating every few seconds between title, album and artist. Which is heavily unreliable to track with my current method, albeit possible.

Windows Media Player

I've also tried using the COM component for windows media player.

import win32com.client
wmp = win32com.client.gencache.EnsureDispatch('WMPlayer.OCX')

# some function I don't have here, it retrieves the current playing song
# and other data

The big problem with that it requires you to start WMP programmatically, which would be extremely user unfriendly

So, what have I found? This SO post redirects to WMP.dll. But as far as I've read, it has the same problem as the COM, you have to start it programmatically. If not, I would really like some directions on how to work with that dll in python.

There would be another a little less hacky solution, which is to write a plugin for WMP, let my users download that plugin and retrieve the data from that plugin. I'd rather not go there, since I have no experience with any of the C languages, nor do I feel like digging into plugin documentations for this.

Zune

A method would be to cycle through the three title states, determine which state it's currently at and find the position of the other two.

IE: First 5 seconds the title is: Super_song Next 5 seconds the title is: By Power_artist Next 5 seconds the title is: Good_album (date)

So I could determine when the album title is by making a regex for the date (which is always there) and then find the title and artist by waiting a few seconds.

This is obviously not a great solution, since it'll take a while and it's not very reliable either, (what if the song name contains a date for example)

The next problem is that it's not consistent either, sometimes the title just stays Zune for minutes long. No idea why.

So, move on to the next method.

There's this application called ZuneNowPlaying. This "somehow" gets the current playing song from Zune and puts it in the registry, this thing does not work with my sloppy title method, since it changes the registry the instant the song changes. Immediately.

This is the solution I had used in the working version of my program, but many users reported that it simply didn't work, nothing happened. And I checked the program and it doesn't reliably change the registry all the time. I don't know why, I don't know how to fix it. Therefor, this solution is also -scrapped-.

Is the fact that it is using the name "MsnMsgrUIManager"#000000"> causing the zune software to send it information about which song is playing? Is there a way to get this information without this kind of hack?

That is found in the discussion of the Zune Now Playing application. The source is not available unfortunately, at least I can't find it. Anyone got more on this?

Third method I had heard of was once again, a dll. ZuneShell.dll it's called. I don't remember where I read about it, nor can I find it via google, since all results are "Is ZuneShell.dll a virus?".

Once again, I run into the problem that I wouldn't know how to work with this even IF I had documentation on it, heck, if it's even what I have been looking for.

Alternate directions to maybe look into

While browsing about this subject, I've seen people talking about retrieving data directly from GUI's. I'm not sure how legit, possible or even how correct my memory of it is, but if it's possible could someone redirect me to more on this?

Anything else, really.


回答1:


I have working code in C++ to print the name of media currently playing in WMP. It's a simple console application (78 lines of code).

Steps:

1) implements a basic COM object implementing IUnknown, IOleClientSite, IServiceProvider and IWMPRemoteMediaServices. This is straightforward (sort of, your mileage may vary) using the ATL template CComObjectRootEx. The only methods needing (simple) code are IServiceProvider::QueryService and IWMPRemoteMediaServices::GetServiceType. All other methods may return E_NOTIMPL

2) Instantiate the "WMPlayer.OCX" COM object (in my case, via CoCreateInstance)

3) Retrieve from the object an IOleObject interface pointer via QueryInterface

4) Instanciate an object from the class seen in 1) (I use the CComObject<>::CreateInstance template)

5) Use the SetClientSite method from the interface you got at 3), passing a pointer to your OleClientSite implementation.

6) During the SetClientSite call, WMP will callback you: fisrt asking for an IServiceProvider interface pointer, second calling the QueryService method, asking for an IWMPRemoteMediaServices interface pointer. Return your implementation of IWMPRemoteMediaServices and, third, you will be called again via GetServiceType. You must then return "Remote". You are now connected to the WMP running instance

7) Query the COM object for an IWMPMedia interface pointer

8) If 7) didn't gave NULL, read the the IWMPMedia::name property.

9) DONE

All the above was tested with VS2010 / Windows Seven, and with WMP running (if there is no Media Player process running, just do nothing).

I don't know if yoy can/want to implement COM interface and object in Python. If you are interested by my C++ code, let me know. You could use that code in a C++ DLL, and then call it from python.




回答2:


I just found a cool Python tool which can query all the controls of any program. Simple, straightforward, and easy to read. It's here:

http://www.brunningonline.net/simon/blog/archives/winGuiAuto.py.html

With that you can get the info from the GUI.

You can also grab the loaded file list. It works for most media player. You can get this information programmatically like this:

http://www.codeproject.com/Articles/18975/Listing-Used-Files

This is C++, but at that point you can wrap the native code. This way you have to extract the ID3 tags yourself. Might worth the shot as it would be an universal solution.



来源:https://stackoverflow.com/questions/19452001/need-a-way-to-retrieve-the-current-playing-song-from-zune-and-windows-media-play

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!