Skip to content
This repository has been archived by the owner on Apr 16, 2019. It is now read-only.

Commit

Permalink
Adds optional true file size reporting of mp3s. This produces much sl…
Browse files Browse the repository at this point in the history
…ower

directory reads, but is less error-prone.
  • Loading branch information
EnigmaCurry committed Dec 29, 2012
1 parent 407aab0 commit 3791b51
Showing 1 changed file with 30 additions and 11 deletions.
41 changes: 30 additions & 11 deletions gmusicfs/gmusicfs.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ class NoCredentialException(Exception):

class Album(object):
'Keep record of Album information'
def __init__(self, api, normtitle):
self.api = api
def __init__(self, library, normtitle):
self.library = library
self.normtitle = normtitle
self.__tracks = []
self.__sorted = True
Expand All @@ -34,10 +34,18 @@ def add_track(self, track):
self.__tracks.append(track)
self.__sorted = False

def get_tracks(self):
def get_tracks(self, get_size=False):
# Re-sort by track number:
if not self.__sorted:
self.__tracks.sort(key=lambda t: t.get('track'))
# Retrieve and remember the filesize of each track:
if get_size and self.library.true_file_size:
for t in self.__tracks:
if not t.has_key('bytes'):
r = urllib2.Request(self.get_track_stream(t))
r.get_method = lambda: 'HEAD'
u = urllib2.urlopen(r)
t['bytes'] = int(u.headers['Content-Length'])
return self.__tracks

def get_track(self, filename):
Expand All @@ -53,7 +61,7 @@ def get_track(self, filename):

def get_track_stream(self, track):
"Get the track stream URL"
return self.api.get_stream_url(track['id'])
return self.library.api.get_stream_url(track['id'])

def get_cover_url(self):
'Get the album cover image URL'
Expand Down Expand Up @@ -88,11 +96,12 @@ def __repr__(self):
class MusicLibrary(object):
'Read information about your Google Music library'

def __init__(self, username=None, password=None):
def __init__(self, username=None, password=None, true_file_size=False):
self.__artists = {} # 'artist name' -> {'album name' : Album(), ...}
self.__albums = [] # [Album(), ...]
self.__login(username, password)
self.__aggregate_albums()
self.true_file_size = true_file_size

def __login(self, username=None, password=None):
# If credentials are not specified, get them from $HOME/.gmusicfs
Expand Down Expand Up @@ -137,7 +146,7 @@ def __aggregate_albums(self):
if artist == '':
artist = 'unknown'
album = all_artist_albums[key] = Album(
self.api, track['albumNorm'])
self, track['albumNorm'])
self.__albums.append(album)
artist_albums = self.__artists.get(artist, None)
if artist_albums:
Expand All @@ -162,7 +171,8 @@ def get_artist_albums(self, artist):

class GMusicFS(LoggingMixIn, Operations):
'Google Music Filesystem'
def __init__(self, path, username=None, password=None):
def __init__(self, path, username=None, password=None,
true_file_size=False):
Operations.__init__(self)
self.artist_dir = re.compile('^/artists/(?P<artist>[^/]+)$')
self.artist_album_dir = re.compile(
Expand All @@ -175,7 +185,8 @@ def __init__(self, path, username=None, password=None):
self.__open_files = {} # path -> urllib2_obj

# login to google music and parse the tracks:
self.library = MusicLibrary(username, password)
self.library = MusicLibrary(username, password,
true_file_size=true_file_size)
log.info("Filesystem ready : %s" % path)

def getattr(self, path, fh=None):
Expand All @@ -200,9 +211,13 @@ def getattr(self, path, fh=None):
elif artist_album_dir_m:
pass
elif artist_album_track_m:
parts = artist_album_track_m.groupdict()
album = self.library.get_artists()[
parts['artist']][parts['album']]
track = album.get_track(parts['track'])
st = {
'st_mode' : (S_IFREG | 0444),
'st_size' : 200000000 }
'st_size' : track.get('bytes', 20000000) }
elif artist_album_image_m:
st = {
'st_mode' : (S_IFREG | 0444),
Expand Down Expand Up @@ -274,7 +289,7 @@ def readdir(self, path, fh):
album = self.library.get_artists()[
parts['artist']][parts['album']]
files = ['.','..']
for track in album.get_tracks():
for track in album.get_tracks(get_size=True):
files.append('%03d - %s.mp3' % (track['track'],
track['titleNorm']))
# Include cover image:
Expand All @@ -293,6 +308,9 @@ def main():
action='store_true', dest='verbose')
parser.add_argument('-vv', '--veryverbose', help='Be very verbose',
action='store_true', dest='veryverbose')
parser.add_argument('-t', '--truefilesize', help='Report true filesizes'
' (slower directory reads)',
action='store_true', dest='true_file_size')
args = parser.parse_args()

mountpoint = os.path.abspath(args.mountpoint)
Expand All @@ -311,7 +329,8 @@ def main():
logging.getLogger('gmusicapi.Api').setLevel(logging.WARNING)
logging.getLogger('fuse').setLevel(logging.WARNING)

fuse = FUSE(GMusicFS(mountpoint), mountpoint, foreground=args.foreground,
fuse = FUSE(GMusicFS(mountpoint, true_file_size=args.true_file_size),
mountpoint, foreground=args.foreground,
ro=True, nothreads=True)

if __name__ == '__main__':
Expand Down

0 comments on commit 3791b51

Please sign in to comment.