Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Listen for distributed notifications from iTunes of the current song
'''
This python script listens for distributed notifications from iTunes of new songs playing,
works alot better then constantly polling.
'''
import Foundation
from AppKit import *
from PyObjCTools import AppHelper
class GetSongs(NSObject):
def getMySongs_(self, song):
song_details = {}
ui = song.userInfo()
song_details = dict(zip(ui.keys(), ui.values()))
print song_details
nc = Foundation.NSDistributedNotificationCenter.defaultCenter()
GetSongs = GetSongs.new()
nc.addObserver_selector_name_object_(GetSongs, 'getMySongs:', 'com.apple.iTunes.playerInfo',None)
NSLog("Listening for new tunes....")
AppHelper.runConsoleEventLoop()
@brandondurham

This comment has been minimized.

Copy link

@brandondurham brandondurham commented Nov 26, 2011

While researching methods for logging listens to a database (for creating powerful "Best of the Year" playlists) I found this Gist. Thank you for posting! Could you recommend best methods for logging this information to a DB?

@0a01-wait

This comment has been minimized.

Copy link

@0a01-wait 0a01-wait commented Dec 9, 2011

great info. not familiar with python, im trying to create an applescript observer to watch for distributed notifications from the djay app. do you have an equivalent model of this for applescript? thanks very much

@atchoo78

This comment has been minimized.

Copy link

@atchoo78 atchoo78 commented Sep 20, 2017

Thanks! I used this as a base script to take it even further and display the current playing track on a dot matrix LED display (via HTTP) connected to my Raspberry PIs GPIO interface.

dotmat

Code (macOS)

import Foundation
from AppKit import *
from PyObjCTools import AppHelper
import requests

LED_URL = "http://raspberrypi.local:8181"

class GetSongs(NSObject):
    def getMySongs_(self, song):
        ui = song.userInfo()
        song_details = dict(zip(ui.keys(), ui.values()))
        nowPlaying = (song_details['Artist'] + " : " + song_details['Name'])
        r = requests.post(url = LED_URL, data = nowPlaying)
        print(nowPlaying)

nc = Foundation.NSDistributedNotificationCenter.defaultCenter()
GetSongs = GetSongs.new()
nc.addObserver_selector_name_object_(GetSongs, 'getMySongs:', 'com.apple.iTunes.playerInfo',None)

NSLog("Listening for new tunes....")
AppHelper.runConsoleEventLoop()

Raspberry PI (Server) code

Luma display library & max7219 display drivers by Richard Hull.

https://github.com/rm-hull/luma.led_matrix

from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
import re
import argparse
import time
from luma.core.interface.serial import spi, noop
from luma.core.render import canvas
from luma.led_matrix.device import max7219
from luma.core.virtual import viewport
from luma.core.legacy import text, show_message
from luma.core.legacy.font import proportional, CP437_FONT, TINY_FONT, SINCLAIR_FONT, LCD_FONT

serial = spi(port=0, device=0, gpio=noop())
device = max7219(serial, cascaded=3, block_orientation=-90, rotate=2)

class S(BaseHTTPRequestHandler):
    def do_POST(self):
        content_length = int(self.headers['Content-Length'])
        post_data = self.rfile.read(content_length)
        show_message(device, post_data, fill="white", font=proportional(LCD_FONT))

def run(server_class=HTTPServer, handler_class=S, port=8181):
    server_address = ('', port)
    httpd = server_class(server_address, handler_class)
    print 'Starting httpd Server...'
    httpd.serve_forever()

if __name__ == "__main__":
    from sys import argv

    if len(argv) == 2:
        run(port=int(argv[1]))
    else:
        run()
@newPythonUser91

This comment has been minimized.

Copy link

@newPythonUser91 newPythonUser91 commented Jul 24, 2020

Is there a way to return the variable song_details to a python script to be queried later? similar to a basic class in python?

@y4rr

This comment has been minimized.

Copy link

@y4rr y4rr commented Feb 17, 2021

This script works only with system python2. Also, the f*ggot company has renamed iTunes. So here's a couple of needed changes:

#!/usr/bin/python

'''
This python script listens for distributed notifications from iTunes of new songs playing, 
works alot better then constantly polling. 
'''
import Foundation
from AppKit import *
from PyObjCTools import AppHelper

class GetSongs(NSObject):
    def getMySongs_(self, song):
        song_details = {}
        ui = song.userInfo()
        song_details = dict(zip(ui.keys(), ui.values()))
        print song_details

nc = Foundation.NSDistributedNotificationCenter.defaultCenter()
GetSongs = GetSongs.new()
nc.addObserver_selector_name_object_(GetSongs, 'getMySongs:', 'com.apple.Music.playerInfo',None)

NSLog("Listening for new tunes....")
AppHelper.runConsoleEventLoop()

@jim-cooley

This comment has been minimized.

Copy link

@jim-cooley jim-cooley commented Oct 19, 2021

Runs with Python3, just be sure to install the right PyObjC wrapper, and modify line 1 to point to your python3 installation if its not in the default location.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment