beets / beets / device.py

# This file is part of beets.
# Copyright 2010, Adrian Sampson.
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
# 
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.

import os
import sys
import socket
import locale
import gpod
from beets.library import BaseLibrary, Item

FIELD_MAP = {
    'artist':   'artist',
    'title':    'title',
    'BPM':      'bpm',
    'genre':    'genre',
    'album':    'album',
    'cd_nr':    'disc',
    'cds':      'disctotal',
    'track_nr': 'track',
    'tracks':   'tracktotal',
}

def track_to_item(track):
    data = {}
    for dname, bname in FIELD_MAP.items():
        data[bname] = track[dname]
    data['length'] = float(track['tracklen']) / 1000
    data['path'] = track.ipod_filename()
    return Item(data)

class PodLibrary(BaseLibrary):
    def __init__(self, path):
        self.db = gpod.Database(path)
        self.syncing = False
    
    @classmethod
    def by_name(cls, name):
        return cls(os.path.join(os.path.expanduser('~'), '.gvfs', name))

    def _start_sync(self):
        # Make sure we have a version of libgpod with these
        # iPhone-specific functions.
        if self.syncing:
            return
        if hasattr(gpod, 'itdb_start_sync'):
            gpod.itdb_start_sync(self.db._itdb)
        self.syncing = True

    def _stop_sync(self):
        if not self.syncing:
            return
        if hasattr(gpod, 'itdb_stop_sync'):
            gpod.itdb_stop_sync(self.db._itdb)
        self.syncing = False

    def add(self, item):
        self._start_sync()
        track = self.db.new_Track()
        track['userdata'] = {
            'transferred': 0,
            'hostname': socket.gethostname(),
            'charset': locale.getpreferredencoding(),
            'pc_mtime': os.stat(item.path).st_mtime,
        }
        track._set_userdata_utf8('filename', item.path.encode())
        for dname, bname in FIELD_MAP.items():
            track[dname] = getattr(item, bname)
        track['tracklen'] = int(item.length * 1000)
        self.db.copy_delayed_files()

    def get(self, query=None):
        query = self._get_query(query)
        for track in self.db:
            item = track_to_item(track)
            if query.match(item):
                yield item

    def save(self):
        self._stop_sync()
        gpod.itdb_write(self.db._itdb, None)

    def load(self, item, load_id=None):
        raise NotImplementedError

    def store(self, item, store_id=None, store_all=False):
        raise NotImplementedError

    def remove(self, item):
        raise NotImplementedError
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.