File indexing completed on 2024-04-28 04:48:05
0001 #!/usr/bin/env python 0002 0003 ############################################################################ 0004 # Python wrapper script for running the Amarok LiveCD remastering scripts 0005 # from within Amarok. Based on the Python-Qt template script for Amarok 0006 # (c) 2005 Mark Kretschmann <kretschmann@kde.org> 0007 # 0008 # (c) 2005 Leo Franchi <lfranchi@gmail.com> 0009 # 0010 # Depends on: Python 2.2, PyQt 0011 ############################################################################ 0012 # 0013 # This program is free software; you can redistribute it and/or modify 0014 # it under the terms of the GNU General Public License as published by 0015 # the Free Software Foundation; either version 2 of the License, or 0016 # (at your option) any later version. 0017 # 0018 ############################################################################ 0019 0020 import ConfigParser 0021 import os 0022 import sys 0023 import threading 0024 import signal 0025 from time import sleep 0026 0027 try: 0028 from qt import * 0029 except: 0030 os.popen( "kdialog --sorry 'PyQt (Qt bindings for Python) is required for this script.'" ) 0031 raise 0032 0033 0034 # Replace with real name 0035 debug_prefix = "LiveCD Remastering" 0036 0037 0038 class ConfigDialog ( QDialog ): 0039 """ Configuration widget """ 0040 0041 def __init__( self ): 0042 QDialog.__init__( self ) 0043 self.setWFlags( Qt.WDestructiveClose ) 0044 self.setCaption("Amarok Live! Configuration") 0045 0046 self.lay = QGridLayout( self, 3, 2) 0047 0048 self.lay.addColSpacing( 0, 300 ) 0049 0050 self.isopath = QLineEdit( self ) 0051 self.isopath.setText( "Path to Amarok Live! iso" ) 0052 self.tmppath = QLineEdit( self ) 0053 self.tmppath.setText( "Temporary directory used, 2.5gb free needed" ) 0054 0055 self.lay.addWidget( self.isopath, 0, 0 ) 0056 self.lay.addWidget( self.tmppath, 1, 0 ) 0057 0058 self.isobutton = QPushButton( self ) 0059 self.isobutton.setText("Browse..." ) 0060 self.tmpbutton = QPushButton( self ) 0061 self.tmpbutton.setText("Browse..." ) 0062 0063 self.cancel = QPushButton( self ) 0064 self.cancel.setText( "Cancel" ) 0065 self.ok = QPushButton( self ) 0066 self.ok.setText( "Ok" ) 0067 0068 self.lay.addWidget( self.isobutton, 0, 1 ) 0069 self.lay.addWidget( self.tmpbutton, 1, 1 ) 0070 self.lay.addWidget( self.cancel, 2, 1 ) 0071 self.lay.addWidget( self.ok, 2, 0) 0072 0073 self.connect( self.isobutton, SIGNAL( "clicked()" ), self.browseISO ) 0074 self.connect( self.tmpbutton, SIGNAL( "clicked()" ), self.browsePath ) 0075 0076 self.connect( self.ok, SIGNAL( "clicked()" ), self.save ) 0077 self.connect( self.ok, SIGNAL( "clicked()" ), self.unpack ) 0078 # self.connect( self.ok, SIGNAL( "clicked()" ), self.destroy ) 0079 self.connect( self.cancel, SIGNAL( "clicked()" ), self, SLOT("reject()") ) 0080 0081 self.adjustSize() 0082 0083 path = None 0084 try: 0085 config = ConfigParser.ConfigParser() 0086 config.read( "remasterrc" ) 0087 path = config.get( "General", "path" ) 0088 iso = config.get( "General", "iso") 0089 0090 if not path == "": self.tmppath.setText(path) 0091 if not iso == "": self.isopath.setText(iso) 0092 except: 0093 pass 0094 0095 0096 0097 def save( self ): 0098 """ Saves configuration to file """ 0099 self.file = file( "remasterrc", 'w' ) 0100 self.config = ConfigParser.ConfigParser() 0101 self.config.add_section( "General" ) 0102 self.config.set( "General", "path", self.tmppath.text() ) 0103 self.config.set( "General", "iso", self.isopath.text() ) 0104 self.config.write( self.file ) 0105 self.file.close() 0106 0107 self.accept() 0108 0109 def clear(): 0110 0111 self.file = file( "remasterrc", 'w' ) 0112 self.config = ConfigParser.ConfigParser() 0113 self.config.add_section( "General" ) 0114 self.config.set( "General", "path", "" ) 0115 self.config.set( "General", "iso", "" ) 0116 self.config.write( self.file ) 0117 self.file.close() 0118 0119 def browseISO( self ): 0120 0121 path = QFileDialog.getOpenFileName( "/home", 0122 "CD Images (*.iso)", 0123 self, 0124 "iso choose dialogr", 0125 "Choose ISO to remaster") 0126 self.isopath.setText( path ) 0127 0128 def browsePath( self ): 0129 0130 tmp = QFileDialog.getExistingDirectory( "/home", 0131 self, 0132 "get tmp dir", 0133 "Choose working directory", 0134 1) 0135 self.tmppath.setText( tmp ) 0136 0137 0138 def unpack( self ): 0139 0140 # now the fun part, we run part 1 0141 fd = os.popen("kde-config --prefix", "r") 0142 kdedir = fd.readline() 0143 kdedir = kdedir.strip() 0144 scriptdir = kdedir + "/share/apps/amarok/scripts/amarok_live" 0145 fd.close() 0146 0147 path, iso = self.readConfig() 0148 os.system("kdesu -t sh %s/amarok.live.remaster.part1.sh %s %s" % (scriptdir, path, iso)) 0149 #os.wait() 0150 print "got path: %s" % path 0151 0152 0153 0154 0155 def readConfig( self ) : 0156 path = "" 0157 iso = "" 0158 try: 0159 config = ConfigParser.ConfigParser() 0160 config.read("remasterrc") 0161 path = config.get("General", "path") 0162 iso = config.get("General", "iso") 0163 except: 0164 pass 0165 return (path, iso) 0166 0167 0168 0169 class Notification( QCustomEvent ): 0170 __super_init = QCustomEvent.__init__ 0171 def __init__( self, str ): 0172 0173 0174 self.__super_init(QCustomEvent.User + 1) 0175 self.string = str 0176 0177 class Remasterer( QApplication ): 0178 """ The main application, also sets up the Qt event loop """ 0179 0180 def __init__( self, args ): 0181 QApplication.__init__( self, args ) 0182 debug( "Started." ) 0183 0184 # Start separate thread for reading data from stdin 0185 self.stdinReader = threading.Thread( target = self.readStdin ) 0186 self.stdinReader.start() 0187 0188 self.readSettings() 0189 0190 0191 # ugly hack, thanks mp8 anyway 0192 os.system("dcop amarok script removeCustomMenuItem \"Amarok live\" \"Add playlist to livecd\"") 0193 os.system("dcop amarok script removeCustomMenuItem \"Amarok live\" \"Add selected to livecd\"") 0194 os.system("dcop amarok script removeCustomMenuItem \"Amarok live\" \"Create Remastered CD\"") 0195 os.system("dcop amarok script removeCustomMenuItem \"Amarok live\" \"Clear Music on livecd\"") 0196 0197 os.system("dcop amarok script addCustomMenuItem \"Amarok live\" \"Add playlist to livecd\"") 0198 os.system("dcop amarok script addCustomMenuItem \"Amarok live\" \"Add selected to livecd\"") 0199 os.system("dcop amarok script addCustomMenuItem \"Amarok live\" \"Create Remastered CD\"") 0200 os.system("dcop amarok script addCustomMenuItem \"Amarok live\" \"Clear Music on livecd\"") 0201 0202 0203 def readSettings( self ): 0204 """ Reads settings from configuration file """ 0205 0206 try: 0207 path = config.get( "General", "path" ) 0208 0209 except: 0210 debug( "No config file found, using defaults." ) 0211 0212 0213 ############################################################################ 0214 # Stdin-Reader Thread 0215 ############################################################################ 0216 0217 def readStdin( self ): 0218 """ Reads incoming notifications from stdin """ 0219 0220 while True: 0221 # Read data from stdin. Will block until data arrives. 0222 line = sys.stdin.readline() 0223 0224 if line: 0225 qApp.postEvent( self, Notification(line) ) 0226 else: 0227 break 0228 0229 0230 ############################################################################ 0231 # Notification Handling 0232 ############################################################################ 0233 0234 def customEvent( self, notification ): 0235 """ Handles notifications """ 0236 0237 string = QString(notification.string) 0238 debug( "Received notification: " + str( string ) ) 0239 0240 if string.contains( "configure" ): 0241 self.configure() 0242 if string.contains( "stop"): 0243 self.stop() 0244 0245 elif string.contains( "customMenuClicked" ): 0246 if "selected" in string: 0247 self.copyTrack( string ) 0248 elif "playlist" in string: 0249 self.copyPlaylist() 0250 elif "Create" in string: 0251 self.createCD() 0252 elif "Clear" in string: 0253 self.clearCD() 0254 0255 0256 # Notification callbacks. Implement these functions to react to specific notification 0257 # events from Amarok: 0258 0259 def configure( self ): 0260 debug( "configuration" ) 0261 0262 self.dia = ConfigDialog() 0263 self.dia.show() 0264 #self.connect( self.dia, SIGNAL( "destroyed()" ), self.readSettings ) 0265 0266 def clearCD( self ): 0267 0268 self.dia = ConfigDialog() 0269 path, iso = self.dia.readConfig() 0270 0271 os.system("rm -rf %s/amarok.live/music/* %s/amarok.live/playlist/* %s/amarok.live/home/amarok/.kde/share/apps/amarok/current.xml" % (path, path, path)) 0272 0273 def onSignal( self, signum, stackframe ): 0274 stop() 0275 0276 def stop( self ): 0277 0278 fd = open("/tmp/amarok.stop", "w") 0279 fd.write( "stopping") 0280 fd.close() 0281 0282 os.system("dcop amarok script removeCustomMenuItem \"Amarok live\" \"Add playlist to livecd\"") 0283 os.system("dcop amarok script removeCustomMenuItem \"Amarok live\" \"Add selected to livecd\"") 0284 os.system("dcop amarok script removeCustomMenuItem \"Amarok live\" \"Create Remastered CD\"") 0285 os.system("dcop amarok script removeCustomMenuItem \"Amarok live\" \"Clear Music on livecd\"") 0286 0287 0288 def copyPlaylist( self ): 0289 0290 self.dia = ConfigDialog() 0291 path, iso = self.dia.readConfig() 0292 if path == "": 0293 os.system("dcop amarok playlist popupMessage 'Please run configure first.'") 0294 return 0295 0296 tmpfileloc = os.tmpnam() 0297 os.system("dcop amarok playlist saveM3u '%s' false" % tmpfileloc) 0298 tmpfile = open(tmpfileloc) 0299 0300 import urllib 0301 0302 files = "" 0303 m3u = "" 0304 for line in tmpfile.readlines(): 0305 if line[0] != "#": 0306 0307 line = line.strip() 0308 0309 # get filename 0310 name = line.split("/")[-1] 0311 0312 #make url 0313 url = "file://" + urllib.quote(line) 0314 0315 #make path on livecd 0316 livecdpath = "/music/" + name 0317 0318 files += url + " " 0319 m3u += livecdpath + "\n" 0320 0321 tmpfile.close() 0322 0323 files = files.strip() 0324 0325 os.system("kfmclient copy %s file://%s/amarok.live/music/" % (files, path)) 0326 0327 import random 0328 suffix = random.randint(0,10000) 0329 # os.system("mkdir %s/amarok.live/home/amarok/.kde/share/apps/amarok/playlists/" % path) 0330 m3uOut = open("/tmp/amarok.live.%s.m3u" % suffix, 'w') 0331 0332 m3u = m3u.strip() 0333 m3uOut.write(m3u) 0334 0335 m3uOut.close() 0336 0337 os.system("mv /tmp/amarok.live.%s.m3u %s/amarok.live/playlist/" % (suffix,path)) 0338 os.system("rm /tmp/amarok.live.%s.m3u" % suffix) 0339 0340 0341 os.remove(tmpfileloc) 0342 0343 def copyTrack( self, menuEvent ): 0344 0345 event = str( menuEvent ) 0346 debug( event ) 0347 self.dia = ConfigDialog() 0348 0349 path,iso = self.dia.readConfig() 0350 if path == "": 0351 os.system("kdialog --sorry 'You have not specified where the Amarok live iso is. Please click configure and do so first.'") 0352 else: 0353 # get the list of files. yes, its ugly. it works though. 0354 #files = event.split(":")[-1][2:-1].split()[2:] 0355 #trying out a new one 0356 #files = event.split(":")[-1][3:-2].replace("\"Amarok live!\" \"add to livecd\" ", "").split("\" \"") 0357 #and another 0358 0359 files = event.replace("customMenuClicked: Amarok live Add selected to livecd", "").split() 0360 0361 allfiles = "" 0362 for file in files: 0363 allfiles += file + " " 0364 allfiles = allfiles.strip() 0365 os.system("kfmclient copy %s file://%s/amarok.live/music/" % (allfiles, path)) 0366 0367 def createCD( self ): 0368 0369 self.dia = ConfigDialog() 0370 path,iso = self.dia.readConfig() 0371 if path == "": 0372 os.system("kdialog --sorry 'You have not configured Amarok live! Please run configure.") 0373 0374 fd = os.popen("kde-config --prefix", "r") 0375 kdedir = fd.readline() 0376 kdedir = kdedir.strip() 0377 scriptdir = kdedir + "/share/apps/amarok/scripts/amarok_live" 0378 fd.close() 0379 0380 os.system("kdesu sh %s/amarok.live.remaster.part2.sh %s" % (scriptdir, path)) 0381 0382 fd = open("/tmp/amarok.script", 'r') 0383 y = fd.readline() 0384 y = y.strip() 0385 if y == "end": # user said no more, clear path 0386 self.dia.clear() 0387 fd.close() 0388 0389 0390 ############################################################################ 0391 0392 def onSignal( signum, stackframe ): 0393 fd = open("/tmp/amarok.stop", "w") 0394 fd.write( "stopping") 0395 fd.close() 0396 0397 print 'STOPPING' 0398 0399 os.system("dcop amarok script removeCustomMenuItem \"Amarok live\" \"Add playlist to livecd\"") 0400 os.system("dcop amarok script removeCustomMenuItem \"Amarok live\" \"Add selected to livecd\"") 0401 os.system("dcop amarok script removeCustomMenuItem \"Amarok live\" \"Create Remastered CD\"") 0402 os.system("dcop amarok script removeCustomMenuItem \"Amarok live\" \"Clear Music on livecd\"") 0403 0404 0405 def debug( message ): 0406 """ Prints debug message to stdout """ 0407 0408 print debug_prefix + " " + message 0409 0410 def main(): 0411 app = Remasterer( sys.argv ) 0412 0413 # not sure if it works or not... playing it safe 0414 dia = ConfigDialog() 0415 0416 app.exec_loop() 0417 0418 if __name__ == "__main__": 0419 0420 mainapp = threading.Thread(target=main) 0421 mainapp.start() 0422 signal.signal(15, onSignal) 0423 print signal.getsignal(15) 0424 while 1: sleep(120) 0425 0426 #main( sys.argv ) 0427