1 /**
2         \file ADM_pluginLoad.cpp
3         \brief Interface for dynamically loaded audio decoder
4 
5         There are 2 known problem here
6         1: The destructor is called instead of calling destroy in the class factory
7         2: Memory leak, ADM_audioPlugins is not destroyed as of today
8 
9 */
10 
11 
12 /***************************************************************************
13  *                                                                         *
14  *   This program is free software; you can redistribute it and/or modify  *
15  *   it under the terms of the GNU General Public License as published by  *
16  *   the Free Software Foundation; either version 2 of the License, or     *
17  *   (at your option) any later version.                                   *
18  ***************************************************************************/
19 #include "ADM_default.h"
20 #include "ADM_ad_plugin.h"
21 #include "DIA_fileSel.h"
22 #include "ADM_dynamicLoading.h"
23 #include <vector>
24 
25 #if 1
26 #define aprintf printf
27 #else
28 #define aprintf(...) {}
29 #endif
30 /*  Exported functions */
31 uint32_t ADM_ad_getNbFilters(void);
32 bool     ADM_ad_getFilterInfo(int filter, const char **name,
33                                 uint32_t *major,uint32_t *minor,uint32_t *patch);
34 
35 /**
36  *
37  */
38 class ADM_ad_plugin : public ADM_LibWrapper
39 {
40 	public:
41                 ADM_ad_CreateFunction		*create;
42                 ADM_ad_DeleteFunction		*destroy;
43                 ADM_ad_SupportedFormat		*supportedFormat;
44                 ADM_ad_GetApiVersion		*getApiVersion;
45                 ADM_ad_GetDecoderVersion	*getDecoderVersion;
46                 ADM_ADM_ad_GetInfo		*getInfo;
47                 std::string			name;
48 
ADM_ad_plugin(const char * file)49 		ADM_ad_plugin(const char *file) : ADM_LibWrapper()
50 		{
51 			initialised = (loadLibrary(file) && getSymbols(6,
52 				&create, "create",
53 				&destroy, "destroy",
54 				&supportedFormat, "supportedFormat",
55 				&getApiVersion, "getApiVersion",
56 				&getDecoderVersion, "getDecoderVersion",
57 				&getInfo, "getInfo"));
58 		};
59 };
60 
61 std::vector<ADM_ad_plugin *> ADM_audioPlugins;
62 /**
63  * 	\fn tryLoadingAudioPlugin
64  *  \brief try to load the plugin given as argument..
65  */
tryLoadingAudioPlugin(const char * file)66 static uint8_t tryLoadingAudioPlugin(const char *file)
67 {
68 	ADM_ad_plugin *plugin = new ADM_ad_plugin(file);
69 
70 	if (!plugin->isAvailable())
71 	{
72 		printf("[ADM_ad_plugin] Unable to load %s\n", ADM_getFileName(std::string(file)).c_str());
73 		goto Err_ad;
74 	}
75 
76 	// Check API version
77 	if (plugin->getApiVersion() != AD_API_VERSION)
78 	{
79 		ADM_warning("[ADM_ad_plugin] File %s has API version too old (%d vs %d)\n",
80 			ADM_getFileName(std::string(file)).c_str(), plugin->getApiVersion(), AD_API_VERSION);
81 		goto Err_ad;
82 	}
83 
84 	// Get infos
85 	uint32_t major, minor, patch;
86 
87 	plugin->getDecoderVersion(&major, &minor, &patch);
88 	plugin->name = ADM_getFileName(std::string(file));
89 
90 	ADM_info("[ADM_ad_plugin] Plugin loaded version %d.%d.%d, name %s, desc: %s\n",
91 		major, minor, patch, plugin->name.c_str(), plugin->getInfo());
92 
93 	ADM_audioPlugins.push_back(plugin);
94 
95 	return 1;
96 
97 Err_ad:
98 	delete plugin;
99 	return 0;
100 }
101 /**
102     \fn ADM_ad_getNbFilters
103     \brief returns the # of loaded audio decoder
104 */
ADM_ad_getNbFilters(void)105 uint32_t ADM_ad_getNbFilters(void)
106 {
107     return (uint32_t )ADM_audioPlugins.size();
108 }
109 /**
110     \fn ADM_ad_getFilterInfo
111     \brief returns infos about a given filter
112     @param filter [in] # of the filter we are intereseted in, between 0 & ADM_ad_getNbFilters
113     @param name [out] Name of the decoder plugin
114     @param major, minor,patch [out] Version number
115     @return true
116 */
ADM_ad_getFilterInfo(int filter,std::string & name,uint32_t * major,uint32_t * minor,uint32_t * patch)117 bool ADM_ad_getFilterInfo(int filter, std::string &name, uint32_t *major,uint32_t *minor,uint32_t *patch)
118 {
119 
120         ADM_assert(filter>=0 && filter<ADM_audioPlugins.size());
121 
122     	ADM_ad_plugin *a=ADM_audioPlugins[filter];
123         a->getDecoderVersion(major, minor, patch);
124 
125         name=a->getInfo();
126         return 1;
127 }
128 
129 /**
130  * 	\fn ADM_ad_loadPlugins
131  *  \brief load all audio plugins
132  */
ADM_ad_loadPlugins(const char * path)133 uint8_t ADM_ad_loadPlugins(const char *path)
134 {
135 #define MAX_EXTERNAL_FILTER 50
136 
137 	char *files[MAX_EXTERNAL_FILTER];
138 	uint32_t nbFile;
139 
140 	memset(files,0,sizeof(char *)*MAX_EXTERNAL_FILTER);
141 	printf("[ADM_ad_plugin] Scanning directory %s\n",path);
142 
143 	if(!buildDirectoryContent(&nbFile, path, files, MAX_EXTERNAL_FILTER, SHARED_LIB_EXT))
144 	{
145 		printf("[ADM_ad_plugin] Cannot parse plugin\n");
146 		return 0;
147 	}
148 
149 	for(int i=0;i<nbFile;i++)
150 		tryLoadingAudioPlugin(files[i]);
151 
152 	printf("[ADM_ad_plugin] Scanning done, found %d codec\n", (int)ADM_audioPlugins.size());
153         clearDirectoryContent(nbFile,files);
154 	return 1;
155 }
156 /**
157  * 	\fn ADM_ad_searchCodec
158  *  \brief Try to instantiate a codec that can decode the given stuff
159  */
ADM_ad_searchCodec(uint32_t fourcc,WAVHeader * info,uint32_t extraLength,uint8_t * extraData)160 ADM_Audiocodec *ADM_ad_searchCodec(uint32_t fourcc,	WAVHeader *info,uint32_t extraLength,uint8_t *extraData)
161 {
162     int best=0;
163     int index=-1;
164 	for(int i=0;i<ADM_audioPlugins.size();i++)
165 	{
166 		ADM_ad_plugin *a=ADM_audioPlugins[i];
167 		ADM_assert(a);
168 		ADM_assert(a->supportedFormat);
169 
170         int score=a->supportedFormat(fourcc);
171         ADM_info("[ADM_ad_plugin]Format 0x%x : probing %s score %d\n",fourcc,a->name.c_str(),score);
172         if(score>best)
173         {
174             index=i;
175             best=score;
176         }
177 	}
178     if(index!=-1 && best >0)
179     {
180         ADM_ad_plugin *a=ADM_audioPlugins[index];
181         ADM_assert(a->create);
182         return a->create(fourcc, info,extraLength,extraData);
183     }
184 	return NULL;
185 }
186 /**
187     \fn ADM_ad_cleanup
188 */
ADM_ad_cleanup(void)189 bool ADM_ad_cleanup(void)
190 {
191     ADM_info("Purging audio decoder\n");
192     for(int i=0;i<ADM_audioPlugins.size();i++)
193     {
194         ADM_ad_plugin *a=ADM_audioPlugins[i];
195         delete a;
196         ADM_audioPlugins[i]=NULL;
197     }
198     ADM_audioPlugins.clear();
199     return true;
200 }
201 //EOF
202