class Channel(QGraphicsWidget):

    def __init__(self , parent):
        QGraphicsWidget.__init__(self)
        self.veromix = parent
        self.index = -1
        self.pa = parent.getPulseAudio()
        self.set_name("")
        self.deleted = True
        self.pa_sink = None
        self.extended_panel_shown = False
        self.extended_panel= None
        self.show_meter = True
        self.expander = None
        self.popup_menu = None
        self.card_settings = None
        self.menus = None
        self.port_actions = None

        self.double_click_filter = ChannelEventFilter(self)
        self.installEventFilter(self.double_click_filter)

        self.init()
        self.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed,True))

    def init(self):
        self.layout = QGraphicsLinearLayout(Qt.Vertical)
        self.layout.setContentsMargins(2,2,2,0)
        self.setLayout(self.layout)
        self.initArrangement()
        self.composeArrangement()
        self.setAcceptDrops(True)
        self._on_upate_expander_enabled()

    def initArrangement(self):
        self.create_frame()
        self.create_panel()
        self.createMute()
        self.createMiddle()
        self.create_expander()

    def composeArrangement(self):
        self.layout.addItem(self.frame)
        self.frame_layout.addItem(self.panel)
        self.panel_layout.addItem(self.mute)
        self.panel_layout.addItem(self.middle)

    def create_frame(self):
        self.frame = Plasma.Frame()
        self.frame_layout = QGraphicsLinearLayout(Qt.Vertical)
        self.frame.setEnabledBorders (Plasma.FrameSvg.NoBorder)
        self.frame.setFrameShadow(Plasma.Frame.Plain)
        self.frame_layout.setContentsMargins(0,0,0,0)
        self.frame.setLayout(self.frame_layout)

    def create_panel(self):
        self.panel = QGraphicsWidget()
        self.panel_layout = QGraphicsLinearLayout(Qt.Horizontal)
        self.panel_layout.setContentsMargins(6,8,10,6)
        self.panel.setLayout(self.panel_layout)

    def createMute(self):
        self.mute = MuteButton(self)
        self.connect(self.mute, SIGNAL("clicked()"), self.on_mute_cb)

    def createMiddle(self):
        self.middle = QGraphicsWidget()
        self.middle_layout = QGraphicsLinearLayout(Qt.Vertical)
        #self.middle_layout.setContentsMargins(6,8,6,0)
        self.middle_layout.setContentsMargins(0,0,0,0)
        self.middle.setLayout(self.middle_layout)
        self.middle.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Minimum))
        self.createSlider()
        self.middle_layout.addItem(self.slider)

    def createSlider(self):
        self.slider = MeterSlider(None, self.veromix.is_slider_unit_value_visible())
        self.slider.installEventFilter(self.double_click_filter)
        self.slider.set_meter_visible(self.veromix.is_meter_visible())
        self.slider.setOrientation(Qt.Horizontal)
        self.slider.setMaximum(self.veromix.get_max_volume_value())
        self.slider.setMinimum(0)
        self.slider.volumeChanged.connect( self.on_slider_cb)

    def create_expander(self):
        self.expander = Plasma.IconWidget(self.panel)
        self.expander.setZValue(10)
        self.connect(self, SIGNAL("geometryChanged()"), self._resize_widgets)
        self.expander.setSizePolicy(QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed))
        self.expander.clicked.connect(self.on_expander_clicked)
        self.expander.setSvg("widgets/arrows", "left-arrow")

    def create_context_menu(self, event):
        self.popup_menu = QMenu()
        self.popup_menu.triggered.connect(self.on_contextmenu_clicked)
        self.context_menu_create_custom()
        self.context_menu_create_mute()
        self.context_menu_create_meter()
        self.context_menu_create_unlock_channels()
        self.context_menu_create_effects()
        self.create_menu_kill_sink()
        self.context_menu_create_settings()
        if event:
            self.popup_menu.exec_(event.screenPos())
        else:
            self.popup_menu.exec_(QCursor.pos())

    def context_menu_create_mute(self):
        action_mute = QAction(i18n("Muted"), self.popup_menu)
        self.popup_menu.addAction(action_mute)
        action_mute.setCheckable(True)
        action_mute.setChecked(self.isMuted())
        action_mute.triggered.connect(self.on_mute_cb)

    def context_menu_create_meter(self):
        action_meter = QAction(i18n("Volume meter"), self.popup_menu)
        self.popup_menu.addAction(action_meter)
        action_meter.setCheckable(True)
        action_meter.setChecked(self.pa_sink.has_monitor())
        action_meter.triggered.connect(self.on_meter_cb)

    def context_menu_create_unlock_channels(self):
        action_unlock = QAction(i18n("Unlock channels"), self.popup_menu)
        self.popup_menu.addAction(action_unlock)
        action_unlock.setCheckable(True)
        action_unlock.setChecked(self.extended_panel_shown)
        action_unlock.triggered.connect(self.toggle_channel_lock)

    def context_menu_create_ports(self):
        self.port_actions = {}
        if len(self.pa_sink.ports.keys()) > 1:
            ports_menu = QMenu(i18n("Ports"), self.popup_menu)
            ports = self.pa_sink.ports

            for port in ports.keys():
                action = QAction(in_unicode(ports[port]), self.popup_menu)
                self.port_actions[action]=port
                if port == self.pa_sink.active_port:
                    action.setCheckable(True)
                    action.setChecked(True)
                else:
                    action.setChecked(False)
                    action.setCheckable(False)
                ports_menu.addAction(action)
            self.popup_menu.addMenu(ports_menu)

    def create_menu_kill_sink(self):
        pass

    def context_menu_create_sounddevices(self):
        self.card_settings = {}
        self.menus = []
        for card in self.veromix.card_infos.values():
            current = self.veromix.get_card_info_for(self)
            if current != None and  current.get_description() == card.get_description():
                card_menu = QMenu(i18n("Profile"), self.popup_menu)
                self.popup_menu.addMenu(card_menu)
            else:
                card_menu = QMenu(card.get_description(), self.popup_menu)
                self.menus.append(card_menu)
            active_profile_name = card.get_active_profile_name()
            self.profiles = card.get_profiles()
            for profile in self.profiles:
                action = QAction(in_unicode(profile.description), card_menu)
                self.card_settings[action] = card
                if profile.name == active_profile_name:
                    action.setCheckable(True)
                    action.setChecked(True)
                card_menu.addAction(action)

    def context_menu_create_sounddevices_other(self):
        if len(self.menus) > 0:
            self.popup_menu.addSeparator()
            for each in self.menus:
                self.popup_menu.addMenu(each)

    def context_menu_create_custom(self):
        pass

    def context_menu_create_effects(self):
        pass

    def context_menu_create_settings(self):
        self.popup_menu.addSeparator()
        action_settings = QAction(i18n("Veromix Settings"), self.popup_menu)
        self.popup_menu.addAction(action_settings)
        action_settings.triggered.connect(self.veromix.applet.showConfigurationInterface)

    def _resize_widgets(self):
        self.expander.setPos(int(self.panel.size().width() - self.expander.size().width()) ,0)

    def on_double_clicked(self):
        self.slider.toggle_meter()
        self.pa_sink.toggle_monitor()
        self.slider.set_meter_value(0)

    def on_step_volume(self, up):
        vol = self.pa_sink.get_volume()
        STEP = 5
        if up:
            vol = vol + STEP
        else:
            vol = vol - STEP
        if vol < 0:
            vol = 0
        if vol > self.veromix.get_max_volume_value():
            vol = self.veromix.get_max_volume_value()
        self.setVolume(vol)

    def setVolume(self, value):
        vol = self.pa_sink.volumeDiffFor(value)
        if self.veromix.get_auto_mute():
            for c in vol:
                if c <= 0:
                    ## FIXME HACK for MurzNN this should be conditional
                    self.pa.set_sink_mute(self.index, True)
                    self.automatically_muted = True
                    return
            if self.automatically_muted :
                self.automatically_muted = False
                self.pa.set_sink_mute(self.index, False)
        self.set_channel_volumes(vol)

    def get_volume(self):
        if self.pa_sink:
            return self.pa_sink.get_volume()
        return [0]

    def on_expander_clicked(self):
        self.contextMenuEvent(None)

    def toggle_channel_lock(self):
        self.middle_layout.removeItem(self.slider)
        self.slider = None
        if (self.extended_panel_shown):
            self.extended_panel_shown = False
            self.expander.setSvg("widgets/arrows", "left-arrow")
            self.createSlider()
            self.middle_layout.addItem(self.slider)
        else:
            self.extended_panel_shown = True
            self.expander.setSvg("widgets/arrows", "down-arrow")
            self.slider = SinkChannelWidget(self.veromix, self)
            self.slider.installEventFilter(self.double_click_filter)
            self.middle_layout.addItem(self.slider)
        self.middle_layout.setContentsMargins(0,0,0,0)
        self.middle.setContentsMargins(0,0,0,0)
        self.update_with_info(self.pa_sink)
        self.veromix.check_geometries()

    def on_update_configuration(self):
        self.slider.set_meter_visible(self.veromix.is_meter_visible())
        self.slider.setMaximum(self.veromix.get_max_volume_value())
        self.slider.set_unit_value_visible(self.veromix.is_slider_unit_value_visible())
        self._on_upate_expander_enabled()

    def _on_upate_expander_enabled(self):
        if self.veromix.is_expander_enabled():
            self.expander.show()
        else:
            self.expander.hide()

    def on_contextmenu_clicked(self, action):
        if action in self.card_settings.keys():
            card = self.card_settings[action]
            for profile in card.get_profiles():
                if action.text() == profile.description:
                    self.veromix.pa.set_card_profile(card.index, profile.name)
        if action in self.port_actions.keys():
            self.pa_sink.set_port(self.port_actions[action])

    def contextMenuEvent(self,event):
        self.create_context_menu(event)

    def on_mute_cb(self):
        self.pa_sink.toggle_mute()

    def on_meter_cb(self):
        self.on_double_clicked()

    def sink_input_kill(self):
        self.pa_sink.kill()

    def set_channel_volumes(self, values):
        self.pa_sink.set_volume(values)

    def on_update_meter(self, index, value, number_of_sinks):
        if self.index == index:
            self.slider.set_meter_value(int(value))

    def update_with_info(self,info):
        self.pa_sink = info
        self.index = info.index
        self.update_label()
        self.updateIcon()
        if self.slider:
            self.slider.update_with_info(info)
        if self.extended_panel:
            self.extended_panel.update_with_info(info)
        self.update()

    def update_label(self):
        if self.pa_sink:
            self.set_name(self.pa_sink.name)

    def getOutputIndex(self):
        return self.index

    def sinkIndexFor( self, index):
        return (index * 100000) + 100000

    def updateIcon(self):
        pass

    def on_slider_cb(self, value):
        self.setVolume(value)

    def isDefaultSink(self):
        if self.pa_sink and "isdefault" in self.pa_sink.props:
            return self.pa_sink.props["isdefault"] == "True"
        return False

    def startDrag(self,event):
        pass

    def removeSlider(self):
        # if a slider is not visible, plasmoidviewer crashes if the slider is not removed.. (dont ask me)
        if self.slider:
            self.middle_layout.removeItem(self.slider)
        self.slider = None

    def isMuted(self):
        if self.pa_sink:
            return self.pa_sink.isMuted()
        return False

    def isSinkOutput(self):
        if self.pa_sink:
            return self.pa_sink.is_sinkoutput()
        return False

    def isSinkInput(self):
        if self.pa_sink:
            return self.pa_sink.is_sinkinput()
        return False

    def isSink(self):
        if self.pa_sink:
            return self.pa_sink.is_sink()
        return False

    def isNowplaying(self):
        return False

    def isSourceOutput(self):
        if self.pa_sink:
            return self.pa_sink.is_sourceoutput()
        return False

    def wheelEvent(self, event):
        if self.slider:
            self.slider.wheelEvent(event)

    def set_name(self, string):
        self._name = in_unicode(string)

    def name(self):
        return self._name

    def update_module_info(self, index, name, argument, n_used, auto_unload):
        pass

    def get_ladspa_type(self):
        return str(type(self))

    def get_pasink_name(self):
        return self.pa_sink.name

## LADSPA helpers

    def populate_presets_menu(self, target_menu, checked_item, add_actions):
        effect_menu = QMenu(i18n("Presets"), target_menu)
        if add_actions:
            self.action_save_preset = QAction(i18n("Save"),effect_menu)
            effect_menu.addAction(self.action_save_preset)
            if not self.is_preset():
                self.action_save_preset.setEnabled(False)

            self.action_save_as_preset = QAction(i18n("Save As..."),effect_menu)
            effect_menu.addAction(self.action_save_as_preset)
            effect_menu.addSeparator()

        for preset in LADSPAPresetLoader().presets():
            action = QAction(preset["preset_name"],effect_menu)
            effect_menu.addAction(action)
            if checked_item == preset["preset_name"]:
                action.setCheckable(True)
                action.setChecked(True)
                action.setEnabled(False)
        target_menu.addMenu(effect_menu)

    def populate_switch_effect_menu(self, target_menu, checked_item):
        effect_menu = QMenu(i18n("Effect"), target_menu)
        for preset in LADSPAEffects().effects():
            action = QAction(preset["preset_name"],effect_menu)
            effect_menu.addAction(action)
            if checked_item == preset["label"]:
                action.setCheckable(True)
                action.setChecked(True)
                action.setEnabled(False)
        target_menu.addMenu(effect_menu)

    def on_set_ladspa_effect(self, value, master):
        parameters = ""
        preset = None
        for p in LADSPAEffects().effects():
            if p["preset_name"] == value:
                parameters = "sink_name=" + urllib.quote(p["name"])
                preset = p

        for p in LADSPAPresetLoader().presets():
            if p["preset_name"] == value:
                parameters = "sink_name=" + urllib.quote(p["preset_name"])
                preset = p

        parameters =  parameters + " master=" + master + " "
        parameters =  parameters + " plugin=" + preset["plugin"]
        parameters =  parameters + " label=" + preset["label"]
        parameters =  parameters + " control=" + preset["control"]
        self.pa_sink.set_ladspa_sink(parameters)

    def next_focus(self, forward=True):
        channels = self.veromix.get_visible_channels()
        if len(channels) > 0:
            index = 0
            if self in channels:
                index = channels.index(self)
                if forward:
                    index = index + 1
                    if index >= len(channels):
                        index = 0
                else:
                    index = index - 1
                    if index < 0:
                        index = len(channels) - 1
            channels[index].set_focus()

    def set_focus(self):
        self.slider.set_focus()

    def pa_sink_proxy(self):
        return self.pa_sink
class MediaPlayerUI(Channel):

    def __init__(self,name, veromix, controller):
        self.controller = controller
        Channel.__init__(self, veromix)
        self.controller.data_updated.connect(self.controller_data_updated)
        self.index = -1
        self._state= None
        self._position = 0
        self._artwork = ""
        self.last_playing_icon = KIcon(self.get_pauseIcon())
        self.layout.setContentsMargins(6,0,6,2)
        self.controller.init_connection()

    def initArrangement(self):
        self.svg_path = self.veromix.applet.package().filePath('images', 'buttons.svgz')
        self.createMiddle()
        self.createSlider()
        self.create_prev_panel()
        self.create_frame()
        self.create_panel()
        self.create_prev_button()
        self.create_play_pause_button()
        self.create_next_button()
        self.create_next_panel()
        self.createPositionLabel()
        self.createLengthLabel()
        self.create_expander()

    def composeArrangement(self):
        self.layout.addItem(self.frame)
        self.frame_layout.addItem(self.panel)
        self.prev_panel_layout.addStretch()
        self.prev_panel_layout.addItem(self.prev)
        self.next_panel_layout.addStretch()
        self.next_panel_layout.addItem(self.next)
        self.prev_panel.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding))
        self.next_panel.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding))
        self.play.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Minimum))
        self.middle_layout.addStretch()
        self.middle_layout.addItem(self.play)
        self.panel.setContentsMargins(0,0,0,0)
        self.panel_layout.setContentsMargins(6,0,10,6)
        self.panel_layout.addStretch()
        self.panel_layout.addItem(self.prev_panel)
        self.panel_layout.addItem(self.middle)
        self.panel_layout.addItem(self.next_panel)
        self.panel_layout.addStretch()

    def on_expander_clicked(self):
        self.middle_layout.removeItem(self.slider)
        if (self.extended_panel_shown):
            self.extended_panel_shown = False
            #self.frame_layout.removeItem(self.extended_panel)
            self.extended_panel.setParent(None)
            self.panel_layout.setContentsMargins(6,0,10,6)
            self.extended_panel = None
            self.slider= None
            self.expander.setSvg("widgets/arrows", "left-arrow")
        else:
            self.extended_panel_shown = True
            self.create_settings_widget()
            #self.frame_layout.addItem(self.extended_panel)
            self.panel_layout.setContentsMargins(6,0,10,20)
            self.extended_panel.setPos(0, int(self.frame.size().height() - 15))
            #self.expander.setSvg("widgets/arrows", "up-arrow")
            self.expander.setSvg("widgets/arrows", "down-arrow")
        self.controller.set_fetch_extended_info(self.extended_panel_shown)
        self.veromix.check_geometries()

    def _resize_widgets(self):
        #self.expander.setPos(int(self.panel.size().width() - self.expander.size().width()) ,self.panel.size().height() - self.expander.size().height())
        self.expander.setPos(int(self.panel.size().width() - self.expander.size().width()) ,0)
        if self.extended_panel:
            self.extended_panel.resize(QSizeF(int(self.frame.size().width()), -1))
            #self.extended_panel.setPos(0, int(self.frame.size().height() - 12))

    def create_settings_widget(self):
        self.createLengthLabel()
        self.createPositionLabel()
        self.createSlider()
        self.extended_panel = QGraphicsWidget(self.frame)
        self.extended_panel_layout = QGraphicsLinearLayout(Qt.Horizontal)
        self.extended_panel.setLayout(self.extended_panel_layout)

        self.extended_panel.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Minimum))
        self.position_label.setSizePolicy(QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum))
        self.length_label.setSizePolicy(QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum))

        self.extended_panel_layout.addItem(self.position_label)
        self.extended_panel_layout.addItem(self.slider)
        self.extended_panel_layout.addItem(self.length_label)

    def controller_data_updated(self):
        self.update_state()
        self.update_cover()
        if self.extended_panel_shown:
            self.update_position()
            self.update_slider()

    def on_update_configuration(self):
        self.set_middle_size()
        if self.veromix.is_albumart_enabled():
            self.middle.setIcon(KIcon())
        self._on_upate_expander_enabled()

    def update_with_info(self, info):
        pass

## update ui

    def update_state(self):
        state = self.controller.state()
        if self._state != state:
            self._state = state
            if state == MediaPlayer.Playing:
                #self.play.setSvg(self.svg_path, "pause-normal")
                self.play.setIcon(KIcon("media-playback-pause"))
                if self.veromix.is_albumart_enabled():
                    self.middle.setIcon(self.last_playing_icon)
            else:
                #self.play.setSvg(self.svg_path, "play-normal")
                self.play.setIcon(KIcon("media-playback-start"))
                if self.veromix.is_albumart_enabled():
                    self.middle.setIcon(KIcon(self.get_pauseIcon()))

    def update_cover(self):
        if not self.veromix.is_albumart_enabled():
            self.middle.setIcon(KIcon())
            return True
        # FIXME
        val = self.controller._cover_string
        if self._artwork !=  val:
            self._artwork = val
            if val == None:
                self.last_playing_icon = KIcon(self.get_pauseIcon())
            else:
                self.last_playing_icon = QIcon(QPixmap(self.controller.artwork()))
            self.middle.setIcon(self.last_playing_icon)

    def update_position(self):
        v = self.controller.position()
        if v != self._position:
            self._position = v
            pos_str = ( '%d:%02d' % (v / 60, v % 60))
            self.position_label.setBoldText(pos_str)
        v = self.controller.length()
        if v :
            pos_str = ( '%d:%02d' % (v / 60, v % 60))
            self.length_label.setBoldText(pos_str)

    def update_slider(self):
        if self.slider and self.extended_panel_shown:
            if self.controller.state() == MediaPlayer.Stopped:
                self.slider.setValueFromPulse(0)
            else:
                if self.controller.length() > 0 :
                    v = self.controller.position() * 100 / self.controller.length()
#                    if self.slider.check_pulse_timestamp():
                    self.slider.setValueFromPulse(v)

    def on_slider_action_triggered(self, action):
        value = self.slider.nativeWidget().sliderPosition()
        if value > -1 and (action == 7 or action == 3):
            self.controller.seek(value)

## initialize ui

    def context_menu_create_mute(self):
        pass

    def on_contextmenu_clicked(self, action):
        pass

    def context_menu_create_unlock_channels(self):
        action_unlock = QAction(i18n("Show position"), self.popup_menu)
        self.popup_menu.addAction(action_unlock)
        action_unlock.setCheckable(True)
        action_unlock.setChecked(self.extended_panel_shown)
        action_unlock.triggered.connect(self.on_expander_clicked)

    def create_next_panel(self):
        self.next_panel = QGraphicsWidget()
        self.next_panel_layout = QGraphicsLinearLayout(Qt.Vertical)
        self.next_panel_layout.setContentsMargins(0,0,0,0)
        self.next_panel.setLayout(self.next_panel_layout)

    def createPositionLabel(self):
        self.position_label = Label()
        self.position_label.setContentsMargins(0,0,0,0)
        self.position_label.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding, True))
        self.position_label.setAlignment(Qt.AlignRight)

    def createLengthLabel(self):
        self.length_label = Label()
        self.length_label.setContentsMargins(0,0,0,0)
        self.length_label.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding, True))
        self.length_label.setAlignment(Qt.AlignLeft)

    def create_prev_panel(self):
        self.prev_panel = Plasma.IconWidget()
        self.prev_panel_layout = QGraphicsLinearLayout(Qt.Vertical)
        self.prev_panel_layout.setContentsMargins(0,0,0,0)
        self.prev_panel.setLayout(self.prev_panel_layout)
        self.prev_panel.setSizePolicy(QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum))

    def createMiddle(self):
        self.middle = Plasma.IconWidget()
        self.middle_layout = QGraphicsLinearLayout(Qt.Vertical)
        self.middle_layout.setContentsMargins(0,0,0,0)
        self.middle.setLayout(self.middle_layout)
        self.set_middle_size()
        self.middle.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding))
        if self.veromix.is_albumart_enabled():
            self.middle.setIcon(KIcon(self.get_pauseIcon()))


    def set_middle_size(self):
        if self.veromix.is_albumart_enabled():
            self.CONTROLSBAR_SIZE = 80
        else:
            self.CONTROLSBAR_SIZE = 30
        self.middle.setMinimumHeight(self.CONTROLSBAR_SIZE)
        self.middle.setPreferredHeight(self.CONTROLSBAR_SIZE)
        self.middle.setMaximumHeight(self.CONTROLSBAR_SIZE)

    def create_next_button(self):
        self.next = MuteButton(self)
        self.next.setAbsSize(20)
        #self.next.setSvg(self.svg_path , "next-normal")
        self.next.setIcon(KIcon("media-skip-forward"))
        self.connect(self.next, SIGNAL("clicked()"), self.on_next_cb  )

    def create_prev_button(self):
        self.prev = MuteButton(self)
        self.prev.setAbsSize(20)
        #self.prev.setSvg(self.svg_path, "prev-normal")
        self.prev.setIcon(KIcon("media-skip-backward"))
        self.connect(self.prev, SIGNAL("clicked()"), self.on_prev_cb  )

    def create_play_pause_button(self):
        self.play = MuteButton(self)
        self.play.setAbsSize(-1)
        #self.play.setSvg(self.svg_path, "stop-normal")
        self.play.setIcon(KIcon("media-playback-stop"))
        self.connect(self.play, SIGNAL("clicked()"), self.on_play_cb  )

    def createMute(self):
        pass

# callbacks

    def on_mute_cb(self):
        pass

    def on_next_cb(self):
        self.controller.next_track()

    def on_prev_cb(self):
        self.controller.prev_track()

    def on_play_cb(self):
        if self.controller.state() == MediaPlayer.Playing:
            self.controller.pause()
        else:
            self.controller.play()

# helpers
    def name(self):
        return self.controller_name()

    def controller_name(self):
        return self.controller.name()

    def get_pauseIcon(self):
        name = self.get_application_name()
        app = self.veromix.query_application(str(name))
        if app == None:
            return name
        return app

    def get_application_name(self):
        return self.controller.get_application_name()

    def matches(self, sink):
        sink = self.get_assotiated_sink_input()
        if sink == None:
            return False
        return True

    def get_assotiated_sink_input(self):
        name = str(self.get_application_name()).lower()
        for sink in self.veromix.get_sinkinput_widgets():
            if str(name).lower().find(sink.name()) >= 0:
                return sink
        for sink in self.veromix.get_sinkinput_widgets():
            if str(sink.name()).lower().find(name) >= 0 :
                return sink
        return None

## overrides

    def isNowplaying(self):
        return True

    def isSinkOutput(self):
        return False

    def isSinkInput(self):
        return False

    def createSlider(self):
        Channel.createSlider(self)
        self.slider.setMaximum(100)
        self.slider.volumeChanged.disconnect(self.on_slider_cb)
        self.slider.nativeWidget ().actionTriggered.connect(self.on_slider_action_triggered)

## testing

    def is_nowplaying_player(self):
        return self.controller.is_mpris2_player()

    def is_mpris2_player(self):
        return self.controller.is_mpris2_player()