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