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

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

parent 4b32b763
......@@ -31,112 +31,110 @@
* as that of the covered work.
*/
#include <iostream>
#include <cstdlib>
#include "audiocodecfactory.h"
#include <cstdlib>
#include <algorithm> // for std::find
#include "fileutils.h"
AudioCodecFactory::AudioCodecFactory() : _CodecsMap(), _defaultCodecOrder(), _Cache(), _CodecInMemory()
{
}
void
AudioCodecFactory::init()
{
std::vector<sfl::Codec*> CodecDynamicList = scanCodecDirectory();
if (CodecDynamicList.size() == 0)
typedef std::vector<sfl::Codec*> CodecVector;
CodecVector codecDynamicList(scanCodecDirectory());
if (codecDynamicList.empty())
_error ("Error - No codecs available");
for (size_t i = 0 ; i < CodecDynamicList.size() ; i++) {
_CodecsMap[ (AudioCodecType) CodecDynamicList[i]->getPayloadType() ] = CodecDynamicList[i];
_debug ("Loaded codec %s" , CodecDynamicList[i]->getMimeSubtype().c_str());
else {
for (CodecVector::const_iterator iter = codecDynamicList.begin();
iter != codecDynamicList.end() ; ++iter) {
codecsMap_[ (AudioCodecType) (*iter)->getPayloadType() ] = *iter;
_debug ("Loaded codec %s" , (*iter)->getMimeSubtype().c_str());
}
}
}
void AudioCodecFactory::setDefaultOrder()
{
_defaultCodecOrder.clear();
CodecsMap::iterator iter;
for (iter = _CodecsMap.begin(); iter != _CodecsMap.end(); ++iter)
_defaultCodecOrder.push_back (iter->first);
defaultCodecOrder_.clear();
CodecsMap::const_iterator iter;
for (iter = codecsMap_.begin(); iter != codecsMap_.end(); ++iter)
defaultCodecOrder_.push_back (iter->first);
}
std::string
AudioCodecFactory::getCodecName (AudioCodecType payload)
{
CodecsMap::iterator iter = _CodecsMap.find (payload);
if (iter!=_CodecsMap.end())
return (iter->second->getMimeSubtype());
CodecsMap::const_iterator iter = codecsMap_.find (payload);
return "";
if (iter != codecsMap_.end())
return iter->second->getMimeSubtype();
else
return "";
}
sfl::Codec*
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;
_error ("CodecDescriptor: cannot find codec %i", payload);
return NULL;
else {
_error ("CodecDescriptor: cannot find codec %i", payload);
return NULL;
}
}
double AudioCodecFactory::getBitRate (AudioCodecType payload)
{
CodecsMap::iterator iter = _CodecsMap.find (payload);
CodecsMap::const_iterator iter = codecsMap_.find (payload);
if (iter!=_CodecsMap.end())
return (iter->second->getBitRate());
return 0.0;
if (iter != codecsMap_.end())
return iter->second->getBitRate();
else
return 0.0;
}
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 0;
else
return 0;
}
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
// we used the CodecOrder vector to save the order.
for (size_t i = 0; i < list.size(); i++) {
int payload = std::atoi (list[i].data());
for (std::vector<std::string>::const_iterator iter = list.begin(); iter != list.end(); ++iter) {
int payload = std::atoi(iter->c_str());
if (isCodecLoaded (payload))
_defaultCodecOrder.push_back ( (AudioCodecType) payload);
defaultCodecOrder_.push_back ( (AudioCodecType) payload);
}
}
void
AudioCodecFactory::deleteHandlePointer (void)
AudioCodecFactory::deleteHandlePointer()
{
for (std::vector<CodecHandlePointer>::const_iterator iter =
_CodecInMemory.begin(); iter != _CodecInMemory.end(); ++iter)
codecInMemory_.begin(); iter != codecInMemory_.end(); ++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<std::string> dirToScan;
dirToScan.push_back (std::string(HOMEDIR) + DIR_SEPARATOR_STR "." PROGDIR "/");
dirToScan.push_back (CODECS_DIR "/");
dirToScan.push_back(std::string(HOMEDIR) + DIR_SEPARATOR_STR "." PROGDIR "/");
dirToScan.push_back(CODECS_DIR "/");
const char *envDir = getenv("CODECS_PATH");
if (envDir)
dirToScan.push_back(std::string(envDir) + DIR_SEPARATOR_STR);
......@@ -162,7 +160,7 @@ std::vector<sfl::Codec*> AudioCodecFactory::scanCodecDirectory (void)
sfl::Codec* audioCodec = loadCodec (dirStr+file);
if (audioCodec) {
codecs.push_back (audioCodec);
_Cache.push_back (file);
libCache_.push_back (file);
}
}
}
......@@ -173,12 +171,12 @@ std::vector<sfl::Codec*> AudioCodecFactory::scanCodecDirectory (void)
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);
if (!codecHandle) {
_error("%s\n", dlerror());
return NULL;
_error("%s\n", dlerror());
return NULL;
}
dlerror();
......@@ -186,13 +184,13 @@ sfl::Codec* AudioCodecFactory::loadCodec (std::string path)
create_t* createCodec = (create_t*) dlsym (codecHandle , "create");
char *error = dlerror();
if (error) {
_error("%s\n", error);
return NULL;
_error("%s\n", error);
return NULL;
}
sfl::Codec* a = createCodec();
_CodecInMemory.push_back (CodecHandlePointer (a, codecHandle));
codecInMemory_.push_back (CodecHandlePointer (a, codecHandle));
return a;
}
......@@ -204,8 +202,8 @@ void AudioCodecFactory::unloadCodec (CodecHandlePointer p)
char *error = dlerror();
if (error) {
_error("%s\n", error);
return;
_error("%s\n", error);
return;
}
destroyCodec (p.first);
......@@ -217,34 +215,22 @@ sfl::Codec* AudioCodecFactory::instantiateCodec (AudioCodecType payload)
{
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) {
create_t* createCodec = (create_t*) dlsym (iter->second , "create");
char *error = dlerror();
if (error)
_error("%s\n", error);
_error("%s\n", error);
else
return createCodec();
return createCodec();
}
}
return NULL;
}
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)
bool AudioCodecFactory::seemsValid (const std::string &lib)
{
// The name of the shared library seems valid <==> it looks like libcodec_xxx.so
// We check this
......@@ -280,24 +266,20 @@ bool AudioCodecFactory::seemsValid (std::string lib)
if (lib.substr (lib.length() - suffix.length() , suffix.length()) == suffix)
return true;
return false;
return false;
}
bool
AudioCodecFactory::alreadyInCache (std::string lib)
AudioCodecFactory::alreadyInCache (const std::string &lib)
{
for (size_t i = 0 ; i < _Cache.size() ; i++)
if (_Cache[i] == lib)
return true;
return false;
return std::find(libCache_.begin(), libCache_.end(), lib) != libCache_.end();
}
bool AudioCodecFactory::isCodecLoaded (int payload)
{
CodecsMap::iterator iter;
for (iter = _CodecsMap.begin(); iter != _CodecsMap.end(); ++iter)
if (iter -> first == payload)
CodecsMap::const_iterator iter;
for (iter = codecsMap_.begin(); iter != codecsMap_.end(); ++iter)
if (iter->first == payload)
return true;
return false;
......@@ -309,17 +291,17 @@ std::vector <std::string> AudioCodecFactory::getCodecSpecifications (const int32
std::stringstream ss;
// Add the name of the codec
v.push_back (getCodecName ( (AudioCodecType) payload));
v.push_back(getCodecName(static_cast<AudioCodecType>(payload)));
// Add the sample rate
ss << getSampleRate ( (AudioCodecType) payload);
v.push_back ( (ss.str()).data());
ss.str ("");
ss << getSampleRate (static_cast<AudioCodecType>(payload));
v.push_back(ss.str());
ss.str("");
// Add the bit rate
ss << getBitRate ( (AudioCodecType) payload);
v.push_back ( (ss.str()).data());
ss.str ("");
ss << getBitRate(static_cast<AudioCodecType>(payload));
v.push_back(ss.str());
ss.str("");
return v;
}
......@@ -40,30 +40,23 @@
#include "global.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
* @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
{
public:
/**
* Constructor
*/
AudioCodecFactory();
/**
* Accessor to data structures
* @return CodecsMap& The available codec
*/
const CodecsMap& getCodecsMap() const {
return _CodecsMap;
return codecsMap_;
}
/**
......@@ -117,13 +110,6 @@ class AudioCodecFactory
*/
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
* @param CodecHandlePointer The map containing the pointer on the object and the pointer on the handle function
......@@ -147,20 +133,23 @@ class AudioCodecFactory
bool isCodecLoaded (int payload);
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 )
* And load the dynamic library
* @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
* @param std::string The path of the shared ( dynamic ) library.
* @return AudioCodec* the pointer of the object loaded.
*/
sfl::Codec* loadCodec (std::string);
sfl::Codec* loadCodec (const std::string &path);
/**
* Unload a codec
......@@ -174,7 +163,7 @@ class AudioCodecFactory
* @return bool True if the file name begins with libcodec_ and ends with .so
* 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
......@@ -183,28 +172,28 @@ class AudioCodecFactory
* @return bool True if the codecs has been scanned
* false otherwise
*/
bool alreadyInCache (std::string);
bool alreadyInCache (const std::string &lib);
/**
* Map the payload of a codec and the object associated ( AudioCodec * )
*/
CodecsMap _CodecsMap;
CodecsMap codecsMap_;
/**
* Vector containing a default order for the codecs
*/
CodecOrder _defaultCodecOrder;
CodecOrder defaultCodecOrder_;
/**
* Vector containing the complete name of the codec shared library scanned
*/
std::vector<std::string> _Cache;
std::vector<std::string> libCache_;
/**
* Vector containing pairs
* Pair between pointer on function handle and pointer on audiocodec object
*/
std::vector< CodecHandlePointer > _CodecInMemory;
std::vector< CodecHandlePointer > codecInMemory_;
};
#endif // __CODEC_DESCRIPTOR_H__
......@@ -173,6 +173,9 @@ std::vector<std::string> ConfigurationManager::getAudioCodecList (void)
list.push_back (ss.str());
}
if (list.empty())
errorAlert(CODECS_NOT_LOADED);
return list;
}
......@@ -189,7 +192,10 @@ std::vector<std::string> ConfigurationManager::getSupportedTlsMethod (void)
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;
}
std::vector<std::string> ConfigurationManager::getActiveAudioCodecList (const std::string& accountID)
......
......@@ -113,10 +113,11 @@ static const SOUND_FORMAT INT32 = 0x8;
#define NOTIFY_ALL TRUE_STR /** Desktop notification level 0: never notify */
// Error codes for error handling
#define NO_ERROR 0x0000 /** No error - Everything alright */
#define ALSA_CAPTURE_DEVICE 0x0001 /** Error while opening capture device */
#define ALSA_PLAYBACK_DEVICE 0x0010 /** Error while opening playback device */
#define PULSEAUDIO_NOT_RUNNING 0x0100 /** Pulseaudio is not running */
#define NO_ERROR 0x0000 /** No error - Everything alright */
#define ALSA_CAPTURE_DEVICE 0x0001 /** Error while opening capture device */
#define ALSA_PLAYBACK_DEVICE 0x0010 /** Error while opening playback device */
#define PULSEAUDIO_NOT_RUNNING 0x0100 /** Pulseaudio is not running */
#define CODECS_NOT_LOADED 0x1000 /** Codecs not found */
#define ALSA 0
#define PULSEAUDIO 1
......
......@@ -2294,11 +2294,6 @@ int32_t ManagerImpl::getAudioManager (void) const
}
void ManagerImpl::notifyErrClient (int32_t errCode)
{
_dbus.getConfigurationManager()->errorAlert(errCode);
}
int ManagerImpl::getAudioDeviceIndex (const std::string &name)
{
int soundCardIndex = 0;
......
......@@ -756,13 +756,6 @@ class ManagerImpl
*/
std::vector< ::std::string > getActiveCodecList (void) const;
/*
* Notify the client that an error occured
* @param errCode The error code. Could be: ALSA_CAPTURE_ERROR
* ALSA_PLAYBACK_ERROR
*/
void notifyErrClient (int32_t errCode);
/**
* Retrieve in the configuration tree the value of a parameter in a specific section
* @param section The section to look in
......
......@@ -87,12 +87,8 @@ void codec_capabilities_load (void)
}
// If we didn't load any codecs, problem ...
if (g_queue_get_length (codecsCapabilities) == 0) {
// Error message
if (g_queue_get_length (codecsCapabilities) == 0)
ERROR ("No audio codecs found");
dbus_unregister (getpid());
exit (1);
}
}
void account_create_codec_list (account_t **acc)
......
......@@ -514,6 +514,9 @@ error_alert (DBusGProxy *proxy UNUSED, int err, void * foo UNUSED)
case PULSEAUDIO_NOT_RUNNING:
msg = _("Pulseaudio notification\n\nPulseaudio is not running");
break;
case CODECS_NOT_LOADED:
msg = _("Codecs notification\n\nCodecs not found");
break;
default:
return;
}
......
......@@ -127,11 +127,13 @@
#define SHORTCUT_TOGGLEHOLD "toggleHold"
/** Error while opening capture device */
#define ALSA_CAPTURE_DEVICE 0x0001
#define ALSA_CAPTURE_DEVICE 0x0001
/** Error while opening playback device */
#define ALSA_PLAYBACK_DEVICE 0x0010
#define ALSA_PLAYBACK_DEVICE 0x0010
/** Error pulseaudio */
#define PULSEAUDIO_NOT_RUNNING 0x0100
#define PULSEAUDIO_NOT_RUNNING 0x0100
/** Error codecs not loaded */
#define CODECS_NOT_LOADED 0x1000
/** Tone to play when no voice mails */
#define TONE_WITHOUT_MESSAGE 0
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment