/*
* -----------------------------------------------------------------------
* File: $HeadURL$
* Revision $LastChangedRevision$
* Last Modified: $LastChangedDate$
* Last Change by: $LastChangedBy$
* -----------------------------------------------------------------------
* Copyright (C) 2007 Keith Stribley <devel@thanlwinsoft.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
* -----------------------------------------------------------------------
*/
/**
*
*/
package org.thanlwinsoft.eclipse.widgets;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.text.DateFormat;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.StringTokenizer;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.IJobManager;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.dialogs.MessageDialogWithToggle;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Scale;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Spinner;
import org.eclipse.swt.layout.GridData;
import org.thanlwinsoft.languagetest.MessageUtil;
import org.thanlwinsoft.languagetest.eclipse.LanguageTestPlugin;
import org.thanlwinsoft.languagetest.eclipse.editors.TestItemEditor;
import org.thanlwinsoft.languagetest.eclipse.editors.TestModuleEditor;
import org.thanlwinsoft.languagetest.eclipse.prefs.RecordingPreferencePage;
import org.thanlwinsoft.languagetest.eclipse.views.TestView;
import org.thanlwinsoft.languagetest.language.test.XmlBeansTestModule;
import org.thanlwinsoft.languagetest.sound.AudioPlayListener;
import org.thanlwinsoft.languagetest.sound.LineController;
import org.thanlwinsoft.languagetest.sound.Recorder;
import org.thanlwinsoft.schemas.languagetest.module.TestItemType;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.jface.viewers.ComboViewer;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
/**
* Composite containing a sound recorder
* the actual playback is done using the player in the TestView ControlPanel.
* @author keith
*
*/
public class SoundRecorder extends Composite implements ISelectionChangedListener, AudioPlayListener
{
private Button recordButton = null;
private Button stopButton = null;
private Scale recordScale = null;
private Spinner startSpinner = null;
private Button startButton = null;
private Spinner endSpinner = null;
private Button endButton = null;
private Button playButton = null;
private Button deleteButton = null;
private LineController lineController = null;
private Recorder recorder = null; // @jve:decl-index=0:
public final static String LINE_CONTROLLER = "LineController"; // @jve:decl-index=0:
private static final int WAV = 0;
private static final int MP3 = 1;
private static final int OGG = 2;
private static final int NUM_ENCODINGS = 3;
private static final int SPINNER2MS = 100; // spinner uses intervals of 0.1s
private static final int INITIAL_LIMIT = 300; // 30s
private long lengthInMs = -1;
private static final String [] EXTENSIONS = new String[] { "wav", "mp3", "ogg" };
private static final String [] FILTERS = new String[] { "*.wav", "*.mp3", "*.ogg" };
private static final String [] TYPES = new String[] { "Wave", "MP3", "OGG Vorbis" };
private Text fileNameText = null;
private Button browseButton = null;
private Combo encodingCombo = null;
private ComboViewer comboViewer = null;
private final static int MAX_SOUND_FILES = 10000;
private Display display = null;
private boolean settingItem = false;
private final DateFormat tempFormat = new SimpleDateFormat("yyyyMMddhhmmss");
public static final String WAVTOMP3_CONVERTER_PREF = "WavToMP3Converter";
public static final String WAVTOMP3_CONV_ARG_PREF = "WavToMP3ConverterArguments";
public static final String MP3TOWAV_CONVERTER_PREF = "MP3ToWavConverter";
public static final String MP3TOWAV_CONV_ARG_PREF = "MP3ToWavConverterArguments";
public static final String WAVTOOGG_CONVERTER_PREF = "WavToOggConverter";
public static final String WAVTOOGG_CONV_ARG_PREF = "WavToOggConverterArguments";
public static final String OGGTOWAV_CONVERTER_PREF = "OGGToWavConverter";
public static final String OGGTOWAV_CONV_ARG_PREF = "OGGToWavConverterArguments";
public final static String OVERWRITE_PREF_KEY = "OverwriteAudioNoPrompt";
private Label spacerLabel;
public SoundRecorder(Composite parent, int style)
{
super(parent, style);
initialize();
RecordingPreferencePage.initializeDefaults();
this.display = parent.getDisplay();
}
private void initialize()
{
GridData gridData2 = new GridData();
gridData2.horizontalAlignment = org.eclipse.swt.layout.GridData.FILL;
GridData gridData1 = new GridData();
gridData1.horizontalAlignment = org.eclipse.swt.layout.GridData.FILL;
GridData gridData = new GridData();
gridData.horizontalSpan = 5;
gridData.horizontalAlignment = org.eclipse.swt.layout.GridData.FILL;
gridData.widthHint = -1;
GridLayout gridLayout = new GridLayout();
gridLayout.numColumns = 7;
recordButton = new Button(this, SWT.NONE);
recordButton.setImage(new Image(Display.getCurrent(), getClass().getResourceAsStream("/org/thanlwinsoft/languagetest/sound/icons/recordMini.png")));
recordButton.addSelectionListener(new org.eclipse.swt.events.SelectionAdapter()
{
public void widgetSelected(org.eclipse.swt.events.SelectionEvent e)
{
record();
}
});
recordButton.setToolTipText(MessageUtil.getString("RecordTooltip"));
stopButton = new Button(this, SWT.NONE);
stopButton.setImage(new Image(Display.getCurrent(), getClass().getResourceAsStream("/org/thanlwinsoft/languagetest/sound/icons/stopMini.png")));
stopButton.addSelectionListener(new org.eclipse.swt.events.SelectionAdapter()
{
public void widgetSelected(org.eclipse.swt.events.SelectionEvent e)
{
stop();
}
});
stopButton.setToolTipText(MessageUtil.getString("StopTooltip"));
recordScale = new Scale(this, SWT.NONE);
recordScale.setPageIncrement(10);
recordScale.setMinimum(0);
recordScale.setMaximum(INITIAL_LIMIT);
recordScale.setIncrement(1);
recordScale.setLayoutData(gridData);
playButton = new Button(this, SWT.NONE);
playButton.setImage(new Image(Display.getCurrent(), getClass().getResourceAsStream("/org/thanlwinsoft/languagetest/sound/icons/playMini.png")));
playButton.addSelectionListener(new org.eclipse.swt.events.SelectionAdapter()
{
public void widgetSelected(org.eclipse.swt.events.SelectionEvent e)
{
play();
}
});
playButton.setToolTipText(MessageUtil.getString("PlayTooltip"));
deleteButton = new Button(this, SWT.NONE);
deleteButton.setImage(new Image(Display.getCurrent(), getClass().getResourceAsStream("/org/thanlwinsoft/languagetest/sound/icons/rubbishBin16.png")));
deleteButton.addSelectionListener(new org.eclipse.swt.events.SelectionAdapter()
{
public void widgetSelected(org.eclipse.swt.events.SelectionEvent e)
{
File file = getAudioFile();
if (file != null && MessageDialog.openConfirm(getShell(),
MessageUtil.getString("ConfirmDeleteTitle"),
MessageUtil.getString("ConfirmDeleteMessage",
file.getName())))
{
file.delete();
fileNameText.setText("");
fileNameText.setToolTipText("");
setEnabledStatus();
}
}
});
deleteButton.setToolTipText(MessageUtil.getString("DeleteAudioTooltip"));
startButton = new Button(this, SWT.LEFT);
startSpinner = new Spinner(this, SWT.NONE);
startSpinner.setValues(0, 0, INITIAL_LIMIT, 1, 1, 10);
spacerLabel = new Label(this, SWT.LEAD);
GridData spacerGridData = new GridData();
spacerGridData.grabExcessHorizontalSpace = true;
spacerGridData.minimumWidth = 50;
spacerGridData.horizontalAlignment = SWT.FILL;
spacerLabel.setText("");
spacerLabel.setLayoutData(spacerGridData);
endSpinner = new Spinner(this, SWT.NONE);
endSpinner.setValues(0, 0, INITIAL_LIMIT, 1, 1, 10);
endButton = new Button(this, SWT.RIGHT);
// Visual Editor doesn't like direct calls to MessageUtil in setText
createEncodingCombo();
GridData fileNameGridData = new GridData();
fileNameGridData.horizontalSpan = 3;
fileNameGridData.horizontalAlignment = GridData.FILL;
fileNameText = new Text(this, SWT.BORDER);
fileNameText.setLayoutData(fileNameGridData);
fileNameText.setToolTipText(MessageUtil.getString("AudioFileNameTooltip"));
GridData browseGridData = new GridData();
browseGridData.horizontalSpan = 2;
browseButton = new Button(this, SWT.NONE);
browseButton.setLayoutData(browseGridData);
browseButton.addSelectionListener(new org.eclipse.swt.events.SelectionAdapter()
{
public void widgetSelected(org.eclipse.swt.events.SelectionEvent e)
{
FileDialog dialog = new FileDialog(getShell(), SWT.SAVE);
dialog.setFilterExtensions(FILTERS);
dialog.setFilterNames(TYPES);
if (fileNameText.getText().length() > 0)
{
dialog.setFileName(fileNameText.getText());
}
fileNameText.setText(dialog.open());
fileNameText.setToolTipText(fileNameText.getText());
}
});
String s = MessageUtil.getString("PlaybackStartButton");
startButton.setText(s);
s = MessageUtil.getString("PlaybackStartTooltip");
startButton.setToolTipText(s);
startButton.setLayoutData(gridData1);
startButton.addSelectionListener(new org.eclipse.swt.events.SelectionAdapter()
{
public void widgetSelected(org.eclipse.swt.events.SelectionEvent e)
{
int value = recordScale.getSelection();
if (value < endSpinner.getSelection() ||
endSpinner.getSelection() <= 0)
{
startSpinner.setSelection(value);
updateTestItem();
spacerLabel.setText("");
spacerLabel.setToolTipText("");
}
else
{
spacerLabel.setText(MessageUtil.getString("EndBeforeStart"));
spacerLabel.setToolTipText(MessageUtil.getString("EndBeforeStart"));
spacerLabel.redraw();
}
}
});
s = MessageUtil.getString("PlaybackEndButton");
endButton.setText(s);
s = MessageUtil.getString("PlaybackEndTooltip");
endButton.setToolTipText(s);
endButton.setLayoutData(gridData2);
endButton.addSelectionListener(new org.eclipse.swt.events.SelectionAdapter()
{
public void widgetSelected(org.eclipse.swt.events.SelectionEvent e)
{
int value = recordScale.getSelection();
if (value > 0 && value > startSpinner.getSelection())
{
endSpinner.setSelection(value);
updateTestItem();
spacerLabel.setText("");
spacerLabel.setToolTipText("");
spacerLabel.redraw();
}
else
{
spacerLabel.setText(MessageUtil.getString("EndBeforeStart"));
spacerLabel.setToolTipText(MessageUtil.getString("EndBeforeStart"));
spacerLabel.redraw();
}
}
});
s = MessageUtil.getString("Browse");
browseButton.setText(s);
startSpinner.addModifyListener(new ModifyListener(){
public void modifyText(ModifyEvent e)
{
setLimits();
updateTestItem();
}});
endSpinner.addModifyListener(new ModifyListener(){
public void modifyText(ModifyEvent e)
{
setLimits();
updateTestItem();
}});
this.setLayout(gridLayout);
setSize(new Point(300, 200));
this.lineController = new LineController(LineController.REC_MODE);
Job job = new Job(LINE_CONTROLLER) {
public boolean belongsTo(Object family) {
return family == LINE_CONTROLLER;
}
protected IStatus run(IProgressMonitor monitor)
{
lineController.run();
return new Status(IStatus.OK, LanguageTestPlugin.ID,
IStatus.OK, LINE_CONTROLLER, null);
}
};
job.setPriority(Job.LONG);
job.schedule();
IEditorPart editor =
PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor();
if (editor instanceof TestModuleEditor)
{
ISelectionProvider sp = (ISelectionProvider)editor.getAdapter(ISelectionProvider.class);
if (sp != null)
{
sp.addSelectionChangedListener(this);
}
}
}
/**
*
*/
protected void stop()
{
if (recorder != null)
{
recorder.stop();
recorder.finish();
if (recorder.isRecordError())
{
LanguageTestPlugin.log(IStatus.ERROR, recorder.getErrorDescription());
MessageDialog.openError(this.getShell(),
MessageUtil.getString("RecordingError"),
recorder.getErrorDescription());
}
lineController.closeLines();
recorder = null;
IProgressMonitor pm =
Job.getJobManager().createProgressGroup();
try
{
IWorkspace workspace = ResourcesPlugin.getWorkspace();
IWorkspaceRoot root = workspace.getRoot();
pm.beginTask("Refresh after conversion",
IProgressMonitor.UNKNOWN);
// TODO make this less expensive, by only refreshing the
// relevant directory
root.refreshLocal(IResource.DEPTH_INFINITE, pm);
}
catch (CoreException e)
{
LanguageTestPlugin.log(IStatus.WARNING,
"Refresh error", e);
}
updateTestItem();
}
else
{
SoundPlayer player = getSoundPlayer();
if (player != null)
{
player.stop();
}
}
}
/**
*
*/
protected void record()
{
if (lineController != null)
{
if (!lineController.linesAreAvailable())
{
lineController.openLines();
}
if (recorder == null)
{
// setting the spinner resets the recorder, so this must be
// before the recorder is created
startSpinner.setSelection(0);
endSpinner.setSelection(0);
recorder = new Recorder(lineController);
recorder.addPlayListener(this);
}
else return;
File targetFile = getAudioFile();
boolean overwriteOK = LanguageTestPlugin.getPrefStore().getBoolean(OVERWRITE_PREF_KEY);
if (targetFile == null)
{
MessageDialog.openError(getShell(),
MessageUtil.getString("NoAudioFileTitle"),
MessageUtil.getString("NoAudioFileMessage"));
return;
}
else if (targetFile.exists() && overwriteOK == false)
{
// final String [] buttons = {
// MessageUtil.getString("Yes"),
// MessageUtil.getString("No"),
// MessageUtil.getString("Cancel")
// };
MessageDialogWithToggle dialog =
MessageDialogWithToggle.openYesNoCancelQuestion(
getShell(), MessageUtil.getString("OverwriteRecordingTitle"),
MessageUtil.getString("OverwriteRecording",
targetFile.getAbsolutePath()),
MessageUtil.getString("AlwaysOverwrite"),
false,
LanguageTestPlugin.getPrefStore(),
OVERWRITE_PREF_KEY);
int choice = 0;
LanguageTestPlugin.getPrefStore().setValue(OVERWRITE_PREF_KEY,
dialog.getToggleState());
try
{
LanguageTestPlugin.getPrefStore().save();
}
catch (IOException e)
{
LanguageTestPlugin.log(IStatus.WARNING,
e.getLocalizedMessage(), e);
}
choice = dialog.getReturnCode();
if (choice != 2)
return;
}
recorder.initialise(targetFile);
setEnabledStatus();
if (recorder.isInitialised())
{
recorder.start();
}
else
{
Job job = new Job("Record") {
protected IStatus run(IProgressMonitor monitor)
{
if (recorder.isInitialised())
{
recorder.start();
}
else
{
this.schedule(100);
}
return new Status(IStatus.OK, LanguageTestPlugin.ID,
IStatus.OK, "Record", null);
}
};
job.schedule(100);
}
}
}
protected void updateTestItem()
{
// don't update the test item while switch from one to another
if (settingItem)
return;
IEditorPart editor =
PlatformUI.getWorkbench().getActiveWorkbenchWindow()
.getActivePage().getActiveEditor();
if (editor instanceof TestModuleEditor)
{
TestModuleEditor tme = (TestModuleEditor)editor;
if (tme.getEditorInput() instanceof IFileEditorInput)
{
TestItemEditor tie = (TestItemEditor)tme.getAdapter(TestItemEditor.class);
ISelection selection = tie.getSelection();
if (tie != null && selection instanceof IStructuredSelection)
{
TestItemType [] items = tie.getSelectedItems();
if (items.length > 0)
{
TestItemType ti = items[0];
if (ti.getSoundFile() == null)
ti.addNewSoundFile();
IPath path = new Path(fileNameText.getText());
if (path.isAbsolute())
{
IPath modulePath = ((IFileEditorInput)tme.getEditorInput()).getFile().getRawLocation();
if (modulePath.removeLastSegments(1).isPrefixOf(path))
{
path = path.removeFirstSegments(modulePath.segmentCount() - 1);
fileNameText.setText(path.toString());
}
}
ti.getSoundFile().setStringValue(fileNameText.getText());
if (startSpinner.getSelection() > 0)
ti.getSoundFile().setStart(startSpinner.getSelection() * SPINNER2MS);
else if (ti.getSoundFile().isSetStart())
ti.getSoundFile().unsetStart();
if (endSpinner.getSelection() > 0)
ti.getSoundFile().setEnd(endSpinner.getSelection() * SPINNER2MS);
else if (ti.getSoundFile().isSetEnd())
ti.getSoundFile().unsetEnd();
if (lengthInMs > -1)
{
ti.getSoundFile().setLength(lengthInMs);
}
tme.setDirty(true);
tie.setSelection(selection);
}
}
}
}
}
protected File getAudioFile()
{
File file = null;
IFile moduleFile = null;
String moduleBaseName = "";
String fileName = "rec" + tempFormat.format(new Date()) + ".wav";
IEditorPart editor =
PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor();
if (editor instanceof TestModuleEditor)
{
TestModuleEditor tme = (TestModuleEditor)editor;
if (tme.getEditorInput() instanceof IFileEditorInput)
{
moduleFile = ((IFileEditorInput)tme.getEditorInput()).getFile();
int extIndex =
moduleFile.getName().indexOf(moduleFile.getFileExtension());
if (extIndex > 0)
{
moduleBaseName = moduleFile.getName().substring(0, extIndex - 1);
}
else
{
moduleBaseName = moduleFile.getName();
}
TestItemEditor tie = (TestItemEditor)tme.getAdapter(TestItemEditor.class);
if (tie != null && tie.getSelection() instanceof IStructuredSelection)
{
tie.addSelectionChangedListener(this);
TestItemType [] items = tie.getSelectedItems();
if (items.length > 0 && items[0].sizeOfNativeLangArray() > 0)
{
String nativeText = items[0].getNativeLangArray(0).getStringValue();
if (moduleFile.getParent().getFullPath().isValidSegment(nativeText))
{
fileName = nativeText + "." + EXTENSIONS[WAV];
}
}
}
}
}
if (fileNameText.getText().length() > 0)
{
// should we use portable string or OS string?
// this is probably more versatile
IPath path = new Path(fileNameText.getText());
if (path.isAbsolute())
{
file = new File(fileNameText.getText());
}
else
{
file = moduleFile.getParent().getFile(path).getRawLocation().toFile();
}
}
else if (moduleFile != null)
{
IContainer moduleParent = (IContainer)moduleFile.getParent();
IPath folderPath = new Path(moduleBaseName + "." + XmlBeansTestModule.FOLDER_EXT);
IFolder folder = moduleParent.getFolder(folderPath);
if (!folder.exists())
{
IJobManager jobMan = Job.getJobManager();
IProgressMonitor pm = jobMan.createProgressGroup();
try
{
folder.create(IResource.NONE, true, pm);
}
catch (CoreException e)
{
MessageDialog.openError(getShell(), MessageUtil.getString("FailedToCreateFolderTitle"),
MessageUtil.getString("FailedToCreateFolderMessage",
folder.getFullPath().toOSString(),
e.getLocalizedMessage()));
}
}
if (folder.isAccessible())
{
IFile testFile = folder.getFile(fileName);
int i = 0;
// find a unique name that doesn't yet exist
// give up eventually if max sane number is reached
while (testFile.exists() && i++ < MAX_SOUND_FILES)
{
fileName = moduleBaseName + i + "." + EXTENSIONS[WAV];
testFile = folder.getFile(fileName);
}
if (testFile != null)
{
file = testFile.getRawLocation().toFile();
int moduleSegments = moduleFile.getParent().getFullPath().segmentCount();
IPath relativePath =
testFile.getFullPath().removeFirstSegments(moduleSegments);
fileNameText.setText(relativePath.toPortableString());
fileNameText.setToolTipText(relativePath.toPortableString());
}
}
encodingCombo.select(WAV);
}
return file;
}
/**
* play the audio file
*/
protected void play()
{
SoundPlayer player = getSoundPlayer();
if (player != null)
{
player.setFile(getAudioFile().getAbsolutePath());
setLimits();
player.play();
}
}
/**
* set the player limits from the start/end spinners
* @param player
*/
protected void setLimits()
{
SoundPlayer player = getSoundPlayer();
if (player == null) return;
// spinners use intervals of 0.1s
long startMs = startSpinner.getSelection() * SPINNER2MS;
long endMs = endSpinner.getSelection() * SPINNER2MS;
long thumbMs = recordScale.getSelection() * SPINNER2MS;
if (endMs > 0 && endMs < startMs)
{
if (spacerLabel.getText().length() == 0)
{
spacerLabel.setText(MessageUtil.getString("EndBeforeStart"));
spacerLabel.setToolTipText(MessageUtil.getString("EndBeforeStart"));
spacerLabel.redraw();
}
endMs = -1;
}
else
{
spacerLabel.setText("");
spacerLabel.setToolTipText("");
}
// if the thumb is in between start and end, then start at the thumb
// give a 1 second tolerance at the end
if (thumbMs + 1000 < endMs && thumbMs > startMs)
{
startMs = thumbMs;
}
player.seek(startMs);
if (endMs > 0)
{
// this is elapsed from seek position
player.stopAfter(endMs - startMs);
}
else
{
player.stopAfter(-1);
}
}
protected SoundPlayer getSoundPlayer()
{
SoundPlayer player = null;
IWorkbenchPage page =
PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
TestView view = (TestView)page.findView(TestView.ID);
if (view == null)
{
try
{
view = (TestView)page.showView(TestView.ID, null, IWorkbenchPage.VIEW_CREATE);
}
catch (PartInitException e)
{
LanguageTestPlugin.log(IStatus.WARNING, e.getLocalizedMessage(), e);
}
}
if (view != null)
{
player = (SoundPlayer)view.getAdapter(SoundPlayer.class);
player.addPlayListener(this);
}
return player;
}
/**
* This method initializes encodingCombo
*
*/
private void createEncodingCombo()
{
GridData gridData3 = new GridData();
gridData3.horizontalSpan = 2;
encodingCombo = new Combo(this, SWT.NONE);
encodingCombo.setLayoutData(gridData3);
encodingCombo.addSelectionListener(new SelectionListener() {
public void widgetDefaultSelected(SelectionEvent e) {}
public void widgetSelected(SelectionEvent e)
{
convertIfNeeded();
}});
comboViewer = new ComboViewer(encodingCombo);
comboViewer.add(TYPES);
encodingCombo.setToolTipText(MessageUtil.getString("AudioFormatTooltip"));
}
/**
* This compares the requested format with the current audio format.
* If the 2 don't match a conversion is initiatied. This may take it to an
* intermediate format. After each conversion, this is recalled to initiate
* the next stage in the conversion.
*/
private void convertIfNeeded()
{
int fileEncoding = getFileEncoding();
int selectedEncoding = encodingCombo.getSelectionIndex();
if (fileEncoding != selectedEncoding)
{
switch (fileEncoding)
{
case WAV:
switch (selectedEncoding)
{
case MP3:
convertWavToMp3();
break;
case OGG:
convertWavToOgg();
break;
}
break;
case MP3:
switch (selectedEncoding)
{
case OGG:
case WAV:
convertMp3ToWav();
break;
}
break;
case OGG:
switch (selectedEncoding)
{
case MP3:
case WAV:
convertOggToWav();
break;
}
break;
}
}
}
private int getFileEncoding()
{
File file = getAudioFile();
int encoding = WAV;
for (int i = 0; i < NUM_ENCODINGS; i++)
{
if (file.getName().endsWith(EXTENSIONS[i]))
return i;
}
return encoding;
}
/**
* Convert file from Wave to MP3
*/
protected void convertWavToMp3()
{
final String converter =
LanguageTestPlugin.getPrefStore().getString(WAVTOMP3_CONVERTER_PREF);
String argumentTemplate =
LanguageTestPlugin.getPrefStore().getString(WAVTOMP3_CONV_ARG_PREF);
externalConverter(EXTENSIONS[MP3], converter, argumentTemplate);
}
/**
* Convert file from MP3 to Wave
*/
protected void convertMp3ToWav()
{
final String converter =
LanguageTestPlugin.getPrefStore().getString(MP3TOWAV_CONVERTER_PREF);
String argumentTemplate =
LanguageTestPlugin.getPrefStore().getString(MP3TOWAV_CONV_ARG_PREF);
externalConverter(EXTENSIONS[WAV], converter, argumentTemplate);
}
/**
* Convert from Wave to Ogg Vorbis
*/
protected void convertWavToOgg()
{
final String converter =
LanguageTestPlugin.getPrefStore().getString(WAVTOOGG_CONVERTER_PREF);
String argumentTemplate =
LanguageTestPlugin.getPrefStore().getString(WAVTOOGG_CONV_ARG_PREF);
externalConverter(EXTENSIONS[OGG], converter, argumentTemplate);
}
/**
* Convert from Ogg to Wave
*/
protected void convertOggToWav()
{
final String converter =
LanguageTestPlugin.getPrefStore().getString(OGGTOWAV_CONVERTER_PREF);
String argumentTemplate =
LanguageTestPlugin.getPrefStore().getString(OGGTOWAV_CONV_ARG_PREF);
externalConverter(EXTENSIONS[WAV], converter, argumentTemplate);
}
protected void externalConverter(final String newExtension,
final String converter, final String argumentTemplate)
{
final File oldFile = getAudioFile();
IPath path = new Path(getAudioFile().getAbsolutePath());
IPath basePath = path.removeFileExtension();
final IPath newPath = basePath.addFileExtension(newExtension);
final String newFilePath = newPath.toOSString();
final String allArgs = MessageFormat.format(argumentTemplate, new Object[]
{path.toOSString(),
newFilePath });
StringTokenizer st = new StringTokenizer(allArgs, " ", false);
final String [] arguments = new String[st.countTokens() + 1];
arguments[0] = converter;
for (int i = 1; i < arguments.length; i++)
{
arguments[i] = st.nextToken();
}
final Display display = getShell().getDisplay();
// Lame checks for term environment variable
final String [] environment = { "TERM=xterm" };
System.out.println(converter + allArgs);
if (converter.length() > 0)
{
Job job = new Job(converter) {
public IStatus run(IProgressMonitor monitor)
{
IStatus s = null;
int retValue = -1;
StringBuilder errorBuilder = new StringBuilder();
try
{
Process p = Runtime.getRuntime().exec(arguments, environment);
retValue = p.waitFor();
BufferedReader br = new BufferedReader(new InputStreamReader(p.getErrorStream()));
while (br.ready())
{
errorBuilder.append(br.readLine());
}
br.close();
br = new BufferedReader(new InputStreamReader(p.getInputStream()));
while (br.ready())
{
errorBuilder.append(br.readLine());
}
br.close();
System.out.println(errorBuilder.toString());
}
catch (IOException e)
{
errorBuilder.append(e.getLocalizedMessage());
e.printStackTrace();
}
catch (InterruptedException e)
{
errorBuilder.append(e.getLocalizedMessage());
e.printStackTrace();
}
finally
{
if (retValue != 0)
{
final String errorMsg = errorBuilder.toString();
display.asyncExec (new Runnable () {
public void run () {
MessageDialog.openWarning(getShell(),
MessageUtil.getString("ConversionProcessFailedTitle"),
MessageUtil.getString("ConversionProcessFailedTitle",
converter, allArgs,errorMsg));
}
});
s = new Status(IStatus.ERROR, LanguageTestPlugin.ID,
IStatus.OK, errorMsg, null);
}
else
{
// update gui
display.asyncExec (new Runnable () {
public void run () {
fileNameText.setText(newPath.toString());
fileNameText.setToolTipText(newPath.toString());
System.out.println(newPath.toString());
updateTestItem();
// may need a second conversion
convertIfNeeded();
setEnabledStatus();
IWorkspace workspace = ResourcesPlugin.getWorkspace();
IWorkspaceRoot root = workspace.getRoot();
if (root.getRawLocation().isPrefixOf(newPath))
{
IFile f = root.getFile(newPath.removeFirstSegments(root.getRawLocation().segmentCount()));
IProgressMonitor pm =
Job.getJobManager().createProgressGroup();
try
{
pm.beginTask("Refresh after conversion",
IProgressMonitor.UNKNOWN);
f.refreshLocal(IResource.DEPTH_INFINITE, pm);
}
catch (CoreException e)
{
LanguageTestPlugin.log(IStatus.WARNING,
"Refresh error", e);
}
finally
{
pm.done();
}
}
}
});
oldFile.delete(); // delete old format
s = new Status(IStatus.OK, LanguageTestPlugin.ID,
IStatus.OK, converter, null);
}
}
return s;
}
};
job.setPriority(Job.BUILD);
job.schedule();
}
else
{
MessageDialog.openInformation(getShell(),
MessageUtil.getString("NoMP3ConverterTitle"),
MessageUtil.getString("NoMP3ConverterMessage"));
}
}
/* (non-Javadoc)
* @see org.eclipse.jface.viewers.ISelectionChangedListener#selectionChanged(org.eclipse.jface.viewers.SelectionChangedEvent)
* called when TestItem selection changes in the TestItemEditor
*/
public void selectionChanged(SelectionChangedEvent event)
{
stop();
if (fileNameText.isDisposed())
return;
settingItem = true;
try
{
if (event.getSelection() instanceof StructuredSelection)
{
StructuredSelection ss = (StructuredSelection)event.getSelection();
TestItemType ti = null;
lengthInMs = -1;
if (ss.getFirstElement() instanceof TestItemType)
{
ti = (TestItemType)ss.getFirstElement();
}
if (ti != null && ti.isSetSoundFile()
&& ti.getSoundFile().getStringValue() != null)
{
spacerLabel.setText("");
fileNameText.setText(ti.getSoundFile().getStringValue());
fileNameText.setToolTipText(ti.getSoundFile().getStringValue());
IPath path = new Path(ti.getSoundFile().getStringValue());
for (int i = 0; i < EXTENSIONS.length; i++)
{
if (EXTENSIONS[i].equalsIgnoreCase(path.getFileExtension()))
{
encodingCombo.select(i);
break;
}
}
int max = INITIAL_LIMIT;
if (ti.getSoundFile().isSetLength())
{
max = (int)(ti.getSoundFile().getLength() / SPINNER2MS);
}
startSpinner.setMaximum(max);
endSpinner.setMaximum(max);
if (ti.getSoundFile().isSetEnd())
{
int value = (int)(ti.getSoundFile().getEnd() / SPINNER2MS);
if (max < value)
{
startSpinner.setMaximum(max);
endSpinner.setMaximum(max);
}
endSpinner.setSelection(value);
}
else endSpinner.setSelection(0);
if (ti.getSoundFile().isSetStart())
{
int value = (int)(ti.getSoundFile().getStart() / SPINNER2MS);
if (max < value)
{
max = value;
startSpinner.setMaximum(max);
endSpinner.setMaximum(max);
}
startSpinner.setSelection(value);
}
else startSpinner.setSelection(0);
}
else
{
fileNameText.setText("");
fileNameText.setToolTipText("");
encodingCombo.select(WAV);
startSpinner.setSelection(0);
endSpinner.setSelection(0);
}
setEnabledStatus();
}
}
finally
{
settingItem = false;
}
}
/* (non-Javadoc)
* @see org.eclipse.swt.widgets.Widget#dispose()
*/
public void dispose()
{
IEditorPart editor =
PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor();
if (editor instanceof TestModuleEditor)
{
ISelectionProvider sp = (ISelectionProvider)editor.getAdapter(ISelectionProvider.class);
if (sp != null)
{
sp.removeSelectionChangedListener(this);
}
}
SoundPlayer player = getSoundPlayer();
if (player != null)
{
player.removePlayListener(this);
}
super.dispose();
}
/* (non-Javadoc)
* @see org.thanlwinsoft.languagetest.sound.AudioPlayListener#initialisationProgress(int)
*/
public void initialisationProgress(int percent)
{
}
/* (non-Javadoc)
* @see org.thanlwinsoft.languagetest.sound.AudioPlayListener#playPosition(long, long)
*/
public void playPosition(long msPosition, long msTotalLength)
{
// use 0.1 sec as interval
final int sTotalLength = (int)(msTotalLength/SPINNER2MS);
final int sPosition = (int)(msPosition/SPINNER2MS);
if (msTotalLength > 0) lengthInMs = msTotalLength;
display.asyncExec (new Runnable () {
public void run () {
if (recordScale.isDisposed()) return;
int oldMax = recordScale.getMaximum();
if (sTotalLength > 0 && oldMax != sTotalLength)
{
recordScale.setMaximum(sTotalLength);
startSpinner.setMaximum(sTotalLength);
endSpinner.setMaximum(sTotalLength);
}
if (sPosition > oldMax)
{
recordScale.setMaximum(oldMax + 600); // add 1 minute
startSpinner.setMaximum(oldMax + 600);
endSpinner.setMaximum(oldMax + 600);
}
recordScale.setSelection(sPosition);
}
});
}
private void setEnabledStatus()
{
boolean enabled = false;
if (fileNameText.getText().length() > 0)
{
enabled = true;
}
deleteButton.setEnabled(enabled);
startButton.setEnabled(enabled);
endButton.setEnabled(enabled);
startSpinner.setEnabled(enabled);
endSpinner.setEnabled(enabled);
playButton.setEnabled(enabled);
}
}