bug#210212 (initial commit)
diff --git a/plugins/org.eclipse.actf.ai.audio.description/.classpath b/plugins/org.eclipse.actf.ai.audio.description/.classpath new file mode 100644 index 0000000..751c8f2 --- /dev/null +++ b/plugins/org.eclipse.actf.ai.audio.description/.classpath
@@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<classpath> + <classpathentry kind="src" path="src"/> + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/> + <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/> + <classpathentry kind="output" path="bin"/> +</classpath>
diff --git a/plugins/org.eclipse.actf.ai.audio.description/.project b/plugins/org.eclipse.actf.ai.audio.description/.project new file mode 100644 index 0000000..f0c20b7 --- /dev/null +++ b/plugins/org.eclipse.actf.ai.audio.description/.project
@@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>org.eclipse.actf.ai.audio.description</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>org.eclipse.jdt.core.javabuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.pde.ManifestBuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.pde.SchemaBuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.eclipse.pde.PluginNature</nature> + <nature>org.eclipse.jdt.core.javanature</nature> + </natures> +</projectDescription>
diff --git a/plugins/org.eclipse.actf.ai.audio.description/META-INF/MANIFEST.MF b/plugins/org.eclipse.actf.ai.audio.description/META-INF/MANIFEST.MF new file mode 100644 index 0000000..e62719a --- /dev/null +++ b/plugins/org.eclipse.actf.ai.audio.description/META-INF/MANIFEST.MF
@@ -0,0 +1,20 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Eclipse ACTF Audio Description Plug-in (Incubation) +Bundle-SymbolicName: org.eclipse.actf.ai.audio.description;singleton:=true +Bundle-Version: 0.0.1 +Bundle-Activator: org.eclipse.actf.ai.audio.description.DescriptionPlugin +Bundle-Vendor: Eclipse.org +Bundle-Localization: plugin +Require-Bundle: org.eclipse.ui, + org.eclipse.core.runtime, + org.eclipse.actf.ai.fennec, + org.eclipse.actf.common, + org.eclipse.actf.ai.navigator, + org.eclipse.actf.ai.voice, + org.eclipse.actf.ai.xmlstore +Eclipse-LazyStart: true +Export-Package: org.eclipse.actf.ai.audio.description, + org.eclipse.actf.ai.audio.description.impl, + org.eclipse.actf.ai.audio.description.util, + org.eclipse.actf.ai.audio.description.views
diff --git a/plugins/org.eclipse.actf.ai.audio.description/about.html b/plugins/org.eclipse.actf.ai.audio.description/about.html new file mode 100644 index 0000000..481dbcf --- /dev/null +++ b/plugins/org.eclipse.actf.ai.audio.description/about.html
@@ -0,0 +1,25 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/> +<title>About</title> +</head> +<body lang="EN-US"> +<h2>About This Content</h2> + +<p>June 5, 2006</p> +<h3>License</h3> +<p>The Eclipse Foundation makes available all content in this plug-in ("Content"). +Unless otherwise indicated below, the Content is provided to you under the terms and conditions of the +Eclipse Public License Version 1.0 ("EPL"). A copy of the EPL is available +at <a href="http://www.eclipse.org/org/documents/epl-v10.php">http://www.eclipse.org/legal/epl-v10.html</a>. +For purposes of the EPL, "Program" will mean the Content.</p> +<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is +being redistributed by another party ("Redistributor") and different terms and conditions may +apply to your use of any object code in the Content. Check the Redistributor’s license +that was provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise +indicated below, the terms and conditions of the EPL still apply to any source code in the Content +and such source code may be obtained at <a href="http://www.eclipse.org/">http://www.eclipse.org</a>.</p> +</body> +</html> \ No newline at end of file
diff --git a/plugins/org.eclipse.actf.ai.audio.description/build.properties b/plugins/org.eclipse.actf.ai.audio.description/build.properties new file mode 100644 index 0000000..86eff37 --- /dev/null +++ b/plugins/org.eclipse.actf.ai.audio.description/build.properties
@@ -0,0 +1,21 @@ +############################################################################### +# Copyright (c) 2007 IBM Corporation and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# IBM Corporation - initial API and implementation +############################################################################### +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + .,\ + plugin.xml,\ + plugin.properties,\ + plugin_ja.properties,\ + icons/,\ + about.html,\ + src/messages.properties,\ + src/messages_ja.properties
diff --git a/plugins/org.eclipse.actf.ai.audio.description/icons/micx16.gif b/plugins/org.eclipse.actf.ai.audio.description/icons/micx16.gif new file mode 100644 index 0000000..f60045c --- /dev/null +++ b/plugins/org.eclipse.actf.ai.audio.description/icons/micx16.gif Binary files differ
diff --git a/plugins/org.eclipse.actf.ai.audio.description/icons/micx48.gif b/plugins/org.eclipse.actf.ai.audio.description/icons/micx48.gif new file mode 100644 index 0000000..3b79303 --- /dev/null +++ b/plugins/org.eclipse.actf.ai.audio.description/icons/micx48.gif Binary files differ
diff --git a/plugins/org.eclipse.actf.ai.audio.description/plugin.properties b/plugins/org.eclipse.actf.ai.audio.description/plugin.properties new file mode 100644 index 0000000..35d412b --- /dev/null +++ b/plugins/org.eclipse.actf.ai.audio.description/plugin.properties
@@ -0,0 +1,12 @@ +############################################################################### +# Copyright (c) 2007 IBM Corporation and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# IBM Corporation - initial API and implementation +############################################################################### +AudioDescription.preference.name=Audio Description +AudioDescription.view.name=Audio Description
diff --git a/plugins/org.eclipse.actf.ai.audio.description/plugin.xml b/plugins/org.eclipse.actf.ai.audio.description/plugin.xml new file mode 100644 index 0000000..9b67bb3 --- /dev/null +++ b/plugins/org.eclipse.actf.ai.audio.description/plugin.xml
@@ -0,0 +1,59 @@ +<?xml version="1.0" encoding="UTF-8"?> +<?eclipse version="3.2"?> +<plugin> + <extension + point="org.eclipse.actf.ai.navigator.MediaControl"> + <controller class="org.eclipse.actf.ai.audio.description.impl.MediaControlImpl"/> + </extension> + <extension + point="org.eclipse.ui.views"> + <view + class="org.eclipse.actf.ai.audio.description.views.DescriptionView" + icon="icons/micx16.gif" + id="org.eclipse.actf.ai.audio.description.views.DescriptionView" + name="%AudioDescription.view.name"/> + </extension> + <extension + point="org.eclipse.ui.perspectiveExtensions"> + <perspectiveExtension targetID="org.eclipse.actf.examples.aibrowser.DefaultPerspective"> + <view + closeable="false" + id="org.eclipse.actf.ai.audio.description.views.DescriptionView" + moveable="true" + ratio="0.7" + relationship="bottom" + relative="org.eclipse.actf.ai.navigator.views.NavigatorTreeView" + showTitle="true" + standalone="false" + visible="true"/> + </perspectiveExtension> + </extension> + <!--extension + point="org.eclipse.ui.actionSets"> + <actionSet + id="org.eclipse.actf.ai.audio.description.actionSet1" + label="org.eclipse.actf.ai.audio.description.actionSet1" + visible="true"> + <action + class="org.eclipse.actf.ai.audio.description.actions.AudioDescriptionActionDelegate" + id="org.eclipse.actf.ai.audio.description.AudioDescription" + label="&Audio Description" + menubarPath="org.eclipse.actf.examples.aibrowser.FileMenu/filegroup" + state="false" + style="toggle" + tooltip="Toggle audio description mode"/> + </actionSet> + </extension--> + <extension + point="org.eclipse.ui.preferencePages"> + <page + class="org.eclipse.actf.ai.audio.description.preferences.ADPreferencePage" + id="org.eclipse.actf.ai.audio.description.preferences.ADPreferencePage" + name="%AudioDescription.preference.name"/> + </extension> + <extension + point="org.eclipse.core.runtime.preferences"> + <initializer class="org.eclipse.actf.ai.audio.description.preferences.ADPreferenceInitializer"/> + </extension> + +</plugin>
diff --git a/plugins/org.eclipse.actf.ai.audio.description/plugin_ja.properties b/plugins/org.eclipse.actf.ai.audio.description/plugin_ja.properties new file mode 100644 index 0000000..db0b66b --- /dev/null +++ b/plugins/org.eclipse.actf.ai.audio.description/plugin_ja.properties
@@ -0,0 +1,12 @@ +############################################################################### +# Copyright (c) 2007 IBM Corporation and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# IBM Corporation - initial API and implementation +############################################################################### +AudioDescription.preference.name=\u97f3\u58f0\u89e3\u8aac +AudioDescription.view.name=\u97f3\u58f0\u89e3\u8aac
diff --git a/plugins/org.eclipse.actf.ai.audio.description/src/messages.properties b/plugins/org.eclipse.actf.ai.audio.description/src/messages.properties new file mode 100644 index 0000000..86b5145 --- /dev/null +++ b/plugins/org.eclipse.actf.ai.audio.description/src/messages.properties
@@ -0,0 +1,21 @@ +############################################################################### +# Copyright (c) 2007 IBM Corporation and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# IBM Corporation - initial API and implementation +############################################################################### +AudioDescription.view.time=Time +AudioDescription.view.desc=Description +AudioDescription.view.enable=Enable +AudioDescription.view.notEnable=Not Enable + +AudioDescription.preference.title=Audio Description Preference +AudioDescription.voice.engine=TTS engine +Metadata.available=Audio Description is Available + +AudioDescription.on=Audio Description is on +AudioDescription.off=Audio Description is off \ No newline at end of file
diff --git a/plugins/org.eclipse.actf.ai.audio.description/src/messages_ja.properties b/plugins/org.eclipse.actf.ai.audio.description/src/messages_ja.properties new file mode 100644 index 0000000..c0b1c63 --- /dev/null +++ b/plugins/org.eclipse.actf.ai.audio.description/src/messages_ja.properties
@@ -0,0 +1,22 @@ +############################################################################### +# Copyright (c) 2007 IBM Corporation and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# IBM Corporation - initial API and implementation +############################################################################### +AudioDescription.view.time=\u6642\u9593 +AudioDescription.view.desc=\u8aac\u660e +AudioDescription.view.enable=\u89e3\u8aac\u30aa\u30f3 +AudioDescription.view.notEnable=\u89e3\u8aac\u30aa\u30d5 + +AudioDescription.preference.title=\u97f3\u58f0\u8a2d\u5b9a +AudioDescription.voice.engine=TTS\u30a8\u30f3\u30b8\u30f3 + +Metadata.available=\u97f3\u58f0\u89e3\u8aac\u5229\u7528\u53ef\u80fd + +AudioDescription.on=\u97f3\u58f0\u89e3\u8aac\u30aa\u30f3 +AudioDescription.off=\u97f3\u58f0\u89e3\u8aac\u30aa\u30d5 \ No newline at end of file
diff --git a/plugins/org.eclipse.actf.ai.audio.description/src/org/eclipse/actf/ai/audio/description/DescriptionPlugin.java b/plugins/org.eclipse.actf.ai.audio.description/src/org/eclipse/actf/ai/audio/description/DescriptionPlugin.java new file mode 100644 index 0000000..317860e --- /dev/null +++ b/plugins/org.eclipse.actf.ai.audio.description/src/org/eclipse/actf/ai/audio/description/DescriptionPlugin.java
@@ -0,0 +1,203 @@ +/******************************************************************************* + * Copyright (c) 2007 IBM Corporation and Others + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Daisuke SATO - initial API and implementation + *******************************************************************************/ +package org.eclipse.actf.ai.audio.description; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.Locale; + +import org.eclipse.actf.ai.audio.description.impl.MetadataManager; +import org.eclipse.actf.ai.audio.description.impl.MetadataProviderImpl; +import org.eclipse.actf.ai.audio.description.views.DescriptionView; +import org.eclipse.actf.ai.navigator.IMediaControl; +import org.eclipse.actf.ai.tts.ITTSEngine; +import org.eclipse.actf.ai.voice.internal.AbstractPreferenceUIPlugin; +import org.eclipse.actf.ai.voice.internal.TTSRegistry; +import org.eclipse.actf.ai.xmlstore.IXMLInfo; +import org.eclipse.actf.ai.xmlstore.IXMLSelector; +import org.eclipse.actf.ai.xmlstore.IXMLStore; +import org.eclipse.actf.ai.xmlstore.IXMLStoreService; +import org.eclipse.actf.ai.xmlstore.XMLStorePlugin; +import org.eclipse.core.runtime.Platform; +import org.eclipse.jface.util.IPropertyChangeListener; +import org.eclipse.jface.util.PropertyChangeEvent; +import org.osgi.framework.BundleContext; + + +/** + * The activator class controls the plug-in life cycle + */ +public class DescriptionPlugin extends AbstractPreferenceUIPlugin implements IPropertyChangeListener { + + // The plug-in ID + public static final String PLUGIN_ID = "org.eclipse.actf.ai.audio.description"; + + public static final String PREF_ENGINE = "AudioDescriptionTTSEngine"; + + // The shared instance + private static DescriptionPlugin plugin; + + private boolean enable = false; + + private MetadataManager activeManager; + + ITTSEngine engine; + + /** + * The constructor + */ + public DescriptionPlugin() { + plugin = this; + } + + public IMetadataProvider getMetadata(String url) { + IXMLStoreService service = XMLStorePlugin.getDefault().getXMLStoreService(); + IXMLStore store = service.getRootStore(); + IXMLSelector selector1 = service.getSelectorWithDocElem("puits", "urn:puits"); + IXMLSelector selector2 = service.getSelectorWithIRI(url); + store = store.specify(selector1); + store = store.specify(selector2); + + ArrayList<IXMLInfo> list = new ArrayList<IXMLInfo>(); + for(Iterator<IXMLInfo> i = store.getInfoIterator(); i.hasNext();){ + list.add(i.next()); + } + if(list.size() == 0) + return null; + MetadataProviderImpl provider = new MetadataProviderImpl(list); + if (provider != null){ + provider.reload(); + provider.setLocale(Locale.getDefault()); + provider.getAlternatives(); + } + return provider; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext) + */ + @Override + public void start(BundleContext context) throws Exception { + super.start(context); + initialize(); + } + + private void initialize() { + engine = newTTSEngine(); + DescriptionPlugin.getDefault().addPropertyChangeListener(this); + } + + private ITTSEngine newTTSEngine() { + ITTSEngine engine; + String e = DescriptionPlugin.getDefault().getPreferenceStore().getString(DescriptionPlugin.PREF_ENGINE); + + // TODO + if (e.equals("org.eclipse.actf.ai.screenreader.jaws")) + return null; + engine = TTSRegistry.createTTSEngine(e); + if(engine != null) + engine.setSpeed(50); + return engine; + } + + @Override + public void propertyChange(PropertyChangeEvent event) { + if (DescriptionPlugin.PREF_ENGINE.equals(event.getProperty())) { + if (null != engine) { + engine.stop(); + engine.dispose(); + engine = newTTSEngine(); + } + } + } + + public ITTSEngine getTTSEngine() { + return engine; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext) + */ + @Override + public void stop(BundleContext context) throws Exception { + plugin = null; + super.stop(context); + } + + /** + * Returns the shared instance + * + * @return the shared instance + */ + public static DescriptionPlugin getDefault() { + return plugin; + } + + DescriptionView view; + + public void setDescriptionView(DescriptionView view) { + this.view = view; + } + + public DescriptionView getDescriptionView() { + return view; + } + + public int setEnable(boolean flag) { + if(!isAvailable()){ + enable = false; + return IMediaControl.STATUS_NOT_AVAILABLE; + } + + enable = flag; + getDescriptionView().setEnable(enable); + if (enable) { + return IMediaControl.STATUS_ON; + } else { + return IMediaControl.STATUS_OFF; + } + } + + public boolean isAvailable() { + if (activeManager == null) + return false; + return activeManager.hasMetadata(); + } + + public boolean canSpeak() { + return engine != null; + } + + public void speak(String str) { + if(engine != null) + engine.speak(str, ITTSEngine.TTSFLAG_FLUSH, -1); + } + + public int toggleEnable() { + return setEnable(!getEnable()); + } + + public boolean getEnable() { + return enable; + } + + public void setActiveMetadata(MetadataManager manager) { + this.activeManager = manager; + } + + public static String getString(String key) { + return Platform.getResourceString(getDefault().getBundle(), key); + } +}
diff --git a/plugins/org.eclipse.actf.ai.audio.description/src/org/eclipse/actf/ai/audio/description/IMetadata.java b/plugins/org.eclipse.actf.ai.audio.description/src/org/eclipse/actf/ai/audio/description/IMetadata.java new file mode 100644 index 0000000..73b69c7 --- /dev/null +++ b/plugins/org.eclipse.actf.ai.audio.description/src/org/eclipse/actf/ai/audio/description/IMetadata.java
@@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright (c) 2007 IBM Corporation and Others + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Daisuke SATO - initial API and implementation + *******************************************************************************/ + +package org.eclipse.actf.ai.audio.description; + + + + +public interface IMetadata { + int IMPORTANCE_LOW = 0; + int IMPORTANCE_MIDDLE = 1; + int IMPORTANCE_HIGH = 2; + + int MASK_NONE = 0; + int MASK_PAUSE_BEFORE = 1; + int MASK_SPEAK = 2; + int MASK_PAUSE_AFTER = 4; + + public String getDescription(); + public int getStartTime(); + public int getDuration(); + public String getLang(); + public int getType(); +}
diff --git a/plugins/org.eclipse.actf.ai.audio.description/src/org/eclipse/actf/ai/audio/description/IMetadataProvider.java b/plugins/org.eclipse.actf.ai.audio.description/src/org/eclipse/actf/ai/audio/description/IMetadataProvider.java new file mode 100644 index 0000000..2ec27de --- /dev/null +++ b/plugins/org.eclipse.actf.ai.audio.description/src/org/eclipse/actf/ai/audio/description/IMetadataProvider.java
@@ -0,0 +1,34 @@ +/******************************************************************************* + * Copyright (c) 2007 IBM Corporation and Others + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Daisuke SATO - initial API and implementation + *******************************************************************************/ +package org.eclipse.actf.ai.audio.description; + +import java.util.ArrayList; +import java.util.Locale; + +public interface IMetadataProvider { + public int getSize(); + + public IMetadata getItem(int index); + + public ArrayList<IMetadata> getAllItems(); + + public int getIndex(int position); + + public void setLocale(Locale locale); + + public int getAlternatives(); + + public void setAlternative(int index); + + public void reload(); + + public boolean hasMetadata(); +}
diff --git a/plugins/org.eclipse.actf.ai.audio.description/src/org/eclipse/actf/ai/audio/description/Messages.java b/plugins/org.eclipse.actf.ai.audio.description/src/org/eclipse/actf/ai/audio/description/Messages.java new file mode 100644 index 0000000..4da2611 --- /dev/null +++ b/plugins/org.eclipse.actf.ai.audio.description/src/org/eclipse/actf/ai/audio/description/Messages.java
@@ -0,0 +1,35 @@ +/******************************************************************************* + * Copyright (c) 2007 IBM Corporation and Others + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Takashi ITOH - initial API and implementation + *******************************************************************************/ + +package org.eclipse.actf.ai.audio.description; + +import java.util.MissingResourceException; +import java.util.ResourceBundle; + + + +public class Messages { + private static final String BUNDLE_NAME = "messages"; //$NON-NLS-1$ + + private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle.getBundle(BUNDLE_NAME); + + private Messages() { + } + + public static String getString(String key) { + // TODO Auto-generated method stub + try { + return RESOURCE_BUNDLE.getString(key); + } catch (MissingResourceException e) { + return '!' + key + '!'; + } + } +}
diff --git a/plugins/org.eclipse.actf.ai.audio.description/src/org/eclipse/actf/ai/audio/description/impl/MediaControlImpl.java b/plugins/org.eclipse.actf.ai.audio.description/src/org/eclipse/actf/ai/audio/description/impl/MediaControlImpl.java new file mode 100644 index 0000000..49be20b --- /dev/null +++ b/plugins/org.eclipse.actf.ai.audio.description/src/org/eclipse/actf/ai/audio/description/impl/MediaControlImpl.java
@@ -0,0 +1,115 @@ +/******************************************************************************* + * Copyright (c) 2007 IBM Corporation and Others + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Daisuke SATO - initial API and implementation + *******************************************************************************/ + +package org.eclipse.actf.ai.audio.description.impl; + +import java.util.HashMap; + +import org.eclipse.actf.ai.audio.description.DescriptionPlugin; +import org.eclipse.actf.ai.audio.description.IMetadataProvider; +import org.eclipse.actf.ai.audio.description.Messages; +import org.eclipse.actf.ai.navigator.IMediaControl; + + + + +public class MediaControlImpl implements IMediaControl { + + private HashMap<IHandle, MetadataManager> map = new HashMap<IHandle, MetadataManager>(); + //private List<MetadataManager> managers = new Vector<MetadataManager>(); + + MetadataManager manager; + MetadataManager oldManager; + + IHandle old = null; + + IHandle handle; + + public void dispose(IHandle handle) { + } + + public void start(IHandle handle) { + //if (handle.getSoundControl() == null || handle.getVideoControl() == null) + //return; + initialize(handle); + } + + private void initialize(IHandle handle) { + this.handle = handle; + MetadataManager temp = map.get(handle); + + if(temp == null){ + String url = handle.getWebBrowser().getURL(); + IMetadataProvider provider = DescriptionPlugin.getDefault().getMetadata(url); + temp = new MetadataManager(handle, provider); + + if(handle.getVideoControl() != null) + handle.getVideoControl().addEventListener(new MediaSyncEventListener(handle, temp)); + //System.out.println(temp); + //map.put(handle, temp); + } + if(manager != null){ + manager.stop(); + } + manager = temp; + manager.start(); + DescriptionPlugin.getDefault().setActiveMetadata(manager); + + if(manager.hasMetadata()){ + if(oldManager != null){ + System.out.println(oldManager.getMetadataProvider()); + System.out.println(manager.getMetadataProvider()); + } + if(oldManager == null || oldManager.getMetadataProvider() != manager.getMetadataProvider()){ + if(handle.getVoice() != null){ + //speakInfo(false); + } + oldManager = manager; + } + }else{ + //handle.getVoice().speak(Messages.getString("Metadata.notAvailable"), false); + } + } + + public void speakInfo(boolean flush) { + DescriptionPlugin plugin = DescriptionPlugin.getDefault(); + if (!plugin.isAvailable()) + return; + if (handle.getVoice() == null) + return; + + if (plugin.getEnable()) { + handle.getVoice().speak(Messages.getString("AudioDescription.on"), flush); + } else { + handle.getVoice().speak(Messages.getString("AudioDescription.off"), flush); + } + } + + public int toggleEnable() { + DescriptionPlugin plugin = DescriptionPlugin.getDefault(); + return plugin.toggleEnable(); + } + + public boolean isAvailable(){ + DescriptionPlugin plugin = DescriptionPlugin.getDefault(); + return plugin.isAvailable(); + } + + public boolean toggleViewShowing() { + DescriptionPlugin plugin = DescriptionPlugin.getDefault(); + return plugin.getDescriptionView().toggleViewShowing(); + } + + public boolean isEnabled() { + DescriptionPlugin plugin = DescriptionPlugin.getDefault(); + return plugin.getEnable(); + } +}
diff --git a/plugins/org.eclipse.actf.ai.audio.description/src/org/eclipse/actf/ai/audio/description/impl/MediaSyncEventListener.java b/plugins/org.eclipse.actf.ai.audio.description/src/org/eclipse/actf/ai/audio/description/impl/MediaSyncEventListener.java new file mode 100644 index 0000000..6b50620 --- /dev/null +++ b/plugins/org.eclipse.actf.ai.audio.description/src/org/eclipse/actf/ai/audio/description/impl/MediaSyncEventListener.java
@@ -0,0 +1,42 @@ +/******************************************************************************* + * Copyright (c) 2007 IBM Corporation and Others + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Daisuke SATO - initial API and implementation + *******************************************************************************/ + +package org.eclipse.actf.ai.audio.description.impl; + +import org.eclipse.actf.ai.fennec.treemanager.IMediaSyncEventListener; +import org.eclipse.actf.ai.navigator.IMediaControl.IHandle; + + + + +public class MediaSyncEventListener implements IMediaSyncEventListener { + + private static final double EVENT_INTERVAL = 0.1; // 100ms + + private IHandle handle; + private MetadataManager manager; + + public MediaSyncEventListener(IHandle handle, MetadataManager manager) { + this.handle = handle; + this.manager = manager; + } + + public void run(){ + if(handle.getVideoControl() != null){ + double time = handle.getVideoControl().getCurrentPosition(); + manager.process(time); + } + } + + public double getInterval() { + return EVENT_INTERVAL; + } +}
diff --git a/plugins/org.eclipse.actf.ai.audio.description/src/org/eclipse/actf/ai/audio/description/impl/MetadataContentProvider.java b/plugins/org.eclipse.actf.ai.audio.description/src/org/eclipse/actf/ai/audio/description/impl/MetadataContentProvider.java new file mode 100644 index 0000000..d7574c1 --- /dev/null +++ b/plugins/org.eclipse.actf.ai.audio.description/src/org/eclipse/actf/ai/audio/description/impl/MetadataContentProvider.java
@@ -0,0 +1,62 @@ +/******************************************************************************* + * Copyright (c) 2007 IBM Corporation and Others + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Daisuke SATO - initial API and implementation + *******************************************************************************/ + +package org.eclipse.actf.ai.audio.description.impl; + +import org.eclipse.actf.ai.audio.description.IMetadata; +import org.eclipse.actf.ai.audio.description.IMetadataProvider; +import org.eclipse.actf.ai.audio.description.util.TimeFormatUtil; +import org.eclipse.jface.viewers.IStructuredContentProvider; +import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.swt.graphics.Image; + + + + +public class MetadataContentProvider extends LabelProvider implements IStructuredContentProvider, ITableLabelProvider{ + + @Override + public void dispose() { + } + + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + } + + public Object[] getElements(Object inputElement) { + if(inputElement instanceof IMetadataProvider){ + IMetadataProvider provider = (IMetadataProvider)inputElement; + + String[][] ret = new String[provider.getSize()][2]; + for(int i=0; i<ret.length; i++){ + IMetadata metadata = provider.getItem(i); + ret[i][0] = ""+TimeFormatUtil.getTimeString(metadata.getStartTime()/100.0); + ret[i][1] = ""+metadata.getDescription(); + } + return ret; + } + return null; + } + + public Image getColumnImage(Object element, int columnIndex) { + // TODO Auto-generated method stub + return null; + } + + public String getColumnText(Object element, int columnIndex) { + if(element instanceof String[]){ + return ((String[])element)[columnIndex]; + } + return ""; + } + +}
diff --git a/plugins/org.eclipse.actf.ai.audio.description/src/org/eclipse/actf/ai/audio/description/impl/MetadataImpl.java b/plugins/org.eclipse.actf.ai.audio.description/src/org/eclipse/actf/ai/audio/description/impl/MetadataImpl.java new file mode 100644 index 0000000..abf203e --- /dev/null +++ b/plugins/org.eclipse.actf.ai.audio.description/src/org/eclipse/actf/ai/audio/description/impl/MetadataImpl.java
@@ -0,0 +1,162 @@ +/******************************************************************************* + * Copyright (c) 2007 IBM Corporation and Others + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Daisuke SATO - initial API and implementation + *******************************************************************************/ +package org.eclipse.actf.ai.audio.description.impl; + +import java.util.Locale; + +import org.eclipse.actf.ai.audio.description.IMetadata; + + +public class MetadataImpl implements IMetadata { + private double scale = 1; + + private String sTime; + + private int type = MASK_SPEAK; + + private int start; + + private int originalTime; + + private int duration; + + private String description; + + private int importance; + + private String lang; + + public MetadataImpl(String start, String duration, String desc, String lang, String importance) { + setStart(start); + setDuration(duration); + setLang(lang); + setDescription(desc); + setImportance(importance); + + } + + private void setStart(String start) { + this.start = string2time(start); + setStringTime(); + } + + private void setDuration(String duration) { + this.duration = string2time(duration); + } + + private void setLang(String lang) { + this.lang = (new Locale(lang)).getLanguage(); + } + + private void setDescription(String desc) { + this.description = desc; + } + + private void setImportance(String importance) { + importance = importance.toLowerCase(); + if (importance.equals("low")) { + this.importance = IMPORTANCE_LOW; + } else if (importance.equals("middle")) { + this.importance = IMPORTANCE_MIDDLE; + } else if (importance.equals("high")) { + this.importance = IMPORTANCE_HIGH; + } + } + + private int string2time(String str) { + int time = 0; + try { + String[] part = str.split(":"); + int[] r = new int[] { 1, 1000, 60000, 3600000 }; + + time = 0; + for (int i = part.length - 1, j = 0; i >= 0; i--, j++) { + int temp = Integer.parseInt(part[i]); + time += temp * r[j]; + } + time /= 10; + } catch (Exception e) { + e.printStackTrace(); + time = 0; + } + return time; + } + + private void setStringTime() { + int temp = getStartTime(); + int mm = 0; + int s = 0; + int m = 0; + int h = 0; + mm = temp % 100; + temp -= mm; + temp /= 100; + s = temp % 60; + temp -= s; + temp /= 60; + m = temp % 60; + temp -= m; + temp /= 60; + h = temp; + + StringBuffer sb = new StringBuffer(); + if (h != 0) { + sb.append(h + "h"); + } + sb.append((m < 10 ? "0" : "") + m + "m"); + sb.append((s < 10 ? "0" : "") + s + "s"); + sb.append((mm < 10 ? "0" : "") + mm); + + sTime = sb.toString(); + } + + public void setScale(double scale) { + this.scale = scale; + } + + public String getDescription() { + return description; + } + + public int getStartTime() { + int temp = start; + if (temp < 0) { + temp = 0; + } + return (int) (temp * scale); + } + + public int getType() { + return type; + } + + @Override + public String toString() { + return start + " (" + duration+") "+description + ", " + importance; + } + + public String getStringTime() { + return sTime; + } + + public void refresh() { + start = originalTime; + setStringTime(); + } + + public int getDuration() { + return duration; + } + + public String getLang() { + return lang; + } +}
diff --git a/plugins/org.eclipse.actf.ai.audio.description/src/org/eclipse/actf/ai/audio/description/impl/MetadataManager.java b/plugins/org.eclipse.actf.ai.audio.description/src/org/eclipse/actf/ai/audio/description/impl/MetadataManager.java new file mode 100644 index 0000000..af6d17c --- /dev/null +++ b/plugins/org.eclipse.actf.ai.audio.description/src/org/eclipse/actf/ai/audio/description/impl/MetadataManager.java
@@ -0,0 +1,158 @@ +/******************************************************************************* + * Copyright (c) 2007 IBM Corporation and Others + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Daisuke SATO - initial API and implementation + *******************************************************************************/ + +package org.eclipse.actf.ai.audio.description.impl; + + +import org.eclipse.actf.ai.audio.description.DescriptionPlugin; +import org.eclipse.actf.ai.audio.description.IMetadata; +import org.eclipse.actf.ai.audio.description.IMetadataProvider; +import org.eclipse.actf.ai.fennec.treemanager.ISoundControl; +import org.eclipse.actf.ai.fennec.treemanager.IVideoControl; +import org.eclipse.actf.ai.navigator.IMediaControl.IHandle; + + + + +public class MetadataManager{ + + private IMetadataProvider metadataProvider; + + private int index; + + private int oldIndex; + + private int forceFlag = IMetadata.MASK_NONE; + + private IHandle handle; + + private IVideoControl video; + + @SuppressWarnings("unused") + private ISoundControl sound; + + private boolean stopFlag = false; + + public void setForceFlag(int flag) { + forceFlag = flag; + } + + public MetadataManager(IHandle handle, IMetadataProvider metadataProvider) { + this.handle = handle; + this.video = handle.getVideoControl(); + this.sound = handle.getSoundControl(); + + this.metadataProvider = metadataProvider; + index = oldIndex = -1; + } + + private boolean pauseBeforeFlag = false; + + private boolean speakFlag = false; + + private boolean pauseAfterFlag = false; + + public void process(double time) { + if(stopFlag) + return; + + DescriptionPlugin.getDefault().getDescriptionView().setTime(time); + + if (metadataProvider == null) + return; + index = metadataProvider.getIndex((int) (time * 100)); + // System.out.println(time+", "+metadataProvider.getItem(index).getTime()); + + if (oldIndex != index && oldIndex < index) { + int type = metadataProvider.getItem(index).getType(); + + pauseBeforeFlag = isIt(type | forceFlag, IMetadata.MASK_PAUSE_BEFORE); + speakFlag = isIt(type | forceFlag, IMetadata.MASK_SPEAK); + pauseAfterFlag = isIt(type | forceFlag, IMetadata.MASK_PAUSE_AFTER); + } + + if (pauseBeforeFlag) { + pauseBeforeFlag = false; + processPause(); + } + if (speakFlag) { + speakFlag = false; + processSpeak(); + } + if (pauseAfterFlag) { + pauseAfterFlag = false; + processPlay(); + } + + oldIndex = index; + } + + private boolean isIt(int type, int pause) { + return (type & pause) == pause; + } + + private void processPause() { + if (DescriptionPlugin.getDefault().getEnable()) + video.pauseMedia(); + } + + private void processPlay() { + if (DescriptionPlugin.getDefault().getEnable()) + video.playMedia(); + } + + private void processSpeak() { + if (DescriptionPlugin.getDefault().getEnable()) { + + /* + int[] volumes = null; + volumes = sound.getVolumes(); + int[] volumes2 = new int[volumes.length]; + for(int i=0; i<volumes2.length; i++) + volumes2[i] = 200; + sound.setVolumes(volumes2); + */ + + String desc = metadataProvider.getItem(index).getDescription(); + say(desc); + } + } + + public void say(String str) { + //System.out.println(str); + DescriptionPlugin plugin = DescriptionPlugin.getDefault(); + + if (plugin.canSpeak()) { + plugin.speak(str); + } else { + handle.getVoice().speak(str, true); + } + } + + public void stop() { + stopFlag = true; + } + + public void start(){ + stopFlag = false; + DescriptionPlugin.getDefault().getDescriptionView().setInput(metadataProvider); + } + + public boolean hasMetadata(){ + if (metadataProvider == null) + return false; + return metadataProvider.hasMetadata(); + } + + public Object getMetadataProvider() { + return metadataProvider; + } +}
diff --git a/plugins/org.eclipse.actf.ai.audio.description/src/org/eclipse/actf/ai/audio/description/impl/MetadataProviderImpl.java b/plugins/org.eclipse.actf.ai.audio.description/src/org/eclipse/actf/ai/audio/description/impl/MetadataProviderImpl.java new file mode 100644 index 0000000..a05afff --- /dev/null +++ b/plugins/org.eclipse.actf.ai.audio.description/src/org/eclipse/actf/ai/audio/description/impl/MetadataProviderImpl.java
@@ -0,0 +1,316 @@ +/******************************************************************************* + * Copyright (c) 2007 IBM Corporation and Others + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Daisuke SATO - initial API and implementation + *******************************************************************************/ +package org.eclipse.actf.ai.audio.description.impl; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Locale; +import java.util.Set; +import java.util.Stack; + +import org.eclipse.actf.ai.audio.description.IMetadata; +import org.eclipse.actf.ai.audio.description.IMetadataProvider; +import org.eclipse.actf.ai.xmlstore.IXMLInfo; +import org.eclipse.actf.ai.xmlstore.XMLStoreException; +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + + +public class MetadataProviderImpl implements IMetadataProvider { + + private static class Key { + public String id; + + public String lang; + + public Key(String id, String lang) { + this.id = id; + if (lang == null || lang.length() == 0) { + this.lang = ""; + } else { + this.lang = (new Locale(lang)).getLanguage(); + } + } + + @Override + public int hashCode() { + return toString().hashCode(); + } + + @Override + public boolean equals(Object o) { + return toString().equals(o.toString()); + } + + @Override + public String toString(){ + return id+lang; + } + } + + private HashMap<Key, ArrayList<IMetadata>> metadataList = new HashMap<Key, ArrayList<IMetadata>>(); + + private ArrayList<IMetadata> metadata; + + private ArrayList<IXMLInfo> entries; + + private Locale locale = null; + + public MetadataProviderImpl(ArrayList<IXMLInfo> entries) { + this.entries = entries; + } + + public void reload() { + metadataList.clear(); + readFile(); + } + + private Stack<String> langStack = new Stack<String>(); + + private class BaseHandler extends DefaultHandler { + private BaseHandler back; + + private IXMLInfo entry; + + public BaseHandler(BaseHandler back, IXMLInfo entry) { + this.back = back; + this.entry = entry; + } + + public BaseHandler(BaseHandler back) { + this.back = back; + this.entry = back.getEntry(); + } + + @Override + public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { + if (attributes.getValue("xml:lang") != null) { + langStack.push(attributes.getValue("xml:lang")); + } else { + langStack.push(langStack.peek() + ""); + } + } + + @Override + public void endElement(String uri, String localName, String qName) throws SAXException { + langStack.pop(); + getEntry().setContentHandler(back); + } + + public IXMLInfo getEntry() { + return entry; + } + } + + private class AllHandler extends BaseHandler { + private boolean altFlag; + + public AllHandler(IXMLInfo entry) { + super(null, entry); + langStack.clear(); + langStack.push(""); + } + + @Override + public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { + super.startElement(uri, localName, qName, attributes); + + if (altFlag) { + if ("item".equals(localName)) { + String importance = attributes.getValue("importance"); + if (importance == null || importance.length() == 0) { + importance = "middle"; + } + getEntry().setContentHandler(new ItemHandler(this, importance)); + } + } else { + if ("alternative".equals(localName)) { + String type = attributes.getValue("type"); + if (type != null && type.equals("audio-description")) { + altFlag = true; + } + } + } + } + + @Override + public void endElement(String uri, String localName, String qName) throws SAXException { + // super.endElement(uri, localName, qName); + } + } + + private class ItemHandler extends BaseHandler { + private boolean descFlag = false; + + private boolean startFlag = false; + + private boolean durationFlag = false; + + private StringBuffer buf = new StringBuffer(); + + private String start; + + private String duration; + + private ArrayList<String> desc = new ArrayList<String>(); + + private ArrayList<String> lang = new ArrayList<String>(); + + private String importance; + + public ItemHandler(BaseHandler back, String importance) { + super(back); + this.importance = importance; + } + + @Override + public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { + super.startElement(uri, localName, qName, attributes); + + if ("start".equals(localName)) { + if (attributes.getValue("type").equals("relTime")) { + startFlag = true; + } + } else if ("duration".equals(localName)) { + durationFlag = true; + } else if ("description".equals(localName)) { + descFlag = true; + } + + } + + @Override + public void characters(char[] ch, int start, int length) throws SAXException { + if (startFlag) { + buf.append(ch, start, length); + } else if (durationFlag) { + buf.append(ch, start, length); + } else if (descFlag) { + buf.append(ch, start, length); + } + } + + @Override + public void endElement(String uri, String localName, String qName) throws SAXException { + if ("start".equals(localName)) { + startFlag = false; + start = buf.toString(); + buf.delete(0, buf.length()); + } else if ("duration".equals(localName)) { + durationFlag = false; + duration = buf.toString(); + buf.delete(0, buf.length()); + } else if ("description".equals(localName)) { + descFlag = false; + desc.add(buf.toString()); + lang.add(langStack.peek()); + buf.delete(0, buf.length()); + } else if ("item".equals(localName)) { + + for (int i = 0; i < desc.size(); i++) { + MetadataImpl mi = new MetadataImpl(start, duration, desc.get(i), lang.get(i), importance); + //System.out.println(start + ", " + duration + ", " + desc.get(i) + ", " + lang.get(i)); + + Key key = new Key(getEntry().getDocumentation(), lang.get(i)); + + ArrayList<IMetadata> list = metadataList.get(key); + + if (list == null) { + list = new ArrayList<IMetadata>(); + metadataList.put(key, list); + } + list.add(mi); + } + super.endElement(uri, localName, qName); + } + } + } + + private void readFile() { + for (int i = 0; i < entries.size(); i++) { + IXMLInfo entry = entries.get(i); + + AllHandler ah = new AllHandler(entry); + entry.setContentHandler(ah); + try { + entry.startSAX(); + } catch (XMLStoreException e) { + e.printStackTrace(); + } catch (SAXException e) { + e.printStackTrace(); + } + } + } + + public void setLocale(Locale locale) { + this.locale = locale; + } + + ArrayList<ArrayList<IMetadata>> alternatives; + + public int getAlternatives() { + Set<Key> keys = metadataList.keySet(); + alternatives = new ArrayList<ArrayList<IMetadata>>(); + for (Iterator<Key> i = keys.iterator(); i.hasNext();) { + Key key = i.next(); + if (key.lang.equals(locale.getLanguage())) { + alternatives.add(metadataList.get(key)); + } + } + if (alternatives.size() > 0) + setMetadata(alternatives.get(0)); + return alternatives.size(); + } + + public void setAlternative(int index) { + metadata = alternatives.get(index); + } + + public void setMetadata(ArrayList<IMetadata> metadata) { + this.metadata = metadata; + } + + public IMetadata getItem(int index) { + if (0 <= index && index < metadata.size()) + return metadata.get(index); + return null; + } + + public ArrayList<IMetadata> getAllItems() { + return metadata; + } + + public int getIndex(int position) { + if (metadata == null) + return 0; + + int ret = 0; + for (int i = 0; i < metadata.size(); i++) { + if (metadata.get(i).getStartTime() >= position) { + ret = i - 1; + return ret; + } + } + return metadata.size() - 1; + } + + public int getSize() { + if (metadata == null) + return 0; + return metadata.size(); + } + + public boolean hasMetadata() { + return metadata.size() > 0; + } +}
diff --git a/plugins/org.eclipse.actf.ai.audio.description/src/org/eclipse/actf/ai/audio/description/preferences/ADPreferenceInitializer.java b/plugins/org.eclipse.actf.ai.audio.description/src/org/eclipse/actf/ai/audio/description/preferences/ADPreferenceInitializer.java new file mode 100644 index 0000000..6ce4251 --- /dev/null +++ b/plugins/org.eclipse.actf.ai.audio.description/src/org/eclipse/actf/ai/audio/description/preferences/ADPreferenceInitializer.java
@@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2007 IBM Corporation and Others + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Daisuke SATO - initial API and implementation + *******************************************************************************/ +package org.eclipse.actf.ai.audio.description.preferences; + +import org.eclipse.actf.ai.audio.description.DescriptionPlugin; +import org.eclipse.actf.ai.voice.internal.TTSRegistry; +import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer; +import org.eclipse.jface.preference.IPreferenceStore; + + +public class ADPreferenceInitializer extends AbstractPreferenceInitializer { + + @Override + public void initializeDefaultPreferences() { + IPreferenceStore store = DescriptionPlugin.getDefault().getPreferenceStore(); + store.setDefault(DescriptionPlugin.PREF_ENGINE, TTSRegistry.getDefaultEngine()); + } +}
diff --git a/plugins/org.eclipse.actf.ai.audio.description/src/org/eclipse/actf/ai/audio/description/preferences/ADPreferencePage.java b/plugins/org.eclipse.actf.ai.audio.description/src/org/eclipse/actf/ai/audio/description/preferences/ADPreferencePage.java new file mode 100644 index 0000000..6bca77d --- /dev/null +++ b/plugins/org.eclipse.actf.ai.audio.description/src/org/eclipse/actf/ai/audio/description/preferences/ADPreferencePage.java
@@ -0,0 +1,52 @@ +/******************************************************************************* + * Copyright (c) 2007 IBM Corporation and Others + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Daisuke SATO - initial API and implementation + *******************************************************************************/ + +package org.eclipse.actf.ai.audio.description.preferences; + +import org.eclipse.actf.ai.audio.description.DescriptionPlugin; +import org.eclipse.actf.ai.audio.description.Messages; +import org.eclipse.actf.ai.voice.internal.TTSRegistry; +import org.eclipse.jface.preference.FieldEditorPreferencePage; +import org.eclipse.jface.preference.RadioGroupFieldEditor; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.IWorkbenchPreferencePage; + + + + +public class ADPreferencePage extends FieldEditorPreferencePage implements IWorkbenchPreferencePage{ + + public ADPreferencePage() { + super(GRID); + setPreferenceStore(DescriptionPlugin.getDefault().getPreferenceStore()); + setDescription(Messages.getString("AudioDescription.preference.title")); //$NON-NLS-1$ + } + + @Override + public void createFieldEditors() { + RadioGroupFieldEditor rgfe; + String[][] labelAndIds = TTSRegistry.getLabelAndIds(); + addField(rgfe = new RadioGroupFieldEditor(DescriptionPlugin.PREF_ENGINE, + Messages.getString("AudioDescription.voice.engine"), 1, labelAndIds, //$NON-NLS-1$ + getFieldEditorParent())); + Composite c = rgfe.getRadioBoxControl(getFieldEditorParent()); + for(int i=0; i<labelAndIds.length; i++){ + if(labelAndIds[i][1].length() == 0){ + c.getChildren()[i].setEnabled(false); + } + } + } + + public void init(IWorkbench workbench) { + + } +}
diff --git a/plugins/org.eclipse.actf.ai.audio.description/src/org/eclipse/actf/ai/audio/description/util/TimeFormatUtil.java b/plugins/org.eclipse.actf.ai.audio.description/src/org/eclipse/actf/ai/audio/description/util/TimeFormatUtil.java new file mode 100644 index 0000000..4749921 --- /dev/null +++ b/plugins/org.eclipse.actf.ai.audio.description/src/org/eclipse/actf/ai/audio/description/util/TimeFormatUtil.java
@@ -0,0 +1,29 @@ +/******************************************************************************* + * Copyright (c) 2007 IBM Corporation and Others + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Daisuke SATO - initial API and implementation + *******************************************************************************/ + +package org.eclipse.actf.ai.audio.description.util; + + +public class TimeFormatUtil { + + public static String getTimeString(double time){ + int mi, se, ms; + int intTime = (int)(time*100); + + ms = intTime%100; + intTime /= 100; + se = intTime%60; + intTime /= 60; + mi = intTime; + + return (mi<10?"0":"")+mi+":"+(se<10?"0":"")+se+"."+(ms<10?"0":"")+ms; + } +}
diff --git a/plugins/org.eclipse.actf.ai.audio.description/src/org/eclipse/actf/ai/audio/description/views/DescriptionView.java b/plugins/org.eclipse.actf.ai.audio.description/src/org/eclipse/actf/ai/audio/description/views/DescriptionView.java new file mode 100644 index 0000000..136cbf8 --- /dev/null +++ b/plugins/org.eclipse.actf.ai.audio.description/src/org/eclipse/actf/ai/audio/description/views/DescriptionView.java
@@ -0,0 +1,113 @@ +/******************************************************************************* + * Copyright (c) 2007 IBM Corporation and Others + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Daisuke SATO - initial API and implementation + *******************************************************************************/ + +package org.eclipse.actf.ai.audio.description.views; + +import org.eclipse.actf.ai.audio.description.DescriptionPlugin; +import org.eclipse.actf.ai.audio.description.Messages; +import org.eclipse.actf.ai.audio.description.impl.MetadataContentProvider; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; +import org.eclipse.ui.IViewPart; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.part.ViewPart; + + + + +public class DescriptionView extends ViewPart { + public static final String ID = "org.eclipse.actf.ai.audio.description.views.DescriptionView"; + + private VideoStatusViewer status; + + private TableViewer tableViewer; + + @Override + public void createPartControl(Composite parent) { + initView(parent); + DescriptionPlugin.getDefault().setDescriptionView(this); + } + + private void initView(Composite parent) { + GridLayout gLayout = new GridLayout(1, true); + gLayout.marginWidth = 0; + gLayout.marginHeight = 0; + parent.setLayout(gLayout); + + status = new VideoStatusViewer(parent); + + tableViewer = new TableViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER); + MetadataContentProvider provider = new MetadataContentProvider(); + tableViewer.setContentProvider(provider); + tableViewer.setLabelProvider(provider); + + Table table = tableViewer.getTable(); + table.setHeaderVisible(true); + table.setLinesVisible(true); + TableColumn tableColumnProperty = new TableColumn(table, SWT.LEFT); + tableColumnProperty.setText(Messages.getString("AudioDescription.view.time")); + tableColumnProperty.setWidth(70); + TableColumn tableColumnValue = new TableColumn(table, SWT.LEFT); + tableColumnValue.setText(Messages.getString("AudioDescription.view.desc")); + tableColumnValue.setWidth(130); + + GridData data = new GridData(GridData.FILL_BOTH); + table.setLayoutData(data); + } + + @Override + public void setFocus() { + + } + + public void setTime(double time) { + status.setTime(time); + } + public void setInput(Object input){ + if(tableViewer.getTable().isDisposed()) + return; + tableViewer.setInput(input); + } + public void setIndex(int index){ + if(tableViewer.getTable().isDisposed()) + return; + tableViewer.getTable().select(index); + } + + public void setEnable(boolean b) { + status.setEnable(b); + } + + public boolean toggleViewShowing() { + IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); + IViewPart part = page.findView(ID); + + if (part != null) { + page.hideView(part); + return false; + } else { + try { + page.showView(ID); + return true; + } catch (PartInitException e) { + e.printStackTrace(); + } + } + return false; + } +}
diff --git a/plugins/org.eclipse.actf.ai.audio.description/src/org/eclipse/actf/ai/audio/description/views/VideoStatusViewer.java b/plugins/org.eclipse.actf.ai.audio.description/src/org/eclipse/actf/ai/audio/description/views/VideoStatusViewer.java new file mode 100644 index 0000000..fa0328a --- /dev/null +++ b/plugins/org.eclipse.actf.ai.audio.description/src/org/eclipse/actf/ai/audio/description/views/VideoStatusViewer.java
@@ -0,0 +1,66 @@ +/******************************************************************************* + * Copyright (c) 2007 IBM Corporation and Others + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Daisuke SATO - initial API and implementation + *******************************************************************************/ + +package org.eclipse.actf.ai.audio.description.views; + +import org.eclipse.actf.ai.audio.description.DescriptionPlugin; +import org.eclipse.actf.ai.audio.description.Messages; +import org.eclipse.actf.ai.audio.description.util.TimeFormatUtil; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; + + + + +public class VideoStatusViewer { + + private Composite parent; + private Label status; + private boolean enable = false; + private String timeText; + + + public VideoStatusViewer(Composite parent){ + this.parent = parent; + initialize(); + } + + public void initialize(){ + status = new Label(parent, SWT.NONE); + GridData data = new GridData(GridData.FILL_HORIZONTAL); + status.setLayoutData(data); + status.setAlignment(SWT.RIGHT); + setTime(0); + enable = DescriptionPlugin.getDefault().getEnable(); + } + + public void setTime(double time){ + timeText = TimeFormatUtil.getTimeString(time); + refreshText(); + } + + private void refreshText(){ + if(status.isDisposed()) + return; + if(enable){ + status.setText(Messages.getString("AudioDescription.view.enable")+" "+timeText); + }else{ + status.setText(Messages.getString("AudioDescription.view.notEnable")+" "+timeText); + } + } + + public void setEnable(boolean b) { + enable = b; + refreshText(); + } +}
diff --git a/plugins/org.eclipse.actf.ai.audio.io/.classpath b/plugins/org.eclipse.actf.ai.audio.io/.classpath new file mode 100644 index 0000000..751c8f2 --- /dev/null +++ b/plugins/org.eclipse.actf.ai.audio.io/.classpath
@@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<classpath> + <classpathentry kind="src" path="src"/> + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/> + <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/> + <classpathentry kind="output" path="bin"/> +</classpath>
diff --git a/plugins/org.eclipse.actf.ai.audio.io/.project b/plugins/org.eclipse.actf.ai.audio.io/.project new file mode 100644 index 0000000..cc0b860 --- /dev/null +++ b/plugins/org.eclipse.actf.ai.audio.io/.project
@@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>org.eclipse.actf.ai.audio.io</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>org.eclipse.jdt.core.javabuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.pde.ManifestBuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.pde.SchemaBuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.eclipse.pde.PluginNature</nature> + <nature>org.eclipse.jdt.core.javanature</nature> + </natures> +</projectDescription>
diff --git a/plugins/org.eclipse.actf.ai.audio.io/META-INF/MANIFEST.MF b/plugins/org.eclipse.actf.ai.audio.io/META-INF/MANIFEST.MF new file mode 100644 index 0000000..89dee95 --- /dev/null +++ b/plugins/org.eclipse.actf.ai.audio.io/META-INF/MANIFEST.MF
@@ -0,0 +1,12 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Eclipse ACTF Audio IO Plug-in (Incubation) +Bundle-SymbolicName: org.eclipse.actf.ai.audio.io +Bundle-Version: 0.0.1 +Bundle-Activator: org.eclipse.actf.ai.audio.io.Activator +Bundle-Vendor: Eclipse.org +Bundle-Localization: plugin +Require-Bundle: org.eclipse.ui, + org.eclipse.core.runtime +Eclipse-LazyStart: true +Export-Package: org.eclipse.actf.ai.audio.io
diff --git a/plugins/org.eclipse.actf.ai.audio.io/about.html b/plugins/org.eclipse.actf.ai.audio.io/about.html new file mode 100644 index 0000000..481dbcf --- /dev/null +++ b/plugins/org.eclipse.actf.ai.audio.io/about.html
@@ -0,0 +1,25 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/> +<title>About</title> +</head> +<body lang="EN-US"> +<h2>About This Content</h2> + +<p>June 5, 2006</p> +<h3>License</h3> +<p>The Eclipse Foundation makes available all content in this plug-in ("Content"). +Unless otherwise indicated below, the Content is provided to you under the terms and conditions of the +Eclipse Public License Version 1.0 ("EPL"). A copy of the EPL is available +at <a href="http://www.eclipse.org/org/documents/epl-v10.php">http://www.eclipse.org/legal/epl-v10.html</a>. +For purposes of the EPL, "Program" will mean the Content.</p> +<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is +being redistributed by another party ("Redistributor") and different terms and conditions may +apply to your use of any object code in the Content. Check the Redistributor’s license +that was provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise +indicated below, the terms and conditions of the EPL still apply to any source code in the Content +and such source code may be obtained at <a href="http://www.eclipse.org/">http://www.eclipse.org</a>.</p> +</body> +</html> \ No newline at end of file
diff --git a/plugins/org.eclipse.actf.ai.audio.io/build.properties b/plugins/org.eclipse.actf.ai.audio.io/build.properties new file mode 100644 index 0000000..e1942be --- /dev/null +++ b/plugins/org.eclipse.actf.ai.audio.io/build.properties
@@ -0,0 +1,15 @@ +############################################################################### +# Copyright (c) 2007 IBM Corporation and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# IBM Corporation - initial API and implementation +############################################################################### +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + about.html,\ + .
diff --git a/plugins/org.eclipse.actf.ai.audio.io/src/org/eclipse/actf/ai/audio/io/Activator.java b/plugins/org.eclipse.actf.ai.audio.io/src/org/eclipse/actf/ai/audio/io/Activator.java new file mode 100644 index 0000000..f948ffd --- /dev/null +++ b/plugins/org.eclipse.actf.ai.audio.io/src/org/eclipse/actf/ai/audio/io/Activator.java
@@ -0,0 +1,62 @@ +/******************************************************************************* + * Copyright (c) 2007 IBM Corporation and Others + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Daisuke SATO - initial API and implementation + *******************************************************************************/ +package org.eclipse.actf.ai.audio.io; + +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.osgi.framework.BundleContext; + +/** + * The activator class controls the plug-in life cycle + */ +public class Activator extends AbstractUIPlugin { + + // The plug-in ID + public static final String PLUGIN_ID = "org.eclipse.actf.ai.audio.io"; + + // The shared instance + private static Activator plugin; + + /** + * The constructor + */ + public Activator() { + plugin = this; + } + + /* + * (non-Javadoc) + * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext) + */ + @Override + public void start(BundleContext context) throws Exception { + super.start(context); + } + + /* + * (non-Javadoc) + * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext) + */ + @Override + public void stop(BundleContext context) throws Exception { + plugin = null; + super.stop(context); + } + + /** + * Returns the shared instance + * + * @return the shared instance + */ + public static Activator getDefault() { + return plugin; + } + +}
diff --git a/plugins/org.eclipse.actf.ai.audio.io/src/org/eclipse/actf/ai/audio/io/AudioFactory.java b/plugins/org.eclipse.actf.ai.audio.io/src/org/eclipse/actf/ai/audio/io/AudioFactory.java new file mode 100644 index 0000000..ea98776 --- /dev/null +++ b/plugins/org.eclipse.actf.ai.audio.io/src/org/eclipse/actf/ai/audio/io/AudioFactory.java
@@ -0,0 +1,92 @@ +/******************************************************************************* + * Copyright (c) 2007 IBM Corporation and Others + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Daisuke SATO - initial API and implementation + *******************************************************************************/ + +package org.eclipse.actf.ai.audio.io; + +import java.net.URL; + +import javax.sound.sampled.Mixer; + +import org.eclipse.actf.ai.audio.io.impl.AudioFileReader; +import org.eclipse.actf.ai.audio.io.impl.AudioPipe; +import org.eclipse.actf.ai.audio.io.impl.LoopedAudioPipe; +import org.eclipse.actf.ai.audio.io.impl.PlaybackDevice; +import org.eclipse.actf.ai.audio.io.impl.RecordDevice; + + + + +public class AudioFactory { + public static IAudioReader createAudioReader(String file) { + return new AudioFileReader(file); + } + + public static IAudioReader createAudioReader(URL url) { + return new AudioFileReader(url); + } + + public static IAudioWriter createDefaultWriter() { + return new PlaybackDevice(); + } + + public static IAudioPipe createAudioPipe(IAudioReader reader, IAudioWriter writer) { + return new AudioPipe(reader, writer); + } + + public static IAudioPipe createLoopedAudioPipe(IAudioReader reader, IAudioWriter writer) { + return new LoopedAudioPipe(reader, writer); + } + + public static IAudioWriter createAudioWriter(Mixer mixer) { + return new PlaybackDevice(mixer); + } + + public static IAudioReader createAudioReader(Mixer mixer, int recordingSmapleRate, int recordingChannels) { + return new RecordDevice(mixer, recordingSmapleRate, recordingChannels); + } + + public static void main(String[] args) { + IAudioReader reader = AudioFactory.createAudioReader("16-16-short-pcm-lpf.wav"); + IAudioWriter writer = AudioFactory.createDefaultWriter(); + IAudioPipe pipe = AudioFactory.createLoopedAudioPipe(reader, writer); + + // buffer size for reading (in milli seconds) + pipe.setBufferSize(100); + + // interval time to try writing (in milli seconds) + pipe.setInterval(1); + + // Create new thread and start playing. + // The pipe automatically opens reader and writer. + pipe.prepare(); + + pipe.start(); + + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + pipe.stop(); + + pipe.start(); + + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + pipe.stop(); + } + +}
diff --git a/plugins/org.eclipse.actf.ai.audio.io/src/org/eclipse/actf/ai/audio/io/AudioIOException.java b/plugins/org.eclipse.actf.ai.audio.io/src/org/eclipse/actf/ai/audio/io/AudioIOException.java new file mode 100644 index 0000000..8fea0c6 --- /dev/null +++ b/plugins/org.eclipse.actf.ai.audio.io/src/org/eclipse/actf/ai/audio/io/AudioIOException.java
@@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2007 IBM Corporation and Others + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Daisuke SATO - initial API and implementation + *******************************************************************************/ + +package org.eclipse.actf.ai.audio.io; + + +public class AudioIOException extends Exception{ + + public AudioIOException(String string) { + super(string); + } + + /** + * + */ + private static final long serialVersionUID = 1L; + +}
diff --git a/plugins/org.eclipse.actf.ai.audio.io/src/org/eclipse/actf/ai/audio/io/AudioPipeListener.java b/plugins/org.eclipse.actf.ai.audio.io/src/org/eclipse/actf/ai/audio/io/AudioPipeListener.java new file mode 100644 index 0000000..1395187 --- /dev/null +++ b/plugins/org.eclipse.actf.ai.audio.io/src/org/eclipse/actf/ai/audio/io/AudioPipeListener.java
@@ -0,0 +1,18 @@ +/******************************************************************************* + * Copyright (c) 2007 IBM Corporation and Others + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Daisuke SATO - initial API and implementation + *******************************************************************************/ + +package org.eclipse.actf.ai.audio.io; + + +public interface AudioPipeListener { + void finished(IAudioPipe pipe); + void stopped(IAudioPipe pipe); +}
diff --git a/plugins/org.eclipse.actf.ai.audio.io/src/org/eclipse/actf/ai/audio/io/AudioUtil.java b/plugins/org.eclipse.actf.ai.audio.io/src/org/eclipse/actf/ai/audio/io/AudioUtil.java new file mode 100644 index 0000000..f61869b --- /dev/null +++ b/plugins/org.eclipse.actf.ai.audio.io/src/org/eclipse/actf/ai/audio/io/AudioUtil.java
@@ -0,0 +1,57 @@ +/******************************************************************************* + * Copyright (c) 2007 IBM Corporation and Others + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Daisuke SATO - initial API and implementation + *******************************************************************************/ + +package org.eclipse.actf.ai.audio.io; + +import java.nio.ByteOrder; + +import javax.sound.sampled.AudioFormat; + + + +public class AudioUtil { + + public static int getBytesPerSecondLR(AudioFormat format) { + return (int) getBytesPerSecond(format) * format.getChannels(); + } + + public static int getBytesPerSecond(AudioFormat format) { + return (int) getBitsPerSecond(format) / 8; + } + + public static int getBitsPerSecond(AudioFormat format){ + return (int) format.getSampleRate() * format.getSampleSizeInBits(); + } + + public static int getSamplesPerSecond(AudioFormat format) { + return (int) format.getSampleRate(); + } + + public static int getSamplesPerSecondLR(AudioFormat format) { + return (int) getSamplesPerSecond(format) * format.getChannels(); + } + + public static int getBytesPerSample(AudioFormat format){ + return format.getSampleSizeInBits() / 8; + } + + public static int getBytesPerSampleLR(AudioFormat format) { + return getBytesPerSample(format) * format.getChannels(); + } + + public static ByteOrder getEndian(AudioFormat format) { + if(format.isBigEndian()) + return ByteOrder.BIG_ENDIAN; + else + return ByteOrder.LITTLE_ENDIAN; + } + +}
diff --git a/plugins/org.eclipse.actf.ai.audio.io/src/org/eclipse/actf/ai/audio/io/IAudioPipe.java b/plugins/org.eclipse.actf.ai.audio.io/src/org/eclipse/actf/ai/audio/io/IAudioPipe.java new file mode 100644 index 0000000..11899e2 --- /dev/null +++ b/plugins/org.eclipse.actf.ai.audio.io/src/org/eclipse/actf/ai/audio/io/IAudioPipe.java
@@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2007 IBM Corporation and Others + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Daisuke SATO - initial API and implementation + *******************************************************************************/ + +package org.eclipse.actf.ai.audio.io; + + +public interface IAudioPipe { + void addAudioPipeListener(AudioPipeListener listener); + + void setInterval(int interval); + void setPriority(int priority); + void setBufferSize(int miliSeconds); + boolean isActive(); + + void prepare(); + void start(int delay); + void start(); + void stop(); + void join(); +}
diff --git a/plugins/org.eclipse.actf.ai.audio.io/src/org/eclipse/actf/ai/audio/io/IAudioReader.java b/plugins/org.eclipse.actf.ai.audio.io/src/org/eclipse/actf/ai/audio/io/IAudioReader.java new file mode 100644 index 0000000..c1d4a9b --- /dev/null +++ b/plugins/org.eclipse.actf.ai.audio.io/src/org/eclipse/actf/ai/audio/io/IAudioReader.java
@@ -0,0 +1,37 @@ +/******************************************************************************* + * Copyright (c) 2007 IBM Corporation and Others + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Daisuke SATO - initial API and implementation + *******************************************************************************/ + +package org.eclipse.actf.ai.audio.io; + +import javax.sound.sampled.AudioFormat; + +import org.eclipse.actf.ai.audio.io.AudioIOException; + + + + + +public interface IAudioReader { + + String getName(); + + AudioFormat getAudioFormat(); + + boolean canRead(); + + void open() throws AudioIOException; + + void close(); + + int read(byte[] data, int offset, int length) throws AudioIOException; + + boolean isClosed(); +}
diff --git a/plugins/org.eclipse.actf.ai.audio.io/src/org/eclipse/actf/ai/audio/io/IAudioWriter.java b/plugins/org.eclipse.actf.ai.audio.io/src/org/eclipse/actf/ai/audio/io/IAudioWriter.java new file mode 100644 index 0000000..381299c --- /dev/null +++ b/plugins/org.eclipse.actf.ai.audio.io/src/org/eclipse/actf/ai/audio/io/IAudioWriter.java
@@ -0,0 +1,35 @@ +/******************************************************************************* + * Copyright (c) 2007 IBM Corporation and Others + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Daisuke SATO - initial API and implementation + *******************************************************************************/ + +package org.eclipse.actf.ai.audio.io; + +import javax.sound.sampled.AudioFormat; + +import org.eclipse.actf.ai.audio.io.AudioIOException; + + + + + +public interface IAudioWriter { + + String getName(); + + int write(byte[] data, int offset, int length) throws AudioIOException; + + boolean canWrite(); + + void open(AudioFormat format) throws AudioIOException; + + void close(); + + boolean isClosed(); +}
diff --git a/plugins/org.eclipse.actf.ai.audio.io/src/org/eclipse/actf/ai/audio/io/impl/AudioFileReader.java b/plugins/org.eclipse.actf.ai.audio.io/src/org/eclipse/actf/ai/audio/io/impl/AudioFileReader.java new file mode 100644 index 0000000..2db216b --- /dev/null +++ b/plugins/org.eclipse.actf.ai.audio.io/src/org/eclipse/actf/ai/audio/io/impl/AudioFileReader.java
@@ -0,0 +1,139 @@ +/******************************************************************************* + * Copyright (c) 2007 IBM Corporation and Others + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Daisuke SATO - initial API and implementation + *******************************************************************************/ + +package org.eclipse.actf.ai.audio.io.impl; + +import java.io.File; +import java.io.IOException; +import java.net.URL; + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.UnsupportedAudioFileException; + +import org.eclipse.actf.ai.audio.io.AudioIOException; +import org.eclipse.actf.ai.audio.io.IAudioReader; + + + + +public class AudioFileReader implements IAudioReader { + + private File file; + + private URL url; + + private AudioFormat format; + + private AudioInputStream stream; + + private boolean opened = false; + + private boolean closed = false; + + public AudioFileReader(String fileName) { + setFile(fileName); + } + + public AudioFileReader(URL url) { + setURL(url); + } + + public String getName() { + if (file != null) + return "File \"" + file.getName() + "\""; + if (url != null) + return "URL \"" + url.getPath() + "\""; + return ""; + } + + private void setFile(String fileName) { + this.file = new File(fileName); + } + + private void setURL(URL url) { + this.url = url; + } + + public boolean canRead() { + try { + if (file != null) + AudioSystem.getAudioInputStream(file); + if (url != null) + AudioSystem.getAudioFileFormat(url); + return true; + } catch (UnsupportedAudioFileException e) { + } catch (IOException e) { + } + return false; + } + + synchronized public void open() throws AudioIOException { + try { + if (file != null) + stream = AudioSystem.getAudioInputStream(file); + if (url != null) + stream = AudioSystem.getAudioInputStream(url); + AudioFormat baseFormat = stream.getFormat(); + + AudioFormat decodedFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, baseFormat.getSampleRate(), + 16, baseFormat.getChannels(), baseFormat.getChannels() * 2, baseFormat.getSampleRate(), false); + + stream = AudioSystem.getAudioInputStream(decodedFormat, stream); + + format = stream.getFormat(); + opened = true; + closed = false; + } catch (UnsupportedAudioFileException e) { + throw new AudioIOException("Unsupported audio file type"); + } catch (IOException e) { + throw new AudioIOException(e.toString()); + } + } + + public AudioFormat getAudioFormat() { + return format; + } + + synchronized public int read(byte[] data, int offset, int length) throws AudioIOException { + if (!opened) { + throw new AudioIOException("not opened"); + } + try { + int nBytesRead = stream.read(data, offset, length); + if (nBytesRead == -1) { + stream.close(); + opened = false; + closed = true; + nBytesRead = 0; + } + return nBytesRead; + } catch (IOException e) { + e.printStackTrace(); + } + return 0; + } + + synchronized public void close() { + try { + if (stream != null) + stream.close(); + } catch (IOException e) { + } + opened = false; + closed = true; + } + + public boolean isClosed() { + return closed; + } +}
diff --git a/plugins/org.eclipse.actf.ai.audio.io/src/org/eclipse/actf/ai/audio/io/impl/AudioPipe.java b/plugins/org.eclipse.actf.ai.audio.io/src/org/eclipse/actf/ai/audio/io/impl/AudioPipe.java new file mode 100644 index 0000000..7059bab --- /dev/null +++ b/plugins/org.eclipse.actf.ai.audio.io/src/org/eclipse/actf/ai/audio/io/impl/AudioPipe.java
@@ -0,0 +1,258 @@ +/******************************************************************************* + * Copyright (c) 2007 IBM Corporation and Others + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Daisuke SATO - initial API and implementation + *******************************************************************************/ + +package org.eclipse.actf.ai.audio.io.impl; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.ShortBuffer; +import java.util.ArrayList; +import java.util.Date; + +import javax.sound.sampled.AudioFormat; + +import org.eclipse.actf.ai.audio.io.AudioIOException; +import org.eclipse.actf.ai.audio.io.AudioPipeListener; +import org.eclipse.actf.ai.audio.io.AudioUtil; +import org.eclipse.actf.ai.audio.io.IAudioPipe; +import org.eclipse.actf.ai.audio.io.IAudioReader; +import org.eclipse.actf.ai.audio.io.IAudioWriter; + + + + +public class AudioPipe implements IAudioPipe{ + + private IAudioReader reader; + + private IAudioWriter writer; + + private AudioFormat format; + + private Thread thread; + + private Runnable runner; + + private byte[] buffer; + + private int bufferSize; + + private int interval = 100; + + private int priority = Thread.NORM_PRIORITY; + + private int bufferSizeInMs = 1000; + + private boolean active; + + private boolean waiting; + + private boolean stopFlag = false; + + private boolean stopFlag2 = false; + + private ArrayList<AudioPipeListener> listeners = new ArrayList<AudioPipeListener>(); + + public AudioPipe(IAudioReader reader, IAudioWriter writer) { + this.reader = reader; + this.writer = writer; + runner = new ReaderWriterRunner(); + } + + public void addAudioPipeListener(AudioPipeListener listener) { + listeners.add(listener); + } + + class ReaderWriterRunner implements Runnable { + private void fadeout(byte[] buffer, int nBytesRead) { + int bps = AudioUtil.getBytesPerSample(format); + + ByteBuffer bb = ByteBuffer.wrap(buffer); + ShortBuffer sb = null; + if (format.isBigEndian()) + bb.order(ByteOrder.BIG_ENDIAN); + else + bb.order(ByteOrder.LITTLE_ENDIAN); + + if (bps == 2) + sb = bb.asShortBuffer(); + + int len = nBytesRead / bps; + + for (int i = 0; i < len; i++) { + double k = (double) (len - i) / (double) len; + if (bps == 1) + bb.put(i, (byte) (bb.get(i) * k)); + else + sb.put(i, (short) (sb.get(i) * k)); + } + } + + public void run() { + try { + while (true) { + if (reader.isClosed()) + break; + + int nBytesRead = reader.read(buffer, 0, buffer.length); + + int nBytesWritten = 0; + do { + if (writer.isClosed()){ + active = false; + fireStopped(); + return; + } + if (stopFlag) { + fadeout(buffer, nBytesRead); + stopFlag = false; + stopFlag2 = true; + } + int temp = writer.write(buffer, nBytesWritten, nBytesRead); + nBytesWritten += temp; + nBytesRead -= temp; + sleep(); + } while (nBytesRead > 0); + + if (stopFlag2) { + stopFlag2 = false; + writer.close(); + } + } + writer.close(); + } catch (AudioIOException e) { + writer.close(); + } catch (Exception e){ + e.printStackTrace(); + writer.close(); + } + active = false; + fireFinished(); + } + } + + private void fireFinished() { + for (int i = 0; i < listeners.size(); i++) { + listeners.get(i).finished(this); + } + } + + private void fireStopped() { + for (int i = 0; i < listeners.size(); i++) { + listeners.get(i).stopped(this); + } + } + + synchronized public void setInterval(int interval) { + this.interval = interval; + } + + synchronized public void setPriority(int priority){ + this.priority = priority; + if(thread != null) + thread.setPriority(priority); + } + + public void prepare() { + try { + reader.open(); + format = reader.getAudioFormat(); + writer.open(format); + } catch (AudioIOException e) { + e.printStackTrace(); + return; + } + } + + public void start() { + start(0); + } + + public void start(final int delay) { + if (active || waiting) + return; + waiting = true; + thread = new Thread(new Runnable() { + public void run(){ + long s = (new Date()).getTime(); + + while (true) { + long n = (new Date()).getTime(); + if (stopFlag) { + waiting = false; + stopFlag = false; + active = false; + fireStopped(); + return; + } + if (s + delay <= n) { + break; + } + try { + Thread.sleep(1); + } catch (InterruptedException e){ + } + } + + while (active) { + try { + Thread.sleep(1); + } catch (InterruptedException e){ + } + } + + prepare(); + + int Bps = AudioUtil.getBytesPerSampleLR(format); + bufferSize = AudioUtil.getBytesPerSecondLR(format) * bufferSizeInMs / 1000 / Bps * Bps; + buffer = new byte[bufferSize]; + active = true; + waiting = false; + runner.run(); + } + }); + thread.setPriority(priority); + thread.setName(reader.getName()+"<->"+writer.getName()); + thread.start(); + } + + synchronized private void sleep() { + try { + Thread.sleep(interval); + Thread.yield(); + } catch (InterruptedException e) { + } + } + + public boolean isActive(){ + return active; + } + + public void stop() { + if (active || waiting) + stopFlag = true; + } + + public void join() { + if(thread == null) + return; + try { + thread.join(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + public void setBufferSize(int miliSeconds){ + bufferSizeInMs = miliSeconds; + } + +}
diff --git a/plugins/org.eclipse.actf.ai.audio.io/src/org/eclipse/actf/ai/audio/io/impl/LoopedAudioPipe.java b/plugins/org.eclipse.actf.ai.audio.io/src/org/eclipse/actf/ai/audio/io/impl/LoopedAudioPipe.java new file mode 100644 index 0000000..ff3c059 --- /dev/null +++ b/plugins/org.eclipse.actf.ai.audio.io/src/org/eclipse/actf/ai/audio/io/impl/LoopedAudioPipe.java
@@ -0,0 +1,104 @@ +/******************************************************************************* + * Copyright (c) 2007 IBM Corporation and Others + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Daisuke SATO - initial API and implementation + *******************************************************************************/ + +package org.eclipse.actf.ai.audio.io.impl; + +import java.util.ArrayList; + +import org.eclipse.actf.ai.audio.io.AudioPipeListener; +import org.eclipse.actf.ai.audio.io.IAudioPipe; +import org.eclipse.actf.ai.audio.io.IAudioReader; +import org.eclipse.actf.ai.audio.io.IAudioWriter; + + + + +public class LoopedAudioPipe implements IAudioPipe, AudioPipeListener { + + IAudioPipe target; + + boolean isActive; + + boolean joining = false; + + private ArrayList<AudioPipeListener> listeners = new ArrayList<AudioPipeListener>(); + + public LoopedAudioPipe(IAudioReader reader, IAudioWriter writer) { + target = new AudioPipe(reader, writer); + target.addAudioPipeListener(this); + } + + public void addAudioPipeListener(AudioPipeListener listener) { + listeners.add(listener); + } + + public boolean isActive() { + return isActive; + } + + public void join() { + joining = true; + target.join(); + fireFinished(); + } + + public void setBufferSize(int miliSeconds) { + target.setBufferSize(miliSeconds); + } + + public void setInterval(int interval) { + target.setInterval(interval); + } + + public void setPriority(int priority) { + target.setPriority(priority); + } + + public void prepare() { + target.prepare(); + } + + public void start() { + start(0); + } + + public void start(int delay) { + target.start(delay); + isActive = true; + joining = false; + } + + public void stop() { + target.stop(); + isActive = false; + fireStopped(); + } + + private void fireFinished() { + for (int i = 0; i < listeners.size(); i++) { + listeners.get(i).finished(this); + } + } + + private void fireStopped() { + for (int i = 0; i < listeners.size(); i++) { + listeners.get(i).stopped(this); + } + } + + public void finished(IAudioPipe pipe) { + if (!joining) + pipe.start(); + } + + public void stopped(IAudioPipe pipe) { + } +}
diff --git a/plugins/org.eclipse.actf.ai.audio.io/src/org/eclipse/actf/ai/audio/io/impl/PlaybackDevice.java b/plugins/org.eclipse.actf.ai.audio.io/src/org/eclipse/actf/ai/audio/io/impl/PlaybackDevice.java new file mode 100644 index 0000000..71c15f1 --- /dev/null +++ b/plugins/org.eclipse.actf.ai.audio.io/src/org/eclipse/actf/ai/audio/io/impl/PlaybackDevice.java
@@ -0,0 +1,101 @@ +/******************************************************************************* + * Copyright (c) 2007 IBM Corporation and Others + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Daisuke SATO - initial API and implementation + *******************************************************************************/ + +package org.eclipse.actf.ai.audio.io.impl; + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.DataLine; +import javax.sound.sampled.LineUnavailableException; +import javax.sound.sampled.Mixer; +import javax.sound.sampled.SourceDataLine; + +import org.eclipse.actf.ai.audio.io.AudioIOException; +import org.eclipse.actf.ai.audio.io.IAudioWriter; + + + + +public class PlaybackDevice implements IAudioWriter { + + private Mixer playbackMixer; + + private SourceDataLine playbackLine; + + private int limit; + + @Override + public boolean equals(Object o) { + if (o instanceof PlaybackDevice) { + return playbackMixer.equals(((PlaybackDevice) o).playbackMixer); + } + return false; + } + + public PlaybackDevice(Mixer mixer) { + this.playbackMixer = mixer; + } + + public PlaybackDevice() { + this.playbackMixer = null; + } + + public String getName() { + if (playbackMixer != null) + return "Device \"" + playbackMixer.getMixerInfo().getName() + "\""; + else + return "Device \"default\""; + } + + synchronized public void close() { + if (playbackLine != null) { + playbackLine.drain(); + playbackLine.close(); + } + } + + public boolean isClosed() { + if (playbackLine == null) + return true; + return !playbackLine.isOpen(); + } + + public boolean canWrite() { + return true; + } + + synchronized public void open(AudioFormat format) throws AudioIOException { + + DataLine.Info info = new DataLine.Info(SourceDataLine.class, format); + + try { + if (playbackMixer != null) + playbackLine = (SourceDataLine) playbackMixer.getLine(info); + else + playbackLine = (SourceDataLine) AudioSystem.getLine(info); + + playbackLine.open(); + + limit = playbackLine.available() / 10 * 5; + + playbackLine.start(); + } catch (LineUnavailableException e1) { + e1.printStackTrace(); + } + } + + synchronized public int write(byte[] data, int offset, int length) throws AudioIOException { + if (playbackLine.available() > limit) { + return playbackLine.write(data, offset, length); + } + return 0; + } +}
diff --git a/plugins/org.eclipse.actf.ai.audio.io/src/org/eclipse/actf/ai/audio/io/impl/RecordDevice.java b/plugins/org.eclipse.actf.ai.audio.io/src/org/eclipse/actf/ai/audio/io/impl/RecordDevice.java new file mode 100644 index 0000000..8a8cbae --- /dev/null +++ b/plugins/org.eclipse.actf.ai.audio.io/src/org/eclipse/actf/ai/audio/io/impl/RecordDevice.java
@@ -0,0 +1,113 @@ +/******************************************************************************* + * Copyright (c) 2007 IBM Corporation and Others + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Daisuke SATO - initial API and implementation + *******************************************************************************/ + +package org.eclipse.actf.ai.audio.io.impl; + +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.DataLine; +import javax.sound.sampled.LineUnavailableException; +import javax.sound.sampled.Mixer; +import javax.sound.sampled.TargetDataLine; + +import org.eclipse.actf.ai.audio.io.AudioIOException; +import org.eclipse.actf.ai.audio.io.IAudioReader; + + + + +public class RecordDevice implements IAudioReader { + + private Mixer recordMixer; + + private AudioFormat format; + + private TargetDataLine recordLine; + + @Override + public boolean equals(Object o) { + if (o instanceof RecordDevice) { + RecordDevice rd = (RecordDevice) o; + if (recordMixer.equals(rd.recordMixer)) { + return format.getChannels() == rd.format.getChannels() + && format.getFrameRate() == rd.format.getFrameRate() + && format.getSampleSizeInBits() == rd.format.getSampleSizeInBits(); + } + } + return false; + } + + public RecordDevice(Mixer mixer, int sampleRate, int channels) { + this.recordMixer = mixer; + format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, sampleRate, 16, channels, 2 * channels, sampleRate, + false); + if (!recordMixer.isLineSupported(new DataLine.Info(TargetDataLine.class, format))) { + check(sampleRate, channels); + } + } + + private void check(int sampleRate, int channels) { + AudioFormat temp; + int[] samples = new int[] { 48000, 44100, 22050, 16000, 8000 }; + + outer: for (int i = 0; i < samples.length; i++) { + if (samples[i] < sampleRate) { + temp = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, samples[i], 16, channels, 2 * channels, + samples[i], false); + if (recordMixer.isLineSupported(new DataLine.Info(TargetDataLine.class, temp))) { + format = temp; + break outer; + } + } + } + } + + public String getName() { + return "Device \"" + recordMixer.getMixerInfo().getName() + // + " (" + (format.getFrameRate() / 1000) + " kHz, " + format.getChannels() + "ch)" + "\""; + } + + public AudioFormat getAudioFormat() { + return format; + } + + synchronized public void close() { + if (recordLine != null) + recordLine.close(); + } + + public boolean isClosed() { + return !recordLine.isOpen(); + } + + public boolean canRead(){ + DataLine.Info info = new DataLine.Info(TargetDataLine.class, format); + return recordMixer.isLineSupported(info); + } + + synchronized public void open() throws AudioIOException { + DataLine.Info info = new DataLine.Info(TargetDataLine.class, format); + + try { + recordLine = (TargetDataLine) recordMixer.getLine(info); + recordLine.open(format); + recordLine.start(); + } catch (LineUnavailableException e) { + e.printStackTrace(); + } + } + + + + synchronized public int read(byte[] data, int offset, int length) throws AudioIOException { + return recordLine.read(data, offset, length); + } + +}