/*
* Created on 28.11.2003
* Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved.
*
* 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 (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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* AELITIS, SAS au capital de 46,603.30 euros
* 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
*
*/
package org.gudy.azureus2.ui.common.util;
import org.gudy.azureus2.core3.config.COConfigurationManager;
import org.gudy.azureus2.core3.disk.DiskManager;
import org.gudy.azureus2.core3.disk.DiskManagerFileInfo;
import org.gudy.azureus2.core3.disk.DiskManagerListener;
import org.gudy.azureus2.core3.disk.DiskManagerPiece;
import org.gudy.azureus2.core3.download.DownloadManager;
import org.gudy.azureus2.core3.download.DownloadManagerDiskListener;
import org.gudy.azureus2.core3.download.DownloadManagerState;
import org.gudy.azureus2.core3.download.impl.DownloadManagerAdapter;
import org.gudy.azureus2.core3.global.GlobalManager;
import org.gudy.azureus2.core3.global.impl.GlobalManagerAdpater;
import org.gudy.azureus2.core3.internat.MessageText;
import org.gudy.azureus2.core3.logging.*;
import org.gudy.azureus2.core3.util.AEMonitor;
import org.gudy.azureus2.core3.util.AEThread;
import org.gudy.azureus2.core3.util.Constants;
import org.gudy.azureus2.core3.util.Debug;
import java.applet.Applet;
import java.applet.AudioClip;
import java.io.File;
import java.net.URL;
/**
* Contains methods to alert the user of certain events.
* @author Rene Leonhardt
*/
public class
UserAlerts
{
private AudioClip audio_clip = null;
private String audio_resource = "";
private AEMonitor this_mon = new AEMonitor( "UserAlerts" );
private boolean startup = true;
public
UserAlerts(
GlobalManager global_manager )
{
final DownloadManagerAdapter download_manager_listener =
new DownloadManagerAdapter()
{
public void
downloadComplete(DownloadManager manager)
{
if( !manager.getDownloadState().getFlag( DownloadManagerState.FLAG_LOW_NOISE )){
activityFinished(true, manager.getDisplayName(), manager);
}
}
};
final DiskManagerListener disk_listener =
new DiskManagerListener()
{
public void
stateChanged(
int oldState,
int newState )
{
}
public void
filePriorityChanged(
DiskManagerFileInfo file )
{
}
public void
pieceDoneChanged(
DiskManagerPiece piece )
{
}
public void
fileAccessModeChanged(
DiskManagerFileInfo file,
int old_mode,
int new_mode )
{
DownloadManager dm = file.getDownloadManager();
if ( old_mode == DiskManagerFileInfo.WRITE &&
new_mode == DiskManagerFileInfo.READ ){
if( dm == null || !dm.getDownloadState().getFlag( DownloadManagerState.FLAG_LOW_NOISE )){
activityFinished(false, file.getFile(true).getName(), file.getDiskManager());
}
}
/*
System.out.println(
"amc:" +
file.getDownloadManager().getDisplayName() + "/" +
file.getName() + ":" + old_mode + " -> " + new_mode );
*/
}
};
final DownloadManagerDiskListener dm_disk_listener =
new DownloadManagerDiskListener()
{
public void
diskManagerAdded(
DiskManager dm )
{
dm.addListener( disk_listener );
}
public void
diskManagerRemoved(
DiskManager dm )
{
dm.removeListener( disk_listener );
}
public boolean
syncInvokeRequired()
{
return( false );
}
};
global_manager.addListener(
new GlobalManagerAdpater()
{
public void
downloadManagerAdded(DownloadManager manager)
{
// don't pop up for non-persistent as these get added late in the day every time
// so we'll notify for each download every startup
if (!startup && manager.isPersistent()) {
boolean bPopup = COConfigurationManager.getBooleanParameter("Popup Download Added");
if ( bPopup ){
if( !manager.getDownloadState().getFlag( DownloadManagerState.FLAG_LOW_NOISE )){
String popup_text = MessageText.getString("popup.download.added",
new String[] { manager.getDisplayName()
});
Logger.log(new LogAlert(manager, true, LogAlert.AT_INFORMATION, popup_text));
}
}
}
manager.addListener( download_manager_listener );
manager.addDiskListener( dm_disk_listener );
}
public void
downloadManagerRemoved(DownloadManager manager)
{
manager.removeListener(download_manager_listener);
manager.removeDiskListener( dm_disk_listener );
}
public void
destroyed()
{
tidyUp();
}
});
startup = false;
}
protected void activityFinished(boolean download, String item_name, Object relatedObject)
{
final String sound_enabler;
final String sound_file;
final String default_sound = "org/gudy/azureus2/ui/icons/downloadFinished.wav";
final String speech_enabler;
final String speech_text;
final String popup_enabler;
final String popup_def_text;
if ( download ){
sound_enabler = "Play Download Finished";
sound_file = "Play Download Finished File";
speech_enabler = "Play Download Finished Announcement";
speech_text = "Play Download Finished Announcement Text";
popup_enabler = "Popup Download Finished";
popup_def_text = "popup.download.finished";
}else{
sound_enabler = "Play File Finished";
sound_file = "Play File Finished File";
speech_enabler = "Play File Finished Announcement";
speech_text = "Play File Finished Announcement Text";
popup_enabler = "Popup File Finished";
popup_def_text = "popup.file.finished";
}
try{
this_mon.enter();
if (COConfigurationManager.getBooleanParameter(popup_enabler)) {
String popup_text = MessageText.getString(popup_def_text, new String[]{item_name});
Logger.log(new LogAlert(relatedObject, true, LogAlert.AT_INFORMATION, popup_text));
}
if(Constants.isOSX) { // OS X cannot concurrently use SWT and AWT
new AEThread("DownloadSound") {
public void runSupport()
{
try {
if(COConfigurationManager.getBooleanParameter( speech_enabler ))
Runtime.getRuntime().exec(new String[]{"say", COConfigurationManager.getStringParameter( speech_text )}); // Speech Synthesis services
if(COConfigurationManager.getBooleanParameter( sound_enabler ))
Runtime.getRuntime().exec(new String[]{"osascript", "-e" ,"beep"}); // Beep alert type is in accordance with System Preferences
Thread.sleep(2500);
}
catch(Throwable e) {}
}
}.start();
}
else if( COConfigurationManager.getBooleanParameter( sound_enabler, false)){
String file = COConfigurationManager.getStringParameter( sound_file );
file = file.trim();
// turn "<default>" into blank
if ( file.startsWith( "<" )){
file = "";
}
if ( audio_clip == null || !file.equals( audio_resource )){
audio_clip = null;
// try explicit file
if ( file.length() != 0 ){
File f = new File( file );
try{
if ( f.exists()){
URL file_url = f.toURL();
audio_clip = Applet.newAudioClip( file_url );
}
}catch( Throwable e ){
Debug.printStackTrace(e);
}finally{
if ( audio_clip == null ){
Logger.log(new LogAlert(relatedObject, LogAlert.UNREPEATABLE,
LogAlert.AT_ERROR, "Failed to load audio file '" + file
+ "'"));
}
}
}
// either non-explicit or explicit missing
if ( audio_clip == null ){
audio_clip = Applet.newAudioClip(UserAlerts.class.getClassLoader().getResource( default_sound ));
}
audio_resource = file;
}
if ( audio_clip != null ){
new AEThread("DownloadSound")
{
public void
runSupport()
{
try{
audio_clip.play();
Thread.sleep(2500);
}catch( Throwable e ){
}
}
}.start();
}
}
}catch( Throwable e ){
Debug.printStackTrace( e );
}finally{
this_mon.exit();
}
}
protected void
tidyUp()
{
/*
The Java audio system keeps some threads running even after playback is finished.
One of them, named "Java Sound event dispatcher", is *not* a daemon
thread and keeps the VM alive.
We have to locate and interrupt it explicitely.
*/
try{
ThreadGroup threadGroup = Thread.currentThread().getThreadGroup();
Thread[] threadList = new Thread[threadGroup.activeCount()];
threadGroup.enumerate(threadList);
for (int i = 0; i < threadList.length; i++){
if(threadList[i] != null && "Java Sound event dispatcher".equals(threadList[i].getName())){
threadList[i].interrupt();
}
}
}catch( Throwable e ){
Debug.printStackTrace( e );
}
}
}