Merge lp:~pietergunnink/zeitgeist-datasources/mpd into lp:zeitgeist-datasources/0.8

Proposed by pgun
Status: Needs review
Proposed branch: lp:~pietergunnink/zeitgeist-datasources/mpd
Merge into: lp:zeitgeist-datasources/0.8
Diff against target: 225 lines (+221/-0)
1 file modified
zeitgeist-mpd (+221/-0)
To merge this branch: bzr merge lp:~pietergunnink/zeitgeist-datasources/mpd
Reviewer Review Type Date Requested Status
Zeitgeist Data-Sources Team Pending
Review via email: mp+61901@code.launchpad.net

Description of the change

This one has a license in the header + copyright. I had to remove the other because I messed something up and I couldn't push anything anymore.

To post a comment you must log in.

Unmerged revisions

1. By pgun

Initial import

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'zeitgeist-mpd'
2--- zeitgeist-mpd 1970-01-01 00:00:00 +0000
3+++ zeitgeist-mpd 2011-05-22 18:08:25 +0000
4@@ -0,0 +1,221 @@
5+#!/usr/bin/env python
6+# -*- coding: utf-8 -*-
7+# Copyright Pieter Gunnink pietergunnink@gmail.com <2011>
8+# GNU General Public Licence (GPL)
9+#
10+# This program is free software; you can redistribute it and/or modify it under
11+# the terms of the GNU General Public License as published by the Free Software
12+# Foundation; either version 2 of the License, or (at your option) any later
13+# version.
14+# This program is distributed in the hope that it will be useful, but WITHOUT
15+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
17+# details.
18+# You should have received a copy of the GNU General Public License along with
19+# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
20+# Place, Suite 330, Boston, MA 02111-1307 USA
21+#
22+import sys
23+
24+from mpd import (MPDClient, CommandError)
25+from socket import error as SocketError
26+
27+from zeitgeist.client import ZeitgeistClient
28+from zeitgeist.datamodel import Event, Subject, Interpretation, Manifestation
29+import argparse
30+import time
31+import threading
32+import re
33+class MpdPlugin:
34+
35+
36+
37+
38+
39+ def __init__(self):
40+ self.set_timer = 5
41+ self.mpd_host = "localhost"
42+ self.mpd_port = "6600"
43+ self.mpd_pass = False #should be false or password
44+ self.mpd_dir = "/home/pieter/Muziek/" #the directory where your MPD music is stored
45+ self.zeit_actor = "application://gmpc.desktop" #the one zeitgeist logs as player of the music !important
46+ self.previous = False
47+
48+ self.connect_mpd()
49+ self.connect_zeit()
50+
51+
52+ self.loc_prefix()
53+ parser = argparse.ArgumentParser(description='Zeitgeist caller for MPD')
54+ parser.add_argument('title', metavar='T', nargs='?', help='the title of the song, as called by MPD')
55+ args = parser.parse_args()
56+ if self.title_call(args.title) == False:
57+ t = threading.Timer(self.set_timer, self.make_call)
58+ t.start()
59+
60+
61+
62+
63+
64+ ### CONNECTIIONS ###
65+ # #
66+ def connect_zeit(self):
67+ ### CONNECT ZEITGEIST
68+ try:
69+ zeit = ZeitgeistClient()
70+ except RuntimeError, e:
71+ print "Unable to connect to Zeitgeist, won't send events. Reason: '%s'" %e
72+ zeit = None
73+ exit(1)
74+
75+
76+ if zeit.get_version() >= [0, 3, 2, 999]:
77+ zeit.register_data_source(
78+ "mpd_datasource",
79+ "MPD",
80+ "Logs music-playback related events from MPD",
81+ [Event.new_for_values(actor = self.zeit_actor)]
82+ )
83+ self.zeit = zeit
84+
85+ def connect_mpd(self):
86+ ### CONNECT TO MPD
87+ ## SETTINGS
88+
89+ client = MPDClient()
90+
91+ try:
92+ client.connect(host=self.mpd_host, port=self.mpd_port)
93+ except SocketError:
94+ exit(1)
95+
96+
97+ if self.mpd_pass:
98+ try:
99+ client.password(self.mpd_pass)
100+ except CommandError:
101+ exit(1)
102+
103+ self.client = client
104+ # #
105+ ### END CONNECTION ###
106+
107+ def loc_prefix(self):
108+ file = open("/etc/mpd.conf")
109+ while True:
110+ line = file.readline()
111+ if not line:
112+ break
113+ p = re.compile('music_directory\s*\".*\"')
114+ m = p.search(line)
115+ if m:
116+ m_dir = re.search("\".*\"",m.group()).group()
117+ p = re.compile("\"")
118+ m_dir = p.sub("", m_dir)
119+ p = re.compile("/$")
120+ if not p.search(m_dir):
121+ m_dir = m_dir + "/"
122+ return m_dir
123+ break
124+
125+ ### CONTROLLER ###
126+ # #
127+ def make_call(self):
128+ ### IS CALLED THE SECOND TIME, SO THAT CONNECTIONS CAN BE CHECKED AND RESTORED
129+
130+ song = self.client.currentsong()
131+
132+ if song == self.previous:
133+ t = threading.Timer(self.set_timer, self.make_call) #to check and send trough every 3 secs
134+ t.start()
135+ else:
136+ if song:
137+ zeit_song = {
138+ "artist": song['artist'],
139+ "title": song['title'],
140+ "album": song['album'],
141+ "location": self.location_song(song["file"])
142+ }
143+ else:
144+ self.connect_mpd()
145+
146+ if self.zeit and zeit_song: #hoerah, we have a connection. Let's send sth
147+
148+ self.send_to_zeit(zeit_song)
149+ elif zeit_song: #there is mpd connection, but no zeit connection
150+ self.connect_zeit()
151+ self.send_to_zeit(zeit_song)
152+ elif self.zeit: #because there is no mpd connection, but there is a zeit connection
153+ self.connect_mpd()
154+ self.send_to_zeit()
155+ else:
156+ self.make_call() #because there is no connection at all :(
157+
158+ t = threading.Timer(self.set_timer, self.make_call) #to check and send trough every 3 secs
159+ t.start()
160+ # #
161+ ### END CONTROLLER ###
162+
163+ ### PROGRAM CALLS ###
164+ # #
165+ def title_call(self, title):
166+ ### CHECKS IF THERE IS A PARAMETER, IF SO THE CURRENT SONG IS NOT CALLED AND LOOP IS NOT STARTED
167+ if title is None:
168+ self.current_song()
169+ return False
170+ else:
171+ self.current_song(title) #means that slef.current_song() will look it up in the db
172+ return True
173+ # #
174+ ### END PROGRAM CALLS ###
175+
176+ ### GETTING SONG FROM MPD ###
177+ # #
178+ def location_song(self, place):
179+ ### RETURNS LOCATION OF SONG, SO ZEITGEIST CLIENTS VAN GET ID3 INFO FROM THERE
180+ location_prefix = self.loc_prefix()
181+ location = location_prefix + place
182+ return location
183+
184+ def current_song(self, title=False):
185+ ### GETS THE SONG FROM MPD AND PASSES IT TROUGH TO ZEITGEIST THROUGH ZEND_TO_ZEIT()
186+ if title == False:
187+ song = self.client.currentsong()
188+ else:
189+ song = self.client.find("title", title)
190+ if song == self.previous:
191+ t = threading.Timer(self.set_timer, self.make_call) #to check and send trough every 3 secs
192+ t.start()
193+ else:
194+ zeit_song = {
195+ "artist": song['artist'],
196+ "title": song['title'],
197+ "album": song['album'],
198+ "location": self.location_song(song["file"])
199+ }
200+ self.send_to_zeit(zeit_song)
201+ # #
202+ ### END GETTING SONG FROM MPD ###
203+
204+ ### SEND TO ZEITGEIST ###
205+ # #
206+ def send_to_zeit(self, song):
207+ ###SENDING SONG TO ZEITGEIST
208+ subject = Subject.new_for_values(
209+ uri=song["location"],
210+ interpretation=unicode(Interpretation.AUDIO),
211+ manifestation=unicode(Manifestation.FILE_DATA_OBJECT),
212+ text=" - ".join([song["title"], song["artist"], song["album"]])
213+ )
214+ event = Event.new_for_values(
215+ timestamp=int(time.time()*1000),
216+ interpretation=unicode(Interpretation.ACCESS_EVENT),
217+ manifestation=unicode(Manifestation.SCHEDULED_ACTIVITY),
218+ actor=self.zeit_actor,
219+ subjects=[subject,]
220+ )
221+ self.zeit.insert_event(event)
222+ # #
223+ ### END SEND TO ZEITGEIST ###
224+
225+x = MpdPlugin()

Subscribers

People subscribed via source and target branches