show path where a panner is discovered
[ardour.git] / libs / ardour / panner_manager.cc
1 #include <glibmm/pattern.h>
2
3 #include "pbd/error.h"
4 #include "pbd/compose.h"
5 #include "pbd/file_utils.h"
6
7 #include "ardour/panner_manager.h"
8 #include "ardour/panner_search_path.h"
9
10 #include "i18n.h"
11
12 using namespace std;
13 using namespace ARDOUR;
14 using namespace PBD;
15
16 PannerManager* PannerManager::_instance = 0;
17
18 PannerManager::PannerManager ()
19 {
20 }
21
22 PannerManager::~PannerManager ()
23 {
24         for (list<PannerInfo*>::iterator p = panner_info.begin(); p != panner_info.end(); ++p) {
25                 delete *p;
26         }
27 }
28
29 PannerManager&
30 PannerManager::instance ()
31 {
32         if (_instance == 0) {
33                 _instance = new PannerManager ();
34         }
35
36         return *_instance;
37 }
38
39 void
40 PannerManager::discover_panners ()
41 {
42         vector<sys::path> panner_modules;
43
44         Glib::PatternSpec so_extension_pattern("*.so");
45         Glib::PatternSpec dylib_extension_pattern("*.dylib");
46
47         find_matching_files_in_search_path (panner_search_path (),
48                                             so_extension_pattern, panner_modules);
49
50         find_matching_files_in_search_path (panner_search_path (),
51                                             dylib_extension_pattern, panner_modules);
52
53         info << string_compose (_("looking for panners in %1"), panner_search_path().to_string()) << endmsg;
54
55         for (vector<sys::path>::iterator i = panner_modules.begin(); i != panner_modules.end(); ++i) {
56                 panner_discover ((*i).to_string());
57         }
58 }
59 int
60 PannerManager::panner_discover (string path)
61 {
62         PannerInfo* pinfo;
63
64         if ((pinfo = get_descriptor (path)) != 0) {
65                 panner_info.push_back (pinfo);
66                 info << string_compose(_("Panner discovered: \"%1\" in %2"), pinfo->descriptor.name, path) << endmsg;
67         }
68
69         return 0;
70 }
71
72 PannerInfo*
73 PannerManager::get_descriptor (string path)
74 {
75         void *module;
76         PannerInfo* info = 0;
77         PanPluginDescriptor *descriptor = 0;
78         PanPluginDescriptor* (*dfunc)(void);
79         const char *errstr;
80
81         if ((module = dlopen (path.c_str(), RTLD_NOW)) == 0) {
82                 error << string_compose(_("PannerManager: cannot load module \"%1\" (%2)"), path, dlerror()) << endmsg;
83                 return 0;
84         }
85
86         dfunc = (PanPluginDescriptor* (*)(void)) dlsym (module, "panner_descriptor");
87
88         if ((errstr = dlerror()) != 0) {
89                 error << string_compose(_("PannerManager: module \"%1\" has no descriptor function."), path) << endmsg;
90                 error << errstr << endmsg;
91                 dlclose (module);
92                 return 0;
93         }
94
95         descriptor = dfunc();
96         if (descriptor) {
97                 info = new PannerInfo (*descriptor, module);
98         } else {
99                 dlclose (module);
100         }
101
102         return info;
103 }
104
105 PannerInfo*
106 PannerManager::select_panner (ChanCount in, ChanCount out)
107 {
108         PanPluginDescriptor* d;
109         int32_t nin = in.n_audio();
110         int32_t nout = out.n_audio();
111
112         /* look for exact match first */
113
114         for (list<PannerInfo*>::iterator p = panner_info.begin(); p != panner_info.end(); ++p) {
115                 d = &(*p)->descriptor;
116
117                 if (d->in == nin && d->out == nout) {
118                         return *p;
119                 }
120         }
121
122         /* no exact match, look for good fit on inputs and variable on outputs */
123
124         for (list<PannerInfo*>::iterator p = panner_info.begin(); p != panner_info.end(); ++p) {
125                 d = &(*p)->descriptor;
126
127                 if (d->in == nin && d->out == -1) {
128                         return *p;
129                 }
130         }
131
132         /* no exact match, look for good fit on outputs and variable on inputs */
133
134         for (list<PannerInfo*>::iterator p = panner_info.begin(); p != panner_info.end(); ++p) {
135                 d = &(*p)->descriptor;
136
137                 if (d->in == -1 && d->out == nout) {
138                         return *p;
139                 }
140         }
141
142         /* no exact match, look for variable fit on inputs and outputs */
143
144         for (list<PannerInfo*>::iterator p = panner_info.begin(); p != panner_info.end(); ++p) {
145                 d = &(*p)->descriptor;
146
147                 if (d->in == -1 && d->out == -1) {
148                         return *p;
149                 }
150         }
151
152         warning << string_compose (_("no panner discovered for in/out = %1/%2"), nin, nout) << endmsg;
153
154         return 0;
155 }