]> git.parisson.com Git - deefuzzer.git/commitdiff
* Got the stream working for a recursive and looped playlist
authorGuillaume Pellerin <yomguy@parisson.com>
Fri, 7 Sep 2007 16:18:22 +0000 (16:18 +0000)
committerGuillaume Pellerin <yomguy@parisson.com>
Fri, 7 Sep 2007 16:18:22 +0000 (16:18 +0000)
* Created Main()
* Begun README

AUTHORS
README
d-fuzz.py
myfuzz.xml
xmltodict2.py

diff --git a/AUTHORS b/AUTHORS
index a3c9349eb3d8bd7b70d50baf2a70fb5b65caec98..76499bdc3943d632f2f01578e592255564ba1d15 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -1,10 +1 @@
-# -*- coding: utf-8 -*-
-#
-# Copyright (c) 2007-2007 Guillaume Pellerin <pellerin@parisson.com>
-# All rights reserved.
-#
-# This software is licensed as described in the file COPYING, which
-# you should have received as part of this distribution. The terms
-# are also available at http://svn.parisson.org/d-fuzz/DFuzzLicense.
-#
-# Author: Guillaume Pellerin <pellerin@parisson.com>
\ No newline at end of file
+Guillaume Pellerin <pellerin@parisson.com>
\ No newline at end of file
diff --git a/README b/README
index a3c9349eb3d8bd7b70d50baf2a70fb5b65caec98..5efba7ccb5fc71e9973805b4e0b77349f4060008 100644 (file)
--- a/README
+++ b/README
@@ -1,10 +1,56 @@
-# -*- coding: utf-8 -*-
-#
-# Copyright (c) 2007-2007 Guillaume Pellerin <pellerin@parisson.com>
-# All rights reserved.
-#
-# This software is licensed as described in the file COPYING, which
-# you should have received as part of this distribution. The terms
-# are also available at http://svn.parisson.org/d-fuzz/DFuzzLicense.
-#
-# Author: Guillaume Pellerin <pellerin@parisson.com>
\ No newline at end of file
+# README
+# ======
+
+d-fuzz : a lightweight icecast streaming client written in python
+
+
+# 1. Introduction
+# ===============
+
+D-Fuzz is a light python program that streams media data from disks to icecast2 with some metadata. It supports MP3, OGG, SPEEX and THEORA media.
+
+It is neccessary to provide a config file which sets all needed parameters (see myfuzz.xml for example).
+
+
+# 2. Installation
+# ===============
+
+see INSTALL
+
+
+# 3. License
+# ===============
+
+ This software is licensed as described in the file COPYING, which
+ you should have received as part of this distribution. The terms
+ are also available at http://svn.parisson.org/d-fuzz/DFuzzLicense
+
+
+# 4. Usage
+# =========
+
+Usage : d-fuzz $1
+  
+  where $1 is the path for a XML config file
+  ex: d-fuzz ./myfuzz.xml
+
+Note that you must edit the config file with right parameter before executing...
+
+# 5. Author
+# =========
+
+see AUTHORS
+
+
+# 6. Aknowledgements
+# ==================
+
+This work is inspired by the great - C - Oddsock's streaming program : Ezstream.
+Since I needed to patch it in order to modify the playlist (randomize for example) and make external batch tools to create multiple channels, I decided to rewrite it from scratch in python. Some parts of this work are also taken from another Parisson's project : Telemeta (see http://svn.parisson.org/telemeta).
+
+
+# 7. Contact / Infos
+# ==================
+
+see http://parisson.com/d-fuzz/ for more details
index 397395df96114512b9b3c25059ef6a2d2f4e7c55..ddaafebf769cbc9fcf24b175414b83e626982270 100755 (executable)
--- a/d-fuzz.py
+++ b/d-fuzz.py
@@ -14,61 +14,73 @@ import os
 import sys
 import shout
 import string
+import subprocess
 from tools import *
 from xmltodict import xmltodict
 from mutagen.oggvorbis import OggVorbis
 
 
+class ExportProcessError:
+
+    def __init__(self, message, command, subprocess):
+        self.message = message
+        self.command = str(command)
+        self.subprocess = subprocess
+
+    def __str__(self):
+        if self.subprocess.stderr != None:
+            error = self.subprocess.stderr.read()
+        else:
+            error = ''
+        return "%s ; command: %s; error: %s" % (self.message,
+                                                self.command,
+                                                error)
+
 class DFuzz:
-    """A d-fuzz station"""
+    """A D-Fuzz station"""
     
     def __init__(self):
         
         self.work_dir = os.environ['HOME']+'.d-fuzz'
         self.conf = []
-        self.id = 0
+        self.id = 999999
         self.buffer_size = 0xFFFF
         
-        
     def prog_info(self):
         return """
-        d-fuzz : easy and light streaming tool
-
-        Copyright (c) 2007-2007 Guillaume Pellerin <pellerin@parisson.com>
-        All rights reserved.
-        
-        This software is licensed as described in the file COPYING, which
-        you should have received as part of this distribution. The terms
-        are also available at http://svn.parisson.org/d-fuzz/DFuzzLicense.2
-        
-        depends : ezstream (patched), icecast2, python,
-        
-        Usage : d-fuzz $1
-            where $1 is the path for a config file
-            ex: d-fuzz /etc/d-fuzz/myfuzz.conf
-
-        see http://parisson.com/d-fuzz/ for more details
+ d-fuzz : easy and light streaming tool
+
+ Copyright (c) 2007-2007 Guillaume Pellerin <pellerin@parisson.com>
+ All rights reserved.
+        
+ This software is licensed as described in the file COPYING, which
+ you should have received as part of this distribution. The terms
+ are also available at http://svn.parisson.org/d-fuzz/DFuzzLicense
+        
+ depends : python, python-xml, shout-python, libshout3, icecast2
+ recommends : python-mutagen
+ provides : shout-python
+       
+ Usage : d-fuzz $1
+  where $1 is the path for a XML config file
+  ex: d-fuzz /etc/d-fuzz/myfuzz.xml
+ see http://parisson.com/d-fuzz/ for more details
         """
 
     def get_conf_dict(self):
         confile = open(self.conf_file,'r')
-        conf_xml = confile.readlines()
-        self.conf = xmltodict(conf_xml)
+        conf_xml = confile.read()
+        self.conf = xmltodict(conf_xml,'utf-8')
         confile.close()
 
     def get_station_names(self):
         return self.conf['station']['name']
         
-        
-
     def check_work_dir(self):
         if not os.isdir.exists(self.work_dir):
             os.mkdir(self.work_dir)
-    
-    def get_playlist_length(self):
-        pass
         
-
     def get_playlist(self):
         file_list = []
         for root, dirs, files in os.walk(self.media_dir):
@@ -76,16 +88,24 @@ class DFuzz:
                 file_list.append(root + os.sep + file)
         return file_list
 
-    def get_next_media(self):
-        playlist = self.get_playlist()
+    def get_next_media(self, playlist):
         lp = len(playlist)
-        if self.id > lp:
+        if self.id >= (lp - 1) :
             self.id = 0
         else:
             self.id = self.id + 1
-        yield playlist[self.id]
-    
+        #print self.id
+        return playlist[self.id]
     
+    def get_random_media(self, playlist):
+        lp = len(playlist)
+        if self.id > lp:
+            self.id = 0
+        else:
+            rand = randrange(0,lp)
+            self.id = self.id + 1
+        print self.id
+        return playlist[self.id]
 
     def core_process(self, command, buffer_size):
         """Apply command and stream data through a generator. 
@@ -102,15 +122,15 @@ class DFuzz:
                     stdout = subprocess.PIPE,
                     close_fds = True)
         except:
-            raise ExportProcessError('Command failure:', command, proc)
-            
-
+            raise IOError('Command failure:', command, proc)
+            #pass
+        
         # Core processing
         while True:
             __chunk = proc.stdout.read(buffer_size)
             status = proc.poll()
-            if status != None and status != 0:
-                raise ExportProcessError('Command failure:', command, proc)
+            #if status != None and status != 0:
+                #raise ExportProcessError('Command failure:', command, proc)
             if len(__chunk) == 0:
                 break
             yield __chunk
@@ -121,62 +141,82 @@ class DFuzz:
     def stream(self, conf_file): 
         self.conf_file = conf_file
         self.get_conf_dict()
-#       for station in conf_dict['station']:
-        chi = 0
+
+        #for station in conf_dict['station']:
+        
         station = self.conf['station']
+        print station
         
         s = shout.Shout()
         print "Using libshout version %s" % shout.version()
-        
-        self.media_dir = station['media']['media_dir'][chi]
-        
-        s.host = station['server']['host'][chi]
-        s.port = station['server']['port'][chi]
+
+        # Media
+        self.media_dir = station['media']['dir']
+        format = station['media']['format']
+        s.format = format
+
+        # Server
+        s.protocol = 'http'     # | 'xaudiocast' | 'icy'
+        s.host = station['server']['host']
+        s.port = int(station['server']['port'])
         s.user = 'source'
-        s.password = station['server']['sourcepassword'][chi]
-        s.mount = station['server']['mountpoint'][chi]
-        s.format = station['media']['format'][chi]
-        s.protocol = 'http'
-        # | 'xaudiocast' | 'icy'
+        s.password = station['server']['sourcepassword']
+        s.mount = '/' + station['infos']['short_name'] + '.' + format
+        s.public = int(station['server']['public'])
+
+        # Infos
         s.name = station['infos']['name']
         s.genre = station['infos']['genre']
-        # s.url = ''
-        # s.public = 0 | 1
+        s.description = station['infos']['description']
+        s.url = station['infos']['url']
+        
         # s.audio_info = { 'key': 'val', ... }
         #  (keys are shout.SHOUT_AI_BITRATE, shout.SHOUT_AI_SAMPLERATE,
         #   shout.SHOUT_AI_CHANNELS, shout.SHOUT_AI_QUALITY)
         
-        
-
         s.open()
 
-        total = 0
-        st = time.time()
+        #total = 0
+        #st = time.time()
         command = 'cat '
-        
-        for media in self.get_next_media():
-            print "opening file %s" % media
-            command = 'cat '+media_dir
-            stream = self.core_process(command, self.buffer_size)
-            #s.set_metadata({'song': fa})
+
+        while True:
+            playlist = self.get_playlist()
+            print 'Playlist :'
+            print playlist
             
+            lp = len(playlist)
+            if lp == 0:
+                break
+
+            media = self.get_next_media(playlist)
+            print 'opening file : %s' % media
+            file_name = string.replace(media, self.media_dir + os.sep, '')
+            print 'streaming file : %s' % file_name
+            s.set_metadata({'song': file_name})
+            command = 'cat "%s"' % media
+            stream = self.core_process(command, self.buffer_size)
+       
             for chunk in stream:
-                total = total + len(self.buffer_size)
+                #total = total + len(self.buffer_size)
                 s.send(chunk)
                 s.sync()
                         
-            et = time.time()
-            br = total*0.008/(et-st)
-            print "Sent %d bytes in %d seconds (%f kbps)" % (total, et-st, br)
+            #et = time.time()
+            #br = total*0.008/(et-st)
+            #print "Sent %d bytes in %d seconds (%f kbps)" % (total, et-st, br)
 
         print s.close()
         
-        
 
-if len(sys.argv) == 2:
+def main():    
     station = DFuzz()
-    station.stream(sys.argv[1])
-else:
-    sys.exit('No way :(')
-
+    if len(sys.argv) == 2:
+        station.stream(sys.argv[1])
+    else:
+        text = station.prog_info()
+        sys.exit(text)
+
+if __name__ == '__main__':
+    main()
 
index f15936972a2eb35e48200de9d49a2b7fc7b99699..597b54f059a3cd29b67cf8fe6dad56a0e47ad937 100644 (file)
@@ -5,7 +5,7 @@
 <station>
     <infos>
         <!-- The short name of your station -->
-        <short_name>Cellar Playlist</short_name>
+        <short_name>Cellar_Playlist</short_name>
         <!-- The title of your station -->
         <name>Cellar @ D-Fuzz, Paris (100% Mix Techno, House and Groove !)</name>
         <!-- The title of your station -->
@@ -14,7 +14,7 @@
         <url_info>http://cellar.parisson.com</url_info>
         <genre>Techno/House</genre>
         <!-- The number of channels for your station -->
-        <channels>2</channel>
+        <channels>2</channels>
     </infos>
     <server>
         <!-- Icecast2 server -->
index 82993612ca557f33f84bf2805781718b0959e640..f630d07ef76dfe077ad171374f581418b255da25 100644 (file)
@@ -10,18 +10,18 @@ import locale
 from xml.parsers import expat
 
 # If we're in Dabo, get the default encoding.
-import dabo
-import dabo.lib.DesignerUtils as desUtil
-from dabo.dLocalize import _
-from dabo.lib.utils import resolvePath
-app = dabo.dAppRef
-if app is not None:
-       default_encoding = app.Encoding
-else:
-               enc = locale.getlocale()[1]
-               if enc is None:
-                       enc = dabo.defaultEncoding
-               default_encoding = enc
+#import dabo
+#import dabo.lib.DesignerUtils as desUtil
+#from dabo.dLocalize import _
+#from dabo.lib.utils import resolvePath
+#app = dabo.dAppRef
+#if app is not None:
+       #default_encoding = app.Encoding
+#else:
+               #enc = locale.getlocale()[1]
+               #if enc is None:
+                       #enc = dabo.defaultEncoding
+               #default_encoding = enc
                
 # Python seems to need to compile code with \n linesep:
 code_linesep = "\n"
@@ -386,12 +386,12 @@ def addInheritedInfo(src, super, updateCode=False):
 
 
 
-if __name__ == "__main__":
-       test_dict = {"name": "test", "attributes":{"path": "c:\\temp\\name",
-                       "problemChars": "Welcome to <Jos\xc3\xa9's \ Stuff!>\xc2\xae".decode("latin-1")}}
-       print "test_dict:", test_dict
-       xml = dicttoxml(test_dict)
-       print "xml:", xml
-       test_dict2 = xmltodict(xml)
-       print "test_dict2:", test_dict2
-       print "same?:", test_dict == test_dict2
+#if __name__ == "__main__":
+       #test_dict = {"name": "test", "attributes":{"path": "c:\\temp\\name",
+                       #"problemChars": "Welcome to <Jos\xc3\xa9's \ Stuff!>\xc2\xae".decode("latin-1")}}
+       #print "test_dict:", test_dict
+       #xml = dicttoxml(test_dict)
+       #print "xml:", xml
+       #test_dict2 = xmltodict(xml)
+       #print "test_dict2:", test_dict2
+       #print "same?:", test_dict == test_dict2