Capture Notifications From Another App?

Hi all,

I’m running the Shazam app for Mac to identify music. Every time Shazam id’s a song, it raises a notification to the notification center. Is there a way for a xojo app to capture this notification so it can build a self-updating list of songs that played?

Thanks!

I would try listening to the NotificationCenter of the NSWorkspace of your app. If you install a general observer first you should be able to find out the selector of the Shazam notifications and install your custom handlers only for them.
This would include using declares or plug-ins.

I don’t think you can read Notifications from other Apps using NSWorkspace.

You’re right. It is NSDistributedNotificationCenter . Any hints, Christian? :wink:

But this is for Distributed Notifications only. It’s a way to realize insecure Interprocess Communication. Not for Notification Center Notifications which could be read by other Apps, AFAIK. But i may be wrong here. :slight_smile:

http://echoprint.me/

here:
http://monkeybreadsoftware.net/class-nsdistributednotificationcentermbs.shtml

Also, doesn’t Shazam save all the songs you tag?

I believe those notifications, the type that pop up on screen, are sent through NSUserNotificationCenter and I don’t see anything in there to register an observer :frowning: But maybe I’m wrong.

There’s no way to capture those notifications… in a sandboxed app. This post suggests a hack by peeking in the sqlite database located at ~/Library/Application Support/NotificationCenter/.db.

If you don’t mind hacking I see Shazam storing it’s data in ~/Library/GroupContainers/#.group.com.shazam/com.shazam.mac.Shazam, and opening the file ShazamDataModel.sqlite-wal in a text editor finds the names of the songs I tested it with.

Also you could write to Shazam asking for better export and access options, like an API of some sort, apple-scriptable, or sending distributed notifications (I checked and it doesn’t).

I haven’t been able to connect as a database but here’s a crude locating and text parsing of it.

[code]Sub Action()
dim f As FolderItem = findShazamDBFile
dim src As String = TextInputStream.Open(f).ReadAll

dim tracks() As String = extractNames(src, “TRACK_NAME=”, “;”)
dim artists() As String = extractNames(src, “ARTIST_NAME=”, “;”)

dim last As integer = Min(tracks.Ubound, artists.Ubound)
for i As integer = 0 to last
TextArea1.AppendText Str(i) + ") " + tracks(i) + ", " + artists(i) + EndOfLine
next

End Sub

Function findShazamDBFile() As FolderItem
dim f1, f2, f3, f4, f5 As FolderItem

f1 = SpecialFolder.UserLibrary
f2 = f1.Child(“Group Containers”)

for i As integer = 1 to f2.Count
if f2.Item(i).Name.Right(16) = “group.com.shazam” then
f3 = f2.Item(i)
exit for i
end
next

f4 = f3.Child(“com.shazam.mac.Shazam”)
f5 = f4.Child(“ShazamDataModel.sqlite-wal”)

return f5

End Function

Function extractNames(src As String, headTag As String, tailTag As String) As String()
dim sa1(), sa2(), names() As String

sa1 = src.Split(headTag)
for i As integer = 1 to sa1.Ubound
sa2 = sa1(i).Split(tailTag)
if sa2.Ubound >= 0 then names.Append( sa2(0).ReplaceAll("+", " ") )
next

return names

End Function[/code]

Wow, thank you everyone, and especially Will!

I have been playing around with the parsing of the sqlite-wal file for a couple of days now too, but the only problem is that the songs are not necessarily stored sequentially. Finding the most recently played song doesn’t seem to be possible using this method.

If anyone sees any way to get that information out of the binary data, please let me know.

The program here: https://github.com/stephanebruckert/ShazamScrobbler , is able to connect to the Shazam sqlite database and sort it by date. I don’t have a clue how to do this in Xojo. Is this something I might be able to hire someone to knock out quickly? Where does someone go to hire a freelance xojo dev?

Thanks again!

A sandboxed app will not be able to access another app database. So if the app is to go to the MAS, that is out of question.

How is the GitHub code accessing it then? It connects to the Shazam database, finds the latest songs tagged and submits them to last.fm.

I don’t need this app to be public, this is for one specific computer in my college’s radio station studio.

Because the app is not sandboxed.

If the app is not public, you do not need to sandbox it.

ShazamScrobbler simply locates on the disk the container in which the SQL file resides :

NSString* const PATH = @"~/Library/Group Containers/4GWDBCF5A4.group.com.shazam/com.shazam.mac.Shazam/";

Should not be out of this world to do the same in Xojo.

Specialfolder.UserLibrary.child("Group Containers").child("4GWDBCF5A4.group.com.shazam").child("com.shazam.mac.Shazam").child("ShazamDataModel.sqlite")

I just verified this is indeed the location of the Shazam database. Now it should not be very difficult to open that for reading with SQLite in Xojo.

Thank you all very much. I’ve got it figured out and am reading the database directly. Works perfectly!