[svn] Many cleanup, both architecture (division of interface), encoding
behavior and also many bugs corrected.
--- a/bestofimms Sun Feb 08 17:27:21 2004 -0500
+++ b/bestofimms Mon Feb 09 23:29:08 2004 -0500
@@ -1,36 +1,17 @@
#!/usr/bin/python
-import imms
+import os
+from sys import stderr, argv
from htmltmpl import TemplateManager, TemplateProcessor
-import os
-import ID3
-from sys import stderr
-from ogg.vorbis import VorbisFile
-
-_template = __file__ + '.tmpl'
-
-def rating_to_color(rating):
- i = rating - 75
- if i <= 25:
- red = 255
- green = i * 255 / 25
- blue = 0
- elif i <= 50:
- red = (50-i) * 255 / 25
- green = 255
- blue = 0
- else:
- red = 0
- green = 255
- blue = (i-50) * 255 / 25
- return "#%02X%02X%02X" % (red, green, blue)
+from utils import get_song_info
+from imms import IMMSDb, rating_to_color
def sort_rating(x, y):
return x['rating']-y['rating']
-def grab_tunes():
- db = imms.IMMSDb()
- rates = db.get_ratings(125)
+def grab_tunes(minrate = 75, maxrate = 150):
+ db = IMMSDb()
+ rates = db.get_ratings(minrate, maxrate)
uids = map(lambda x: x[0], rates)
files = db.get_paths(uids)
d = {}
@@ -51,37 +32,27 @@
res = []
for tune in tunes:
song = tune['path']
- try:
- os.stat(song)
- except:
- continue
+ if not os.path.isfile(song):
+ continue
+ artist, title = get_song_info(song)
+ if artist and title:
+ tune['path'] = artist + ' - ' + title
tune['color'] = rating_to_color(tune['rating'])
- if song[-4:] == '.mp3':
- id3 = ID3.ID3(song)
- try:
- tune['path'] = \
- id3['ARTIST'] + \
- ' - ' + id3['TITLE']
- except:
- pass
- elif song[-4:] == '.ogg':
- vf = VorbisFile(song)
- vc = vf.comment()
- try:
- tune['path'] = \
- vc['ARTIST'][0] + \
- u' - ' + vc['TITLE'][0]
- except:
- pass
res.append(tune)
return res
-def output_web():
+def output_web(template):
tproc = TemplateProcessor()
- tmpl = TemplateManager().prepare(_template)
- tproc.set('Bestof', check_tunes(grab_tunes()))
- print tproc.process(tmpl)
+ tmpl = TemplateManager().prepare(template)
+ tproc.set('Bestof', check_tunes(grab_tunes(125)))
+ return tproc.process(tmpl)
+
+_template = 'bestofimms.tmpl'
+if globals().has_key('__file__'):
+ _template = __file__ + '.tmpl'
if __name__ == '__main__':
- output_web()
+ if len(argv) > 1:
+ _template = argv[1]
+ print output_web(_template)
--- a/bestofimms.tmpl Sun Feb 08 17:27:21 2004 -0500
+++ b/bestofimms.tmpl Mon Feb 09 23:29:08 2004 -0500
@@ -1,12 +1,21 @@
-<html>
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html
+ PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
- <title>Fabien Niñoles's Top Songs</title>
+ <title>Fabien Niñoles's Top Songs</title>
+ <style type="text/css">
+ <!--
+ body { background: black; color: grey }
+ -->
+ </style>
</head>
- <body style="background: black; color: white">
+ <body>
<h1>Fabien Niñoles's Top Songs</h1>
<ul>
<TMPL_LOOP Bestof>
- <li style="color: <TMPL_VAR color>"><TMPL_VAR rating> - <tt><TMPL_VAR path></tt></li>
+ <li><span style="color: <TMPL_VAR color>"><TMPL_VAR rating> - <tt><TMPL_VAR path></tt></span></li>
</TMPL_LOOP>
</ul>
</body>
--- a/cleanimms Sun Feb 08 17:27:21 2004 -0500
+++ b/cleanimms Mon Feb 09 23:29:08 2004 -0500
@@ -1,39 +1,41 @@
#!/usr/bin/python
import os
-import sqlite
-from ogg.vorbis import VorbisFile
-import ID3
import readline
-import imms
+from imms import IMMSCleaner, IMMSDb
from utils import unique, copy_file, set_file_completer
-
-class CleanupIMMS:
- def __init__(self, db_file):
- self.db = imms.IMMSDb(db_file)
- def check_uid(self, uid):
- lib = self.db.get_library_entries(uid = uid)
- if len(lib) == 0:
- print "Erased uid = ", uid
- self.db.erase_uid(uid)
- def check_sid(self, sid):
- lib = self.db.get_library_entries(sid = sid)
- if len(lib) == 0:
- print "Erased sid = ", uid
- self.db.erase_sid(sid)
- def handle_no_file(self, path, uid, sid):
- other_paths = self.db.get_library_entries(uid = uid)
+class CLICleaner(IMMSCleaner):
+ def check_if_uid_exist(self, uid):
+ other_paths = self.db.get_library_entry(uid = uid)
other_paths = unique(map(lambda x: x[0], other_paths))
for opath in other_paths:
if os.path.isfile(opath):
- return None
- other_paths = self.db.get_library_entries(sid = sid)
+ # if one, release it.
+ return 1
+ return 0
+ def check_and_edit_path(self, path, uid, sid):
+ """Must return the new file name, None to remove
+ it. If the new file name is already in the Db,
+ it will be skip."""
+ # if path exist, skip it.
+ if os.path.isfile(path):
+ return path
+ # if exist another uid with a valid path, remove it.
+ if self.check_if_uid_exist(uid):
+ return None
+ # Elsewhere, first build a list of valid candidate from sid...
+ other_paths = self.db.get_library_entry(sid = sid)
other_paths = unique(map(lambda x: x[0], other_paths))
+ return self.edit_filename(path, other_paths)
+ def edit_filename(self, path, other_paths):
+ # Add them to the history for editing
for opath in other_paths:
if os.path.isfile(opath):
readline.add_history(opath)
+ # And also add the current file as a base for editing.
readline.add_history(path)
+ # Sniff! This doesn't seems to work
readline.insert_text('Edit')
while 1:
cmd = raw_input("I can't find '%s'.\n"
@@ -42,56 +44,18 @@
cmd = cmd.lstrip()[0].lower()
if cmd == 'e':
newpath = raw_input()
+ # Already exist, so delete.
if newpath in other_paths:
return None
+ # new file so keep it.
if os.path.isfile(newpath):
return newpath
+ # Elsewhere move it.
print "Invalid filename!"
elif cmd == 's':
return path;
elif cmd == 'r':
return None
- def clean_library(self):
- lib = self.db.get_library_entries()
- deleted_uids = []
- deleted_sids = []
- for entry in lib:
- path, uid, sid = entry
- if not os.path.isfile(path):
- uid = int(uid)
- sid = int(sid)
- newfile = self.handle_no_file(path, uid, sid)
- if not newfile:
- print "Erasing ", path
- self.db.erase_filename(path)
- deleted_uids.append(uid)
- deleted_sids.append(sid)
- elif newfile != path:
- print "Renaming ", path, " into ", newfile
- self.db.update_filename(path, newfile)
- else:
- print "Skipping ", path
- map(self.check_uid, unique(deleted_uids))
- map(self.check_sid, unique(deleted_sids))
- def clean_rating(self):
- rates = self.db.get_ratings()
- rates = unique(map(lambda x: x[0], rates))
- map(self.check_uid, rates)
- def clean_acoustic(self):
- uids = map(lambda x: x[0], self.db.get_acoustics())
- map(self.check_uid, uids)
- def clean_info(self):
- sids = map(lambda x: x[0], self.db.get_infos())
- map(self.check_sid, sids)
- def clean_last(self):
- sids = map(lambda x: x[0], self.db.get_last())
- map(self.check_sid, sids)
- def clean_all(self):
- self.clean_library()
- self.clean_rating()
- self.clean_acoustic()
- self.clean_info()
- self.clean_last()
if __name__ == '__main__':
set_file_completer()
@@ -100,11 +64,15 @@
db_backup = db_file + '.bak'
copy_file(db_file, db_backup).close()
try:
- clean_up = CleanupIMMS(db_file)
+ CLICleaner(IMMSDb(db_file)).clean_all()
except Exception, inst:
print inst
- ans = raw_input('Do you want to get back the backup file? ')
- if len(ans) > 0:
- if ans.lstrip()[0].lower() == 'y':
- copy_file(db_backup, db_file)
+ while 1:
+ ans = raw_input('Do you want to get back the backup file? ')
+ if len(ans) > 0:
+ ans = ans.lstrip()[0].lower()
+ if ans == 'y':
+ copy_file(db_backup, db_file)
+ elif ans == 'n':
+ break
print "backup file preserved: %s." % db_backup
--- a/imms.py Sun Feb 08 17:27:21 2004 -0500
+++ b/imms.py Mon Feb 09 23:29:08 2004 -0500
@@ -1,18 +1,32 @@
-import os
+import os.path
+from sys import stderr
import sqlite
+from utils import sql_quote, unique
+
+_log = stderr
-def quote_sql(str):
- return str.replace("'", "''")
-
+def rating_to_color(rating):
+ i = rating - 75
+ red = green = blue = 0
+ if i <= 25:
+ red = 255
+ green = i * 255 / 25
+ elif i <= 50:
+ red = (50-i) * 255 / 25
+ green = 255
+ else:
+ green = 255
+ blue = (i-50) * 255 / 25
+ return "#%02x%02x%02x" % (red, green, blue)
+
class IMMSDb:
def __init__(self, dbname = None):
if not dbname:
dbname = os.environ['HOME'] + '/.imms/imms.db'
# autocommit = 1 disable autocommit!
- self.cx = sqlite.connect(dbname, autocommit = 1,
- timeout = 2, encoding = ('utf-8', 'replace'))
+ self.cx = sqlite.connect(dbname, autocommit = 1, timeout = 5)
self.cu = self.cx.cursor()
- def get_library_entry(self):
+ def get_library_entry(self, **kw):
qry = "SELECT path, uid, sid FROM Library";
first = 1
for key in kw.keys():
@@ -24,18 +38,19 @@
if key in ['uid', 'sid']:
qry += "%s = %d" % (key, kw[key])
else:
- qry += "%s = '%s'" % (key, quote_sql(kw[key]))
+ qry += "%s = '%s'" % (key, sql_quote(kw[key]))
qry += ";"
self.cu.execute(qry)
return self.cu.fetchall()
+ return res
def update_filename(self, oldname, newname):
self.cu.execute("""UPDATE Library
SET path = '%s'
- WHERE path = '%s';""" % (quote_sql(newname),
- quote_sql(oldname)))
+ WHERE path = '%s';""" % (sql_quote(newname),
+ sql_quote(oldname)))
def erase_filename(self, name):
self.cu.execute("""DELETE FROM Library
- WHERE path = '%s';""" % quote_sql(name))
+ WHERE path = '%s';""" % sql_quote(name))
def erase_uid(self, uid):
self.cu.execute("""BEGIN TRANSACTION;
DELETE FROM Library WHERE uid = %d;
@@ -47,10 +62,10 @@
DELETE FROM Library WHERE sid = %d;
DELETE FROM Info WHERE sid = %d;
DELETE FROM Last WHERE sid = %d;
- COMMIT;""")
+ COMMIT;""" % (sid, sid, sid))
def erase_path(self, path):
self.cu.execute("DELETE FROM Library WHERE path = '%s';" \
- % quote_sql(path))
+ % sql_quote(path))
def get_paths(self, uids = None, sids = None):
qry = "SELECT uid, sid, path FROM Library"
first = 1
@@ -79,48 +94,51 @@
ORDER BY Rating.rating;''' % (min, max))
return self.cu.fetchall()
def get_acoustics(self, uids = None):
- qry = "SELECT uid, bpm. spectrum FROM Acoustic"
+ qry = "SELECT uid, bpm, spectrum FROM Acoustic"
first = 1
- for uid in uids:
- if first:
- qry += ' WHERE'
- first = 0
- else:
- qry += ' OR'
- qry += " uid = %d" % uid
+ if uids:
+ for uid in uids:
+ if first:
+ qry += ' WHERE'
+ first = 0
+ else:
+ qry += ' OR'
+ qry += " uid = %d" % uid
qry += ';'
self.cu.execute(qry)
return self.cu.fetchall()
def get_infos(self, sids = None):
- qry = "SELECT sid, artist, title FROM Infos"
+ qry = "SELECT sid, artist, title FROM Info"
first = 1
- for sid in sids:
- if first:
- qry += ' WHERE'
- first = 0
- else:
- qry += ' OR'
- qry += " sid = %d" % id
+ if sids:
+ for sid in sids:
+ if first:
+ qry += ' WHERE'
+ first = 0
+ else:
+ qry += ' OR'
+ qry += " sid = %d" % id
qry += ';'
self.cu.execute(qry)
return self.cu.fetchall()
def get_last(self, sids = None):
qry = "SELECT sid, last FROM Last"
first = 1
- for sid in sids:
- if first:
- qry += ' WHERE'
- first = 0
- else:
- qry += ' OR'
- qry += " sid = %d" % id
+ if sids:
+ for sid in sids:
+ if first:
+ qry += ' WHERE'
+ first = 0
+ else:
+ qry += ' OR'
+ qry += " sid = %d" % id
qry += ';'
self.cu.execute(qry)
return self.cu.fetchall()
def get_uid_by_path(self, path):
- entries = self.get_library_entries(path = path)
+ entries = self.get_library_entry(path = path)
return map(lambda x: x[1], entries)
- def get_ratings_and_info(self, uids = None):
+ def get_ratings_and_paths(self, uids = None):
qry = '''SELECT l.uid, r.rating, l.path, ls.last
FROM Library l, Rating r, Last ls
WHERE l.uid = r.uid AND l.sid = ls.sid'''
@@ -136,17 +154,99 @@
results = {}
tune = self.cu.fetchone()
while tune:
- try:
- uid = int(tune[0])
- if results.has_key(uid):
- results[uid]['path'].append(
- tune[2].decode('utf-8', 'replace'))
- else:
- results[uid] = {
- 'rating' : int(tune[1]),
- 'path' : [ tune[2].decode('utf-8', 'replace') ],
- 'last' : int(tune[3])}
- except UnicodeDecodeError:
- print tune[2]
- tune = self.cu.fetchone()
+ uid = int(tune[0])
+ if results.has_key(uid):
+ results[uid]['path'].append(tune[2])
+ else:
+ results[uid] = {
+ 'rating' : int(tune[1]),
+ 'path' : [ tune[2] ],
+ 'last' : int(tune[3])}
+ tune = self.cu.fetchone()
return results
+ def get_ratings_and_infos(self):
+ self.cu.execute('''SELECT r.rating, i.artist, i.title
+ FROM Library l, Rating r, Info i
+ WHERE l.uid = r.uid AND l.sid = i.sid;''')
+ return self.cu.fetchall()
+
+class IMMSCleaner:
+ def __init__(self, db):
+ self.db = db
+ def check_uid(self, uid):
+ lib = self.db.get_library_entry(uid = uid)
+ if len(lib) == 0:
+ print >> _log, "Erased uid = ", uid
+ self.db.erase_uid(uid)
+ def check_sid(self, sid):
+ lib = self.db.get_library_entry(sid = sid)
+ if len(lib) == 0:
+ print >> _log, "Erased sid = ", sid
+ self.db.erase_sid(sid)
+ def is_path_in_db(self, path):
+ return len(self.db.get_library_entry(path = path))
+ # Note: I doesn't much how I handle the two following functions...
+ # May be I must just have the second one and handle everything
+ # else in the derived class.
+ def check_and_edit_path(self, path, uid, sid):
+ """Must return the new path, None to remove
+ it. If the new file name is already in the Db,
+ it will be skip. The skip is more efficient if path
+ is return.
+ This is the default handler which always skip the file by
+ returning path directly.
+ """
+ # The right thing (but not safe) would be to erase the
+ # file if it already exist in the db... But I find it
+ # too much unsafe... Erasing a file shouldn't be easy to
+ # do.
+ return path
+ def clean_library(self):
+ lib = self.db.get_library_entry()
+ print >> _log, "Processing %d entries" % len(lib)
+ deleted_uids = []
+ deleted_sids = []
+ for entry in lib:
+ path, uid, sid = entry
+ uid = int(uid)
+ sid = int(sid)
+ newfile = self.check_and_edit_path(path, uid, sid)
+ if not newfile:
+ print >> _log, "Erasing ", path
+ self.db.erase_filename(path)
+ deleted_uids.append(uid)
+ deleted_sids.append(sid)
+ elif (path == newfile):
+ pass
+ elif self.is_path_in_db(newfile):
+ print >> _log, "Skipping ", path
+ pass
+ else:
+ print >> _log, "Renaming ", path, " into ", newfile
+ self.db.update_filename(path, newfile)
+ map(self.check_uid, unique(deleted_uids))
+ map(self.check_sid, unique(deleted_sids))
+ def clean_rating(self):
+ print >> _log, "Clean Rating"
+ rates = self.db.get_ratings()
+ rates = unique(map(lambda x: x[0], rates))
+ map(self.check_uid, rates)
+ def clean_acoustic(self):
+ print >> _log, "Clean Acoustic"
+ uids = self.db.get_acoustics()
+ uids = map(lambda x: x[0], uids )
+ map(self.check_uid, uids)
+ def clean_info(self):
+ print >> _log, "Clean Info"
+ sids = map(lambda x: x[0], self.db.get_infos())
+ map(self.check_sid, sids)
+ def clean_last(self):
+ print >> _log, "Clean Last"
+ sids = map(lambda x: x[0], self.db.get_last())
+ map(self.check_sid, sids)
+ def clean_all(self):
+ self.clean_library()
+ self.clean_rating()
+ self.clean_acoustic()
+ self.clean_info()
+ self.clean_last()
--- a/immsview Sun Feb 08 17:27:21 2004 -0500
+++ b/immsview Mon Feb 09 23:29:08 2004 -0500
@@ -20,9 +20,13 @@
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.
-_version_ = "$Id: immsview 1713 2004-02-08 21:55:24Z fabien $"
+_version_ = "$Id: immsview 1715 2004-02-10 04:29:08Z fabien $"
# $Log$
+# Revision 1.30 2004/02/10 04:29:08 fabien
+# Many cleanup, both architecture (division of interface), encoding
+# behavior and also many bugs corrected.
+#
# Revision 1.29 2004/02/08 21:55:24 fabien
# New bestofimms, cleanimms, imms.py and utils.py.
#
@@ -149,34 +153,13 @@
import xmms.control
import time
import Gnuplot
-from imms import IMMSDb
+from imms import IMMSDb, rating_to_color
+from utils import strdelay
gtk.glade.bindtextdomain('immsview', '/usr/share/immsview/LANG')
gtk.glade.textdomain('immsview')
_ = gettext.gettext
-
-def strtime(seconds):
- secs = abs(round(seconds))
- minutes = secs / 60;
- hours = minutes / 60;
- days = hours / 24;
- secs = secs % 60;
- minutes %= 60;
- hours %= 24;
-
- if seconds < 0:
- s = "-"
- else:
- s = ""
- if days >= 1:
- s += "%dd %dh" % (days, hours)
- elif hours >= 1:
- s += "%dh%02d" % (hours, minutes)
- elif minutes >= 1:
- s += "%d'%02d\"" % (minutes, secs)
- else:
- s += "%d\"" % (secs)
- return s
+stderr = sys.stderr
class XMMSControl:
def __getattr__(self, name):
@@ -196,24 +179,11 @@
else:
self.set_playlist_pos(idx)
+_gdk_colors = []
+for i in range(75,150+1):
+ _gdk_colors.append(rating_to_color(i))
-_gdk_colors = []
-for i in range(76):
- if i <= 25:
- red = 255
- green = i * 255 / 25
- blue = 0
- elif i <= 50:
- red = (50-i) * 255 / 25
- green = 255
- blue = 0
- else:
- red = 0
- green = 255
- blue = (i-50) * 255 / 25
- _gdk_colors.append("#%02X%02X%02X" % (red, green, blue))
-
-def rating_to_color(rate):
+def gdk_rating_to_color(rate):
rate = min(max(rate,75),150)
return _gdk_colors[rate-75]
@@ -227,7 +197,7 @@
COL_SELECT = 4
COL_UID = 5
COL_RATING_COLOR = 6
- COL_PATHS_NUMBER = 7
+ COL_PATHS = 7
def __init__(self, db):
gtk.ListStore.__init__(self,
gobject.TYPE_INT,
@@ -237,7 +207,7 @@
gobject.TYPE_BOOLEAN,
gobject.TYPE_INT,
gobject.TYPE_STRING,
- gobject.TYPE_INT,
+ gobject.TYPE_PYOBJECT,
)
self.db = db
self.set_default_sort_func(self.default_sort)
@@ -265,11 +235,11 @@
self.set(giter,
IMMSStore.COL_UID, uid,
IMMSStore.COL_RATING, tune['rating'],
- IMMSStore.COL_PATH, fn,
+ IMMSStore.COL_PATH, fn.decode('utf-8','replace'),
IMMSStore.COL_LAST, tune['last'],
- IMMSStore.COL_LAST_STR, strtime(self.curtime-tune['last']),
- IMMSStore.COL_RATING_COLOR, rating_to_color(tune['rating']),
- IMMSStore.COL_PATHS_NUMBER, len(tune['path']),
+ IMMSStore.COL_LAST_STR, strdelay(self.curtime-tune['last']),
+ IMMSStore.COL_RATING_COLOR, gdk_rating_to_color(tune['rating']),
+ IMMSStore.COL_PATHS, tune['path'],
IMMSStore.COL_SELECT, gtk.FALSE)
return giter
def update(self):
@@ -278,8 +248,8 @@
col, order = self.get_sort_column_id()
if col:
self.set_sort_column_id(-1, gtk.SORT_ASCENDING)
- tunes = self.db.get_ratings_and_info()
- print time.ctime(time.time()) + ": inserting"
+ tunes = self.db.get_ratings_and_paths()
+ print >> stderr, time.ctime(time.time()) + ": inserting"
self._update_me(tunes)
print time.ctime(time.time()) + ": end insert"
if col:
@@ -300,38 +270,6 @@
next = self.iter_next(giter)
self.remove(giter)
giter = next
- def refresh(self, tunes):
- "refresh only get new data and update last time and rating."
- freed_giters = []
- # first, try to recycle current giter.
- giter = self.get_iter_first()
- while giter:
- # check if giter exist in DB.
- guid = self.get_value(giter, IMMSStore.COL_UID)
- if tunes.has_key(guid):
- tune = tunes[guid]
- self.set(giter,
- IMMSStore.COL_RATING, tune['rating'],
- IMMSStore.COL_LAST, tune['last'],
- IMMSStore.COL_LAST_STR,
- strtime(self.curtime-tune['last']),
- IMMSStore.COL_RATING_COLOR,
- rating_to_color(tune['rating']))
- else:
- # Elsewhere, collect them for further use...
- # Hopefully, ListStore have persistent giter!
- freed_giters.append(giter)
- giter = self.iter_next(giter)
- # populate the remeaning tunes into the collected giters
- for uid, tune in tunes.iteritems():
- if len(freed_giters) > 0:
- giter = freed_giters.pop()
- else:
- giter = None
- self.tune_to_giter(uid, tune, None, giter)
- # then erase the remeaning giter.
- for giter in freed_giters:
- self.remove(giter)
def find_selected_giter(self):
giter = self.get_iter_first()
while giter:
@@ -353,7 +291,7 @@
uid = uids[0]
giter = self.find_giter_from_uid(uid)
if not giter:
- tunes = self.db.get_ratings_and_info([uid])
+ tunes = self.db.get_ratings_and_paths([uid])
if tunes > 0:
giter = self.tune_to_giter(uid, tunes[uid], song)
else:
@@ -370,14 +308,14 @@
return res
def update_giter(self, giter, path = None):
uid = self.get_value(giter, IMMSStore.COL_UID)
- tunes = self.db.get_ratings_and_info([uid,])
+ tunes = self.db.get_ratings_and_paths([uid,])
if len(tunes) > 0:
return self.tune_to_giter(uid, tunes[uid], path, giter)
return giter
## def get_value(self, giter, col):
## # sniff! Can't override built-ins
## if col == IMMSStore.COL_LAST_STR:
-## return strtime(time.time() -
+## return strdelay(time.time() -
## self.get_value(giter, IMMSStore.COL_LAST))
## else:
## return gtk.ListStore.get_value(self, giter, col)
@@ -421,10 +359,6 @@
text = IMMSStore.COL_LAST_STR)
column.set_sort_column_id(IMMSStore.COL_LAST)
self.append_column(column)
- column = gtk.TreeViewColumn(_("#"), renderer,
- weight_set = IMMSStore.COL_SELECT,
- text = IMMSStore.COL_PATHS_NUMBER)
- self.append_column(column)
column = gtk.TreeViewColumn(_("File"), renderer,
weight_set = IMMSStore.COL_SELECT,
text = IMMSStore.COL_PATH)
@@ -446,12 +380,19 @@
self.set_cursor(model.get_path(giter))
def get_filename(self, giter):
model = self.get_model()
- fn = model.get_value(model.update_giter(giter), IMMSStore.COL_PATH)
- try:
- os.stat(fn)
- except OSError:
+ model.update_giter(giter)
+ paths = model.get_value(giter, IMMSStore.COL_PATHS)
+ enc_path = model.get_value(giter, IMMSStore.COL_PATH)
+ paths = filter(os.path.isfile, paths)
+ # No valid file in list
+ if len(paths) == 0:
return None
- return fn
+ # Try to find the currently display file
+ for fn in paths:
+ if enc_path == fn.decode('utf8', 'replace'):
+ return fn
+ # Else, return the first find
+ return paths[0]
def get_file_selected(self):
model, giter = self.get_selection().get_selected()
if giter:
@@ -494,8 +435,8 @@
song = self.xmms.get_current_file()
try:
self.iview.set_current_song(song)
- except:
- pass
+ except Exception, e:
+ print >> stderr, e
def do_play(self, dummy):
fn = self.iview.get_file_selected()
if fn:
--- a/utils.py Sun Feb 08 17:27:21 2004 -0500
+++ b/utils.py Mon Feb 09 23:29:08 2004 -0500
@@ -1,9 +1,62 @@
-#!/usr/bin/python
-
import dircache, os.path
from sys import stderr
import readline
+def sql_quote(str):
+ return str.replace("'", "''")
+
+def get_song_info(path):
+ "Return (artist, title) pair from path."
+ artist, title = None, None
+ if os.path.isfile(path):
+ if path[-4:] == '.mp3':
+ from ID3 import ID3
+ id3 = ID3(path)
+ try:
+ artist = id3['ARTIST']
+ except:
+ pass
+ try:
+ title = id3['TITLE']
+ except:
+ pass
+ elif path[-4:] == '.ogg':
+ from ogg.vorbis import VorbisFile
+ vf = VorbisFile(path)
+ vc = vf.comment()
+ try:
+ artist = vc['ARTIST'][0]
+ except:
+ pass
+ try:
+ title = vc['TITLE'][0]
+ except:
+ pass
+ return artist, title
+
+def strdelay(seconds):
+ secs = abs(round(seconds))
+ minutes = secs / 60;
+ hours = minutes / 60;
+ days = hours / 24;
+ secs = secs % 60;
+ minutes %= 60;
+ hours %= 24;
+
+ if seconds < 0:
+ s = "-"
+ else:
+ s = ""
+ if days >= 1:
+ s += "%dd %dh" % (days, hours)
+ elif hours >= 1:
+ s += "%dh%02d" % (hours, minutes)
+ elif minutes >= 1:
+ s += "%d'%02d\"" % (minutes, secs)
+ else:
+ s += "%d\"" % (secs)
+ return s
+
def set_file_completer():
readline.set_completer_delims('')
readline.set_completer(_file_completer)