diff --git a/livesupport/etc/debian/rules b/livesupport/etc/debian/rules
index e6b3424ad..0c40eb0e0 100755
--- a/livesupport/etc/debian/rules
+++ b/livesupport/etc/debian/rules
@@ -139,6 +139,8 @@ install-arch:
$(CURDIR)/debian/livesupport/opt/livesupport/var/LiveSupport/gLiveSupport*.res \
$(CURDIR)/debian/livesupport/opt/livesupport/var/LiveSupport/livesupport.png \
$(CURDIR)/debian/livesupport/opt/livesupport/var/LiveSupport/stationLogo.png \
+ $(CURDIR)/debian/livesupport/opt/livesupport/var/LiveSupport/testAudio.ogg \
+ $(CURDIR)/debian/livesupport/opt/livesupport/var/LiveSupport/testAudio.ogg.license \
$(CURDIR)/debian/livesupport-studio/opt/livesupport/var/LiveSupport
mkdir -p $(CURDIR)/debian/livesupport-studio/usr/share/applications
cp -a $(CURDIR)/debian/livesupport-studio.desktop \
diff --git a/livesupport/src/modules/widgets/include/LiveSupport/Widgets/EntryBin.h b/livesupport/src/modules/widgets/include/LiveSupport/Widgets/EntryBin.h
index 21816020b..b37da20fc 100644
--- a/livesupport/src/modules/widgets/include/LiveSupport/Widgets/EntryBin.h
+++ b/livesupport/src/modules/widgets/include/LiveSupport/Widgets/EntryBin.h
@@ -104,13 +104,24 @@ class EntryBin : public BlueBin
return entry;
}
+ /**
+ * Return the entry held in this container (const version).
+ *
+ * @return the entry held in this container.
+ */
+ const Gtk::Entry *
+ getEntry(void) const throw ()
+ {
+ return entry;
+ }
+
/**
* Return the text of the entry.
*
* @return the get_text() string of the Gtk::Entry.
*/
Glib::ustring
- get_text(void) throw ()
+ get_text(void) const throw ()
{
return getEntry()->get_text();
}
diff --git a/livesupport/src/products/gLiveSupport/etc/Makefile.in b/livesupport/src/products/gLiveSupport/etc/Makefile.in
index fd7875372..d1c24da26 100644
--- a/livesupport/src/products/gLiveSupport/etc/Makefile.in
+++ b/livesupport/src/products/gLiveSupport/etc/Makefile.in
@@ -341,8 +341,10 @@ install: all
${MKDIR} ${USR_ETC_DIR}
${MKDIR} ${USR_VAR_DIR}/LiveSupport
${CP} ${TMP_DIR}/*.res ${USR_VAR_DIR}/LiveSupport
- ${CP} ${VAR_DIR}/livesupport.png ${VAR_DIR}/stationLogo.png \
- ${USR_VAR_DIR}/LiveSupport
+ ${CP} ${VAR_DIR}/livesupport.png \
+ ${VAR_DIR}/stationLogo.png \
+ ${VAR_DIR}/testAudio.ogg \
+ ${VAR_DIR}/testAudio.ogg.license ${USR_VAR_DIR}/LiveSupport
${CP} ${BIN_DIR}/gLiveSupport.sh ${USR_BIN_DIR}
${CP} ${G_LIVESUPPORT_EXE} ${USR_BIN_DIR}
${CP} ${ETC_DIR}/gLiveSupport.xml.template ${USR_ETC_DIR}
diff --git a/livesupport/src/products/gLiveSupport/etc/gLiveSupport.xml b/livesupport/src/products/gLiveSupport/etc/gLiveSupport.xml
index 416c347f9..cf56397bd 100644
--- a/livesupport/src/products/gLiveSupport/etc/gLiveSupport.xml
+++ b/livesupport/src/products/gLiveSupport/etc/gLiveSupport.xml
@@ -89,6 +89,9 @@
+
+
+
@@ -155,6 +158,8 @@
+
+
+
+
+
@@ -153,7 +156,9 @@
-
+
+
+
+
+
+
@@ -153,7 +156,9 @@
-
+
+
+
close();
}
+
+/*------------------------------------------------------------------------------
+ * Test if we can switch back and forth between devices.
+ *----------------------------------------------------------------------------*/
+void
+AudioPlayerTest :: switchDevicesTest(void)
+ throw (CPPUNIT_NS::Exception)
+{
+ Ptr::Ref audioPlayerFactory;
+ audioPlayerFactory = AudioPlayerFactory::getInstance();
+ CPPUNIT_ASSERT(audioPlayerFactory.get());
+
+ Ptr::Ref audioPlayer;
+ audioPlayer = audioPlayerFactory->getAudioPlayer();
+ CPPUNIT_ASSERT(audioPlayer.get());
+
+ audioPlayer->setAudioDevice("/dev/dsp");
+ CPPUNIT_ASSERT_NO_THROW(
+ audioPlayer->open("file:var/testAudio.ogg")
+ );
+ audioPlayer->start();
+ Ptr::Ref sleepT(new time_duration(microseconds(10)));
+ while (audioPlayer->isPlaying()) {
+ TimeConversion::sleep(sleepT);
+ }
+ audioPlayer->close();
+
+ audioPlayer->setAudioDevice("plughw:0,0");
+ CPPUNIT_ASSERT_NO_THROW(
+ audioPlayer->open("file:var/testAudio.ogg")
+ );
+ audioPlayer->start();
+ while (audioPlayer->isPlaying()) {
+ TimeConversion::sleep(sleepT);
+ }
+ audioPlayer->close();
+}
+
diff --git a/livesupport/src/products/gLiveSupport/src/AudioPlayerTest.h b/livesupport/src/products/gLiveSupport/src/AudioPlayerTest.h
index ac653f280..5d67e37a6 100644
--- a/livesupport/src/products/gLiveSupport/src/AudioPlayerTest.h
+++ b/livesupport/src/products/gLiveSupport/src/AudioPlayerTest.h
@@ -73,6 +73,7 @@ class AudioPlayerTest : public BaseTestMethod
CPPUNIT_TEST(firstTest);
CPPUNIT_TEST(playAudioClipTest);
CPPUNIT_TEST(playPlaylistTest);
+ CPPUNIT_TEST(switchDevicesTest);
CPPUNIT_TEST_SUITE_END();
private:
@@ -108,6 +109,14 @@ class AudioPlayerTest : public BaseTestMethod
void
playPlaylistTest(void) throw (CPPUNIT_NS::Exception);
+ /**
+ * Test if we can switch back and forth between devices.
+ *
+ * @exception CPPUNIT_NS::Exception on test failures.
+ */
+ void
+ switchDevicesTest(void) throw (CPPUNIT_NS::Exception);
+
public:
/**
diff --git a/livesupport/src/products/gLiveSupport/src/GLiveSupport.cxx b/livesupport/src/products/gLiveSupport/src/GLiveSupport.cxx
index d185ab398..29afe939d 100644
--- a/livesupport/src/products/gLiveSupport/src/GLiveSupport.cxx
+++ b/livesupport/src/products/gLiveSupport/src/GLiveSupport.cxx
@@ -127,6 +127,11 @@ static const std::string cuePlayerElementName = "cuePlayer";
*----------------------------------------------------------------------------*/
static const std::string stationLogoConfigElementName = "stationLogo";
+/*------------------------------------------------------------------------------
+ * The name of the config element for the test audio file location
+ *----------------------------------------------------------------------------*/
+static const std::string testAudioUrlConfigElementName = "testAudioUrl";
+
/*------------------------------------------------------------------------------
* The name of the user preference for storing Scratchpad contents
*----------------------------------------------------------------------------*/
@@ -333,6 +338,17 @@ GLiveSupport :: configure(const xmlpp::Element & element)
mkdir(configFileName->c_str(), 0700); // create dir if does not exist
configFileName->append(configFileNameStr);
optionsContainer.reset(new OptionsContainer(element, configFileName));
+
+ // read the test audio file location
+ nodes = element.get_children(testAudioUrlConfigElementName);
+ if (nodes.size() < 1) {
+ throw std::invalid_argument("no test audio url element");
+ }
+ const xmlpp::Element* testAudioUrlElement
+ = dynamic_cast(nodes.front());
+ testAudioUrl.reset(new Glib::ustring(
+ testAudioUrlElement->get_attribute("path")
+ ->get_value() ));
}
@@ -1487,3 +1503,40 @@ GLiveSupport :: loadWindowPositions(void) throw ()
}
}
+
+/*------------------------------------------------------------------------------
+ * Set the device for the cue audio player.
+ *----------------------------------------------------------------------------*/
+void
+LiveSupport :: GLiveSupport ::
+GLiveSupport :: setCueAudioDevice(Ptr::Ref deviceName)
+ throw ()
+{
+ cuePlayer->setAudioDevice(*deviceName);
+}
+
+
+/*------------------------------------------------------------------------------
+ * Play a test sound on the cue audio player.
+ *----------------------------------------------------------------------------*/
+void
+LiveSupport :: GLiveSupport ::
+GLiveSupport :: playTestSoundOnCue(void) throw ()
+{
+ if (cueItemPlayingNow) {
+ stopCueAudio(); // stop the audio player and
+ } // release old resources
+
+ try {
+ cuePlayer->open(*testAudioUrl);
+ cuePlayer->start();
+ Ptr::Ref sleepT(new time_duration(microseconds(10)));
+ while (cuePlayer->isPlaying()) {
+ TimeConversion::sleep(sleepT);
+ }
+ } catch (std::runtime_error &e) {
+ // "invalid device" error from open(); do nothing
+ }
+ cuePlayer->close();
+}
+
diff --git a/livesupport/src/products/gLiveSupport/src/GLiveSupport.h b/livesupport/src/products/gLiveSupport/src/GLiveSupport.h
index 2ebabf20e..41ce55982 100644
--- a/livesupport/src/products/gLiveSupport/src/GLiveSupport.h
+++ b/livesupport/src/products/gLiveSupport/src/GLiveSupport.h
@@ -254,6 +254,11 @@ class GLiveSupport : public LocalizedConfigurable,
*/
Glib::RefPtr stationLogoPixbuf;
+ /**
+ * The location of the test audio file.
+ */
+ Ptr::Ref testAudioUrl;
+
/**
* Read a supportedLanguages configuration element,
* and fill the supportedLanguages map with its contents.
@@ -907,6 +912,21 @@ class GLiveSupport : public LocalizedConfigurable,
detachCueAudioListener(AudioPlayerEventListener * listener)
throw (std::invalid_argument);
+ /**
+ * Set the device for the cue audio player.
+ *
+ * @param deviceName the name of the new device
+ */
+ void
+ setCueAudioDevice(Ptr::Ref deviceName)
+ throw ();
+
+ /**
+ * Play a test sound on the cue audio player.
+ */
+ void
+ playTestSoundOnCue(void) throw ();
+
/**
* Search in the local storage.
*
diff --git a/livesupport/src/products/gLiveSupport/src/OptionsWindow.cxx b/livesupport/src/products/gLiveSupport/src/OptionsWindow.cxx
index f8d93eec6..3471cc3ed 100644
--- a/livesupport/src/products/gLiveSupport/src/OptionsWindow.cxx
+++ b/livesupport/src/products/gLiveSupport/src/OptionsWindow.cxx
@@ -219,6 +219,28 @@ OptionsWindow :: onCloseButtonClicked(bool needConfirm) throw ()
}
+/*------------------------------------------------------------------------------
+ * Event handler for the test button
+ *----------------------------------------------------------------------------*/
+void
+OptionsWindow :: onTestButtonClicked(const EntryBin * entry)
+ throw ()
+{
+ Ptr::Ref optionsContainer
+ = gLiveSupport->getOptionsContainer();
+
+ Ptr::Ref
+ oldDevice = optionsContainer->getOptionItem(OptionsContainer::
+ outputPlayerDeviceName);
+ Ptr::Ref
+ newDevice(new Glib::ustring(entry->get_text()));
+
+ gLiveSupport->setCueAudioDevice(newDevice); // NOTE: we can't use the
+ gLiveSupport->playTestSoundOnCue(); // output player b/c that
+ gLiveSupport->setCueAudioDevice(oldDevice); // would trigger onStop()
+}
+
+
/*------------------------------------------------------------------------------
* Create a new user entry field item.
*----------------------------------------------------------------------------*/
@@ -279,6 +301,20 @@ OptionsWindow :: constructSoundSection(void) throw ()
OptionsContainer::cuePlayerDeviceName);
audioDeviceTable->attach(*cuePlayerEntry, 1, 2, 0, 1);
+ Button * cueTestButton;
+ try {
+ cueTestButton = Gtk::manage(wf->createButton(
+ *getResourceUstring("testButtonLabel") ));
+ } catch (std::invalid_argument &e) {
+ // TODO: signal error
+ std::cerr << e.what() << std::endl;
+ std::exit(1);
+ }
+ cueTestButton->signal_clicked().connect(sigc::bind(
+ sigc::mem_fun(*this,&OptionsWindow::onTestButtonClicked),
+ cuePlayerEntry));
+ audioDeviceTable->attach(*cueTestButton, 2, 3, 0, 1);
+
// display the settings for the output player device
Glib::ustring outputPlayerLabelContents;
try {
@@ -298,6 +334,20 @@ OptionsWindow :: constructSoundSection(void) throw ()
OptionsContainer::outputPlayerDeviceName);
audioDeviceTable->attach(*outputPlayerEntry, 1, 2, 1, 2);
+ Button * outputTestButton;
+ try {
+ outputTestButton = Gtk::manage(wf->createButton(
+ *getResourceUstring("testButtonLabel") ));
+ } catch (std::invalid_argument &e) {
+ // TODO: signal error
+ std::cerr << e.what() << std::endl;
+ std::exit(1);
+ }
+ outputTestButton->signal_clicked().connect(sigc::bind(
+ sigc::mem_fun(*this, &OptionsWindow::onTestButtonClicked),
+ outputPlayerEntry));
+ audioDeviceTable->attach(*outputTestButton, 2, 3, 1, 2);
+
// make a new box and pack the components into it
Gtk::VBox * section = Gtk::manage(new Gtk::VBox);
section->pack_start(*audioDeviceTable, Gtk::PACK_SHRINK, 5);
diff --git a/livesupport/src/products/gLiveSupport/src/OptionsWindow.h b/livesupport/src/products/gLiveSupport/src/OptionsWindow.h
index a6e81f918..49e1023d2 100644
--- a/livesupport/src/products/gLiveSupport/src/OptionsWindow.h
+++ b/livesupport/src/products/gLiveSupport/src/OptionsWindow.h
@@ -152,7 +152,7 @@ class OptionsWindow : public WhiteWindow, public LocalizedObject
*/
EntryBin *
createEntry(OptionsContainer::OptionItemString optionItem)
- throw ();
+ throw ();
/**
* Construct the "Sound" section.
@@ -160,7 +160,7 @@ class OptionsWindow : public WhiteWindow, public LocalizedObject
* @return a pointer to the new box (already Gtk::manage()'ed)
*/
Gtk::VBox*
- constructSoundSection(void) throw ();
+ constructSoundSection(void) throw ();
/**
* Construct the "Servers" section.
@@ -168,7 +168,7 @@ class OptionsWindow : public WhiteWindow, public LocalizedObject
* @return a pointer to the new box (already Gtk::manage()'ed)
*/
Gtk::VBox*
- constructServersSection(void) throw ();
+ constructServersSection(void) throw ();
/**
* Construct the "About" section.
@@ -176,7 +176,7 @@ class OptionsWindow : public WhiteWindow, public LocalizedObject
* @return a pointer to the new box (already Gtk::manage()'ed)
*/
Gtk::VBox*
- constructAboutSection(void) throw ();
+ constructAboutSection(void) throw ();
protected:
@@ -184,19 +184,19 @@ class OptionsWindow : public WhiteWindow, public LocalizedObject
* Event handler for the Cancel button.
*/
virtual void
- onCancelButtonClicked(void) throw ();
+ onCancelButtonClicked(void) throw ();
/**
* Event handler for the Apply button.
*/
virtual void
- onApplyButtonClicked(void) throw ();
+ onApplyButtonClicked(void) throw ();
/**
* Event handler for the OK button.
*/
virtual void
- onOkButtonClicked(void) throw ();
+ onOkButtonClicked(void) throw ();
/**
* Event handler for the Close button.
@@ -207,9 +207,19 @@ class OptionsWindow : public WhiteWindow, public LocalizedObject
* @see WhiteWindow::onCloseButtonClicked()
*/
virtual void
- onCloseButtonClicked(bool needConfirm = true) throw ();
+ onCloseButtonClicked(bool needConfirm = true) throw ();
+
+ /**
+ * Event handler for the test button
+ *
+ * @param entry the text entry field containing the new device name
+ * @see GLiveSupport::setCueAudioDevice()
+ * @see GLiveSupport::playTestSoundOnCue()
+ */
+ virtual void
+ onTestButtonClicked(const EntryBin * entry) throw ();
+
-
public:
/**
* Constructor.
@@ -219,14 +229,13 @@ class OptionsWindow : public WhiteWindow, public LocalizedObject
* @param bundle the resource bundle holding localized resources
*/
OptionsWindow(Ptr::Ref gLiveSupport,
- Ptr::Ref bundle)
- throw ();
+ Ptr::Ref bundle) throw ();
/**
* Virtual destructor.
*/
virtual
- ~OptionsWindow(void) throw ()
+ ~OptionsWindow(void) throw ()
{
}
diff --git a/livesupport/src/products/gLiveSupport/var/root.txt b/livesupport/src/products/gLiveSupport/var/root.txt
index af3fd4125..2fa57641f 100644
--- a/livesupport/src/products/gLiveSupport/var/root.txt
+++ b/livesupport/src/products/gLiveSupport/var/root.txt
@@ -231,6 +231,7 @@ root:table
cueDeviceLabel:string { "Cue audio device:" }
outputDeviceLabel:string { "Live Mode audio device:" }
+ testButtonLabel:string { "Test" }
authenticationLabel:string { "Authentication server" }
storageLabel:string { "Storage server" }
diff --git a/livesupport/src/products/gLiveSupport/var/testAudio.ogg b/livesupport/src/products/gLiveSupport/var/testAudio.ogg
new file mode 100644
index 000000000..0667eabe4
Binary files /dev/null and b/livesupport/src/products/gLiveSupport/var/testAudio.ogg differ
diff --git a/livesupport/src/products/gLiveSupport/var/testAudio.ogg.license b/livesupport/src/products/gLiveSupport/var/testAudio.ogg.license
new file mode 100644
index 000000000..27159cd0f
--- /dev/null
+++ b/livesupport/src/products/gLiveSupport/var/testAudio.ogg.license
@@ -0,0 +1,20 @@
+This is a shortened and reencoded version of the following sound file
+
+File:
+ Name: "cowbell.aif"
+ Url: http://freesound.iua.upf.edu/samplesViewSingle.php?id=14782
+ Date of upload: 2006-01-24 20:28:02
+
+Designer / Creator / Uploader:
+ Name: "ignotus"
+ Url: http://freesound.iua.upf.edu/usersViewSingle.php?id=13366
+
+Description:
+ By "ignotus" : A cow in the high pastures of the Picos de Europa,
+ northwest Spain. Recorded with a mini-DV camcorder built-in stereo mic.
+
+Tags:
+ animal bell field-recording nature
+
+It was released under the Creative Commons Sampling Plus 1.0 license
+http://creativecommons.org/licenses/by-nd/2.0/