# Copyright (C) 2008-2010 Adam Olsen
#
# This program 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 2, or (at your option)
# any later version.
#
# This program 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 this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
#
# The developers of the Exaile media player hereby grant permission
# for non-GPL compatible GStreamer and Exaile plugins to be used and
# distributed together with GStreamer and Exaile. This permission is
# above and beyond the permissions granted by the GPL license by which
# Exaile is covered. If you modify this code, you may extend this
# exception to your version of the code, but you are not obligated to
# do so. If you do not wish to do so, delete this exception statement
# from your version.

"""
Devices

contains the DeviceManager and some generic Device classes
"""

from xl import common, event, collection


class DeviceManager(object):
    """
        manages devices
    """
    def __init__(self):
        self.devices = {}

    def add_device(self, device):
        # make sure we don't overwrite existing devices
        count = 3
        if device.get_name() in self.devices:
            device.name += " (2)"
        while device.get_name() in self.devices:
            device.name = device.name[:-4] + " (%s)"%count
            count += 1

        self.devices[device.get_name()] = device
        event.log_event("device_added", self, device)

    def remove_device(self, device):
        try:
            if device.connected:
                device.disconnect()
            del self.devices[device.get_name()]
        except KeyError:
            pass
        event.log_event("device_removed", self, device)

    def list_devices(self):
        return self.devices.values()

class TransferNotSupportedError(Exception):
    pass

class Device(object):
    """
        a device

        must be subclassed for use
    """
    class_autoconnect = False
    library_class = collection.Library

    def __init__(self, name):
        self.name = name
        self.collection = collection.Collection(name=self.name)
        self.playlists = []
        self._connected = False
        self.transfer = None    # subclasses need to override this
                                # if they want transferring

    def __get_connected(self):
        return self._connected

    def __set_connected(self, val):
        prior = self._connected
        self._connected = val
        if prior != val:
            if val:
                event.log_event("device_connected", self, self)
            else:
                event.log_event("device_disconnected", self, self)

    connected = property(__get_connected, __set_connected)

    def get_name(self):
        return self.name

    def autoconnect(self):
        if self.class_autoconnect:
            self.connect()

    def is_connected(self):
        return self.connected

    def connect(self):
        """
            connects to the device, creating Collections and Playlists
            as appropriate
        """
        raise NotImplementedError

    def disconnect(self):
        """
            disconnect from the device. should clear all stored metadata
        """
        raise NotImplementedError

    def get_collection(self):
        """
            returns the device's collection, if applicable
        """
        return self.collection

    def get_playlists(self):
        """
            returns a list of all playlists on the device, if any
        """
        return self.playlists

    def add_tracks(self, tracks):
        """
            Send tracks to the device
        """
        if not self.transfer:
            raise TransferNotSupportedError, "Device class does not " \
                    "support transfer."
        self.transfer.enqueue(tracks)

    def start_transfer(self):
        if not self.transfer:
            raise TransferNotSupportedError, "Device class does not " \
                    "support transfer."
        self.transfer.transfer()

# vim: et sts=4 sw=4

