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:
parent
5fde29379e
commit
1a3cf69ba9
7 changed files with 125 additions and 5 deletions
|
@ -142,11 +142,15 @@ class AudioPlayerInterface
|
|||
* @param fileUrl a URL to a file
|
||||
* @exception std::invalid_argument if the supplied fileUrl
|
||||
* 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 #start
|
||||
*/
|
||||
virtual void
|
||||
open(const std::string fileUrl) throw (std::invalid_argument)
|
||||
open(const std::string fileUrl) throw (std::invalid_argument,
|
||||
std::runtime_error)
|
||||
= 0;
|
||||
|
||||
/**
|
||||
|
|
|
@ -233,7 +233,8 @@ GstreamerPlayer :: eosEventHandler(GstElement * element,
|
|||
*----------------------------------------------------------------------------*/
|
||||
void
|
||||
GstreamerPlayer :: open(const std::string fileUrl)
|
||||
throw (std::invalid_argument)
|
||||
throw (std::invalid_argument,
|
||||
std::runtime_error)
|
||||
{
|
||||
std::string filePath;
|
||||
GstElement * pipe;
|
||||
|
@ -294,7 +295,12 @@ GstreamerPlayer :: open(const std::string fileUrl)
|
|||
// connect the eos signal handler
|
||||
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));
|
||||
}
|
||||
|
||||
|
|
|
@ -295,11 +295,15 @@ class GstreamerPlayer : virtual public Configurable,
|
|||
* @param fileUrl a URL to a file
|
||||
* @exception std::invalid_argument if the supplied fileUrl
|
||||
* 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 #start
|
||||
*/
|
||||
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
|
||||
|
|
|
@ -134,6 +134,8 @@ GstreamerPlayerTest :: simplePlayTest(void)
|
|||
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();
|
||||
|
@ -168,6 +170,8 @@ GstreamerPlayerTest :: getPositionTest(void)
|
|||
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());
|
||||
start = TimeConversion::now();
|
||||
|
@ -213,6 +217,8 @@ GstreamerPlayerTest :: setDeviceTest(void)
|
|||
player->open("file:var/test-short.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();
|
||||
|
@ -231,6 +237,8 @@ GstreamerPlayerTest :: setDeviceTest(void)
|
|||
player->open("file:var/test-short.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();
|
||||
|
@ -249,6 +257,8 @@ GstreamerPlayerTest :: setDeviceTest(void)
|
|||
player->open("file:var/test-short.mp3");
|
||||
} catch (std::invalid_argument &e) {
|
||||
CPPUNIT_FAIL(e.what());
|
||||
} catch (std::runtime_error &e) {
|
||||
CPPUNIT_FAIL(e.what());
|
||||
}
|
||||
CPPUNIT_ASSERT(player->setAudioDevice("/dev/dsp"));
|
||||
CPPUNIT_ASSERT(!player->isPlaying());
|
||||
|
@ -282,6 +292,8 @@ GstreamerPlayerTest :: simpleSmilTest(void)
|
|||
player->open("file:var/simpleSmil.smil");
|
||||
} catch (std::invalid_argument &e) {
|
||||
CPPUNIT_FAIL(e.what());
|
||||
} catch (std::runtime_error &e) {
|
||||
CPPUNIT_FAIL(e.what());
|
||||
}
|
||||
CPPUNIT_ASSERT(!player->isPlaying());
|
||||
CPPUNIT_ASSERT_NO_THROW(
|
||||
|
@ -311,6 +323,8 @@ GstreamerPlayerTest :: secondSmilTest(void)
|
|||
player->open("file:var/sequentialSmil.smil");
|
||||
} catch (std::invalid_argument &e) {
|
||||
CPPUNIT_FAIL(e.what());
|
||||
} catch (std::runtime_error &e) {
|
||||
CPPUNIT_FAIL(e.what());
|
||||
}
|
||||
CPPUNIT_ASSERT(!player->isPlaying());
|
||||
CPPUNIT_ASSERT_NO_THROW(
|
||||
|
@ -341,6 +355,8 @@ GstreamerPlayerTest :: animatedSmilTest(void)
|
|||
player->open("file:var/animatedSmil.smil");
|
||||
} catch (std::invalid_argument &e) {
|
||||
CPPUNIT_FAIL(e.what());
|
||||
} catch (std::runtime_error &e) {
|
||||
CPPUNIT_FAIL(e.what());
|
||||
}
|
||||
CPPUNIT_ASSERT(!player->isPlaying());
|
||||
player->start();
|
||||
|
@ -389,6 +405,8 @@ GstreamerPlayerTest :: checkErrorConditions(void)
|
|||
player->open("totally/bad/URL");
|
||||
} catch (std::invalid_argument &e) {
|
||||
gotException = true;
|
||||
} catch (std::runtime_error &e) {
|
||||
CPPUNIT_FAIL(e.what());
|
||||
}
|
||||
CPPUNIT_ASSERT(gotException);
|
||||
|
||||
|
@ -405,6 +423,8 @@ GstreamerPlayerTest :: checkErrorConditions(void)
|
|||
player->open("file:var/test.mp3");
|
||||
} catch (std::invalid_argument &e) {
|
||||
CPPUNIT_FAIL(e.what());
|
||||
} catch (std::runtime_error &e) {
|
||||
CPPUNIT_FAIL(e.what());
|
||||
}
|
||||
player->close();
|
||||
gotException = false;
|
||||
|
@ -412,6 +432,8 @@ GstreamerPlayerTest :: checkErrorConditions(void)
|
|||
player->open("totally/bad/URL");
|
||||
} catch (std::invalid_argument &e) {
|
||||
gotException = true;
|
||||
} catch (std::runtime_error &e) {
|
||||
CPPUNIT_FAIL(e.what());
|
||||
}
|
||||
CPPUNIT_ASSERT(gotException);
|
||||
|
||||
|
@ -634,6 +656,8 @@ GstreamerPlayerTest :: timeSteps(const std::string fileName)
|
|||
player->open(fileName);
|
||||
} catch (std::invalid_argument &e) {
|
||||
CPPUNIT_FAIL(e.what());
|
||||
} catch (std::runtime_error &e) {
|
||||
CPPUNIT_FAIL(e.what());
|
||||
}
|
||||
end = TimeConversion::now();
|
||||
openTime.reset(new time_duration(*end - *start));
|
||||
|
@ -697,6 +721,8 @@ GstreamerPlayerTest :: pauseResumeTest(void)
|
|||
player->open("file:var/test10001.mp3");
|
||||
} catch (std::invalid_argument &e) {
|
||||
CPPUNIT_FAIL(e.what());
|
||||
} catch (std::runtime_error &e) {
|
||||
CPPUNIT_FAIL(e.what());
|
||||
}
|
||||
CPPUNIT_ASSERT(!player->isPlaying());
|
||||
|
||||
|
@ -729,3 +755,64 @@ GstreamerPlayerTest :: pauseResumeTest(void)
|
|||
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();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -78,6 +78,7 @@ class GstreamerPlayerTest : public CPPUNIT_NS::TestFixture,
|
|||
CPPUNIT_TEST(eventListenerOnStopTest);
|
||||
CPPUNIT_TEST(openTimeTest);
|
||||
CPPUNIT_TEST(pauseResumeTest);
|
||||
CPPUNIT_TEST(openSoundcardTwiceTest);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
private:
|
||||
|
@ -209,6 +210,15 @@ class GstreamerPlayerTest : public CPPUNIT_NS::TestFixture,
|
|||
void
|
||||
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:
|
||||
|
||||
|
|
|
@ -1018,20 +1018,23 @@ GLiveSupport :: playOutputAudio(Ptr<Playable>::Ref playable)
|
|||
} catch (XmlRpcException &e) {
|
||||
Ptr<Glib::ustring>::Ref eMsg
|
||||
= getResourceUstring("audioErrorMsg");
|
||||
eMsg->append("\n");
|
||||
eMsg->append(e.what());
|
||||
displayMessageWindow(eMsg);
|
||||
} catch (std::invalid_argument &e) {
|
||||
Ptr<Glib::ustring>::Ref eMsg
|
||||
= getResourceUstring("audioErrorMsg");
|
||||
eMsg->append("\n");
|
||||
eMsg->append(e.what());
|
||||
displayMessageWindow(eMsg);
|
||||
} catch (std::runtime_error &e) {
|
||||
Ptr<Glib::ustring>::Ref eMsg
|
||||
= getResourceUstring("audioErrorMsg");
|
||||
eMsg->append("\n");
|
||||
eMsg->append(e.what());
|
||||
displayMessageWindow(eMsg);
|
||||
}
|
||||
|
||||
|
||||
outputPlayerIsPaused = false;
|
||||
}
|
||||
|
||||
|
@ -1125,16 +1128,19 @@ GLiveSupport :: playCueAudio(Ptr<Playable>::Ref playable)
|
|||
} catch (XmlRpcException &e) {
|
||||
Ptr<Glib::ustring>::Ref eMsg
|
||||
= getResourceUstring("audioErrorMsg");
|
||||
eMsg->append("\n");
|
||||
eMsg->append(e.what());
|
||||
displayMessageWindow(eMsg);
|
||||
} catch (std::invalid_argument &e) {
|
||||
Ptr<Glib::ustring>::Ref eMsg
|
||||
= getResourceUstring("audioErrorMsg");
|
||||
eMsg->append("\n");
|
||||
eMsg->append(e.what());
|
||||
displayMessageWindow(eMsg);
|
||||
} catch (std::runtime_error &e) {
|
||||
Ptr<Glib::ustring>::Ref eMsg
|
||||
= getResourceUstring("audioErrorMsg");
|
||||
eMsg->append("\n");
|
||||
eMsg->append(e.what());
|
||||
displayMessageWindow(eMsg);
|
||||
}
|
||||
|
|
|
@ -146,6 +146,9 @@ PlaylistEvent :: start(void) throw ()
|
|||
} catch (std::invalid_argument &e) {
|
||||
std::cerr << e.what() << std::endl;
|
||||
// TODO: handle error?
|
||||
} catch (std::runtime_error &e) {
|
||||
std::cerr << e.what() << std::endl;
|
||||
// TODO: handle error?
|
||||
}
|
||||
state = running;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue