2 # Copyright (C) 2009 Anton Khirnov <wyskas@gmail.com>
4 # Nephilim is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU General Public License as published by
6 # the Free Software Foundation, either version 3 of the License, or
7 # (at your option) any later version.
9 # Nephilim is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
14 # You should have received a copy of the GNU General Public License
15 # along with Nephilim. If not, see <http://www.gnu.org/licenses/>.
18 from PyQt4
import QtCore
20 from string
import Template
22 from common
import sec2min
25 """Song provides a dictionary-like wrapper around song metadata.
26 Its instances _shouldn't_ be stored, use SongRef or PlaylistEntryRef for that.
27 Access '?tag' to get always at least an empty string. """
29 def __init__(self
, data
= {}):
32 dict.__setitem
__(self
, key
.lower(), data
[key
])
33 if not 'file' in self
:
36 def __eq__(self
, other
):
37 if not isinstance(other
, Song
):
39 return self
['file'] == other
['file']
41 def __ne__(self
, other
):
42 if not isinstance(other
, Song
):
44 return self
['file'] != other
['file']
46 def __getitem__(self
, key
):
49 return dict.__getitem
__(self
, key
)
51 if key
and key
[0] == '?':
53 return self
[key
] if key
in self
else ''
56 return int(self
['track'])
59 return int(self
['track'].split('/')[0])
63 return sec2min(int(self
['time']))
68 elif key
== 'albumartist':
70 elif key
== 'songdir':
71 return os
.path
.dirname(self
['file'])
75 def __contains__(self
, item
):
76 if dict.__contains
__(self
, item
.lower()):
84 def __nonzero__(self
):
85 return bool(self
['file'])
87 def expand_tags(self
, s
):
88 """Expands tags in form ${tag} in string s."""
90 ret
= ret
.safe_substitute(self
)
94 """SongRef stores only a reference to the song (uri) instead
95 of full metadata to conserve memory. Song's tags can be accessed
96 as in Song, but it requires a call to MPD for each tag. """
100 def __init__(self
, mpclient
, path
):
101 self
.mpclient
= mpclient
104 def __getitem__(self
, key
):
105 return self
.song()[key
]
107 def __nonzero__(self
):
108 return bool(self
.path
)
111 return list(self
.mpclient
.find_sync('file', self
.path
))[0]
113 class PlaylistEntryRef
:
114 """This class stores a reference to a playlist entry instead of full
115 metadata to conserve memory. Song's tags can be accessed
116 as in Song, but it requires a call to MPD for each tag. """
120 def __init__(self
, mpclient
, plid
):
121 self
.mpclient
= mpclient
124 def __getitem__(self
, key
):
125 return self
.plid
if key
== 'id' else self
.song()[key
]
127 def __nonzero__(self
):
128 return self
.plid
!= '-1'
131 return self
.mpclient
.get_plist_song(self
.plid
)