00001 import os
00002 import ctypes
00003
00004 import cterm
00005
00006 import clnch_misc
00007 import clnch_statusbar
00008 import clnch_colortable
00009 import clnch_ini
00010
00011
00012
00013 class SongMCI:
00014
00015 def __init__( self, filename ):
00016 self.filename = filename
00017 ret = ctypes.windll.winmm.mciSendStringW( u'open "%s" alias %d' % ( self.filename, id(self) ), None, 0, None )
00018 ret = ctypes.windll.winmm.mciSendStringW( u'set %d time format milliseconds' % ( id(self), ), None, 0, None )
00019
00020 def __del__(self):
00021 self.close()
00022
00023 def play(self):
00024 ret = ctypes.windll.winmm.mciSendStringW( u'play %d' % ( id(self), ), None, 0, None )
00025
00026 def isPlaying(self):
00027 buf = ctypes.create_unicode_buffer(32)
00028 ret = ctypes.windll.winmm.mciSendStringW( u'status %d mode' % ( id(self), ), buf, len(buf), None )
00029 if buf.value == u'playing':
00030 return True
00031 else:
00032 return False
00033
00034 def stop(self):
00035 ret = ctypes.windll.winmm.mciSendStringW( u'stop %d' % ( id(self), ), None, 0, None )
00036
00037 def seek( self, pos ):
00038 value = long( pos * 1000 )
00039 if self.isPlaying():
00040 ret = ctypes.windll.winmm.mciSendStringW( u'play %d from %d' % ( id(self), value ), None, 0, None )
00041
00042 def length(self):
00043 buf = ctypes.create_unicode_buffer(32)
00044 ret = ctypes.windll.winmm.mciSendStringW( u'status %d length' % ( id(self), ), buf, len(buf), None )
00045 if ret : return 0.0
00046 return long(buf.value)/1000.0
00047
00048 def position(self):
00049 buf = ctypes.create_unicode_buffer(32)
00050 ret = ctypes.windll.winmm.mciSendStringW( u'status %d position' % ( id(self), ), buf, len(buf), None )
00051 if ret : return 0.0
00052 return long(buf.value)/1000.0
00053
00054 def close(self):
00055 ret = ctypes.windll.winmm.mciSendStringW( u'close %d' % ( id(self), ), None, 0, None )
00056
00057
00058 class MusicPlayer:
00059
00060 def __init__( self, main_window ):
00061
00062 self.main_window = main_window
00063
00064 self.items = []
00065 self.cursor = 0
00066
00067 self.song = None
00068 self.playing = False
00069 self.song_name = u""
00070
00071 self.position = None
00072 self.length = None
00073
00074 self.status_bar = MusicPlayerStatusBar(self)
00075 self.main_window.statusBar().registerLayer(self.status_bar)
00076 self.main_window.paint()
00077
00078 self.main_window.setTimer( self.onTimer, 10 )
00079 self.main_window.setTimer( self.onTimerStatusBar, 1000 )
00080
00081 def destroy(self):
00082
00083 self.stop()
00084
00085 self.main_window.killTimer( self.onTimer )
00086 self.main_window.killTimer( self.onTimerStatusBar )
00087
00088 self.main_window.statusBar().unregisterLayer(self.status_bar)
00089 self.main_window.paint()
00090
00091 def setPlayList( self, items, selection ):
00092 self.stop()
00093 self.items = items
00094 self.cursor = selection
00095 self.song_name = self.items[self.cursor]
00096 self.main_window.paint()
00097
00098 def getPlayList(self):
00099 return ( self.items, self.cursor )
00100
00101 def save( self, section ):
00102 i=0
00103 for item in self.items:
00104 clnch_ini.set( section, "playlist_%d"%(i,), item.encode("utf8") )
00105 i+=1
00106
00107 while True:
00108 if not clnch_ini.remove_option( section, "playlist_%d"%(i,) ) : break
00109 i+=1
00110
00111 clnch_ini.set( section, "track", str(self.cursor) )
00112 clnch_ini.set( section, "position", str(int(self.position)) )
00113
00114 def load( self, section ):
00115 for i in xrange(100):
00116 try:
00117 item =clnch_misc.normPath(unicode( clnch_ini.get( section, "playlist_%d"%(i,) ), "utf8" ))
00118 self.items.append(item)
00119 except:
00120 break
00121
00122 self.cursor = clnch_ini.getint( section, "track", 0 )
00123 self.position = clnch_ini.getint( section, "position", 0 )
00124
00125 self.cursor = min( self.cursor, len(self.items) )
00126 self.song_name = self.items[self.cursor]
00127 self.play()
00128 self.seek(self.position)
00129 self.pause()
00130 self.main_window.paint()
00131
00132 def play(self):
00133 self.song = SongMCI( self.items[self.cursor] )
00134 self.song.play()
00135 self.playing = True
00136
00137 def stop(self):
00138 if self.song:
00139 self.song.close()
00140 self.song = None
00141 self.playing = False
00142
00143 def pause(self):
00144 if self.song:
00145 if self.song.isPlaying():
00146 self.song.stop()
00147 self.playing = False
00148 else:
00149 self.song.play()
00150 self.playing = True
00151
00152 def seek(self,pos):
00153 if self.song:
00154 self.song.seek(pos)
00155
00156 def advance( self, delta ):
00157 if self.song:
00158 p = self.song.position()
00159 t = self.song.length()
00160 p += delta
00161 p = min( p, t )
00162 p = max( p, 0.0 )
00163 self.song.seek(p)
00164
00165 def prev(self):
00166 if self.cursor-1 >= 0:
00167 self.cursor -= 1
00168 self.song_name = self.items[self.cursor]
00169 self.play()
00170 self.main_window.paint()
00171
00172 def next(self):
00173 if self.cursor+1 < len(self.items):
00174 self.cursor += 1
00175 self.song_name = self.items[self.cursor]
00176 self.play()
00177 self.main_window.paint()
00178
00179 def select( self, sel ):
00180 if sel < len(self.items):
00181 self.cursor = sel
00182 self.song_name = self.items[sel]
00183 self.play()
00184 self.main_window.paint()
00185
00186 def isPlaying(self):
00187 return self.playing
00188
00189 def onTimer(self):
00190 if self.song:
00191 if not self.song.isPlaying():
00192 if self.playing:
00193 self.next()
00194 self.position = self.song.position()
00195 self.length = self.song.length()
00196 else:
00197 self.position = None
00198 self.length = None
00199
00200 def onTimerStatusBar(self):
00201 self.main_window.paint()
00202
00203
00204 def _timeString(t):
00205 m = int( t / (60) )
00206 t -= m * (60)
00207 s = int( t )
00208 return u"%d:%02d" % (m,s)
00209
00210 class MusicPlayerStatusBar( clnch_statusbar.StatusBarLayer ):
00211
00212 def __init__( self, music_player ):
00213 clnch_statusbar.StatusBarLayer.__init__( self, 1.0 )
00214 self.music_player = music_player
00215
00216 def paint( self, window, x, y, width, height ):
00217 if self.music_player.position!=None and self.music_player.length!=None:
00218 right = " %s - %s " % ( _timeString(self.music_player.position), _timeString(self.music_player.length-self.music_player.position) )
00219 else:
00220 right = " "
00221 left = u" [ Music %d/%d ] %s" % ( self.music_player.cursor+1, len(self.music_player.items), self.music_player.song_name )
00222 left = clnch_misc.adjustStringWidth( window, left, width-len(right), clnch_misc.ALIGN_LEFT, clnch_misc.ELLIPSIS_RIGHT )
00223 attr = cterm.Attribute( fg=clnch_colortable.bar_fg )
00224 window.putString( x, y, width, y, attr, left+right )