Commit 786cd2d1 authored by Tristan Matthews's avatar Tristan Matthews
Browse files

* #6849: show error window if codecs are missing, instead of dying

parent 4b32b763
...@@ -31,112 +31,110 @@ ...@@ -31,112 +31,110 @@
* as that of the covered work. * as that of the covered work.
*/ */
#include <iostream>
#include <cstdlib>
#include "audiocodecfactory.h" #include "audiocodecfactory.h"
#include <cstdlib>
#include <algorithm> // for std::find
#include "fileutils.h" #include "fileutils.h"
AudioCodecFactory::AudioCodecFactory() : _CodecsMap(), _defaultCodecOrder(), _Cache(), _CodecInMemory()
{
}
void void
AudioCodecFactory::init() AudioCodecFactory::init()
{ {
std::vector<sfl::Codec*> CodecDynamicList = scanCodecDirectory(); typedef std::vector<sfl::Codec*> CodecVector;
if (CodecDynamicList.size() == 0) CodecVector codecDynamicList(scanCodecDirectory());
if (codecDynamicList.empty())
_error ("Error - No codecs available"); _error ("Error - No codecs available");
else {
for (size_t i = 0 ; i < CodecDynamicList.size() ; i++) { for (CodecVector::const_iterator iter = codecDynamicList.begin();
_CodecsMap[ (AudioCodecType) CodecDynamicList[i]->getPayloadType() ] = CodecDynamicList[i]; iter != codecDynamicList.end() ; ++iter) {
_debug ("Loaded codec %s" , CodecDynamicList[i]->getMimeSubtype().c_str()); codecsMap_[ (AudioCodecType) (*iter)->getPayloadType() ] = *iter;
_debug ("Loaded codec %s" , (*iter)->getMimeSubtype().c_str());
}
} }
} }
void AudioCodecFactory::setDefaultOrder() void AudioCodecFactory::setDefaultOrder()
{ {
_defaultCodecOrder.clear(); defaultCodecOrder_.clear();
CodecsMap::iterator iter; CodecsMap::const_iterator iter;
for (iter = _CodecsMap.begin(); iter != _CodecsMap.end(); ++iter) for (iter = codecsMap_.begin(); iter != codecsMap_.end(); ++iter)
_defaultCodecOrder.push_back (iter->first); defaultCodecOrder_.push_back (iter->first);
} }
std::string std::string
AudioCodecFactory::getCodecName (AudioCodecType payload) AudioCodecFactory::getCodecName (AudioCodecType payload)
{ {
CodecsMap::iterator iter = _CodecsMap.find (payload); CodecsMap::const_iterator iter = codecsMap_.find (payload);
if (iter!=_CodecsMap.end())
return (iter->second->getMimeSubtype());
return ""; if (iter != codecsMap_.end())
return iter->second->getMimeSubtype();
else
return "";
} }
sfl::Codec* sfl::Codec*
AudioCodecFactory::getCodec (AudioCodecType payload) AudioCodecFactory::getCodec (AudioCodecType payload)
{ {
CodecsMap::iterator iter = _CodecsMap.find (payload); CodecsMap::const_iterator iter = codecsMap_.find (payload);
if (iter != _CodecsMap.end()) if (iter != codecsMap_.end())
return iter->second; return iter->second;
else {
_error ("CodecDescriptor: cannot find codec %i", payload); _error ("CodecDescriptor: cannot find codec %i", payload);
return NULL;
return NULL; }
} }
double AudioCodecFactory::getBitRate (AudioCodecType payload) double AudioCodecFactory::getBitRate (AudioCodecType payload)
{ {
CodecsMap::iterator iter = _CodecsMap.find (payload); CodecsMap::const_iterator iter = codecsMap_.find (payload);
if (iter!=_CodecsMap.end()) if (iter != codecsMap_.end())
return (iter->second->getBitRate()); return iter->second->getBitRate();
else
return 0.0; return 0.0;
} }
int AudioCodecFactory::getSampleRate (AudioCodecType payload) const int AudioCodecFactory::getSampleRate (AudioCodecType payload) const
{ {
CodecsMap::const_iterator iter = _CodecsMap.find (payload); CodecsMap::const_iterator iter = codecsMap_.find (payload);
if (iter != _CodecsMap.end()) if (iter != codecsMap_.end())
return iter->second->getClockRate(); return iter->second->getClockRate();
else
return 0; return 0;
} }
void AudioCodecFactory::saveActiveCodecs (const std::vector<std::string>& list) void AudioCodecFactory::saveActiveCodecs (const std::vector<std::string>& list)
{ {
_defaultCodecOrder.clear(); defaultCodecOrder_.clear();
// list contains the ordered payload of active codecs picked by the user // list contains the ordered payload of active codecs picked by the user
// we used the CodecOrder vector to save the order. // we used the CodecOrder vector to save the order.
for (size_t i = 0; i < list.size(); i++) { for (std::vector<std::string>::const_iterator iter = list.begin(); iter != list.end(); ++iter) {
int payload = std::atoi (list[i].data()); int payload = std::atoi(iter->c_str());
if (isCodecLoaded (payload)) if (isCodecLoaded (payload))
_defaultCodecOrder.push_back ( (AudioCodecType) payload); defaultCodecOrder_.push_back ( (AudioCodecType) payload);
} }
} }
void void
AudioCodecFactory::deleteHandlePointer (void) AudioCodecFactory::deleteHandlePointer()
{ {
for (std::vector<CodecHandlePointer>::const_iterator iter = for (std::vector<CodecHandlePointer>::const_iterator iter =
_CodecInMemory.begin(); iter != _CodecInMemory.end(); ++iter) codecInMemory_.begin(); iter != codecInMemory_.end(); ++iter)
unloadCodec (*iter); unloadCodec (*iter);
_CodecInMemory.clear(); codecInMemory_.clear();
} }
std::vector<sfl::Codec*> AudioCodecFactory::scanCodecDirectory (void) std::vector<sfl::Codec*> AudioCodecFactory::scanCodecDirectory()
{ {
std::vector<sfl::Codec*> codecs; std::vector<sfl::Codec*> codecs;
std::vector<std::string> dirToScan; std::vector<std::string> dirToScan;
dirToScan.push_back (std::string(HOMEDIR) + DIR_SEPARATOR_STR "." PROGDIR "/"); dirToScan.push_back(std::string(HOMEDIR) + DIR_SEPARATOR_STR "." PROGDIR "/");
dirToScan.push_back (CODECS_DIR "/"); dirToScan.push_back(CODECS_DIR "/");
const char *envDir = getenv("CODECS_PATH"); const char *envDir = getenv("CODECS_PATH");
if (envDir) if (envDir)
dirToScan.push_back(std::string(envDir) + DIR_SEPARATOR_STR); dirToScan.push_back(std::string(envDir) + DIR_SEPARATOR_STR);
...@@ -162,7 +160,7 @@ std::vector<sfl::Codec*> AudioCodecFactory::scanCodecDirectory (void) ...@@ -162,7 +160,7 @@ std::vector<sfl::Codec*> AudioCodecFactory::scanCodecDirectory (void)
sfl::Codec* audioCodec = loadCodec (dirStr+file); sfl::Codec* audioCodec = loadCodec (dirStr+file);
if (audioCodec) { if (audioCodec) {
codecs.push_back (audioCodec); codecs.push_back (audioCodec);
_Cache.push_back (file); libCache_.push_back (file);
} }
} }
} }
...@@ -173,12 +171,12 @@ std::vector<sfl::Codec*> AudioCodecFactory::scanCodecDirectory (void) ...@@ -173,12 +171,12 @@ std::vector<sfl::Codec*> AudioCodecFactory::scanCodecDirectory (void)
return codecs; return codecs;
} }
sfl::Codec* AudioCodecFactory::loadCodec (std::string path) sfl::Codec* AudioCodecFactory::loadCodec (const std::string &path)
{ {
void * codecHandle = dlopen (path.c_str() , RTLD_LAZY); void * codecHandle = dlopen (path.c_str() , RTLD_LAZY);
if (!codecHandle) { if (!codecHandle) {
_error("%s\n", dlerror()); _error("%s\n", dlerror());
return NULL; return NULL;
} }
dlerror(); dlerror();
...@@ -186,13 +184,13 @@ sfl::Codec* AudioCodecFactory::loadCodec (std::string path) ...@@ -186,13 +184,13 @@ sfl::Codec* AudioCodecFactory::loadCodec (std::string path)
create_t* createCodec = (create_t*) dlsym (codecHandle , "create"); create_t* createCodec = (create_t*) dlsym (codecHandle , "create");
char *error = dlerror(); char *error = dlerror();
if (error) { if (error) {
_error("%s\n", error); _error("%s\n", error);
return NULL; return NULL;
} }
sfl::Codec* a = createCodec(); sfl::Codec* a = createCodec();
_CodecInMemory.push_back (CodecHandlePointer (a, codecHandle)); codecInMemory_.push_back (CodecHandlePointer (a, codecHandle));
return a; return a;
} }
...@@ -204,8 +202,8 @@ void AudioCodecFactory::unloadCodec (CodecHandlePointer p) ...@@ -204,8 +202,8 @@ void AudioCodecFactory::unloadCodec (CodecHandlePointer p)
char *error = dlerror(); char *error = dlerror();
if (error) { if (error) {
_error("%s\n", error); _error("%s\n", error);
return; return;
} }
destroyCodec (p.first); destroyCodec (p.first);
...@@ -217,34 +215,22 @@ sfl::Codec* AudioCodecFactory::instantiateCodec (AudioCodecType payload) ...@@ -217,34 +215,22 @@ sfl::Codec* AudioCodecFactory::instantiateCodec (AudioCodecType payload)
{ {
std::vector< CodecHandlePointer >::iterator iter; std::vector< CodecHandlePointer >::iterator iter;
for (iter = _CodecInMemory.begin(); iter != _CodecInMemory.end(); ++iter) { for (iter = codecInMemory_.begin(); iter != codecInMemory_.end(); ++iter) {
if (iter->first->getPayloadType() == payload) { if (iter->first->getPayloadType() == payload) {
create_t* createCodec = (create_t*) dlsym (iter->second , "create"); create_t* createCodec = (create_t*) dlsym (iter->second , "create");
char *error = dlerror(); char *error = dlerror();
if (error) if (error)
_error("%s\n", error); _error("%s\n", error);
else else
return createCodec(); return createCodec();
} }
} }
return NULL; return NULL;
} }
bool AudioCodecFactory::seemsValid (const std::string &lib)
sfl::Codec* AudioCodecFactory::getFirstCodecAvailable (void)
{
CodecsMap::iterator iter = _CodecsMap.begin();
if (iter != _CodecsMap.end())
return iter->second;
else
return NULL;
}
bool AudioCodecFactory::seemsValid (std::string lib)
{ {
// The name of the shared library seems valid <==> it looks like libcodec_xxx.so // The name of the shared library seems valid <==> it looks like libcodec_xxx.so
// We check this // We check this
...@@ -280,24 +266,20 @@ bool AudioCodecFactory::seemsValid (std::string lib) ...@@ -280,24 +266,20 @@ bool AudioCodecFactory::seemsValid (std::string lib)
if (lib.substr (lib.length() - suffix.length() , suffix.length()) == suffix) if (lib.substr (lib.length() - suffix.length() , suffix.length()) == suffix)
return true; return true;
return false; return false;
} }
bool bool
AudioCodecFactory::alreadyInCache (std::string lib) AudioCodecFactory::alreadyInCache (const std::string &lib)
{ {
for (size_t i = 0 ; i < _Cache.size() ; i++) return std::find(libCache_.begin(), libCache_.end(), lib) != libCache_.end();
if (_Cache[i] == lib)
return true;
return false;
} }
bool AudioCodecFactory::isCodecLoaded (int payload) bool AudioCodecFactory::isCodecLoaded (int payload)
{ {
CodecsMap::iterator iter; CodecsMap::const_iterator iter;
for (iter = _CodecsMap.begin(); iter != _CodecsMap.end(); ++iter) for (iter = codecsMap_.begin(); iter != codecsMap_.end(); ++iter)
if (iter -> first == payload) if (iter->first == payload)
return true; return true;
return false; return false;
...@@ -309,17 +291,17 @@ std::vector <std::string> AudioCodecFactory::getCodecSpecifications (const int32 ...@@ -309,17 +291,17 @@ std::vector <std::string> AudioCodecFactory::getCodecSpecifications (const int32
std::stringstream ss; std::stringstream ss;
// Add the name of the codec // Add the name of the codec
v.push_back (getCodecName ( (AudioCodecType) payload)); v.push_back(getCodecName(static_cast<AudioCodecType>(payload)));
// Add the sample rate // Add the sample rate
ss << getSampleRate ( (AudioCodecType) payload); ss << getSampleRate (static_cast<AudioCodecType>(payload));
v.push_back ( (ss.str()).data()); v.push_back(ss.str());
ss.str (""); ss.str("");
// Add the bit rate // Add the bit rate
ss << getBitRate ( (AudioCodecType) payload); ss << getBitRate(static_cast<AudioCodecType>(payload));
v.push_back ( (ss.str()).data()); v.push_back(ss.str());
ss.str (""); ss.str("");
return v; return v;
} }
...@@ -40,30 +40,23 @@ ...@@ -40,30 +40,23 @@
#include "global.h" #include "global.h"
#include "audiocodec.h" #include "audiocodec.h"
/** Enable us to keep the handle pointer on the codec dynamicaly loaded so that we could destroy when we dont need it anymore */
typedef std::pair<sfl::Codec* , void*> CodecHandlePointer;
/** Maps a pointer on an audiocodec object to a payload */
typedef std::map<AudioCodecType , sfl::Codec*> CodecsMap;
/* /*
* @file codecdescriptor.h * @file codecdescriptor.h
* @brief Handle audio codecs, load them in memory * @brief Handle audio codecs, load them in memory
*/ */
/** Maps a pointer on an audiocodec object to a payload */
typedef std::map<AudioCodecType, sfl::Codec*> CodecsMap;
class AudioCodecFactory class AudioCodecFactory
{ {
public: public:
/**
* Constructor
*/
AudioCodecFactory();
/** /**
* Accessor to data structures * Accessor to data structures
* @return CodecsMap& The available codec * @return CodecsMap& The available codec
*/ */
const CodecsMap& getCodecsMap() const { const CodecsMap& getCodecsMap() const {
return _CodecsMap; return codecsMap_;
} }
/** /**
...@@ -117,13 +110,6 @@ class AudioCodecFactory ...@@ -117,13 +110,6 @@ class AudioCodecFactory
*/ */
void deleteHandlePointer (void); void deleteHandlePointer (void);
/**
* Get the first element of the CodecsMap struct.
* i.e the one with the lowest payload
* @return AudioCodec The pointer on the codec object
*/
sfl::Codec* getFirstCodecAvailable (void);
/** /**
* Instantiate a codec, used in AudioRTP to get an instance of Codec per call * Instantiate a codec, used in AudioRTP to get an instance of Codec per call
* @param CodecHandlePointer The map containing the pointer on the object and the pointer on the handle function * @param CodecHandlePointer The map containing the pointer on the object and the pointer on the handle function
...@@ -147,20 +133,23 @@ class AudioCodecFactory ...@@ -147,20 +133,23 @@ class AudioCodecFactory
bool isCodecLoaded (int payload); bool isCodecLoaded (int payload);
private: private:
/** Enable us to keep the handle pointer on the codec dynamicaly loaded so that we could destroy when we dont need it anymore */
typedef std::pair<sfl::Codec* , void*> CodecHandlePointer;
/** /**
* Scan the installation directory ( --prefix configure option ) * Scan the installation directory ( --prefix configure option )
* And load the dynamic library * And load the dynamic library
* @return std::vector<AudioCodec*> The list of the codec object successfully loaded in memory * @return std::vector<AudioCodec*> The list of the codec object successfully loaded in memory
*/ */
std::vector<sfl::Codec *> scanCodecDirectory (void); std::vector<sfl::Codec *> scanCodecDirectory ();
/** /**
* Load a codec * Load a codec
* @param std::string The path of the shared ( dynamic ) library. * @param std::string The path of the shared ( dynamic ) library.
* @return AudioCodec* the pointer of the object loaded. * @return AudioCodec* the pointer of the object loaded.
*/ */
sfl::Codec* loadCodec (std::string); sfl::Codec* loadCodec (const std::string &path);
/** /**
* Unload a codec * Unload a codec
...@@ -174,7 +163,7 @@ class AudioCodecFactory ...@@ -174,7 +163,7 @@ class AudioCodecFactory
* @return bool True if the file name begins with libcodec_ and ends with .so * @return bool True if the file name begins with libcodec_ and ends with .so
* false otherwise * false otherwise
*/ */
bool seemsValid (std::string); static bool seemsValid (const std::string &lib);
/** /**
* Check if the codecs shared library has already been scanned during the session * Check if the codecs shared library has already been scanned during the session
...@@ -183,28 +172,28 @@ class AudioCodecFactory ...@@ -183,28 +172,28 @@ class AudioCodecFactory
* @return bool True if the codecs has been scanned * @return bool True if the codecs has been scanned
* false otherwise * false otherwise
*/ */
bool alreadyInCache (std::string); bool alreadyInCache (const std::string &lib);
/** /**
* Map the payload of a codec and the object associated ( AudioCodec * ) * Map the payload of a codec and the object associated ( AudioCodec * )
*/ */
CodecsMap _CodecsMap; CodecsMap codecsMap_;
/** /**
* Vector containing a default order for the codecs * Vector containing a default order for the codecs
*/ */
CodecOrder _defaultCodecOrder; CodecOrder defaultCodecOrder_;
/** /**
* Vector containing the complete name of the codec shared library scanned * Vector containing the complete name of the codec shared library scanned
*/ */
std::vector<std::string> _Cache; std::vector<std::string> libCache_;
/** /**
* Vector containing pairs * Vector containing pairs
* Pair between pointer on function handle and pointer on audiocodec object * Pair between pointer on function handle and pointer on audiocodec object
*/ */
std::vector< CodecHandlePointer > _CodecInMemory; std::vector< CodecHandlePointer > codecInMemory_;
}; };
#endif // __CODEC_DESCRIPTOR_H__ #endif // __CODEC_DESCRIPTOR_H__
...@@ -173,6 +173,9 @@ std::vector<std::string> ConfigurationManager::getAudioCodecList (void) ...@@ -173,6 +173,9 @@ std::vector<std::string> ConfigurationManager::getAudioCodecList (void)
list.push_back (ss.str()); list.push_back (ss.str());
} }
if (list.empty())
errorAlert(CODECS_NOT_LOADED);
return list; return list;
} }
...@@ -189,7 +192,10 @@ std::vector<std::string> ConfigurationManager::getSupportedTlsMethod (void) ...@@ -189,7 +192,10 @@ std::vector<std::string> ConfigurationManager::getSupportedTlsMethod (void)
std::vector<std::string> ConfigurationManager::getAudioCodecDetails (const int32_t& payload) std::vector<std::string> ConfigurationManager::getAudioCodecDetails (const int32_t& payload)
{ {
return Manager::instance().getAudioCodecFactory().getCodecSpecifications (payload); std::vector<std::string> result(Manager::instance().getAudioCodecFactory().getCodecSpecifications(payload));
if (result.empty())
errorAlert(CODECS_NOT_LOADED);
return result;
}