/*
* Jajuk
* Copyright (C) The Jajuk Team
* http://jajuk.info
*
* 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
* of the License, or 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
package org.jajuk.services.dbus;
/**
* Provides implementation of the D-Bus interface and implementation of the
* D-Bus support code for connecting to D-Bus
*/
import static org.jajuk.ui.actions.JajukActions.DECREASE_VOLUME;
import static org.jajuk.ui.actions.JajukActions.EXIT;
import static org.jajuk.ui.actions.JajukActions.FORWARD_TRACK;
import static org.jajuk.ui.actions.JajukActions.INCREASE_VOLUME;
import static org.jajuk.ui.actions.JajukActions.NEXT_ALBUM;
import static org.jajuk.ui.actions.JajukActions.NEXT_TRACK;
import static org.jajuk.ui.actions.JajukActions.PAUSE_RESUME_TRACK;
import static org.jajuk.ui.actions.JajukActions.PREVIOUS_ALBUM;
import static org.jajuk.ui.actions.JajukActions.PREVIOUS_TRACK;
import static org.jajuk.ui.actions.JajukActions.REWIND_TRACK;
import static org.jajuk.ui.actions.JajukActions.SHUFFLE_GLOBAL;
import static org.jajuk.ui.actions.JajukActions.STOP_TRACK;
import java.util.HashSet;
import java.util.Set;
import org.freedesktop.dbus.DBusConnection;
import org.freedesktop.dbus.exceptions.DBusException;
import org.jajuk.base.File;
import org.jajuk.base.FileManager;
import org.jajuk.base.Item;
import org.jajuk.events.JajukEvent;
import org.jajuk.events.JajukEvents;
import org.jajuk.events.ObservationManager;
import org.jajuk.events.Observer;
import org.jajuk.services.bookmark.Bookmarks;
import org.jajuk.services.notification.INotificator;
import org.jajuk.services.notification.NotificatorFactory;
import org.jajuk.services.players.QueueModel;
import org.jajuk.ui.actions.ActionManager;
import org.jajuk.ui.actions.JajukActions;
import org.jajuk.util.Conf;
import org.jajuk.util.Const;
import org.jajuk.util.UtilString;
import org.jajuk.util.error.JajukException;
import org.jajuk.util.log.Log;
/**
* .
*/
public class DBusSupportImpl implements DBusSupport, Observer {
/** The D-Bus Path that is used. */
private static final String PATH = "/JajukDBus";
/** The D-Bus name of the Bus that we request. */
private static final String BUS = "org.jajuk.dbus.DBusSupport";
DBusConnection conn;
/**
* Set up the D-Bus connection and export an object to allow other
* applications to control Jajuk via D-Bus.
*
* This will catch errors and report them to the logfile.
*
* Scope is package protected to only let DBusManager have access to it.
*/
void connect() {
Log.info("Trying to start support for D-Bus on Linux with Bus: " + BUS + " and Path: " + PATH);
try {
conn = DBusConnection.getConnection(DBusConnection.SESSION);
conn.requestBusName(BUS);
conn.exportObject(PATH, this);
Log.info("D-Bus support started successfully");
} catch (DBusException e) {
Log.error(e);
}
// register to player events
ObservationManager.register(this);
}
/**
* Disconnects from D-Bus.
*
* Scope is package protected to only let DBusManager have access to it.
*/
void disconnect() {
Log.info("Disconnecting from D-Bus");
ObservationManager.unregister(this);
if (conn != null) {
conn.disconnect();
}
}
/*
* Interface methods to react on D-Bus signals
*
* These methods are invoked via D-Bus and trigger the corresponding action in
* Jajuk
*/
/*
* (non-Javadoc)
*
* @see org.jajuk.services.dbus.DBusSupport#forward()
*/
@Override
public void forward() throws Exception {
Log.info("Invoking D-Bus action for 'forward'");
ActionManager.getAction(FORWARD_TRACK).perform(null);
}
/*
* (non-Javadoc)
*
* @see org.jajuk.services.dbus.DBusSupport#next()
*/
@Override
public void next() throws Exception {
Log.info("Invoking D-Bus action for 'next'");
ActionManager.getAction(NEXT_TRACK).perform(null);
}
/*
* (non-Javadoc)
*
* @see org.jajuk.services.dbus.DBusSupport#playPause()
*/
@Override
public void playPause() throws Exception {
Log.info("Invoking D-Bus action for 'play/pause'");
ActionManager.getAction(PAUSE_RESUME_TRACK).perform(null);
}
/*
* (non-Javadoc)
*
* @see org.jajuk.services.dbus.DBusSupport#previous()
*/
@Override
public void previous() throws Exception {
Log.info("Invoking D-Bus action for 'previous'");
ActionManager.getAction(PREVIOUS_TRACK).perform(null);
}
/*
* (non-Javadoc)
*
* @see org.jajuk.services.dbus.DBusSupport#rewind()
*/
@Override
public void rewind() throws Exception {
Log.info("Invoking D-Bus action for 'rewind'");
ActionManager.getAction(REWIND_TRACK).perform(null);
}
/*
* (non-Javadoc)
*
* @see org.jajuk.services.dbus.DBusSupport#stop()
*/
@Override
public void stop() throws Exception {
Log.info("Invoking D-Bus action for 'stop'");
ActionManager.getAction(STOP_TRACK).perform(null);
}
/*
* (non-Javadoc)
*
* @see org.jajuk.services.dbus.DBusSupport#decreaseVolume()
*/
@Override
public void decreaseVolume() throws Exception {
Log.info("Invoking D-Bus action for 'decreaseVolume'");
ActionManager.getAction(DECREASE_VOLUME).perform(null);
}
/*
* (non-Javadoc)
*
* @see org.jajuk.services.dbus.DBusSupport#exit()
*/
@Override
public void exit() throws Exception {
Log.info("Invoking D-Bus action for 'exit'");
ActionManager.getAction(EXIT).perform(null);
}
/*
* (non-Javadoc)
*
* @see org.jajuk.services.dbus.DBusSupport#increaseVolume()
*/
@Override
public void increaseVolume() throws Exception {
Log.info("Invoking D-Bus action for 'increaseVolume'");
ActionManager.getAction(INCREASE_VOLUME).perform(null);
}
/*
* (non-Javadoc)
*
* @see org.jajuk.services.dbus.DBusSupport#nextAlbum()
*/
@Override
public void nextAlbum() throws Exception {
Log.info("Invoking D-Bus action for 'nextAlbum'");
ActionManager.getAction(NEXT_ALBUM).perform(null);
}
/*
* (non-Javadoc)
*
* @see org.jajuk.services.dbus.DBusSupport#previousAlbum()
*/
@Override
public void previousAlbum() throws Exception {
Log.info("Invoking D-Bus action for 'previousAlbum'");
ActionManager.getAction(PREVIOUS_ALBUM).perform(null);
}
/*
* (non-Javadoc)
*
* @see org.jajuk.services.dbus.DBusSupport#shuffleGlobal()
*/
@Override
public void shuffleGlobal() throws Exception {
Log.info("Invoking D-Bus action for 'shuffleGlobal'");
ActionManager.getAction(SHUFFLE_GLOBAL).perform(null);
}
/*
* (non-Javadoc)
*
* @see org.jajuk.services.dbus.DBusSupport#mute()
*/
@Override
public void mute() throws Exception {
Log.info("Invoking D-Bus action for 'mute'");
ActionManager.getAction(JajukActions.MUTE_STATE).perform(null);
}
/*
* (non-Javadoc)
*
* @see org.jajuk.services.dbus.DBusSupport#currentHTML()
*/
@Override
public String currentHTML() throws Exception {
Log.info("Invoking D-Bus action for 'currentHTML'");
return QueueModel.getCurrentFileTitle();
}
/*
* (non-Javadoc)
*
* @see org.jajuk.services.dbus.DBusSupport#current()
*/
@Override
public String current() throws Exception {
Log.info("Invoking D-Bus action for 'current'");
String title = null;
File file = QueueModel.getPlayingFile();
if (QueueModel.isPlayingRadio()) {
title = QueueModel.getCurrentRadio().getName();
} else if (file != null && !QueueModel.isStopped()) {
String pattern = Conf.getString(Const.CONF_PATTERN_FRAME_TITLE);
try {
title = UtilString.applyPattern(file, pattern, false, false);
} catch (JajukException e) {
Log.error(e);
}
} else {
title = "not playing right now...";
}
return title;
}
/*
* (non-Javadoc)
*
* @see org.jajuk.services.dbus.DBusSupport#banCurrent()
*/
@Override
public void banCurrent() throws Exception {
Log.info("Invoking D-Bus action for 'banCurrent'");
ActionManager.getAction(JajukActions.BAN).perform(null);
}
/*
* (non-Javadoc)
*
* @see org.jajuk.services.dbus.DBusSupport#showCurrentlyPlaying()
*/
@Override
public void showCurrentlyPlaying() throws Exception {
// simply raise the event so any registered handler will take care of it
Log.info("Invoking D-Bus action for 'showCurrentlyPlaying'");
ObservationManager.notify(new JajukEvent(JajukEvents.SHOW_CURRENTLY_PLAYING));
}
/* (non-Javadoc)
* @see org.jajuk.services.dbus.DBusSupport#bookmarkCurrentTrack()
*/
@Override
public void bookmarkCurrentlyPlaying() throws Exception {
File file = QueueModel.getPlayingFile();
Log.info("Invoking D-Bus action for 'bookmarkCurrentTrack', file: "
+ (file == null ? "<null>" : file.toString()));
if (!QueueModel.isPlayingRadio() && file != null && !QueueModel.isStopped()) {
// the action expects a JComponent, which we do not have here, therefore we do it directly here
// ActionManager.getAction(JajukActions.BOOKMARK_SELECTION).perform()
Bookmarks.getInstance().addFile(file);
INotificator notifier = NotificatorFactory.getNotificator();
if (notifier != null) {
String pattern = Conf.getString(Const.CONF_PATTERN_BALLOON_NOTIFIER);
String text = UtilString.applyPattern(file, pattern, false, false);
notifier.notify("Bookmarked", text);
}
}
}
/**
* Required method for DBusInterface.
*
* @return true, if checks if is remote
*/
@Override
public boolean isRemote() {
return false;
}
/*
* (non-Javadoc)
*
* @see org.jajuk.events.Observer#getRegistrationKeys()
*/
@Override
public Set<JajukEvents> getRegistrationKeys() {
Set<JajukEvents> keys = new HashSet<JajukEvents>();
// keys.add(JajukEvents.PLAYER_STOP);
// keys.add(JajukEvents.PLAYER_PAUSE);
// keys.add(JajukEvents.PLAYER_RESUME);
keys.add(JajukEvents.FILE_LAUNCHED);
return keys;
}
/*
* (non-Javadoc)
*
* @see org.jajuk.events.Observer#update(org.jajuk.events.JajukEvent)
*/
@Override
public void update(JajukEvent event) {
JajukEvents subject = event.getSubject();
// Reset rate and total play time (automatic part of rating system)
if (subject.equals(JajukEvents.FILE_LAUNCHED)) {
String id = (String) ObservationManager.getDetail(event, Const.DETAIL_CURRENT_FILE_ID);
Item item = FileManager.getInstance().getItemByID(id);
Log.debug("Got update for new file launched, item: " + item);
try {
if (conn == null) {
Log.warn("Cannot send DBus-Signal when not connected to D-Bus!");
return;
}
conn.sendSignal(new DBusSignalImpl.FileChangedSignal("testfile: " + item, PATH));
} catch (DBusException e) {
Log.error(e);
}
} else {
Log.warn("Unexpected subject received in Observer: " + event);
}
}
}