# -*- coding: utf-8 -*-
# Elisa - Home multimedia server
# Copyright (C) 2006-2008 Fluendo Embedded S.L. (www.fluendo.com).
# All rights reserved.
#
# This file is available under one of two license agreements.
#
# This file is licensed under the GPL version 3.
# See "LICENSE.GPL" in the root of this distribution including a special
# exception to use Elisa with Fluendo's plugins.
#
# The GPL part of Elisa is also available under a commercial licensing
# agreement from Fluendo.
# See "LICENSE.Elisa" in the root directory of this distribution package
# for details on that license.


__maintainer__ = 'Florian Boucault <florian@fluendo.com>'
__maintainer2__ = 'Philippe Normand <philippe@fluendo.com>'


from elisa.base_components.view import View
from elisa.core import common
from elisa.core import player
from twisted.internet import reactor, defer
import gst
import os

class PlayerView(View):
    """
    This class implements a view which can create a
    Player instance and manage it.
    This class can be inherited to provide the
    toolkit dependent display, as well as the
    GStreamer video and audio sinks
    """

    supported_controllers = ('base:player_controller',)
    
    def __init__(self):
        super(PlayerView, self).__init__()
        self.player = common.application.player_registry.create_player()
        
    def initialize(self):
        super(PlayerView, self).initialize()
        bus = common.application.bus
        bus.register(self._is_playing, player.PlayerPlaying)
        bus.register(self._stopped, player.PlayerStopping)
        bus.register(self._error, player.PlayerError)

    def _is_playing(self, message, sender):
        if sender == self.player:
            self.player.volume = self.controller.model.volume
            if self.controller.model.state != player.STATES.PLAYING:
                self.controller.model.state = player.STATES.PLAYING
    
    def _error(self, message, sender):
        self._stopped(message, sender)

    def _stopped(self, message, sender):
        if sender == self.player:
            if self.controller.model.state != player.STATES.STOPPED:
                self.controller.model.state = player.STATES.STOPPED

    def attribute_set(self, origin, key, old_value, new_value):
        super(PlayerView, self).attribute_set(origin, key, old_value, new_value)
        self.debug("attribute %r set to %r", key, new_value)
        if key == 'state':

            if new_value == player.STATES.PLAYING:
                self.player.volume = self.controller.model.volume
                self.state_changed(new_value)
                self.player.play()
            elif new_value == player.STATES.PAUSED:
                self.state_changed(new_value)
                self.player.pause()
            elif new_value == player.STATES.STOPPED:
                self.state_changed(new_value)
                if self.player.state != player.STATES.STOPPED:
                    self.player.stop()
        elif key == 'uri':
            self.player.uri = new_value
            self.uri_changed(new_value)
        elif key == 'seek_to':
            self.seek_to_changed(new_value)
        elif key == 'volume':
            self.volume_changed(new_value)
        elif key == 'muted':
            self.player.muted = new_value
        elif key == 'pause_requested':
            self.pause_requested_changed(new_value)
        elif key == 'focused':
            self.focused_changed(new_value)
        elif key == 'media_type':
            self.media_type_changed(new_value)

    def media_type_changed(self, media_type):
        if media_type and self.player.uri:
            self._update_subtitle(self.player.uri)
            
    def state_changed(self, state):
        self.player.volume = self.controller.model.volume
        if self.controller.model.muted:
            self.player.muted = True
        else:
            self.player.muted = False

        self._update_model_position()

    def _update_model_position(self):
        if self.controller.model.duration != self.player.duration:
            self.controller.model.duration = self.player.duration
        if self.controller.model.position != self.player.position:
            self.controller.model.position = self.player.position
        if self.controller.model.state == player.STATES.PLAYING:
            reactor.callLater(0.5, self._update_model_position)

    def uri_changed(self, uri):
        pass

    def pause_requested_changed(self, value):
        pass

    def volume_changed(self, value):
        self.player.volume = value

    def seek_to_changed(self, position):
        self.player.position = position

    def controller_changed(self, old_controller, new_controller):
        state = self.controller.state
        if state == player.STATES.PLAYING:
            self.player.play()
        elif state == player.STATES.PAUSED:
            self.player.pause()
        elif state == player.STATES.STOPPED:
            self.player.stop()

    def _update_subtitle(self, uri):
        """
        We only support text
        """
        self.player.subtitle_uri = None

        SUBTITLE_FORMATS = ("asc", "txt", "srt", "smi", "ssa")

        if uri and self.controller.model.media_type == 'video':
            self.debug("Searching subtitles for %s", uri)
            
            media_manager = common.application.media_manager
            filename = uri.filename
            try:
                ext_index = filename.index(uri.extension)
            except ValueError:
                # extension given but not found
                self.debug("Extension of %r not found, skipping subtitles "\
                           " detection", uri)
            else:
                basename = uri.filename[:ext_index-1]
                parent = uri.parent

                def got_children(children, uri):
                    found = False
                    for child_uri, metadata in children:
                        child_basename, dummy = os.path.splitext(child_uri.filename)
                        if child_basename == basename and \
                               child_uri.extension in SUBTITLE_FORMATS:
                            self.player.subtitle_uri = child_uri
                            self.info("Found subtitles in file: %s", child_uri)
                            found = True
                            break
                    if not found:
                        self.info("No subtitles found for %r", uri)

                dfr = media_manager.get_direct_children(uri.parent, [])
                dfr.addCallback(got_children, uri.parent)
