]> git.parisson.com Git - deefuzzer.git/commitdiff
cleanup, better exception handling, add partial WebM support, add a curl based stream...
authorGuillaume Pellerin <yomguy@parisson.com>
Mon, 31 Mar 2014 10:22:41 +0000 (12:22 +0200)
committerGuillaume Pellerin <yomguy@parisson.com>
Mon, 31 Mar 2014 10:22:41 +0000 (12:22 +0200)
deefuzzer/core.py
deefuzzer/station.py
deefuzzer/tools/__init__.py
deefuzzer/tools/ogg.py
deefuzzer/tools/streamer.py [new file with mode: 0644]
deefuzzer/tools/webm.py [new file with mode: 0644]

index 92251cf4a5459b2210b28f54a34b2ac94cdce732..6099c07a02f86fa19419dceb4f5357c0a07f951c 100644 (file)
@@ -48,6 +48,9 @@ from deefuzzer.tools import *
 class DeeFuzzer(Thread):
     """a DeeFuzzer diffuser"""
 
+    m3u = None
+    rss = None
+
     def __init__(self, conf_file):
         Thread.__init__(self)
         self.conf_file = conf_file
@@ -112,7 +115,9 @@ class DeeFuzzer(Thread):
                 station = self.conf['deefuzzer']['station'][i]
             self.stations.append(Station(station, q, self.logger, self.m3u))
 
-        self.set_m3u_playlist()
+        if self.m3u:
+            self.set_m3u_playlist()
+        
         p = Producer(q)
         p.start()
 
index 32ce0cc62b8db985b48be3bd5b877ef31267747a..bf866752a4dcaaa9e511b9e55bed1b512d5656ef 100644 (file)
@@ -53,6 +53,7 @@ from relay import *
 from streamer import *
 from tools import *
 
+
 class Station(Thread):
     """a DeeFuzzer shouting station thread"""
 
@@ -60,6 +61,16 @@ class Station(Thread):
     counter = 0
     delay = 0
     start_time = time.time()
+    server_ping = False    
+    playlist = []
+    lp = 1
+    player_mode = 0
+    osc_control_mode = 0
+    twitter_mode = 0
+    jingles_mode = 0
+    relay_mode = 0
+    record_mode = 0
+    run_mode = 1
 
     def __init__(self, station, q, logger, m3u):
         Thread.__init__(self)
@@ -67,7 +78,6 @@ class Station(Thread):
         self.q = q
         self.logger = logger
         self.m3u = m3u
-        self.server_ping = False
 
         # Media
         self.media_dir = self.station['media']['dir']
@@ -126,8 +136,10 @@ class Station(Thread):
         self.channel_url = self.server_url + self.channel.mount
 
         # RSS
-        self.rss_dir = self.station['rss']['dir']
-        self.rss_enclosure = self.station['rss']['enclosure']
+        if 'rss' in self.station:
+            self.rss_mode = int(self.station['rss']['mode'])
+            self.rss_dir = self.station['rss']['dir']
+            self.rss_enclosure = self.station['rss']['enclosure']
 
         if 'media_url' in self.station['rss']:
             self.rss_media_url = self.station['rss']['media_url']
@@ -140,10 +152,6 @@ class Station(Thread):
         self.rss_current_file = self.base_name + '_current.xml'
         self.rss_playlist_file = self.base_name + '_playlist.xml'
 
-        # Playlist
-        self.playlist = self.get_playlist()
-        self.lp = len(self.playlist)
-
         # Logging
         self.logger.write_info('Opening ' + self.short_name + ' - ' + self.channel.name + \
                 ' (' + str(self.lp) + ' tracks)...')
@@ -156,10 +164,8 @@ class Station(Thread):
 
         # The station's player
         self.player = Player(self.type)
-        self.player_mode = 0
 
-        # OSCing
-        self.osc_control_mode = 0
+        # OSCing    
         # mode = 0 means Off, mode = 1 means On
         if 'control' in self.station:
             self.osc_control_mode = int(self.station['control']['mode'])
@@ -177,8 +183,6 @@ class Station(Thread):
                 self.osc_controller.start()
 
         # Jingling between each media.
-        # mode = 0 means Off, mode = 1 means On
-        self.jingles_mode = 0
         if 'jingles' in self.station:
             self.jingles_mode =  int(self.station['jingles']['mode'])
             self.jingles_shuffle = self.station['jingles']['shuffle']
@@ -187,8 +191,6 @@ class Station(Thread):
                 self.jingles_callback('/jingles', [1])
 
         # Relaying
-        # mode = 0 means Off, mode = 1 means On
-        self.relay_mode = 0
         if 'relay' in self.station:
             self.relay_mode = int(self.station['relay']['mode'])
             self.relay_url = self.station['relay']['url']
@@ -197,8 +199,6 @@ class Station(Thread):
                 self.relay_callback('/media/relay', [1])
 
         # Twitting
-        # mode = 0 means Off, mode = 1 means On
-        self.twitter_mode = 0
         if 'twitter' in self.station:
             self.twitter_mode = int(self.station['twitter']['mode'])
             self.twitter_key = self.station['twitter']['key']
@@ -215,18 +215,12 @@ class Station(Thread):
                 self.twitter_callback('/twitter', [1])
 
         # Recording
-        # mode = 0 means Off, mode = 1 means On
-        self.record_mode = 0
         if 'record' in self.station:
             self.record_mode = int(self.station['record']['mode'])
             self.record_dir = self.station['record']['dir']
             if self.record_mode:
                 self.record_callback('/record', [1])
 
-        # Running
-        # mode = 0 means Off, mode = 1 means On
-        self.run_mode = 1
-
     def run_callback(self, path, value):
         value = value[0]
         self.run_mode = value
@@ -371,8 +365,12 @@ class Station(Thread):
                 if len(new_tracks):
                     new_tracks_objs = self.media_to_objs(self.new_tracks)
                     for media_obj in new_tracks_objs:
-                        title = media_obj.metadata['title']
-                        artist = media_obj.metadata['artist']
+                        title = ''
+                        artist = ''
+                        if media_obj.metadata.has_key('title'):
+                            title = media_obj.metadata['title']
+                        if media_obj.metadata.has_key('artist'):
+                            artist = media_obj.metadata['artist']
                         if not (title or artist):
                             song = str(media_obj.file_name)
                         else:
@@ -398,7 +396,8 @@ class Station(Thread):
 
                 self.logger.write_info('Station ' + self.channel_url + \
                                  ' : generating new playlist (' + str(self.lp) + ' tracks)')
-                self.update_rss(self.media_to_objs(self.playlist),
+                if self.rss_mode:
+                    self.update_rss(self.media_to_objs(self.playlist),
                                 self.rss_playlist_file, '(playlist)')
 
             if self.jingles_mode and not (self.counter % 2) and self.jingles_length:
@@ -417,16 +416,21 @@ class Station(Thread):
         media_objs = []
         for media in media_list:
             file_name, file_title, file_ext = get_file_info(media)
-            if file_ext.lower() == 'mp3' and mimetypes.guess_type(media)[0] == 'audio/mpeg':
+            if file_ext.lower() == 'mp3' or mimetypes.guess_type(media)[0] == 'audio/mpeg':
                 try:
                     media_objs.append(Mp3(media))
                 except:
                     continue
-            elif file_ext.lower() == 'ogg' and mimetypes.guess_type(media)[0] == 'audio/ogg':
+            elif file_ext.lower() == 'ogg' or mimetypes.guess_type(media)[0] == 'audio/ogg':
                 try:
                     media_objs.append(Ogg(media))
                 except:
                     continue
+            elif file_ext.lower() == 'webm' or mimetypes.guess_type(media)[0] == 'video/webm':
+                try:
+                    media_objs.append(WebM(media))
+                except:
+                    continue
         return media_objs
 
     def update_rss(self, media_list, rss_file, sub_title):
@@ -524,8 +528,13 @@ class Station(Thread):
     def set_read_mode(self):
         self.prefix = '#nowplaying'
         self.current_media_obj = self.media_to_objs([self.media])
-        self.title = self.current_media_obj[0].metadata['title']
-        self.artist = self.current_media_obj[0].metadata['artist']
+        try:
+            self.title = self.current_media_obj[0].metadata['title']
+            self.artist = self.current_media_obj[0].metadata['artist']
+        except:
+            self.title = 'title'
+            self.artist = 'artist'
+
         self.title = self.title.replace('_', ' ')
         self.artist = self.artist.replace('_', ' ')
 
@@ -537,15 +546,15 @@ class Station(Thread):
         self.song = song.encode('utf-8')
         self.artist = self.artist.encode('utf-8')
         self.metadata_file = self.metadata_dir + os.sep + self.current_media_obj[0].file_name + '.xml'
-        #self.update_rss(self.current_media_obj, self.metadata_file, '')
-        self.update_rss(self.current_media_obj, self.rss_current_file, '(currently playing)')
+        if self.rss_mode:
+            self.update_rss(self.current_media_obj, self.rss_current_file, '(currently playing)')
         self.logger.write_info('DeeFuzzing on %s :  id = %s, name = %s' \
             % (self.short_name, self.id, self.current_media_obj[0].file_name))
         self.player.set_media(self.media)
 
-        if self.player_mode == 0:
+        if self.player_mode:
             self.stream = self.player.file_read_slow()
-        elif self.player_mode == 1:
+        else:
             self.stream = self.player.file_read_fast()
 
     def set_webm_read_mode(self):
@@ -584,7 +593,6 @@ class Station(Thread):
                 self.q.task_done()
                 pass
 
-
     def run(self):
         self.q.get(1)
         self.ping_server()
index 03fd06deaad466a52d91cfc02d6b385abced9e0d..6dc964d9781e6cccac6654b14402eed67417d60b 100644 (file)
@@ -3,6 +3,7 @@ from xmltodict import *
 from PyRSS2Gen import *
 from mp3 import *
 from ogg import *
+from webm import *
 from logger import *
 from osc import *
 from twitt import *
index 6467715d655f6864e35502bf8c03f78a2122c1e9..9b3a85ff99d43cf233750b31a73faecd38903f02 100644 (file)
@@ -83,10 +83,10 @@ class Ogg:
         return 'ogg'
 
     def get_mime_type(self):
-        return 'application/ogg'
+        return 'audio/ogg'
 
     def get_description(self):
-        return 'FIXME'
+        return 'OGG Vorbis'
 
     def get_file_info(self):
         try:
diff --git a/deefuzzer/tools/streamer.py b/deefuzzer/tools/streamer.py
new file mode 100644 (file)
index 0000000..1d11091
--- /dev/null
@@ -0,0 +1,81 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2006-2011 Guillaume Pellerin
+
+# <yomguy@parisson.com>
+
+# This software is a computer program whose purpose is to stream audio
+# and video data through icecast2 servers.
+
+# This software is governed by the CeCILL license under French law and
+# 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".
+
+# 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.
+
+# In this respect, the user's attention is drawn to the risks associated
+# with loading, using,  modifying and/or developing or reproducing the
+# software by the user in light of its specific status of free software,
+# that may mean that it is complicated to manipulate, and that also
+# 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
+# data to be ensured and, more generally, to use and operate it in the
+# same conditions as regards security.
+
+# The fact that you are presently reading this means that you have had
+# knowledge of the CeCILL license and that you accept its terms.
+
+# Author: Guillaume Pellerin <yomguy@parisson.com>
+
+from threading import Thread
+
+class HTTPStreamer(Thread):
+
+    protocol = 'http'
+    host = str
+    port = str
+    mount = str
+    user = str
+    password = str
+    public = str
+    audio_info = dict
+    name = str
+    genre = str
+    decription = str
+    format = str
+    url = str
+    delay = 0
+
+    def __init__(self):
+        Thread.__init__(self)
+        import pycurl
+        self.curl = pycurl.Curl()
+
+    def set_callback(self, read_callback):
+        self.read_callback = read_callback
+
+    def delay(self):
+        return self.delay
+
+    def open(self):
+        import pycurl
+        self.uri = self.protocol + '://' + self.host + ':' + str(self.port) + \
+                        self.mount + '?' + 'password=' + self.password
+        self.curl.setopt(pycurl.URL, self.uri)
+        self.curl.setopt(pycurl.UPLOAD, 1)
+        self.curl.setopt(pycurl.READFUNCTION, self.read_callback)
+
+    def run(self):
+        self.curl.perform()
+
+    def close(self):
+        self.curl.close()
diff --git a/deefuzzer/tools/webm.py b/deefuzzer/tools/webm.py
new file mode 100644 (file)
index 0000000..389149d
--- /dev/null
@@ -0,0 +1,56 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+#
+# Copyright Guillaume Pellerin (2006-2009)
+
+# <yomguy@parisson.com>
+
+# This software is a computer program whose purpose is to stream audio
+# and video data through icecast2 servers.
+
+# This software is governed by the CeCILL  license under French law and
+# 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".
+
+# 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.
+
+# In this respect, the user's attention is drawn to the risks associated
+# with loading,  using,  modifying and/or developing or reproducing the
+# software by the user in light of its specific status of free software,
+# that may mean  that it is complicated to manipulate,  and  that  also
+# 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
+# data to be ensured and,  more generally, to use and operate it in the
+# same conditions as regards security.
+
+# The fact that you are presently reading this means that you have had
+# knowledge of the CeCILL license and that you accept its terms.
+
+# Author: Guillaume Pellerin <yomguy@parisson.com>
+
+import os
+import string
+import datetime
+from utils import *
+
+
+class WebM(object):
+    """An WebM file object"""
+
+    def __init__(self, media):
+        self.media = media
+        self.item_id = ''
+        self.source = self.media
+        self.mime_type = 'video/webm'
+        self.extension = 'webm'
+        self.description = 'WebM'
+        self.metadata = {}
+        self.file_name, self.file_title, self.file_ext = get_file_info(media)