]> git.parisson.com Git - deefuzzer.git/commitdiff
reorder objects, add yaml example, add m3u playlist support
authorGuillaume Pellerin <yomguy@parisson.com>
Fri, 18 Oct 2013 20:54:59 +0000 (22:54 +0200)
committerGuillaume Pellerin <yomguy@parisson.com>
Fri, 18 Oct 2013 20:54:59 +0000 (22:54 +0200)
39 files changed:
deefuzzer/core.py [changed mode: 0755->0644]
deefuzzer/player.py [new file with mode: 0644]
deefuzzer/recorder.py [new file with mode: 0644]
deefuzzer/relay.py [new file with mode: 0644]
deefuzzer/scripts/osc_jingles_start.py [deleted file]
deefuzzer/scripts/osc_jingles_stop.py [deleted file]
deefuzzer/scripts/osc_player_fast.py [deleted file]
deefuzzer/scripts/osc_player_next.py [deleted file]
deefuzzer/scripts/osc_player_slow.py [deleted file]
deefuzzer/scripts/osc_record_start.py [deleted file]
deefuzzer/scripts/osc_record_stop.py [deleted file]
deefuzzer/scripts/osc_relay_start.py [deleted file]
deefuzzer/scripts/osc_relay_stop.py [deleted file]
deefuzzer/scripts/osc_twitter_start.py [deleted file]
deefuzzer/scripts/osc_twitter_stop.py [deleted file]
deefuzzer/station.py
deefuzzer/streamer.py [new file with mode: 0644]
deefuzzer/tools/__init__.py
deefuzzer/tools/logger.py
deefuzzer/tools/player.py [deleted file]
deefuzzer/tools/recorder.py [deleted file]
deefuzzer/tools/relay.py [deleted file]
deefuzzer/tools/streamer.py [deleted file]
deefuzzer/tools/tools.py [deleted file]
deefuzzer/tools/utils.py [new file with mode: 0644]
example/deefuzzer.xml
example/deefuzzer.yaml [new file with mode: 0644]
example/deefuzzer_doc.xml
scripts/osc/osc_jingles_start.py [new file with mode: 0644]
scripts/osc/osc_jingles_stop.py [new file with mode: 0644]
scripts/osc/osc_player_fast.py [new file with mode: 0644]
scripts/osc/osc_player_next.py [new file with mode: 0644]
scripts/osc/osc_player_slow.py [new file with mode: 0644]
scripts/osc/osc_record_start.py [new file with mode: 0644]
scripts/osc/osc_record_stop.py [new file with mode: 0644]
scripts/osc/osc_relay_start.py [new file with mode: 0644]
scripts/osc/osc_relay_stop.py [new file with mode: 0644]
scripts/osc/osc_twitter_start.py [new file with mode: 0644]
scripts/osc/osc_twitter_stop.py [new file with mode: 0644]

old mode 100755 (executable)
new mode 100644 (file)
index 2eb5583..92251cf
@@ -44,6 +44,7 @@ from threading import Thread
 from deefuzzer.station import *
 from deefuzzer.tools import *
 
+
 class DeeFuzzer(Thread):
     """a DeeFuzzer diffuser"""
 
diff --git a/deefuzzer/player.py b/deefuzzer/player.py
new file mode 100644 (file)
index 0000000..043a80e
--- /dev/null
@@ -0,0 +1,145 @@
+#!/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 relay import *
+
+
+class Player:
+    """A file streaming iterator"""
+
+    def __init__(self, stream_type='icecast'):
+        if stream_type == 'icecast':
+            self.main_buffer_size = 0x100000
+            self.relay_queue_size = 0x100000
+            self.sub_buffer_size = 0x10000
+        elif stream_type == 'stream-m':
+            self.main_buffer_size = 0x100000
+            self.relay_queue_size = 0x100000
+            self.sub_buffer_size = 0x10000
+
+    def set_media(self, media):
+        self.media = media
+
+    def start_relay(self, url):
+        self.url = url
+        self.relay = Relay(self.sub_buffer_size, self.relay_queue_size)
+        self.relay.set_url(self.url)
+        self.relay.open()
+        self.relay.start()
+        self.queue = self.relay.queue
+
+    def stop_relay(self):
+        self.relay.close()
+
+    def file_read_fast(self):
+        """Read media and stream data through a generator."""
+        m = open(self.media, 'r')
+        while True:
+            __main_chunk = m.read(self.sub_buffer_size)
+            if not __main_chunk:
+                break
+            yield __main_chunk
+        m.close()
+
+    def file_read_slow(self):
+        """Read a bigger part of the media and stream the little parts
+         of the data through a generator"""
+        m = open(self.media, 'r')
+        while True:
+            self.main_chunk = m.read(self.main_buffer_size)
+            if not self.main_chunk:
+                break
+            i = 0
+            while True:
+                start = i * self.sub_buffer_size
+                end = self.sub_buffer_size + (i * self.sub_buffer_size)
+                self.sub_chunk = self.main_chunk[start:end]
+                if not self.sub_chunk:
+                    break
+                yield self.sub_chunk
+                i += 1
+        self.main_chunk = 0
+        self.sub_chunk = 0
+        m.close()
+
+    def relay_read(self):
+        """Read a distant media through its URL"""
+        while True:
+            self.sub_chunk = self.queue.get(self.sub_buffer_size)
+            if not self.sub_chunk:
+                break
+            yield self.sub_chunk
+            self.queue.task_done()
+        self.sub_chunk = 0
+
+
+class FileReader:
+
+    def __init__(self, fp):
+        self.fp = open(fp, 'r')
+
+    def read_callback(self, size):
+        return self.fp.read(size)
+
+
+class URLReader:
+
+    def __init__(self, relay):
+        self.relay = urllib.urlopen(relay)
+        self.rec_mode = 0
+
+    def set_recorder(self, recorder, mode=1):
+        self.rec_mode = mode
+        self.recorder = recorder
+
+    def read_callback(self, size):
+        try:
+            chunk = self.relay.read(size)
+        except:
+            while True:
+                try:
+                    self.relay = urllib.urlopen(relay)
+                    chunk = self.relay.read(size)
+                    break
+                except:
+                    time.sleep(0.5)
+                    continue
+
+        if self.rec_mode == 1 and chunk:
+            self.recorder.write(chunk)
+        return chunk
diff --git a/deefuzzer/recorder.py b/deefuzzer/recorder.py
new file mode 100644 (file)
index 0000000..4ddb312
--- /dev/null
@@ -0,0 +1,62 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2006-2009 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>
+
+import os
+
+
+class Recorder:
+    """A file streaming iterator"""
+
+    def __init__(self, path):
+        self.path = path
+        self.recording = True
+
+    def open(self, filename):
+        self.filename = filename
+        self.media = open(self.path + os.sep + self.filename, 'w')
+
+    def write(self, chunk):
+        try:
+            if self.recording:
+                self.media.write(chunk)
+                self.media.flush()
+        except:
+            pass
+
+    def close(self):
+        self.media.close()
diff --git a/deefuzzer/relay.py b/deefuzzer/relay.py
new file mode 100644 (file)
index 0000000..4adbd63
--- /dev/null
@@ -0,0 +1,75 @@
+#!/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
+import Queue
+import urllib
+
+
+class Relay(Thread):
+
+    def __init__(self, sub_buffer_size, queue_size):
+        Thread.__init__(self)
+        self.sub_buffer_size = sub_buffer_size
+        self.queue_size = queue_size
+        self.queue = Queue.Queue(self.queue_size)
+
+    def set_url(self, url):
+        self.url = url
+
+    def open(self):
+        try:
+            self.stream = urllib.urlopen(self.url)
+            self.isopen = True
+        except:
+            self.isopen = False
+
+    def close(self):
+        if self.stream:
+            self.isopen = False
+
+    def run(self):
+        while True:
+            if self.isopen:
+                self.chunk = self.stream.read(self.sub_buffer_size)
+                self.queue.put_nowait(self.chunk)
+#                print self.queue.qsize()
+            else:
+                self.stream.close()
+                break
+
diff --git a/deefuzzer/scripts/osc_jingles_start.py b/deefuzzer/scripts/osc_jingles_start.py
deleted file mode 100644 (file)
index 3f2ebf0..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-import liblo, sys
-
-# send all messages to port 1234 on the local machine
-try:
-    target = liblo.Address(1234)
-except liblo.AddressError, err:
-    print str(err)
-    sys.exit()
-
-# send message "/foo/message1" with int, float and string arguments
-liblo.send(target, "/jingles", 1)
diff --git a/deefuzzer/scripts/osc_jingles_stop.py b/deefuzzer/scripts/osc_jingles_stop.py
deleted file mode 100644 (file)
index d29f721..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-import liblo, sys
-
-# send all messages to port 1234 on the local machine
-try:
-    target = liblo.Address(1234)
-except liblo.AddressError, err:
-    print str(err)
-    sys.exit()
-
-# send message "/foo/message1" with int, float and string arguments
-liblo.send(target, "/jingles", 0)
diff --git a/deefuzzer/scripts/osc_player_fast.py b/deefuzzer/scripts/osc_player_fast.py
deleted file mode 100644 (file)
index 92a60fe..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-import liblo, sys
-
-# send all messages to port 1234 on the local machine
-try:
-    target = liblo.Address(1234)
-except liblo.AddressError, err:
-    print str(err)
-    sys.exit()
-
-# send message "/foo/message1" with int, float and string arguments
-liblo.send(target, "/player", 1)
diff --git a/deefuzzer/scripts/osc_player_next.py b/deefuzzer/scripts/osc_player_next.py
deleted file mode 100644 (file)
index 21a91ee..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-import liblo, sys
-
-# send all messages to port 1234 on the local machine
-try:
-    target = liblo.Address(1234)
-except liblo.AddressError, err:
-    sys.exit(err)
-
-# send message "/foo/message1" with int, float and string arguments
-liblo.send(target, "/media/next", 1)
diff --git a/deefuzzer/scripts/osc_player_slow.py b/deefuzzer/scripts/osc_player_slow.py
deleted file mode 100644 (file)
index 02948e0..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-import liblo, sys
-
-# send all messages to port 1234 on the local machine
-try:
-    target = liblo.Address(1234)
-except liblo.AddressError, err:
-    print str(err)
-    sys.exit()
-
-# send message "/foo/message1" with int, float and string arguments
-liblo.send(target, "/player", 0)
diff --git a/deefuzzer/scripts/osc_record_start.py b/deefuzzer/scripts/osc_record_start.py
deleted file mode 100644 (file)
index 779e90b..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-import liblo, sys
-
-# send all messages to port 1234 on the local machine
-try:
-    target = liblo.Address(1234)
-except liblo.AddressError, err:
-    print str(err)
-    sys.exit()
-
-# send message "/foo/message1" with int, float and string arguments
-liblo.send(target, "/record", 1)
diff --git a/deefuzzer/scripts/osc_record_stop.py b/deefuzzer/scripts/osc_record_stop.py
deleted file mode 100644 (file)
index 8056c69..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-import liblo, sys
-
-# send all messages to port 1234 on the local machine
-try:
-    target = liblo.Address(1234)
-except liblo.AddressError, err:
-    print str(err)
-    sys.exit()
-
-# send message "/foo/message1" with int, float and string arguments
-liblo.send(target, "/record", 0)
diff --git a/deefuzzer/scripts/osc_relay_start.py b/deefuzzer/scripts/osc_relay_start.py
deleted file mode 100644 (file)
index 14bcb69..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-import liblo, sys
-
-# send all messages to port 1234 on the local machine
-try:
-    target = liblo.Address(1234)
-except liblo.AddressError, err:
-    print str(err)
-    sys.exit()
-
-# send message "/foo/message1" with int, float and string arguments
-liblo.send(target, "/media/relay", 1)
diff --git a/deefuzzer/scripts/osc_relay_stop.py b/deefuzzer/scripts/osc_relay_stop.py
deleted file mode 100644 (file)
index eaefe1a..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-import liblo, sys
-
-# send all messages to port 1234 on the local machine
-try:
-    target = liblo.Address(1234)
-except liblo.AddressError, err:
-    print str(err)
-    sys.exit()
-
-# send message "/foo/message1" with int, float and string arguments
-liblo.send(target, "/media/relay", 0)
diff --git a/deefuzzer/scripts/osc_twitter_start.py b/deefuzzer/scripts/osc_twitter_start.py
deleted file mode 100644 (file)
index c298be6..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-import liblo, sys
-
-# send all messages to port 1234 on the local machine
-try:
-    target = liblo.Address(1234)
-except liblo.AddressError, err:
-    print str(err)
-    sys.exit()
-
-# send message "/foo/message1" with int, float and string arguments
-liblo.send(target, "/twitter", 1)
diff --git a/deefuzzer/scripts/osc_twitter_stop.py b/deefuzzer/scripts/osc_twitter_stop.py
deleted file mode 100644 (file)
index 3470fcc..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-import liblo, sys
-
-# send all messages to port 1234 on the local machine
-try:
-    target = liblo.Address(1234)
-except liblo.AddressError, err:
-    print str(err)
-    sys.exit()
-
-# send message "/foo/message1" with int, float and string arguments
-liblo.send(target, "/twitter", 0)
index be6fe8187218b85856a686a8d68545aaf4c80b5f..da9acc439f494935d23c700fd330ed979f2352cd 100644 (file)
@@ -45,10 +45,14 @@ import random
 import shout
 import urllib
 import mimetypes
+
 from threading import Thread
+from player import *
+from recorder import *
+from relay import *
+from streamer import *
 from tools import *
 
-
 class Station(Thread):
     """a DeeFuzzer shouting station thread"""
 
@@ -73,6 +77,8 @@ class Station(Thread):
         self.ogg_quality = self.station['media']['ogg_quality']
         self.samplerate = self.station['media']['samplerate']
         self.voices = self.station['media']['voices']
+        if 'm3u' in self.station['media'].keys():
+            self.m3u_playlist_file = self.station['media']['m3u']
 
         # Server
         if 'mountpoint' in self.station['server'].keys():
@@ -319,13 +325,19 @@ class Station(Thread):
 
     def get_playlist(self):
         file_list = []
-        for root, dirs, files in os.walk(self.media_dir):
-            for file in files:
-                s = file.split('.')
-                ext = s[len(s)-1]
-                if ext.lower() == self.channel.format and not os.sep+'.' in file:
-                    file_list.append(root + os.sep + file)
-        file_list.sort()
+        if not self.m3u_playlist_file:
+            for root, dirs, files in os.walk(self.media_dir):
+                for file in files:
+                    s = file.split('.')
+                    ext = s[len(s)-1]
+                    if ext.lower() == self.channel.format and not os.sep+'.' in file:
+                        file_list.append(root + os.sep + file)
+            file_list.sort()
+        else:
+            f = open(self.m3u_playlist_file, 'r')
+            for path in f.readlines():
+                if '#' != path[0]:
+                    file_list.append(path[:-1])
         return file_list
 
     def get_jingles(self):
@@ -341,12 +353,12 @@ class Station(Thread):
 
     def get_next_media(self):
         # Init playlist
-        if self.lp != 0:
+        if self.lp:
             playlist = self.playlist
             new_playlist = self.get_playlist()
             lp_new = len(new_playlist)
 
-            if lp_new != self.lp or self.counter == 0:
+            if lp_new != self.lp or not self.counter:
                 self.id = 0
                 self.lp = lp_new
 
@@ -356,7 +368,7 @@ class Station(Thread):
                 new_tracks = new_playlist_set - playlist_set
                 self.new_tracks = list(new_tracks.copy())
 
-                if len(new_tracks) != 0:
+                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']
@@ -376,7 +388,7 @@ class Station(Thread):
                             self.update_twitter(message)
 
                 # Shake it, Fuzz it !
-                if self.shuffle_mode == 1:
+                if self.shuffle_mode:
                     random.shuffle(playlist)
 
                 # Play new tracks first
@@ -389,7 +401,7 @@ class Station(Thread):
                 self.update_rss(self.media_to_objs(self.playlist),
                                 self.rss_playlist_file, '(playlist)')
 
-            if self.jingles_mode == 1 and (self.counter % 2) == 0 and not self.jingles_length == 0:
+            if self.jingles_mode and not (self.counter % 2) and self.jingles_length:
                 media = self.jingles_list[self.jingle_id]
                 self.jingle_id = (self.jingle_id + 1) % self.jingles_length
             else:
@@ -572,6 +584,7 @@ class Station(Thread):
                 self.q.task_done()
                 pass
 
+
     def run(self):
         self.q.get(1)
         self.ping_server()
diff --git a/deefuzzer/streamer.py b/deefuzzer/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()
index 9327c415e028af7ad0c9acf64d2aca1bd8510a7c..03fd06deaad466a52d91cfc02d6b385abced9e0d 100644 (file)
@@ -4,10 +4,6 @@ from PyRSS2Gen import *
 from mp3 import *
 from ogg import *
 from logger import *
-from player import *
-from recorder import *
 from osc import *
 from twitt import *
-from relay import *
-from tools import *
-from streamer import *
+from utils import *
index 2f68c4d0020dd136ed765c3fdf7dcd3309bcdb04..041f04c16c7ab35939c8f459be1fcba954f5517c 100644 (file)
@@ -3,6 +3,7 @@
 
 import logging
 
+
 class Logger:
     """A logging object"""
 
diff --git a/deefuzzer/tools/player.py b/deefuzzer/tools/player.py
deleted file mode 100644 (file)
index 1be33c2..0000000
+++ /dev/null
@@ -1,144 +0,0 @@
-#!/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 relay import *
-
-class Player:
-    """A file streaming iterator"""
-
-    def __init__(self, stream_type='icecast'):
-        if stream_type == 'icecast':
-            self.main_buffer_size = 0x100000
-            self.relay_queue_size = 0x100000
-            self.sub_buffer_size = 0x10000
-        elif stream_type == 'stream-m':
-            self.main_buffer_size = 0x100000
-            self.relay_queue_size = 0x100000
-            self.sub_buffer_size = 0x10000
-
-    def set_media(self, media):
-        self.media = media
-
-    def start_relay(self, url):
-        self.url = url
-        self.relay = Relay(self.sub_buffer_size, self.relay_queue_size)
-        self.relay.set_url(self.url)
-        self.relay.open()
-        self.relay.start()
-        self.queue = self.relay.queue
-
-    def stop_relay(self):
-        self.relay.close()
-
-    def file_read_fast(self):
-        """Read media and stream data through a generator."""
-        m = open(self.media, 'r')
-        while True:
-            __main_chunk = m.read(self.sub_buffer_size)
-            if not __main_chunk:
-                break
-            yield __main_chunk
-        m.close()
-
-    def file_read_slow(self):
-        """Read a bigger part of the media and stream the little parts
-         of the data through a generator"""
-        m = open(self.media, 'r')
-        while True:
-            self.main_chunk = m.read(self.main_buffer_size)
-            if not self.main_chunk:
-                break
-            i = 0
-            while True:
-                start = i * self.sub_buffer_size
-                end = self.sub_buffer_size + (i * self.sub_buffer_size)
-                self.sub_chunk = self.main_chunk[start:end]
-                if not self.sub_chunk:
-                    break
-                yield self.sub_chunk
-                i += 1
-        self.main_chunk = 0
-        self.sub_chunk = 0
-        m.close()
-
-    def relay_read(self):
-        """Read a distant media through its URL"""
-        while True:
-            self.sub_chunk = self.queue.get(self.sub_buffer_size)
-            if not self.sub_chunk:
-                break
-            yield self.sub_chunk
-            self.queue.task_done()
-        self.sub_chunk = 0
-
-
-class FileReader:
-
-    def __init__(self, fp):
-        self.fp = open(fp, 'r')
-
-    def read_callback(self, size):
-        return self.fp.read(size)
-
-
-class URLReader:
-
-    def __init__(self, relay):
-        self.relay = urllib.urlopen(relay)
-        self.rec_mode = 0
-
-    def set_recorder(self, recorder, mode=1):
-        self.rec_mode = mode
-        self.recorder = recorder
-
-    def read_callback(self, size):
-        try:
-            chunk = self.relay.read(size)
-        except:
-            while True:
-                try:
-                    self.relay = urllib.urlopen(relay)
-                    chunk = self.relay.read(size)
-                    break
-                except:
-                    time.sleep(0.5)
-                    continue
-
-        if self.rec_mode == 1 and chunk:
-            self.recorder.write(chunk)
-        return chunk
diff --git a/deefuzzer/tools/recorder.py b/deefuzzer/tools/recorder.py
deleted file mode 100644 (file)
index f7f3d79..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2006-2009 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>
-
-import os
-
-class Recorder:
-    """A file streaming iterator"""
-
-    def __init__(self, path):
-        self.path = path
-        self.recording = True
-
-    def open(self, filename):
-        self.filename = filename
-        self.media = open(self.path + os.sep + self.filename, 'w')
-
-    def write(self, chunk):
-        try:
-            if self.recording:
-                self.media.write(chunk)
-                self.media.flush()
-        except:
-            pass
-
-    def close(self):
-        self.media.close()
diff --git a/deefuzzer/tools/relay.py b/deefuzzer/tools/relay.py
deleted file mode 100644 (file)
index 7973db0..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-#!/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
-import Queue
-import urllib
-
-class Relay(Thread):
-
-    def __init__(self, sub_buffer_size, queue_size):
-        Thread.__init__(self)
-        self.sub_buffer_size = sub_buffer_size
-        self.queue_size = queue_size
-        self.queue = Queue.Queue(self.queue_size)
-
-    def set_url(self, url):
-        self.url = url
-
-    def open(self):
-        try:
-            self.stream = urllib.urlopen(self.url)
-            self.isopen = True
-        except:
-            self.isopen = False
-
-    def close(self):
-        if self.stream:
-            self.isopen = False
-
-    def run(self):
-        while True:
-            if self.isopen:
-                self.chunk = self.stream.read(self.sub_buffer_size)
-                self.queue.put_nowait(self.chunk)
-#                print self.queue.qsize()
-            else:
-                self.stream.close()
-                break
-
-
diff --git a/deefuzzer/tools/streamer.py b/deefuzzer/tools/streamer.py
deleted file mode 100644 (file)
index 1d11091..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-#!/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/tools.py b/deefuzzer/tools/tools.py
deleted file mode 100644 (file)
index 8282cfc..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-#
-# Copyright (c) 2007-2009 Guillaume Pellerin <yomguy@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/deefuzz/wiki/DefuzzLicense.
-#
-# Author: Guillaume Pellerin <yomguy@parisson.com>
-
-import os
-import re
-import string
-
-def clean_word(word) :
-    """ Return the word without excessive blank spaces, underscores and
-    characters causing problem to exporters"""
-    word = re.sub("^[^\w]+","",word)    #trim the beginning
-    word = re.sub("[^\w]+$","",word)    #trim the end
-    word = re.sub("_+","_",word)        #squeeze continuous _ to one _
-    word = re.sub("^[^\w]+","",word)    #trim the beginning _
-    #word = string.replace(word,' ','_')
-    #word = string.capitalize(word)
-    dict = '&[];"*:,'
-    for letter in dict:
-        word = string.replace(word,letter,'_')
-    return word
-
-def get_file_info(media):
-    file_name = media.split(os.sep)[-1]
-    file_title = file_name.split('.')[:-1]
-    file_title = '.'.join(file_title)
-    file_ext = file_name.split('.')[-1]
-    return file_name, file_title, file_ext
diff --git a/deefuzzer/tools/utils.py b/deefuzzer/tools/utils.py
new file mode 100644 (file)
index 0000000..8282cfc
--- /dev/null
@@ -0,0 +1,36 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+#
+# Copyright (c) 2007-2009 Guillaume Pellerin <yomguy@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/deefuzz/wiki/DefuzzLicense.
+#
+# Author: Guillaume Pellerin <yomguy@parisson.com>
+
+import os
+import re
+import string
+
+def clean_word(word) :
+    """ Return the word without excessive blank spaces, underscores and
+    characters causing problem to exporters"""
+    word = re.sub("^[^\w]+","",word)    #trim the beginning
+    word = re.sub("[^\w]+$","",word)    #trim the end
+    word = re.sub("_+","_",word)        #squeeze continuous _ to one _
+    word = re.sub("^[^\w]+","",word)    #trim the beginning _
+    #word = string.replace(word,' ','_')
+    #word = string.capitalize(word)
+    dict = '&[];"*:,'
+    for letter in dict:
+        word = string.replace(word,letter,'_')
+    return word
+
+def get_file_info(media):
+    file_name = media.split(os.sep)[-1]
+    file_title = file_name.split('.')[:-1]
+    file_title = '.'.join(file_title)
+    file_ext = file_name.split('.')[-1]
+    return file_name, file_title, file_ext
index 38bac9e14d76090b72250310a6e4683d7ffffb10..5bb453a472c5240cc85ae440c46ec1968679e5c1 100644 (file)
@@ -25,6 +25,7 @@
             <samplerate>44100</samplerate>
             <voices>2</voices>
             <shuffle>1</shuffle>
+            <m3u>/path/to/m3u_file</m3u>
         </media>
         <rss>
             <dir>/path/to/rss/</dir>
diff --git a/example/deefuzzer.yaml b/example/deefuzzer.yaml
new file mode 100644 (file)
index 0000000..b917790
--- /dev/null
@@ -0,0 +1,47 @@
+deefuzzer:
+  log: /path/to/log/mystation.log
+  m3u: /path/to/m3u/mystation.m3u
+
+  station:
+    control: {mode: 0,
+             port: 16001}
+
+    server: {host: 127.0.0.1,
+             mountpoint: monitor,
+             port: 8000, public: 0,
+             sourcepassword: source2parisson,
+             type: icecast}
+
+    infos: {name: my_station,
+            description: my_station,
+            genre: music,
+            url: 'http://parisson.com'}
+
+    media: {dir: /path/to/mp3/,
+            m3u: /path/to/m3u_file,
+            format: mp3,
+            bitrate: 96,
+            ogg_quality: 4,
+            samplerate: 48000,
+            shuffle: 0,
+            voices: '2'}
+
+    jingles: {dir: /path/to/jingles,
+              mode: 0,
+              shuffle: 1}
+
+    record: {dir: /home/telecaster/archives/mp3,
+             mode: 0}
+
+    relay: {author: Inconnu,
+            mode: 0,
+            url: 'http://127.0.0.1:8000/telecaster_live.mp3'}
+
+    rss: {dir: /var/www/rss,
+          enclosure: 0,
+          media_url: 'http://localhost/rss/'}
+
+
+    twitter: {key: 76728330-OjKgbHtn4II86Ad7pNUGEzfNAkGTW5Wvw38qUmLE,
+              mode: 0, secret: 4egZs1dSM37XVY8zXa016Yueku2fleXF2bx8k25V4,
+              tags: bla bla}
index e6b64558dd332978312bbae49f5c2d6dc2f94b6e..71cff5414dbbdf21cc97a0afa282bc2e593e7d6e 100644 (file)
@@ -47,6 +47,8 @@
             <voices>2</voices>
             <!-- If '1', the playlist will be randomized. '0' for aphanumeric order -->
             <shuffle>1</shuffle>
+            <!-- You can also give a M3U playlist file -->
+            <m3u>/path/to/m3u_file</m3u>
         </media>
         <rss>
             <!-- A path to the directory containing RSS (XML) files that is 'currently playing'
diff --git a/scripts/osc/osc_jingles_start.py b/scripts/osc/osc_jingles_start.py
new file mode 100644 (file)
index 0000000..3f2ebf0
--- /dev/null
@@ -0,0 +1,14 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+import liblo, sys
+
+# send all messages to port 1234 on the local machine
+try:
+    target = liblo.Address(1234)
+except liblo.AddressError, err:
+    print str(err)
+    sys.exit()
+
+# send message "/foo/message1" with int, float and string arguments
+liblo.send(target, "/jingles", 1)
diff --git a/scripts/osc/osc_jingles_stop.py b/scripts/osc/osc_jingles_stop.py
new file mode 100644 (file)
index 0000000..d29f721
--- /dev/null
@@ -0,0 +1,14 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+import liblo, sys
+
+# send all messages to port 1234 on the local machine
+try:
+    target = liblo.Address(1234)
+except liblo.AddressError, err:
+    print str(err)
+    sys.exit()
+
+# send message "/foo/message1" with int, float and string arguments
+liblo.send(target, "/jingles", 0)
diff --git a/scripts/osc/osc_player_fast.py b/scripts/osc/osc_player_fast.py
new file mode 100644 (file)
index 0000000..92a60fe
--- /dev/null
@@ -0,0 +1,14 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+import liblo, sys
+
+# send all messages to port 1234 on the local machine
+try:
+    target = liblo.Address(1234)
+except liblo.AddressError, err:
+    print str(err)
+    sys.exit()
+
+# send message "/foo/message1" with int, float and string arguments
+liblo.send(target, "/player", 1)
diff --git a/scripts/osc/osc_player_next.py b/scripts/osc/osc_player_next.py
new file mode 100644 (file)
index 0000000..21a91ee
--- /dev/null
@@ -0,0 +1,13 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+import liblo, sys
+
+# send all messages to port 1234 on the local machine
+try:
+    target = liblo.Address(1234)
+except liblo.AddressError, err:
+    sys.exit(err)
+
+# send message "/foo/message1" with int, float and string arguments
+liblo.send(target, "/media/next", 1)
diff --git a/scripts/osc/osc_player_slow.py b/scripts/osc/osc_player_slow.py
new file mode 100644 (file)
index 0000000..02948e0
--- /dev/null
@@ -0,0 +1,14 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+import liblo, sys
+
+# send all messages to port 1234 on the local machine
+try:
+    target = liblo.Address(1234)
+except liblo.AddressError, err:
+    print str(err)
+    sys.exit()
+
+# send message "/foo/message1" with int, float and string arguments
+liblo.send(target, "/player", 0)
diff --git a/scripts/osc/osc_record_start.py b/scripts/osc/osc_record_start.py
new file mode 100644 (file)
index 0000000..779e90b
--- /dev/null
@@ -0,0 +1,14 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+import liblo, sys
+
+# send all messages to port 1234 on the local machine
+try:
+    target = liblo.Address(1234)
+except liblo.AddressError, err:
+    print str(err)
+    sys.exit()
+
+# send message "/foo/message1" with int, float and string arguments
+liblo.send(target, "/record", 1)
diff --git a/scripts/osc/osc_record_stop.py b/scripts/osc/osc_record_stop.py
new file mode 100644 (file)
index 0000000..8056c69
--- /dev/null
@@ -0,0 +1,14 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+import liblo, sys
+
+# send all messages to port 1234 on the local machine
+try:
+    target = liblo.Address(1234)
+except liblo.AddressError, err:
+    print str(err)
+    sys.exit()
+
+# send message "/foo/message1" with int, float and string arguments
+liblo.send(target, "/record", 0)
diff --git a/scripts/osc/osc_relay_start.py b/scripts/osc/osc_relay_start.py
new file mode 100644 (file)
index 0000000..14bcb69
--- /dev/null
@@ -0,0 +1,14 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+import liblo, sys
+
+# send all messages to port 1234 on the local machine
+try:
+    target = liblo.Address(1234)
+except liblo.AddressError, err:
+    print str(err)
+    sys.exit()
+
+# send message "/foo/message1" with int, float and string arguments
+liblo.send(target, "/media/relay", 1)
diff --git a/scripts/osc/osc_relay_stop.py b/scripts/osc/osc_relay_stop.py
new file mode 100644 (file)
index 0000000..eaefe1a
--- /dev/null
@@ -0,0 +1,14 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+import liblo, sys
+
+# send all messages to port 1234 on the local machine
+try:
+    target = liblo.Address(1234)
+except liblo.AddressError, err:
+    print str(err)
+    sys.exit()
+
+# send message "/foo/message1" with int, float and string arguments
+liblo.send(target, "/media/relay", 0)
diff --git a/scripts/osc/osc_twitter_start.py b/scripts/osc/osc_twitter_start.py
new file mode 100644 (file)
index 0000000..c298be6
--- /dev/null
@@ -0,0 +1,14 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+import liblo, sys
+
+# send all messages to port 1234 on the local machine
+try:
+    target = liblo.Address(1234)
+except liblo.AddressError, err:
+    print str(err)
+    sys.exit()
+
+# send message "/foo/message1" with int, float and string arguments
+liblo.send(target, "/twitter", 1)
diff --git a/scripts/osc/osc_twitter_stop.py b/scripts/osc/osc_twitter_stop.py
new file mode 100644 (file)
index 0000000..3470fcc
--- /dev/null
@@ -0,0 +1,14 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+import liblo, sys
+
+# send all messages to port 1234 on the local machine
+try:
+    target = liblo.Address(1234)
+except liblo.AddressError, err:
+    print str(err)
+    sys.exit()
+
+# send message "/foo/message1" with int, float and string arguments
+liblo.send(target, "/twitter", 0)