+d-fuzz (0.3.3-1) unstable; urgency=low
+
+ * add twitter api
+ * cleanup RSS and song metadata
+
+ -- momo <momo@wm16.parisson.org> Tue, 27 Oct 2009 13:44:06 +0100
+
d-fuzz (0.3.0-1) unstable; urgency=low
* new and much upgraded DeeFuzz
Package: deefuzz
Architecture: any
-Depends: ${shlibs:Depends}, ${misc:Depends}, icecast2, python-xml, python-shout, libshout3, python-mutagen
+Depends: ${shlibs:Depends}, ${misc:Depends}, icecast2, python-xml, python-shout, libshout3, python-mutagen, python-twitter
Description: easy and light media streaming tool
DeeFuzz Tools are new light and easy tools to stream audio and video over internet. It is dedicated to people who wants to create playlisted webradios or webTVs with rich media contents. Here are the main features of the DeeFuzz Tools:
* MP3 and OGG (audio & video) file streaming over internet
# abiding by the rules of distribution of free software. You can use,
# modify and/ or redistribute the software under the terms of the CeCILL
# license as circulated by CEA, CNRS and INRIA at the following URL
-# "http://www.cecill.info".
+# "http://www.cecill.info".
# As a counterpart to the access to the source code and rights to copy,
# modify and redistribute granted by the license, users are provided only
# with a limited warranty and the software's author, the holder of the
# economic rights, and the successive licensors have only limited
-# liability.
+# liability.
# In this respect, the user's attention is drawn to the risks associated
# with loading, using, modifying and/or developing or reproducing the
# therefore means that it is reserved for developers and experienced
# professionals having in-depth computer knowledge. Users are therefore
# encouraged to load and test the software's suitability as regards their
-# requirements in conditions enabling the security of their systems and/or
+# requirements in conditions enabling the security of their systems and/or
# data to be ensured and, more generally, to use and operate it in the
# same conditions as regards security.
from threading import Thread
from tools import *
-version = '0.3.2'
+version = '0.3.3'
year = datetime.datetime.now().strftime("%Y")
platform_system = platform.system()
Usage : deefuzzer $1
where $1 is the path for a XML config file
ex: deefuzzer example/myfuzz.xml
-
+
see http://svn.parisson.org/deefuzzer/ for more details
"""
# Create M3U playlist
self.logger.write('Writing M3U file to : ' + self.m3u)
-
+
def get_conf_dict(self):
confile = open(self.conf_file,'r')
conf_xml = confile.read()
self.set_m3u_playlist()
- # Create a Producer
+ # Create a Producer
p = Producer(q)
p.start()
-
+
# Start the Stations
for i in range(0,self.nb_stations):
self.stations[i].start()
def run(self):
i=0
q = self.q
- while 1:
+ while 1:
q.put(i,1)
i+=1
# Logging
self.logger.write('Opening ' + self.short_name + ' - ' + self.channel.name + \
' (' + str(self.lp) + ' tracks)...')
-
+
self.metadata_relative_dir = 'metadata'
self.metadata_url = self.channel.url + '/rss/' + self.metadata_relative_dir
self.metadata_dir = self.rss_dir + os.sep + self.metadata_relative_dir
if self.twitter_mode == '1':
self.twitter = Twitter(self.twitter_user, self.twitter_pass)
self.tinyurl = tinyurl.create_one(self.channel.url + '/m3u/' + self.m3u.split(os.sep)[-1])
-
+
def update_twitter(self):
if self.twitter_mode == '1':
message = 'Now deefuzzing: ' + self.song + ' #' + self.artist.replace(' ', '') + ' #m3u : '
self.twitter.post(message[:114] + self.tinyurl)
-
+
def update_rss(self, media_list, rss_file, sub_title):
rss_item_list = []
if not os.path.exists(self.rss_dir):
_date_now = datetime.datetime.now()
date_now = str(_date_now)
media_absolute_playtime = _date_now
-
+
for media in media_list:
media_stats = os.stat(media.media)
media_date = time.localtime(media_stats[8])
media.metadata['Duration'] = str(media.length).split('.')[0]
media.metadata['Bitrate'] = str(media.bitrate) + ' kbps'
media.metadata['Next play'] = str(media_absolute_playtime).split('.')[0]
-
+
media_description = '<table>'
media_description_item = '<tr><td>%s: </td><td><b>%s</b></td></tr>'
for key in media.metadata.keys():
song = str(media.file_title)
else:
song = artist + ' : ' + title
-
+
media_absolute_playtime += media.length
-
+
if self.rss_enclosure == '1':
media_link = self.channel.url + '/media/' + media.file_name
media_link = media_link.decode('utf-8')
self.logger.write('DeeFuzzing this file on %s : id = %s, name = %s' \
% (self.short_name, self.id, self.current_media_obj[0].file_name))
self.update_twitter()
-
+
stream = self.core_process_read(media)
q.task_done()
class Twitter:
"""Post a message to Twitter"""
-
+
def __init__(self, username, password):
#Thread.__init__(self)
self.username = username
self.password = password
self.api = twitter.Api(username=self.username, password=self.password)
-
+
def set_message(self, message):
self.message = message
<description>My personal best funky playlist ever !</description>
<url>http://mydomain.com</url>
<genre>Other</genre>
- <channels>1</channels>
</infos>
<server>
<host>localhost</host>
<description>My personal best groovy playlist ever !</description>
<url>http://mydomain.com</url>
<genre>Other</genre>
- <channels>1</channels>
</infos>
<server>
<host>localhost</host>
#if enc is None:
#enc = dabo.defaultEncoding
#default_encoding = enc
-
+
# Python seems to need to compile code with \n linesep:
code_linesep = "\n"
eol = os.linesep
self._propDict = None
self._currPropAtt = ""
self._currPropDict = None
-
+
def StartElement(self, name, attributes):
"""SAX start element even handler"""
if attributes.has_key(att):
del attributes[att]
element["attributes"] = attributes
-
+
# Push element onto the stack and make it a child of parent
if len(self.nodeStack) > 0:
parent = self.nodeStack[-1]
if not element.has_key("cdata"):
element["cdata"] = ""
element["cdata"] += data
-
+
def Parse(self, xml):
# Create a SAX parser
slsh = "\\"
# val = val.replace(slsh, slsh+slsh)
if not noEscape:
- # First escape internal ampersands. We need to double them up due to a
+ # First escape internal ampersands. We need to double them up due to a
# quirk in wxPython and the way it displays this character.
val = val.replace("&", "&&")
# Escape any internal quotes
att += " %s=%s" % (key, val)
ret += "%s<%s%s" % ("\t" * level, dct["name"], att)
- if (not dct.has_key("cdata") and not dct.has_key("children")
+ if (not dct.has_key("cdata") and not dct.has_key("children")
and not dct.has_key("code") and not dct.has_key("properties")):
ret += " />%s" % eol
else:
cd += eol
ret += "%s<%s><![CDATA[%s%s]]>%s%s</%s>%s" % (methodTab,
- mthd, eol, cd, eol,
+ mthd, eol, cd, eol,
methodTab, mthd, eol)
ret += "%s</code>%s" % ("\t" * (level+1), eol)
ret += "%s<%s>%s" % (currTab, prop, eol)
for propItm, itmVal in val.items():
itmTab = "\t" * (level+3)
- ret += "%s<%s>%s</%s>%s" % (itmTab, propItm, itmVal,
+ ret += "%s<%s>%s</%s>%s" % (itmTab, propItm, itmVal,
propItm, eol)
ret += "%s</%s>%s" % (currTab, prop, eol)
ret += "%s</properties>%s" % ("\t" * (level+1), eol)
-
+
if dct.has_key("children") and len(dct["children"]) > 0:
ret += eol
for child in dct["children"]:
def flattenClassDict(cd, retDict=None):
"""Given a dict containing a series of nested objects such as would
be created by restoring from a cdxml file, returns a dict with all classIDs
- as keys, and a dict as the corresponding value. The dict value will have
+ as keys, and a dict as the corresponding value. The dict value will have
keys for the attributes and/or code, depending on what was in the original
dict. The end result is to take a nested dict structure and return a flattened
dict with all objects at the top level.
classCode = classCD.get("code", {})
classKids = classCD.get("children", [])
currDict = retDict.get(classID, {})
- retDict[classID] = {"attributes": classAtts, "code": classCode,
+ retDict[classID] = {"attributes": classAtts, "code": classCode,
"properties": classProps}
retDict[classID].update(currDict)
# Now update the child objects in the dict
else:
# Not a file; most likely just a component in another class
currDict = retDict.get(classID, {})
- retDict[classID] = {"attributes": atts, "code": code,
+ retDict[classID] = {"attributes": atts, "code": code,
"properties": props}
retDict[classID].update(currDict)
if kids:
def addInheritedInfo(src, super, updateCode=False):
- """Called recursively on the class container structure, modifying
- the attributes to incorporate superclass information. When the
- 'updateCode' parameter is True, superclass code is added to the
+ """Called recursively on the class container structure, modifying
+ the attributes to incorporate superclass information. When the
+ 'updateCode' parameter is True, superclass code is added to the
object's code
"""
atts = src.get("attributes", {})