Exemple #1
0
 def start(self):
     self.timer = objc.ObjCClass("NSTimer").timerWithTimeInterval(
         0.1,
         target=self,
         selector=objc.SEL("pollControllerWithSender:"),
         userInfo=None,
         repeats=True)
     objc.ObjCClass("NSRunLoop").currentRunLoop().addTimer(
         self.timer, forMode="kCFRunLoopCommonModes")
     pass
        def tableView_cellForRowAtIndexPath_(self, tableView, indexPath):
            if self.isEnumerating:
                cellIdentifer = "MQVActivityCell"
                cell = tableView.dequeueReusableCellWithIdentifier(
                    cellIdentifer)
                if cell is None:
                    cell = objc.ObjCClass(
                        "UITableViewCell").alloc().initWithStyle(
                            0, reuseIdentifier=cellIdentifer)
                    pass

                cell.userInteractionEnabled = False

                activityIndicator = objc.ObjCClass(
                    "UIActivityIndicatorView").alloc(
                    ).initWithActivityIndicatorStyle(100)
                activityIndicator.hidesWhenStopped = True
                activityIndicator.center = objc.NSPoint(
                    self.tableView.frame.size.width / 2,
                    cell.frame.size.height / 2)

                cell.contentView.addSubview(activityIndicator)
                activityIndicator.startAnimating()
                return cell

            cellIdentifer = "MQVSongCell"
            cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifer)
            if cell is None:
                cell = objc.ObjCClass("UITableViewCell").alloc().initWithStyle(
                    3, reuseIdentifier=cellIdentifer)
                pass

            if len(self.songList) < indexPath.row:
                return cell

            song = self.songList[indexPath.row]

            cell.textLabel.text = song.title
            cell.detailTextLabel.text = song.artist
            cell.imageView.image = song.art

            if song.exists:
                cell.userInteractionEnabled = True
                cell.textLabel.enabled = True
                cell.detailTextLabel.enabled = True
                pass
            else:
                cell.userInteractionEnabled = False
                cell.textLabel.enabled = False
                cell.detailTextLabel.enabled = False
                pass
            return cell
Exemple #3
0
    def reorder(self, targetItemIndex: int, targetPositionIndex: int):
        """Reorders the song at the targetItemIndex to the targetPositionIndex."""

        tracklist = self._getResponse().tracklist

        # convert the indices from the queue to the tracklist indices.
        nowPlayingitemIndex = tracklist.playingItem.indexPath.row
        targetItemIndex += nowPlayingitemIndex + 1
        targetPositionIndex += nowPlayingitemIndex + 1

        collection = tracklist.items
        maxTargetPosition = collection.numberOfItemsInSection(0)

        if targetItemIndex > maxTargetPosition:
            raise IndexError(
                "targetItemIndex ({}) must be lower than {}.".format(
                    targetItemIndex - (nowPlayingitemIndex + 1),
                    maxTargetPosition - nowPlayingitemIndex))
        elif targetPositionIndex > maxTargetPosition:
            raise IndexError(
                "targetPositionIndex ({}) must be lower than {}.".format(
                    targetPositionIndex - (nowPlayingitemIndex + 1),
                    maxTargetPosition - nowPlayingitemIndex))
        elif targetPositionIndex < 0:
            raise IndexError(
                "targetPositionIndex ({}) must be 0 or higher.".format(
                    targetPositionIndex - (nowPlayingitemIndex + 1)))

        targetItemIndexPath = objc.ObjCClass("NSIndexPath").indexPathForRow(
            targetItemIndex, inSection=0)
        targetItem = collection.itemAtIndexPath(targetItemIndexPath)
        positionalItemIndexPath = objc.ObjCClass(
            "NSIndexPath").indexPathForRow(targetPositionIndex - 1,
                                           inSection=0)
        positionalItem = collection.itemAtIndexPath(positionalItemIndexPath)

        reorderCommand = tracklist.reorderCommand()
        if reorderCommand.canMoveItem(targetItem) is False:
            raise RuntimeError("Unable to move item at targetItemIndex.")

        reorderRequest = reorderCommand.moveItem(targetItem,
                                                 afterItem=positionalItem)

        self.reorderRequestCompletion.clear()
        objc.ObjCClass("MPCPlayerChangeRequest").performRequest(
            reorderRequest, completion=self._reorderRequestHandler)
        self.reorderRequestCompletion.wait()

        # wait for the command to actually take effect.
        time.sleep(0.1)
        pass
Exemple #4
0
	def __init__(self, callback, allowMultiple=False):
		self.callback = callback
		
		self.tableViewController = objc.ObjCClass("UITableViewController").alloc().initWithStyle(0)
		self.tableViewController.tableView.allowsMultipleSelection = allowMultiple

		self.dataSource = objc.ObjCClass("MQVDataSource").alloc().initWithTableView(self.tableViewController.tableView)
		self.tableViewController.tableView.dataSource = self.dataSource
		

		self.navigationController = objc.ObjCClass("MQVNavigationController").alloc().initWithRootViewController(self.tableViewController)
		self.navigationController.MQVDelegate = self

		self.closeEvent = threading.Event()
		pass
Exemple #5
0
    def __init__(self):
        self.musicPlayer = objc.ObjCClass(
            "MPMusicPlayerController").systemMusicPlayer
        self.requestController = self.musicPlayer.requestController

        self.reorderRequestCompletion = threading.Event()
        self.clearRequestCompletion = threading.Event()
        self.prepareCompletion = threading.Event()

        def reorderRequestHandler(arg1: objc.ObjCInstance,
                                  arg2: objc.ObjCInstance,
                                  arg3: objc.ObjCInstance, arg4: int) -> None:
            self.reorderRequestCompletion.set()
            pass

        self._reorderRequestHandler = objc.Block(reorderRequestHandler)

        def clearRequestHandler(arg1: objc.ObjCInstance,
                                arg2: objc.ObjCInstance,
                                arg3: objc.ObjCInstance, arg4: int) -> None:
            self.clearRequestCompletion.set()
            pass

        self._clearRequestHandler = objc.Block(clearRequestHandler)

        def prepareHandler(error: objc.ObjCInstance) -> None:
            self.prepareCompletion.set()
            pass

        self._prepareHandler = objc.Block(prepareHandler)
        pass
        def initWithTableView_(self, tableView):
            self.musicPlayer = objc.ObjCClass(
                "MPMusicPlayerController").systemMusicPlayer
            self.tableView = tableView

            self.songList = []

            self.isEnumerating = False
            self.enumerationLock = threading.Lock()

            self.beginEnumeratingSongs()

            self.changeDetector = objc.ObjCClass(
                "MQVSongChangeDetector").alloc().init()
            self.changeDetector.MQVCallback = self.beginEnumeratingSongs
            self.changeDetector.start()
            return self
Exemple #7
0
	def present(self):
		"""Presents the viewer."""

		application = objc.ObjCClass("UIApplication").sharedApplication
		rootViewController = application.keyWindow.rootViewController
		rootViewController.presentViewController(self.navigationController, animated=True, completion=None)
		
		self.closeEvent.clear()
		pass
        def reloadTable(self):
            self.tableView.reloadData()

            if self.tableView.numberOfRowsInSection(0) != 0:
                indexZero = objc.ObjCClass("NSIndexPath").indexPathForRow(
                    0, inSection=0)
                self.tableView.scrollToRowAtIndexPath(indexZero,
                                                      atScrollPosition=1,
                                                      animated=True)
                pass
            pass
Exemple #9
0
        def init(self):
            """set attribute MQVCallback to receive notifications."""
            self.musicPlayer = objc.ObjCClass(
                "MPMusicPlayerController").systemMusicPlayer

            self.MQVCallback = None

            index = self.musicPlayer.indexOfNowPlayingItem + 1
            song = self.musicPlayer.nowPlayingItemAtIndex(index)
            if song:
                self.lastSong = song.copy()
            return self
Exemple #10
0
    def replaceQueue(self, songList: list):
        """
		Clears the current queue and replaces it with the given list. This will preserve the currently playing song.

		parameters
		----------

		songList : list
			A list of MQVSong instances.
		"""

        songList = [song.songObject for song in songList]
        songList.insert(0, self.musicPlayer.nowPlayingItem)

        self.musicPlayer.pause()
        currentTime = self.musicPlayer.currentPlaybackTime

        clearRequest = self._getResponse().tracklist.resetCommand().clear()

        self.clearRequestCompletion.clear()
        objc.ObjCClass("MPCPlayerChangeRequest").performRequest(
            clearRequest, completion=self._clearRequestHandler)
        self.clearRequestCompletion.wait()

        self.musicPlayer.shuffleMode = 1
        songCollection = objc.ObjCClass(
            "MPMediaItemCollection").collectionWithItems(songList)
        self.musicPlayer.setQueueWithItemCollection(songCollection)

        self.musicPlayer.prepareToPlay()

        self.prepareCompletion.clear()
        self.musicPlayer.prepareToPlayWithCompletionHandler(
            self._prepareHandler)
        self.prepareCompletion.wait()

        self.musicPlayer.play()
        self.musicPlayer.currentPlaybackTime = currentTime
        pass
Exemple #11
0
        def initWithRootViewController_(self, rootController):
            self = objc.ObjCInstance(
                objc.send_super(__class__, self, "initWithRootViewController:",
                                rootController))  # pylint: disable=undefined-variable
            if self:
                self.MQVDelegate = None
                self.modalPresentationStyle = 0

                stopButton = objc.ObjCClass(
                    "UIBarButtonItem").alloc().initWithBarButtonSystemItem(
                        14, target=self, action=objc.SEL("closeAction"))
                reloadButton = objc.ObjCClass(
                    "UIBarButtonItem").alloc().initWithTitle(
                        "Reload",
                        style=0,
                        target=self,
                        action=objc.SEL("reloadAction"))
                shuffleButton = objc.ObjCClass(
                    "UIBarButtonItem").alloc().initWithTitle(
                        "Shuffle",
                        style=0,
                        target=self,
                        action=objc.SEL("shuffleAction"))
                doneButton = objc.ObjCClass(
                    "UIBarButtonItem").alloc().initWithTitle(
                        "Done",
                        style=2,
                        target=self,
                        action=objc.SEL("doneAction"))

                self.navigationBar.topItem.leftBarButtonItem = stopButton
                self.navigationBar.topItem.rightBarButtonItems = [
                    doneButton, shuffleButton, reloadButton
                ]
                pass
            return self
        def enumerateSongs(self):
            newSongList = []

            currentIndex = self.musicPlayer.indexOfNowPlayingItem + 1
            maxIndex = self.musicPlayer.numberOfItems()

            for index in range(currentIndex, maxIndex):
                song = self.musicPlayer.nowPlayingItemAtIndex(index)
                if song and "MPModelObjectMediaItem" in song.debugDescription and song.title is None:
                    break
                else:
                    newSongList.append(
                        objc.ObjCClass("MQVSong").alloc().initWithSong(song))
                    pass
                pass

            self.songList = newSongList

            self.enumerationLock.release()
            self.isEnumerating = False

            self.reloadTable()
            pass
import rubicon.objc as objc
import objc_util  # pylint: disable=import-error
import threading

import time

from .mqv_song import MQVSong
from .mqv_songchangedetector import MQVSongChangeDetector

_warnForDefinedClass = False

NSLog = objc_util.c.NSLog
NSLog.argtypes = [objc_util.c_void_p]

try:
    MQVDataSource = objc.ObjCClass("MQVDataSource")
    if _warnForDefinedClass:
        print("MQVDataSource already defined")
except NameError:
    UITableViewDataSource = objc.ObjCProtocol("UITableViewDataSource")

    class MQVDataSource(objc.NSObject, protocols=[UITableViewDataSource]):
        @objc.objc_method
        def initWithTableView_(self, tableView):
            self.musicPlayer = objc.ObjCClass(
                "MPMusicPlayerController").systemMusicPlayer
            self.tableView = tableView

            self.songList = []

            self.isEnumerating = False
Exemple #14
0
import rubicon.objc as objc

_warnForDefinedClass = False

try:
    MQVNavigationController = objc.ObjCClass("MQVNavigationController")
    if _warnForDefinedClass:
        print("MQVNavigationController already defined")
except NameError:
    UINavigationController = objc.ObjCClass("UINavigationController")

    class MQVNavigationController(UINavigationController):
        @objc.objc_method
        def initWithRootViewController_(self, rootController):
            self = objc.ObjCInstance(
                objc.send_super(__class__, self, "initWithRootViewController:",
                                rootController))  # pylint: disable=undefined-variable
            if self:
                self.MQVDelegate = None
                self.modalPresentationStyle = 0

                stopButton = objc.ObjCClass(
                    "UIBarButtonItem").alloc().initWithBarButtonSystemItem(
                        14, target=self, action=objc.SEL("closeAction"))
                reloadButton = objc.ObjCClass(
                    "UIBarButtonItem").alloc().initWithTitle(
                        "Reload",
                        style=0,
                        target=self,
                        action=objc.SEL("reloadAction"))
                shuffleButton = objc.ObjCClass(
Exemple #15
0
from musicruntime.musicqueueviewer import MusicQueueViewer
from musicruntime.musicplayercontroller import MusicPlayerController


def callback(selected: list, sender: MusicQueueViewer):
    controller = MusicPlayerController()

    currentIndex = 0
    for selection in selected:
        try:
            controller.reorder(selection[0], currentIndex)
            pass
        except Exception as e:
            print("Unable to move song ({}), Exception({})".format(
                selection[1].title, e))
            pass
        currentIndex += 1
        pass
    pass


viewer = MusicQueueViewer(callback, allowMultiple=True)
viewer.present()
viewer.waitModal()

app = objc.ObjCClass("UIApplication").sharedApplication
nav = app._systemNavigationAction()
if nav:
    nav.sendResponseForDestination(0)
    pass
Exemple #16
0
import rubicon.objc as objc

_warnForDefinedClass = False

try:
    MQVSong = objc.ObjCClass("MQVSong")
    if _warnForDefinedClass:
        print("MQVSong already defined")
except NameError:

    class MQVSong(objc.NSObject):
        """
		A wrapper around MPMediaItem.

		Since this is a ObjCClass, it should be initialized like so, MQVSong.alloc().initWithSong(songObject)

		Attributes
		----------

		title : str

		artist : str

		exists : bool
			If the song exists in the users library

		art : rubicon.objc.ObjCInstance
			A UIImage instance of the song's artwork

		parameters
		----------
Exemple #17
0
	def shuffleAction(self):
		musicPlayer = objc.ObjCClass("MPMusicPlayerController").systemMusicPlayer
		musicPlayer.shuffleMode = 1
		musicPlayer.shuffleMode = 2
		pass
Exemple #18
0
import rubicon.objc as objc
import objc_util  # pylint: disable=import-error

_warnForDefinedClass = False

try:
    MQVSongChangeDetector = objc.ObjCClass("MQVSongChangeDetector")
    if _warnForDefinedClass:
        print("MQVSongChangeDetector already defined")
except NameError:

    class MQVSongChangeDetector(objc.NSObject):
        lastSong = objc.objc_property()

        @objc.objc_method
        def init(self):
            """set attribute MQVCallback to receive notifications."""
            self.musicPlayer = objc.ObjCClass(
                "MPMusicPlayerController").systemMusicPlayer

            self.MQVCallback = None

            index = self.musicPlayer.indexOfNowPlayingItem + 1
            song = self.musicPlayer.nowPlayingItemAtIndex(index)
            if song:
                self.lastSong = song.copy()
            return self

        @objc.objc_method
        def pollControllerWithSender_(self, sender):
            index = self.musicPlayer.indexOfNowPlayingItem + 1