Added initial code
[qice] / qice.py
1 #!/usr/bin/env python
2 # qice.py
3 #       Copyright 2008 kinta <kinta@communia.org>
4 #       
5 #       This program is free software; you can redistribute it and/or modify
6 #       it under the terms of the GNU General Public License as published by
7 #       the Free Software Foundation; either version 2 of the License, or
8 #       (at your option) any later version.
9 #       
10 #       This program is distributed in the hope that it will be useful,
11 #       but WITHOUT ANY WARRANTY; without even the implied warranty of
12 #       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 #       GNU General Public License for more details.
14 #       
15 #       You should have received a copy of the GNU General Public License
16 #       along with this program; if not, write to the Free Software
17 #       Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 #       MA 02110-1301, USA.
19 # deps= libshout shout2send aumix osso-xterm mplayer
20 import sys
21 from PyQt4 import QtCore
22 from PyQt4 import QtGui
23 import os
24 import subprocess
25 import pygst
26 pygst.require('0.10')
27 import gst
28 import gst.interfaces
29 import ConfigParser
30 #
31 import gobject
32 #
33
34 stream=["host", "port", "mountpoint", "user", "pw"]
35 sndarch="dsppcmsrc"#"alsasrc"
36 sndarchsink="dsppcmsink"#"alsasink"
37 term="osso-xterm"#"xterm"
38 home_directory = os.popen("echo $HOME").readline()[0:-1]
39 config_directory = home_directory + '/.qice'
40 if os.path.isdir(config_directory):
41         pass
42 else:
43         os.popen("mkdir "+config_directory)
44 config_file = config_directory + '/server.cfg'
45 config = ConfigParser.ConfigParser()
46 config.read(config_file)
47 if config.has_section("server"):
48         print("configuracio trobada")
49 else:
50         print("no te lopcio per tant escribim")
51         config.add_section("server")
52         for index,item in enumerate(stream):
53                 config.set("server",item,item)
54         targetwrite=file(config_file,'w')
55         config.write(targetwrite)
56         targetwrite.close()
57
58
59 class MainWindow(QtGui.QMainWindow):
60    def __init__(self, * args):
61        apply(QtGui.QMainWindow.__init__, (self, ) + args)
62        gobject.threads_init()
63        self.vlayout = QtGui.QGridLayout()
64        
65        self.fileMenu = QtGui.QMenu(self.tr("&File"), self)
66        self.quitAction = self.fileMenu.addAction(self.tr("E&xit"))
67        self.editServer = self.fileMenu.addAction(self.tr("Edit c&onnection"))
68        self.mixer = self.fileMenu.addAction(self.tr("&Mixer"))
69        self.menuBar().addMenu(self.fileMenu)
70        
71        self.stream = QtGui.QPushButton("Stream", self)
72        self.dump = QtGui.QPushButton("dump", self)
73        self.monitor = QtGui.QPushButton("Monitor", self)
74        self.record = QtGui.QPushButton("Record", self)
75        self.label = QtGui.QTextEdit("",self)
76        
77        self.label.setReadOnly(True)
78        self.label.setGeometry(10, 100, 361, 141)
79        self.stream.setCheckable(1)
80        self.dump.setCheckable(1)
81        self.monitor.setCheckable(1)
82        self.record.setCheckable(1)
83
84        self.dump.setEnabled(False)
85
86        self.vlayout.addWidget(self.stream,0,0,1,1)
87        self.vlayout.addWidget(self.dump,1,0,1,1)
88        #self.vlayout.addSpacing(20)
89        self.vlayout.addWidget(self.monitor,0,1,1,1)
90        self.vlayout.addWidget(self.record,0,2,1,1)
91        self.vlayout.addWidget(self.label,2,0,1,3)
92
93        self.connect(self.stream, QtCore.SIGNAL("clicked()"), self.streamcon)
94        self.connect(self.dump, QtCore.SIGNAL("clicked()"), self.dumpstream)
95        self.connect(self.monitor, QtCore.SIGNAL("clicked()"), self.monstr)
96        self.connect(self.record, QtCore.SIGNAL("clicked()"), self.recordstr)
97        self.connect(self.quitAction, QtCore.SIGNAL("triggered()"), self.quito)
98        self.connect(self.editServer, QtCore.SIGNAL("triggered()"), self.setserver)
99        self.connect(self.mixer, QtCore.SIGNAL("triggered()"), self.aumixer)
100        central = QtGui.QWidget(self)
101        central.setLayout(self.vlayout)
102        self.setCentralWidget(central)
103
104    def streamcon(self):
105        if self.stream.isChecked():
106                 try:
107                         self.label.append("connecting")
108                         self.server=config.get("server","host")
109                         self.port=config.get("server","port")
110                         self.mount=config.get("server","mountpoint")
111                         self.pw=config.get("server","pw")
112                         self.user=config.get("server","user")
113                         self.audio_pipeline = gst.parse_launch(sndarch+" ! audioconvert ! vorbisenc name=\"enc\" quality=0.10 ! queue ! oggmux name=mux ! queue ! shout2send  ip="+self.server+" port="+self.port+" password="+self.pw+" mount=/"+self.mount)
114                         self.audio_pipeline.get_bus().add_watch(self.connectEventos)
115                         self.audio_pipeline.set_state(gst.STATE_PLAYING)
116                         self.label.append("connected")
117                         self.record.setEnabled(False)
118                         self.monitor.setEnabled(False)
119                         self.dump.setEnabled(True)
120                 except gobject.GError, e:
121                         self.label.append("No es posible crear la tuberia, " + str(e))
122                         self.stream.setChecked(0)
123                         return -1
124        else:
125                 self.label.append("disconnecting")
126                 try:
127                         self.dump.setChecked(False)
128                         self.dumpstream()
129                         self.audio_pipeline.set_state(gst.STATE_NULL)
130                         self.label.append("disconnected")
131                         self.record.setEnabled(True)
132                         self.monitor.setEnabled(True)
133                         self.dump.setEnabled(False)
134                 except gobject.GError, e:
135                         self.label.append("No es posible canviar a estat nul la tuberia, " + str(e))
136                         return -1
137
138    def monstr(self):
139        if self.monitor.isChecked():
140                 try:
141                         self.label.append("monitoring")
142                         self.mon_pipeline = gst.parse_launch(sndarch+" !"+sndarchsink)
143                         self.mon_pipeline.get_bus().add_watch(self.eventos)
144                         self.mon_pipeline.set_state(gst.STATE_PLAYING)
145                         self.record.setEnabled(False)
146                         self.stream.setEnabled(False)
147                 except gobject.GError, e:
148                         self.label.append("No es posible crear la tuberia, " + str(e))
149                         self.monitor.setChecked(0)
150                         return -1
151        else:
152                 self.label.append("disabling monitor")
153                 try:
154                         self.mon_pipeline.set_state(gst.STATE_NULL)
155                         self.label.append("unmonitoring")
156                         self.record.setEnabled(True)
157                         self.stream.setEnabled(True)
158                 except gobject.GError, e:
159                         self.label.append("No es posible canviar a estat nul la tuberia, " + str(e))
160                         return -1
161    def recordstr(self):
162        if self.record.isChecked():
163                 filename = QtGui.QFileDialog.getSaveFileName(self, 'Where?',home_directory)
164                 filename = str(filename)
165                 try:
166                         self.label.append("recording")
167                         self.rec_pipeline = gst.parse_launch(sndarch+" ! audioconvert ! vorbisenc name=\"enc\" quality=0.10 ! queue ! oggmux name=mux ! queue ! filesink location="+filename)
168                         self.rec_pipeline.get_bus().add_watch(self.eventos)
169                         self.rec_pipeline.set_state(gst.STATE_PLAYING)
170                         self.stream.setEnabled(False)
171                         self.monitor.setEnabled(False)
172                 except gobject.GError, e:
173                         self.label.append("No es posible crear la tuberia, " + str(e))
174                         self.record.setChecked(0)
175                         return -1
176        else:
177                 self.label.append("stop recording")
178                 try:
179                         self.rec_pipeline.set_state(gst.STATE_NULL)
180                         self.label.append("stoped")
181                         self.stream.setEnabled(True)
182                         self.monitor.setEnabled(True)
183                 except gobject.GError, e:
184                         self.label.append("No es posible canviar a estat nul la tuberia, " + str(e))
185                         return -1       
186
187
188    def alert(self, msg):
189         QtGui.QMessageBox.critical(self, 'CRITICAL', msg, QtGui.QMessageBox.Ok)
190    def pregunta(self, msg):
191         pregunta=QtGui.QMessageBox.question(self, 'ATENCIO', msg, QtGui.QMessageBox.Ok | QtGui.QMessageBox.Cancel)
192         #resposta=pregunta.exec()
193         if pregunta == 1024:
194                 return "OK"
195         else :
196                 return "Cancel"
197    def quito(self,**kwargs):
198         self.close()
199    def setserver(self,**kwargs):
200         os.popen2(term+" -e \"nano ~/.qice/server.cfg\"")
201         config.read(config_file)
202    def aumixer(self,**kwargs):
203         os.popen2("aumix")
204    def eventos(self, bus, msg):
205         #DEBUG = print(str(msg)+" "+str(msg.type))
206         t = msg.type    
207         if t == gst.MESSAGE_UNKNOWN:
208                 e, d = msg.parse_error()
209                 self.label.append("CONNECT ERROR: "+e)
210         if t == gst.MESSAGE_ERROR:
211                 e, d = msg.parse_error()
212                 self.label.append("ERROR: "+e)
213         return True
214    def connectEventos(self, bus, msg):
215         #DEBUG = print(str(msg)+" "+str(msg.type))
216         t = msg.type    
217         if t == gst.MESSAGE_UNKNOWN:
218                 e, d = msg.parse_error()
219                 self.label.append("CONNECT ERROR: "+e)
220         if t == gst.MESSAGE_ERROR:
221                 e, d = msg.parse_error()
222                 self.label.append("ERROR: "+e)
223                 self.stream.setChecked(False)
224                 self.streamcon()
225         return True
226    def dumpstream(self):
227        if self.dump.isChecked():
228                 self.server=config.get("server","host")
229                 self.port=config.get("server","port")
230                 self.mount=config.get("server","mountpoint")
231                 self.pw=config.get("server","pw")
232                 self.user=config.get("server","user")
233                 filename = QtGui.QFileDialog.getSaveFileName(self, 'Where?',home_directory)
234                 self.filename = str(filename)
235                 self.label.append("dumping")
236                 mplayer=os.popen2( term+" -e \"mplayer http://"+self.server+":"+self.port+"/"+self.mount+" -dumpstream -dumpfile "+self.filename+" && sleep 2\"")[1].readline()
237                 
238        else:
239                 pidofmp=os.popen2("pidof mplayer")[1].readline()
240                 if pidofmp!="":
241                         os.popen2("kill -15 `pidof mplayer`")
242
243
244 def main(args):
245    app=QtGui.QApplication(args)
246    win=MainWindow()
247    win.show()
248    win.setWindowTitle("Qice")
249    app.connect(app, QtCore.SIGNAL("lastWindowClosed()")
250                , app
251                , QtCore.SLOT("quit()")
252                )
253    app.exec_()
254
255 if __name__=="__main__":
256        main(sys.argv)