Нужен способ получить текущую воспроизводимую песню из Zune и Windows Media Player с помощью Python

Мое приложение извлекает текущую воспроизводимую песню из множества музыкальных проигрывателей. Однако у меня большие проблемы с реализацией Zune и Windows Media Player.

Я много гуглил на эту тему, к сожалению, это только больше и больше меня сбивает с толку.

Что я обычно делаю для других приложений:

  1. Перебирать все открытые окна каждые 4 секунды
  2. Получить заголовок всех окон
  3. Проверьте заголовок на наличие шаблона (т.е. " - Spotify ")
  4. Если он есть, отрегулируйте заголовок для вывода.

WMP В названии нет текущей воспроизводимой песни.

Zune это делает, но он каждые несколько секунд переключается между названием, альбомом и исполнителем. Что крайне ненадежно отслеживать с помощью моего текущего метода, хотя и возможно.

Проигрыватель Windows Media

Я также пытался использовать компонент COM для проигрывателя Windows Media.

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

Большая проблема в том, что вам нужно запускать WMP программно, что было бы крайне неудобным для пользователя.

Итак, что я нашел? Это сообщение SO перенаправляет на WMP.dll. Но насколько я читал, у него та же проблема, что и у СОМ, его надо запускать программно. Если нет, мне бы очень хотелось узнать, как работать с этой dll в python.

Было бы другое, немного менее хакерское решение, заключающееся в том, чтобы написать плагин для WMP, позволить моим пользователям загрузить этот плагин и получить данные из этого плагина. Я бы не стал туда заходить, так как у меня нет опыта ни с одним из языков C, и мне не хочется копаться в документации по плагинам для этого.

Zune

Метод заключается в циклическом просмотре трех состояний заголовка, определении того, в каком состоянии он находится в данный момент, и поиске положения двух других.

IE: Первые 5 секунд название: Super_song Следующие 5 секунд название: By Power_artist Следующие 5 секунд название: Good_album (дата)

Таким образом, я мог определить, когда название альбома, создав регулярное выражение для даты (которое всегда есть), а затем найти название и исполнителя, подождав несколько секунд.

Это, очевидно, не лучшее решение, так как это займет некоторое время и не очень надежно (например, что, если название песни содержит дату)

Следующая проблема заключается в том, что это также непоследовательно, иногда название просто остается Zune в течение нескольких минут. Не знаю, почему.

Итак, переходим к следующему способу.

Это приложение называется ZuneNowPlaying. Это «каким-то образом» получает текущую воспроизводимую песню из Zune и помещает ее в реестр, эта штука не работает с моим неаккуратным методом названия, поскольку он меняет реестр в момент изменения песни. Немедленно.

Это решение я использовал в рабочей версии своей программы, но многие пользователи сообщали, что оно просто не работало, ничего не происходило. И я проверил программу, и она не всегда надежно меняет реестр. Я не знаю почему, я не знаю, как это исправить. Таким образом, это решение также отбрасывается.

Является ли тот факт, что он использует имя «MsnMsgrUIManager»#000000»>, заставляет программное обеспечение zune отправлять ему информацию о том, какая песня играет? Есть ли способ получить эту информацию без такого взлома?

Это найдено в обсуждении приложения Zune Now Playing. К сожалению, источник недоступен, по крайней мере, я не могу его найти. У кого-нибудь есть больше об этом?

Третий метод, о котором я слышал, снова был dll. ZuneShell.dll это называется. Я не помню, где читал об этом, и не могу найти через google, так как все результаты "Является ли ZuneShell.dll вирусом?".

И снова я столкнулся с проблемой, что не знаю, как с этим работать, даже ЕСЛИ у меня есть документация по нему, черт возьми, даже если это то, что я искал.

Альтернативные направления для изучения

Просматривая эту тему, я видел, как люди говорили о получении данных непосредственно из графического интерфейса. Я не уверен, насколько законно, возможно или даже насколько правильно я помню об этом, но если это возможно, может ли кто-нибудь перенаправить меня на более подробную информацию об этом?

Что-нибудь еще, правда.


person Azeirah    schedule 18.10.2013    source источник
comment
Рассматривали ли вы попытку прочитать данные из памяти процесса zune? Кажется, для этого в python существует (устаревшая) библиотека с именем pymem.   -  person loopbackbee    schedule 21.10.2013
comment
@goncalopp У меня нет, и я посмотрю на это.   -  person Azeirah    schedule 21.10.2013
comment
Кажется возможным получить доступ к работающему экземпляру WMP с помощью dll, но я думаю, что это не так просто, см. здесь. Возможно, вы могли бы черпать вдохновение из источника. подключаемого модуля CurrentTrack для Pidgin. Справедливое предупреждение: он на C++ и имеет комментарий автора: это решение отстой... но пока я не могу понять, как использовать COM API...   -  person    schedule 23.10.2013


Ответы (2)


У меня есть рабочий код на С++ для печати имени медиа, воспроизводимого в настоящее время в WMP. Это простое консольное приложение (78 строк кода).

Шаги:

1) реализует базовый COM-объект, реализующий IUnknown, IOleClientSite, IServiceProvider и IWMPRemoteMediaServices. Это просто (вроде как, ваш пробег может отличаться) с использованием шаблона ATL CComObjectRootEx. Единственными методами, которым требуется (простой) код, являются IServiceProvider::QueryService и IWMPRemoteMediaServices::GetServiceType. Все остальные методы могут возвращать E_NOTIMPL.

2) Создайте экземпляр COM-объекта "WMPlayer.OCX" (в моем случае через CoCreateInstance)

3) Получить из объекта указатель интерфейса IOleObject через QueryInterface

4) Создать экземпляр объекта из класса, показанного в 1) (я использую шаблон CComObject‹>::CreateInstance)

5) Используйте метод SetClientSite из интерфейса, который вы получили в пункте 3), передав указатель на вашу реализацию OleClientSite.

6) Во время вызова SetClientSite WMP перезвонит вам: сначала запросив указатель интерфейса IServiceProvider, затем вызвав метод QueryService, запросив указатель интерфейса IWMPRemoteMediaServices. Верните свою реализацию IWMPRemoteMediaServices и, в-третьих, вас снова вызовут через GetServiceType. Затем вы должны вернуть «Remote». Теперь вы подключены к работающему экземпляру WMP.

7) Запрос COM-объекта для указателя интерфейса IWPMedia

8) Если 7) не дал NULL, прочтите свойство IWPMedia::name.

9) ВЫПОЛНЕНО

Все вышеперечисленное тестировалось с VS2010/Windows Seven и с запущенным WMP (если нет запущенного процесса Media Player, просто ничего не делать).

Я не знаю, можете ли вы реализовать COM-интерфейс и объект в Python. Если вас заинтересовал мой код C++, дайте мне знать. Вы можете использовать этот код в C++ DLL, а затем вызвать его из python.

person manuell    schedule 24.10.2013
comment
Это объяснение, к сожалению, слишком расплывчато для меня, я уже совершенно не представляю, что делать на первом этапе. И так мало документации по использованию COM с языками сценариев (конечно, в частности с python). Изменить: если вы не можете помочь мне с Python, я открою новый вопрос, чтобы перенаправить вопрос пользователям python win32api. - person Azeirah; 27.10.2013
comment
@Azeirah, я не могу помочь с Python. У вас остается 2 альтернативы: 1) создать DLL (или EXE) на C++, которая будет COM-сервером, вызываемым из Python. Или 2) Реализовать все это непосредственно в Python, ЕСЛИ можно реализовать в Python интерфейс, который не наследуется от IDispatch. - person manuell; 27.10.2013
comment
Я знаю, что это было какое-то время, однако у меня все еще есть эта проблема. Теперь я знаю гораздо больше о C++, python и обо всем этом. Если у вас все еще есть код С++, который вы упомянули в этом ответе, не могли бы вы отправить его на мою электронную почту? электронная почта@martijnbrekelmans.com - person Azeirah; 12.08.2015
comment
Время каникул, вот, на следующей неделе я займусь археологическими работами. Ткните меня, если я, кажется, забыл. - person manuell; 13.08.2015
comment
Эй, вот твой тык :) - person Azeirah; 26.08.2015
comment
Нашел на своем старом ПК. Еще работает. Сборка env — это Visual Studio 2010. Вам нужны все файлы решений или только уникальный файл c++? - person manuell; 26.08.2015
comment
Если возможно, я хотел бы весь пакет. Спасибо, что раскопал! - person Azeirah; 26.08.2015
comment
Отправлю письмо завтра утром. Франция, здесь. - person manuell; 26.08.2015

Я только что нашел классный инструмент Python, который может запрашивать все элементы управления любой программы. Просто, понятно и легко читается. Это здесь:

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

При этом вы можете получить информацию из графического интерфейса.

Вы также можете получить список загруженных файлов. Он работает для большинства медиаплееров. Вы можете получить эту информацию программно следующим образом:

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

Это C++, но в этот момент вы можете обернуть нативный код. Таким образом, вы должны самостоятельно извлечь теги ID3. Возможно, стоит попробовать, так как это было бы универсальным решением.

person Kobor42    schedule 24.10.2013
comment
Извлечение всех файлов на самом деле звучит как достойный план резервного копирования. Однако в WMP большую часть времени открыты два файла, так что с этим трудно работать. Я думаю, что я посмотрю больше на это, если все остальное не удастся. - person Azeirah; 27.10.2013
comment
Он не запрашивает все файлы, а только тот, который воспроизводится. Каждая песня отображается в плейлисте WMP, но для непрерывного чтения открыта только проигрываемая в данный момент песня. Мое второе предложенное решение ищет только один дескриптор открытого файла. Кстати, что вы думаете о pywinauto? - person Kobor42; 28.10.2013