All pastes #1946870 Raw Edit

Untitled

public text v1 · immutable
#1946870 ·published 2010-09-22 22:03 UTC
rendered paste body
Index: __init__.py
===================================================================
--- __init__.py	(revision 78)
+++ __init__.py	(working copy)
@@ -12,106 +12,20 @@
     You should have received a copy of the GNU General Public License
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 """
-from xl import event
-from xl import providers
-from xl import xdg
+
+import os, signal, socket, subprocess
 import pygst
 pygst.require('0.10')
 import gst
-import socket,os
-from threading import Thread
-import signal
-import time
-import array
-import struct
-import subprocess
+from xl import common, event, providers, xdg
 
-plugin_name = "projectM"
-pcm_socket_path = os.path.join(xdg.get_plugin_data_dir(), '.projectM-exaile')
-if not os.path.exists(pcm_socket_path):
-    open(pcm_socket_path, 'a')
-projectM_bin = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'projectM-exaile')
+import logging
+logger = logging.getLogger(__name__)
 
-ENABLED=0
-AUDIO_SINK=None
-CONNECTED=0
-PCM_DATA_SIZE=1024
-PCM_DATA=None
-projectM_proc=None
+PROJECTM = None
+AUDIO_SINK = None
 
 
-def run_projectM(arg):
-
-    global projectM_proc
-    global projectM_bin
-
-    cmd = [projectM_bin, arg]
-    try:
-        projectM_proc = subprocess.Popen(cmd,shell=False)
-        if projectM_proc.pid:
-            print "projectM-exaile: Spawned projectM Process ID: %s" % projectM_proc.pid
-        else:
-            print "projectM-exaile: Failed to spawn projectM Process"
-    except:
-        print "projectM-exaile: Failed to spawn projectM Process"
-
-def kill_projectM():
-    global projectM_proc
-    print "projectM-exaile: Trying to Kill projectM PID: %i" % projectM_proc.pid
-    try:
-        if(projectM_proc.pid):
-            os.kill(projectM_proc.pid,signal.SIGKILL)
-            print "projectM-exaile: Killed"
-    except:
-        return
-
-class pcm_sock_thread ( Thread ):
-    def __init__ (self):
-        Thread.__init__(self)
-    def run ( self ):
-        create_pcm_socket()
-
-def destroy_pcm_socket():
-    global conn
-    global CONNECTED
-    conn.close()
-    CONNECTED=0
-
-def create_pcm_socket():
-    global conn
-    global CONNECTED,PCM_DATA_SIZE,pcm_socket_path
-    try:
-        os.remove(pcm_socket_path)
-    except OSError:
-        pass
-    #Bind Unix Socket for connection from projectM-exaile
-    s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
-    s.bind(pcm_socket_path)
-    print "projectM-exaile: Bound to %s" % pcm_socket_path
-    s.listen(1)
-    #Wait for projectM-exaile to connect
-    print "projectM-exaile: Waiting for connection"
-    conn = s.accept()[0]
-    CONNECTED=1
-    print "projectM-exaile: projectM Connected"
-
-def write_pcm_socket(data):
-    global conn
-    global CONNECTED
-    global pcm_socket_path
-    if(CONNECTED==0):
-        return
-    try:
-        #Send Data
-        print "START WRITE", len(data)
-        conn.send(data)
-        print "END WRITE"
-    except:
-        print "projectM-exaile: ProjectM Disconnected"
-        kill_projectM()
-        destroy_pcm_socket()
-        return
-
 def enable(exaile):
     if (exaile.loading):
         event.add_callback(_enable, 'exaile_loaded')
@@ -119,46 +33,102 @@
         _enable(None, exaile, None)
 
 def disable(exaile):
-    global ENABLED
-    ENABLED=0
-    kill_projectM()
-    destroy_pcm_socket()
-    print('%s Disabled' % plugin_name)
+    teardown(exaile)
 
 def _enable(eventname, exaile, nothing):
-    global ENABLED
-    global AUDIO_SINK, pcm_socket_path
-    ENABLED = 1
-    AUDIO_SINK = AudioSink(exaile)
+    global PROJECTM, AUDIO_SINK
+    PROJECTM = ProjectM()
+    AUDIO_SINK = AudioSink(PROJECTM)
     providers.register('playback_audio_sink', AUDIO_SINK)
-    sck_thrd = pcm_sock_thread()
-    sck_thrd.start()
-    run_projectM(pcm_socket_path)
-    print('%s Enabled' % plugin_name)
+    PROJECTM.spawn()
 
 def teardown(exaile):
-    global ENABLED
-    ENABLED=0
-    print "projectM-exaile: Shutting down"
-    kill_projectM()
-    destroy_pcm_socket()
-    print "projectM-exaile: Shutdown"
+    global PROJECTM, AUDIO_SINK
+    PROJECTM.kill()
 
+class ProjectM(object):
+    pcm_socket_path = os.path.join(xdg.get_plugin_data_dir(), 'projectM', 'projectM-exaile.sock')
+    projectm_binary = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'projectM-exaile')
+    def __init__(self):
+        self.connected = False
+        self.pid = None
+        self._sock = None
+        self._conn = None
+
+    def spawn(self):
+        self._make_socket()
+
+        command = [self.projectm_binary, self.pcm_socket_path]
+        try:
+            proc = subprocess.Popen(command)
+            if not proc.pid:
+                raise ValueError # TODO: get a better exception type here
+        except:
+            logger.error("Failed to spawn projectM process.")
+            common.log_exception()
+        else:
+            self.pid = proc.pid
+            logger.debug("Spawned projectM process, pid %s."%self.pid)
+
+    def kill(self):
+        if not self.pid:
+            return
+        try:
+            os.kill(self.pid, signal.SIGKILL)
+            logger.debug("projectM process killed.")
+        except:
+            logger.warning("Failed to kill projectM process, pid %s."%self.pid)
+        else:
+            self.pid = None
+        finally:
+            self._close_socket()
+
+    def send_pcm(self, data):
+        if not self.connected:
+            return
+        try:
+            self._conn.send(data)
+        except:
+            logger.warning("Disconnected from projectM")
+            self.kill()
+
+    @common.threaded
+    def _make_socket(self):
+        try:
+            os.makedirs(os.path.dirname(self.pcm_socket_path))
+        except OSError:
+            pass
+        try:
+            os.remove(self.pcm_socket_path)
+        except OSError:
+            pass
+        self._sock = sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+        sock.bind(self.pcm_socket_path)
+        sock.listen(1)
+        self._conn = sock.accept()[0]
+        self.connected = True
+
+    def _close_socket(self):
+        self._conn.close()
+        self._conn = None
+        self._sock = None
+        self.connected = False
+
+
+
 class AudioSink(gst.Bin):
-    def __init__(self, exaile):
+    def __init__(self, projectm):
         gst.Bin.__init__(self)
         self.name = 'projectm-audiosink'
-        self.arr = None
-        self.exaile = exaile
+        self.projectm = projectm
+
         elems = []
         self.convert = gst.element_factory_make("audioconvert")
         elems.append(self.convert)
         self.caps = gst.Caps("audio/x-raw-float, width=32, depth=32")
-        self.filter = gst.element_factory_make("capsfilter")
-        self.filter.props.caps = self.caps
-        elems.append(self.filter)
         self.sink = gst.element_factory_make("appsink", "projectm-audiosink")
         self.sink.set_property('emit-signals', True)
+        self.sink.set_property('caps', self.caps)
         self.sink.connect('new-preroll', self.new_preroll)
         self.sink.connect('new-buffer', self.new_buffer)
         elems.append(self.sink)
@@ -168,12 +138,8 @@
         self.add_pad(gst.GhostPad('sink', self.sinkpad))
 
     def new_preroll(self, sink):
-        print "PREROLL"
         buf = sink.emit('pull-preroll')
 
     def new_buffer(self, sink):
-        print "BUFFER"
-        global PCM_DATA,CONNECTED
         buf = sink.emit('pull-buffer')
-        PCM_DATA = buf.data
-        write_pcm_socket(PCM_DATA)
+        self.projectm.send_pcm(buf.data)