now AudioPlayerInterface::open() will throw an std::runtime_error

exception if the file can not be openned, for example because
the audio device in blocked by another process (maybe an other player)
fix for issue #1398
This commit is contained in:
maroy 2005-09-30 10:13:11 +00:00
parent 5fde29379e
commit 1a3cf69ba9
7 changed files with 125 additions and 5 deletions

View file

@ -142,11 +142,15 @@ class AudioPlayerInterface
* @param fileUrl a URL to a file * @param fileUrl a URL to a file
* @exception std::invalid_argument if the supplied fileUrl * @exception std::invalid_argument if the supplied fileUrl
* seems to be invalid. * seems to be invalid.
* @exception std::runtime_error if the file could not be openned,
* for example because the audio device of the player
* is being exclusively used by an other process.
* @see #close * @see #close
* @see #start * @see #start
*/ */
virtual void virtual void
open(const std::string fileUrl) throw (std::invalid_argument) open(const std::string fileUrl) throw (std::invalid_argument,
std::runtime_error)
= 0; = 0;
/** /**

View file

@ -233,7 +233,8 @@ GstreamerPlayer :: eosEventHandler(GstElement * element,
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
void void
GstreamerPlayer :: open(const std::string fileUrl) GstreamerPlayer :: open(const std::string fileUrl)
throw (std::invalid_argument) throw (std::invalid_argument,
std::runtime_error)
{ {
std::string filePath; std::string filePath;
GstElement * pipe; GstElement * pipe;
@ -294,7 +295,12 @@ GstreamerPlayer :: open(const std::string fileUrl)
// connect the eos signal handler // connect the eos signal handler
g_signal_connect(decoder, "eos", G_CALLBACK(eosEventHandler), this); g_signal_connect(decoder, "eos", G_CALLBACK(eosEventHandler), this);
gst_element_set_state(pipeline, GST_STATE_PAUSED); if (gst_element_set_state(pipeline,GST_STATE_PAUSED) == GST_STATE_FAILURE) {
close();
// the error is most probably caused by not being able to open
// the audio device (as it might be blocked by an other process
throw std::runtime_error("can't open audio device " + audioDevice);
}
gst_bin_sync_children_state(GST_BIN(pipeline)); gst_bin_sync_children_state(GST_BIN(pipeline));
} }

View file

@ -295,11 +295,15 @@ class GstreamerPlayer : virtual public Configurable,
* @param fileUrl a URL to a file * @param fileUrl a URL to a file
* @exception std::invalid_argument if the supplied fileUrl * @exception std::invalid_argument if the supplied fileUrl
* seems to be invalid. * seems to be invalid.
* @exception std::runtime_error if the file could not be openned,
* for example because the audio device of the player
* is being exclusively used by an other process.
* @see #close * @see #close
* @see #start * @see #start
*/ */
virtual void virtual void
open(const std::string fileUrl) throw (std::invalid_argument); open(const std::string fileUrl) throw (std::invalid_argument,
std::runtime_error);
/** /**
* Tell if the object is currently opened (has a file source to * Tell if the object is currently opened (has a file source to

View file

@ -134,6 +134,8 @@ GstreamerPlayerTest :: simplePlayTest(void)
player->open("file:var/test.mp3"); player->open("file:var/test.mp3");
} catch (std::invalid_argument &e) { } catch (std::invalid_argument &e) {
CPPUNIT_FAIL(e.what()); CPPUNIT_FAIL(e.what());
} catch (std::runtime_error &e) {
CPPUNIT_FAIL(e.what());
} }
CPPUNIT_ASSERT(!player->isPlaying()); CPPUNIT_ASSERT(!player->isPlaying());
player->start(); player->start();
@ -168,6 +170,8 @@ GstreamerPlayerTest :: getPositionTest(void)
player->open("file:var/test.mp3"); player->open("file:var/test.mp3");
} catch (std::invalid_argument &e) { } catch (std::invalid_argument &e) {
CPPUNIT_FAIL(e.what()); CPPUNIT_FAIL(e.what());
} catch (std::runtime_error &e) {
CPPUNIT_FAIL(e.what());
} }
CPPUNIT_ASSERT(!player->isPlaying()); CPPUNIT_ASSERT(!player->isPlaying());
start = TimeConversion::now(); start = TimeConversion::now();
@ -213,6 +217,8 @@ GstreamerPlayerTest :: setDeviceTest(void)
player->open("file:var/test-short.mp3"); player->open("file:var/test-short.mp3");
} catch (std::invalid_argument &e) { } catch (std::invalid_argument &e) {
CPPUNIT_FAIL(e.what()); CPPUNIT_FAIL(e.what());
} catch (std::runtime_error &e) {
CPPUNIT_FAIL(e.what());
} }
CPPUNIT_ASSERT(!player->isPlaying()); CPPUNIT_ASSERT(!player->isPlaying());
player->start(); player->start();
@ -231,6 +237,8 @@ GstreamerPlayerTest :: setDeviceTest(void)
player->open("file:var/test-short.mp3"); player->open("file:var/test-short.mp3");
} catch (std::invalid_argument &e) { } catch (std::invalid_argument &e) {
CPPUNIT_FAIL(e.what()); CPPUNIT_FAIL(e.what());
} catch (std::runtime_error &e) {
CPPUNIT_FAIL(e.what());
} }
CPPUNIT_ASSERT(!player->isPlaying()); CPPUNIT_ASSERT(!player->isPlaying());
player->start(); player->start();
@ -249,6 +257,8 @@ GstreamerPlayerTest :: setDeviceTest(void)
player->open("file:var/test-short.mp3"); player->open("file:var/test-short.mp3");
} catch (std::invalid_argument &e) { } catch (std::invalid_argument &e) {
CPPUNIT_FAIL(e.what()); CPPUNIT_FAIL(e.what());
} catch (std::runtime_error &e) {
CPPUNIT_FAIL(e.what());
} }
CPPUNIT_ASSERT(player->setAudioDevice("/dev/dsp")); CPPUNIT_ASSERT(player->setAudioDevice("/dev/dsp"));
CPPUNIT_ASSERT(!player->isPlaying()); CPPUNIT_ASSERT(!player->isPlaying());
@ -282,6 +292,8 @@ GstreamerPlayerTest :: simpleSmilTest(void)
player->open("file:var/simpleSmil.smil"); player->open("file:var/simpleSmil.smil");
} catch (std::invalid_argument &e) { } catch (std::invalid_argument &e) {
CPPUNIT_FAIL(e.what()); CPPUNIT_FAIL(e.what());
} catch (std::runtime_error &e) {
CPPUNIT_FAIL(e.what());
} }
CPPUNIT_ASSERT(!player->isPlaying()); CPPUNIT_ASSERT(!player->isPlaying());
CPPUNIT_ASSERT_NO_THROW( CPPUNIT_ASSERT_NO_THROW(
@ -311,6 +323,8 @@ GstreamerPlayerTest :: secondSmilTest(void)
player->open("file:var/sequentialSmil.smil"); player->open("file:var/sequentialSmil.smil");
} catch (std::invalid_argument &e) { } catch (std::invalid_argument &e) {
CPPUNIT_FAIL(e.what()); CPPUNIT_FAIL(e.what());
} catch (std::runtime_error &e) {
CPPUNIT_FAIL(e.what());
} }
CPPUNIT_ASSERT(!player->isPlaying()); CPPUNIT_ASSERT(!player->isPlaying());
CPPUNIT_ASSERT_NO_THROW( CPPUNIT_ASSERT_NO_THROW(
@ -341,6 +355,8 @@ GstreamerPlayerTest :: animatedSmilTest(void)
player->open("file:var/animatedSmil.smil"); player->open("file:var/animatedSmil.smil");
} catch (std::invalid_argument &e) { } catch (std::invalid_argument &e) {
CPPUNIT_FAIL(e.what()); CPPUNIT_FAIL(e.what());
} catch (std::runtime_error &e) {
CPPUNIT_FAIL(e.what());
} }
CPPUNIT_ASSERT(!player->isPlaying()); CPPUNIT_ASSERT(!player->isPlaying());
player->start(); player->start();
@ -389,6 +405,8 @@ GstreamerPlayerTest :: checkErrorConditions(void)
player->open("totally/bad/URL"); player->open("totally/bad/URL");
} catch (std::invalid_argument &e) { } catch (std::invalid_argument &e) {
gotException = true; gotException = true;
} catch (std::runtime_error &e) {
CPPUNIT_FAIL(e.what());
} }
CPPUNIT_ASSERT(gotException); CPPUNIT_ASSERT(gotException);
@ -405,6 +423,8 @@ GstreamerPlayerTest :: checkErrorConditions(void)
player->open("file:var/test.mp3"); player->open("file:var/test.mp3");
} catch (std::invalid_argument &e) { } catch (std::invalid_argument &e) {
CPPUNIT_FAIL(e.what()); CPPUNIT_FAIL(e.what());
} catch (std::runtime_error &e) {
CPPUNIT_FAIL(e.what());
} }
player->close(); player->close();
gotException = false; gotException = false;
@ -412,6 +432,8 @@ GstreamerPlayerTest :: checkErrorConditions(void)
player->open("totally/bad/URL"); player->open("totally/bad/URL");
} catch (std::invalid_argument &e) { } catch (std::invalid_argument &e) {
gotException = true; gotException = true;
} catch (std::runtime_error &e) {
CPPUNIT_FAIL(e.what());
} }
CPPUNIT_ASSERT(gotException); CPPUNIT_ASSERT(gotException);
@ -634,6 +656,8 @@ GstreamerPlayerTest :: timeSteps(const std::string fileName)
player->open(fileName); player->open(fileName);
} catch (std::invalid_argument &e) { } catch (std::invalid_argument &e) {
CPPUNIT_FAIL(e.what()); CPPUNIT_FAIL(e.what());
} catch (std::runtime_error &e) {
CPPUNIT_FAIL(e.what());
} }
end = TimeConversion::now(); end = TimeConversion::now();
openTime.reset(new time_duration(*end - *start)); openTime.reset(new time_duration(*end - *start));
@ -697,6 +721,8 @@ GstreamerPlayerTest :: pauseResumeTest(void)
player->open("file:var/test10001.mp3"); player->open("file:var/test10001.mp3");
} catch (std::invalid_argument &e) { } catch (std::invalid_argument &e) {
CPPUNIT_FAIL(e.what()); CPPUNIT_FAIL(e.what());
} catch (std::runtime_error &e) {
CPPUNIT_FAIL(e.what());
} }
CPPUNIT_ASSERT(!player->isPlaying()); CPPUNIT_ASSERT(!player->isPlaying());
@ -729,3 +755,64 @@ GstreamerPlayerTest :: pauseResumeTest(void)
player->deInitialize(); player->deInitialize();
} }
/*------------------------------------------------------------------------------
* Open the same soundcard twice, thus force an error
*----------------------------------------------------------------------------*/
void
GstreamerPlayerTest :: openSoundcardTwiceTest(void)
throw (CPPUNIT_NS::Exception)
{
Ptr<time_duration>::Ref sleepT(new time_duration(microseconds(10)));
Ptr<GstreamerPlayer>::Ref player2;
// create a second player, with the same config as our usual player
try {
Ptr<xmlpp::DomParser>::Ref parser(
new xmlpp::DomParser(configFileName, true));
const xmlpp::Document * document = parser->get_document();
const xmlpp::Element * root = document->get_root_node();
player2.reset(new GstreamerPlayer());
player2->configure(*root);
} catch (std::invalid_argument &e) {
CPPUNIT_FAIL("semantic error in configuration file");
} catch (xmlpp::exception &e) {
CPPUNIT_FAIL(e.what());
}
// initialize & start playing on the first player
player->initialize();
try {
player->open("file:var/test.mp3");
} catch (std::invalid_argument &e) {
CPPUNIT_FAIL(e.what());
} catch (std::runtime_error &e) {
CPPUNIT_FAIL(e.what());
}
CPPUNIT_ASSERT(!player->isPlaying());
player->start();
CPPUNIT_ASSERT(player->isPlaying());
// now open the same again in the second one
player2->initialize();
try {
player2->open("file:var/test.mp3");
} catch (std::invalid_argument &e) {
CPPUNIT_FAIL(e.what());
} catch (std::runtime_error &e) {
// this is what we're expecting, if open failed for the reason of
// the soundcard being blocked. this doesn't always happen with
// ALSA drivers (with dmix, for example)
}
CPPUNIT_ASSERT(!player2->isPlaying());
// close everything
player2->close();
player2->deInitialize();
player->close();
player->deInitialize();
}

View file

@ -78,6 +78,7 @@ class GstreamerPlayerTest : public CPPUNIT_NS::TestFixture,
CPPUNIT_TEST(eventListenerOnStopTest); CPPUNIT_TEST(eventListenerOnStopTest);
CPPUNIT_TEST(openTimeTest); CPPUNIT_TEST(openTimeTest);
CPPUNIT_TEST(pauseResumeTest); CPPUNIT_TEST(pauseResumeTest);
CPPUNIT_TEST(openSoundcardTwiceTest);
CPPUNIT_TEST_SUITE_END(); CPPUNIT_TEST_SUITE_END();
private: private:
@ -209,6 +210,15 @@ class GstreamerPlayerTest : public CPPUNIT_NS::TestFixture,
void void
pauseResumeTest(void) throw (CPPUNIT_NS::Exception); pauseResumeTest(void) throw (CPPUNIT_NS::Exception);
/**
* Test for opening the same sound card twice
* (thus forcing an error)
*
* @exception CPPUNIT_NS::Exception on test failures.
*/
void
openSoundcardTwiceTest(void) throw (CPPUNIT_NS::Exception);
public: public:

View file

@ -1018,16 +1018,19 @@ GLiveSupport :: playOutputAudio(Ptr<Playable>::Ref playable)
} catch (XmlRpcException &e) { } catch (XmlRpcException &e) {
Ptr<Glib::ustring>::Ref eMsg Ptr<Glib::ustring>::Ref eMsg
= getResourceUstring("audioErrorMsg"); = getResourceUstring("audioErrorMsg");
eMsg->append("\n");
eMsg->append(e.what()); eMsg->append(e.what());
displayMessageWindow(eMsg); displayMessageWindow(eMsg);
} catch (std::invalid_argument &e) { } catch (std::invalid_argument &e) {
Ptr<Glib::ustring>::Ref eMsg Ptr<Glib::ustring>::Ref eMsg
= getResourceUstring("audioErrorMsg"); = getResourceUstring("audioErrorMsg");
eMsg->append("\n");
eMsg->append(e.what()); eMsg->append(e.what());
displayMessageWindow(eMsg); displayMessageWindow(eMsg);
} catch (std::runtime_error &e) { } catch (std::runtime_error &e) {
Ptr<Glib::ustring>::Ref eMsg Ptr<Glib::ustring>::Ref eMsg
= getResourceUstring("audioErrorMsg"); = getResourceUstring("audioErrorMsg");
eMsg->append("\n");
eMsg->append(e.what()); eMsg->append(e.what());
displayMessageWindow(eMsg); displayMessageWindow(eMsg);
} }
@ -1125,16 +1128,19 @@ GLiveSupport :: playCueAudio(Ptr<Playable>::Ref playable)
} catch (XmlRpcException &e) { } catch (XmlRpcException &e) {
Ptr<Glib::ustring>::Ref eMsg Ptr<Glib::ustring>::Ref eMsg
= getResourceUstring("audioErrorMsg"); = getResourceUstring("audioErrorMsg");
eMsg->append("\n");
eMsg->append(e.what()); eMsg->append(e.what());
displayMessageWindow(eMsg); displayMessageWindow(eMsg);
} catch (std::invalid_argument &e) { } catch (std::invalid_argument &e) {
Ptr<Glib::ustring>::Ref eMsg Ptr<Glib::ustring>::Ref eMsg
= getResourceUstring("audioErrorMsg"); = getResourceUstring("audioErrorMsg");
eMsg->append("\n");
eMsg->append(e.what()); eMsg->append(e.what());
displayMessageWindow(eMsg); displayMessageWindow(eMsg);
} catch (std::runtime_error &e) { } catch (std::runtime_error &e) {
Ptr<Glib::ustring>::Ref eMsg Ptr<Glib::ustring>::Ref eMsg
= getResourceUstring("audioErrorMsg"); = getResourceUstring("audioErrorMsg");
eMsg->append("\n");
eMsg->append(e.what()); eMsg->append(e.what());
displayMessageWindow(eMsg); displayMessageWindow(eMsg);
} }

View file

@ -146,6 +146,9 @@ PlaylistEvent :: start(void) throw ()
} catch (std::invalid_argument &e) { } catch (std::invalid_argument &e) {
std::cerr << e.what() << std::endl; std::cerr << e.what() << std::endl;
// TODO: handle error? // TODO: handle error?
} catch (std::runtime_error &e) {
std::cerr << e.what() << std::endl;
// TODO: handle error?
} }
state = running; state = running;
} }