1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
#
# Copyright (C) 2009 Anton Khirnov <wyskas@gmail.com>
#
# Nephilim is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Nephilim is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Nephilim. If not, see <http://www.gnu.org/licenses/>.
#
from PyQt4 import QtCore
import os
from common import sec2min
class Song(dict):
"""Song provides a dictionary-like wrapper around song metadata.
Its instances _shouldn't_ be stored, use SongRef or PlaylistEntryRef for that."""
def __init__(self, data):
for tag in data:
if isinstance(data[tag], list):
data[tag] = ','.join(data[tag])
dict.__init__(self, data)
def __eq__(self, other):
if not isinstance(other, Song):
return NotImplemented
return self['file'] == other['file']
def __ne__(self, other):
if not isinstance(other, Song):
return NotImplemented
return self['file'] != other['file']
def __getitem__(self, key):
try:
return dict.__getitem__(self, key)
except KeyError:
if key == 'tracknum':
try:
return int(self['track'])
except ValueError:
try:
return int(self['track'].split('/')[0])
except ValueError:
return 0
elif key == 'length':
return sec2min(int(self['time']))
elif key == 'id':
return '-1'
elif key == 'title':
return self['file']
elif key == 'albumartist':
return self['artist']
return ''
def __nonzero__(self):
return bool(self['file'])
def expand_tags(self, str):
"""Expands tags in form $tag in str."""
ret = str
ret = ret.replace('$title', self['title']) #to ensure that it is set to at least filename
for tag in self.keys() + ['tracknum', 'length', 'id']:
ret = ret.replace('$' + tag, unicode(self[tag]))
ret = ret.replace('$songdir', os.path.dirname(self['file']))
return ret
class SongRef:
"""SongRef stores only a reference to the song (uri) instead
of full metadata to conserve memory. Song's tags can be accessed
as in Song, but it requires a call to MPD for each tag. """
path = None
mpclient = None
def __init__(self, mpclient, path):
self.mpclient = mpclient
self.path = path
def __getitem__(self, key):
return self.song()[key]
def __nonzero__(self):
return bool(self.path)
def song(self):
try:
return Song(self.mpclient.find('file', self.path)[0])
except IndexError:
return Song({})
class PlaylistEntryRef:
"""This class stores a reference to a playlist entry instead of full
metadata to conserve memory. Song's tags can be accessed
as in Song, but it requires a call to MPD for each tag. """
plid = None
mpclient = None
def __init__(self, mpclient, plid):
self.mpclient = mpclient
self.plid = plid
def __getitem__(self, key):
return self.plid if key == 'id' else self.song()[key]
def __nonzero__(self):
return self.plid != '-1'
def song(self):
try:
return self.mpclient.playlistid(self.plid)
except IndexError:
return Song({})
|