Forum Archive

using a C function

arandomperson

I'm trying to get information about the current song playing outside of the stock music app. Coming from jailbreak development, I know I can use the c function "MRMediaRemoteGetNowPlayingInfo" in the private framework mediaRemote. But I don't know how I would be able to call that in Pythonista.

Any help is appreciated!

mikael

@arandomperson, have you looked at the documentation for the objc_util module? The first example is even about checking the now playing song. If that is not what you were after, you might try loading the framework you mentioned.

arandomperson

@mikael, Yes I have looked at the documentation, though the example only works for the stock application. Also the function I eluded to is not a class method, but a function. I’m looking into ctypes, but I dont know how to pass a dispatch queue or a completion block to it, As I’m not too familiar with ctypes.

arandomperson

Currently I was able to test the framework by calling "c.MRMediaRemoteSendComman(2, 0)" but the closest I got to calling "MRMediaRemoteGetNowPlayingInfo" was with this code:

from objc_util import *
from ctypes import *
import ctypes

c = ctyles.CDLL(None)
MRMediaRemoteGetNowPlayingInfo = c.MRMediaRemoteGetNowPlayingInfo 
MRMediaRemoteGetNowPlayingInfo .restype = c_void_p
MRMediaRemoteGetNowPlayingInfo .argtypes = [c_void_p, c_void_p]

queue = c.dispatch_get_current_queue

info = c_void_p()
MRMediaRemoteGetNowPlayingInfo(queue, byref(info))
print(objcCInstance(info))

But this just crashes the app, i'm pretty sure the problem is with the queue, but i'm not able to call "dispatch_get_main_queue" because its just says its unable to find the symbol.

Again, any help would be great!

mikael

Do you have the faulthandler by @dgelessus installed? Always handy when you see the ObjC exception and do not have to guess.

mikael

@arandomperson, have you tried loading the framework in a similar manner to this?

NSBundle.bundle(Path="/System/Library/Frameworks/MultipeerConnectivity.framework").load()
MCPeerID = ObjCClass('MCPeerID')
MCSession = ObjCClass('MCSession')

You could also check the rest of the Multipeer code for a reference on how to handle completion blocks. Unfortunately I cannot help you with details, as that part of the code was contributed whole cloth by @JonB.

MartinPacker

Typo “ctyles” of any consequence here?

cvp

@MartinPacker I suppose he did manually recopy his code without copying/pasting it because this short code has directly an error "NameError: name 'ctyles' is not defined"

But, well seen anyway

cvp

Fauthandler gives Fatal Python error: Segmentation fault in line

MRMediaRemoteGetNowPlayingInfo(queue, byref(info))
JonB

You can't go guessing arguments. Look at the headers. That function takes a dispatch queue (which you forgot to call the function to get the queue) and an ObjCBlock, which takes ine argument, a dictionary that has the info you want.

Here is a simple bit to get the dictionary. note the values are usually objc types, so you may need to convert to more useful values. Explore the now_playing_dict.keys to see what you have accessible.

from objc_util import *
from ctypes import *
import ctypes

MRMediaRemoteGetNowPlayingInfo = c.MRMediaRemoteGetNowPlayingInfo 
MRMediaRemoteGetNowPlayingInfo.restype = None
MRMediaRemoteGetNowPlayingInfo.argtypes = [c_void_p, ObjCBlock]
now_playing_dict={}
from threading import Event
e=Event()

def info_cb(_blk,info):
    now_playing_dict.clear()
    if info:
        infodict=ObjCInstance(info)
        for k in infodict.allKeys():
            now_playing_dict[str(k)]= infodict[k]
    e.set()

cb=ObjCBlock(info_cb,argtypes=[c_void_p,c_void_p], restype=None)
q=ObjCInstance(c.dispatch_get_current_queue())
MRMediaRemoteGetNowPlayingInfo(q, cb)

#since the callback happens in another thread, we wait for the event to be set
e.wait()
print(now_playing_dict['kMRMediaRemoteNowPlayingInfoTitle'])
arandomperson

@JonB Thanks for the help, I did manage to get it working by studying a couple of examples, but your code looks so much nicer.

arandomperson

@mikael faulthandler seems really useful, Thanks!