1 /***************************************************************************
2 	    PluginManager.h  -  manager class for kwave's plugins
3 			     -------------------
4     begin                : Sun Aug 27 2000
5     copyright            : (C) 2000 by Thomas Eschenbacher
6     email                : Thomas.Eschenbacher@gmx.de
7  ***************************************************************************/
8 
9 /***************************************************************************
10  *                                                                         *
11  *   This program is free software; you can redistribute it and/or modify  *
12  *   it under the terms of the GNU General Public License as published by  *
13  *   the Free Software Foundation; either version 2 of the License, or     *
14  *   (at your option) any later version.                                   *
15  *                                                                         *
16  ***************************************************************************/
17 
18 #ifndef PLUGIN_MANAGER_H
19 #define PLUGIN_MANAGER_H
20 
21 #include "config.h"
22 
23 #include <QtGlobal>
24 #include <QList>
25 #include <QListIterator>
26 #include <QMap>
27 #include <QMutableListIterator>
28 #include <QObject>
29 #include <QPointer>
30 #include <QWidget>
31 
32 #include "libkwave/InsertMode.h"
33 #include "libkwave/Sample.h"
34 #include "libkwave/ViewManager.h"
35 
36 class QLibrary;
37 class QString;
38 class QStringList;
39 
40 class KPluginFactory;
41 
42 namespace Kwave
43 {
44     class PlaybackController;
45     class PlaybackDeviceFactory;
46     class PlayBackParam;
47     class Plugin;
48     class PluginContext;
49     class SampleSink;
50     class SignalManager;
51     class Writer;
52 
53     /**
54      * Manages the loading, initializing, starting, running and closing
55      * of the plugins of kwave. Each instance of a TopWidget creates a
56      * new instance of the PluginManager to be independent from other
57      * toplevel widgets.
58      */
59     class Q_DECL_EXPORT PluginManager: public QObject
60     {
61 	Q_OBJECT
62 
63     public:
64 
65 	/**
66 	 * Constructor.
67 	 * @param parent reference to the toplevel widget (our parent)
68 	 * @param signal_manager reference to a SignalManager
69 	 */
70 	PluginManager(QWidget *parent, Kwave::SignalManager &signal_manager);
71 
72 	/**
73 	 * Default destructor
74 	 */
75 	virtual ~PluginManager();
76 
77 	/**
78 	 * Tries to load all plugins. If a pesistent plugin is found,
79 	 * it will stay loaded in memory, all other (non-persistent)
80 	 * plugins will be unloaded afterwards. This also filters out
81 	 * all plugins that do not correctly load.
82 	 * @internal used once by each toplevel window at startup
83 	 * @return true if at least one plugin was loaded, false if none
84 	 */
85 	bool loadAllPlugins();
86 
87 	/**
88 	 * Stops all currently running plugins
89 	 */
90 	void stopAllPlugins();
91 
92 	/**
93 	 * Executes a plugin in the context of a given parent widget.
94 	 * @param name the name of the plugin
95 	 * @param params pointer to a parameter list
96 	 *               or null if defaults should be used
97 	 * @return zero on success or negative error code
98 	 */
99 	int executePlugin(const QString &name, QStringList *params);
100 
101 	/**
102 	 * Returns true if there is no running plugin that blocks
103 	 * a "close" operation.
104 	 */
105 	bool canClose();
106 
107 	/** Returns true if at least one plugin is currently running */
108 	bool onePluginRunning();
109 
110 	/**
111 	 * Waits until all currently running actions have completed.
112 	 */
113 	void sync();
114 
115 	/**
116 	 * Loads a plugin, calls it's setup function and then closes
117 	 * it again. The parameters will be loaded before the setup
118 	 * and saved if the setup has not been aborted.
119 	 * @param name the name of the plugin
120 	 * @param params pointer to a parameter list
121 	 *               or null if defaults should be used
122 	 * @retval  0 if succeeded and accepted
123 	 * @retval  1 if canceled
124 	 * @retval -1 if failed
125 	 */
126 	int setupPlugin(const QString &name, const QStringList &params);
127 
128 	/**
129 	 * loads a plugin's default parameters from the user's
130 	 * configuration file. If nothing is found in the config file,
131 	 * the return value will be 0. If the current version number of
132 	 * the plugin does not match the version number in the config file,
133 	 * the return value will also be 0.
134 	 * @param name the name of the plugin
135 	 * @return list of strings
136 	 */
137 	QStringList defaultParams(const QString &name);
138 
139 	/**
140 	 * Returns the length of the current signal in samples.
141 	 * If no signal is present the return value will be 0.
142 	 */
143 	sample_index_t signalLength();
144 
145 	/**
146 	 * Returns the current sample rate in samples per second.
147 	 * If no signal is present the return value will be 0.
148 	 */
149 	double signalRate();
150 
151 	/**
152 	 * Returns the start of the selection. If nothing is currently
153 	 * selected this will be the first sample (0).
154 	 */
155 	sample_index_t selectionStart();
156 
157 	/**
158 	 * Returns the end of the selection. If nothing is currently
159 	 * selected this will be the last sample (length-1).
160 	 */
161 	sample_index_t selectionEnd();
162 
163 	/**
164 	 * Sets the current start and length of the selection to new values.
165 	 * @param offset index of the first sample
166 	 * @param length number of samples
167 	 */
168 	void selectRange(sample_index_t offset, sample_index_t length);
169 
170 	/**
171 	 * Opens a Kwave::MultiTrackSink for playback purposes.
172 	 * @param tracks number of tracks
173 	 * @param playback_params points to a class that holds all playback
174 	 *                        parameters. If null, the default parameters
175 	 *                        of the current signal will be used
176 	 * @return a multitrack sink that receives the playback stream
177 	 */
178 	Kwave::SampleSink *openMultiTrackPlayback(
179 	    unsigned int tracks,
180             const Kwave::PlayBackParam *playback_params = Q_NULLPTR
181 	);
182 
183 	/**
184 	 * Returns a reference to the current playback controller. This is
185 	 * only needed for plugins doing playback.
186 	 */
187 	Kwave::PlaybackController &playbackController();
188 
189 	/**
190 	 * assigns a new parent widget, to be used for messages
191 	 * @param new_parent pointer to a QWidget
192 	 */
setParentWidget(QWidget * new_parent)193 	inline void setParentWidget(QWidget *new_parent) {
194 	    m_parent_widget = new_parent;
195 	}
196 
197 	/** returns a pointer to the parent widget */
parentWidget()198 	inline QPointer<QWidget> parentWidget()
199 	{
200 	    return m_parent_widget;
201 	}
202 
203 	/** returns a reference to our signal manager */
signalManager()204 	inline Kwave::SignalManager &signalManager()
205 	{
206 	    return m_signal_manager;
207 	}
208 
209 	/**
210 	 * Insert a new signal view into this widget (or the upper/lower
211 	 * dock area.
212 	 * @param view the signal view, must not be a null pointer
213 	 * @param controls a widget with controls, optionally, can be null
214 	 */
215 	void insertView(Kwave::SignalView *view, QWidget *controls);
216 
217 	/**
218 	 * registers a view manager, must only be called once!
219 	 */
220 	void registerViewManager(Kwave::ViewManager *view_manager);
221 
222 	/**
223 	 * Enqueues a command that will be processed threadsafe in the X11
224 	 * thread.
225 	 */
226 	void enqueueCommand(const QString &command);
227 
228 	/**
229 	 * Searches the standard KDE data directories for plugins (through
230 	 * the KDE's standard search algorithm) and creates a map of
231 	 * plugin names and file names. First it collects a list of
232 	 * filenames and then filters it to sort out invalid entries.
233 	 */
234 	void searchPluginModules();
235 
236 	/** structure with information about a plugin */
237 	typedef struct  {
238 	    QString            m_name;        /**< name of the plugin   */
239 	    QString            m_author;      /**< name of the author   */
240 	    QString            m_description; /**< short description    */
241 	    QString            m_version;     /**< settings version     */
242 	    KPluginFactory    *m_factory;     /**< plugin factory       */
243 	    int                m_use_count;   /**< usage counter        */
244 	} PluginModule;
245 
246 	/**
247 	 * returns a list with info of all known plugins
248 	 * @todo rename to pluginModuleList
249 	 */
250 	const QList<PluginModule> pluginInfoList() const;
251 
252 	/**
253 	 * Migrate a plugin to the currently active file context (which
254 	 * might be different from the one that is currently executing
255 	 * the plugin). The plugin will be removed from our lists and
256 	 * inserted into the currently active plugin manager instance.
257 	 * @param plugin the plugin to migrate
258 	 */
259 	void migratePluginToActiveContext(Kwave::Plugin *plugin);
260 
261 	/** Let this instance be the active one */
setActive()262 	void setActive() { m_active_instance = this; }
263 
264     signals:
265 
266 	/**
267 	 * Forwards commands to the parent TopWidget execute a command
268 	 */
269 	void sigCommand(const QString &command);
270 
271 	/**
272 	 * Informs all plugins and client windows that we close down
273 	 */
274 	void sigClosed();
275 
276 	/**
277 	 * Informs the plugins that the name of the signal has changed.
278 	 * This might be used to update the caption of a window.
279 	 */
280 	void sigSignalNameChanged(const QString &name);
281 
282 	/**
283 	 * informs about progress, e.g. for showing a message in
284 	 * a splash screen or status bar.
285 	 */
286 	void sigProgress(const QString &message);
287 
288     public slots:
289 
290 	/**
291 	 * Notify all plugins that the signal or file is to be closed
292 	 */
293 	void signalClosed();
294 
295 	/**
296 	 * Called if the name of the current signal has changed. This will be
297 	 * forwarded to all plugins by emitting the signal sigSignalNameChanged.
298 	 * @see sigSignalNameChanged()
299 	 */
300 	void setSignalName(const QString &name);
301 
302     private slots:
303 
304         /**
305          * Will be connected to the plugin's "closed" signal.
306          * @param p pointer to the plugin to be closed
307          */
308         void pluginClosed(Kwave::Plugin *p);
309 
310 	/** called when a plugin has started (running) it's worker thread */
311 	void pluginStarted(Kwave::Plugin *p);
312 
313 	/** called when a plugin has finished it's worker thread */
314 	void pluginDone(Kwave::Plugin *p);
315 
316     private:
317 
318 	/** typedef: QPointer to a Kwave::Plugin */
319 	typedef QPointer<Kwave::Plugin> KwavePluginPointer;
320 
321 	/** typedef: list of pointers to kwave plugins */
322 	typedef QList< KwavePluginPointer > PluginList;
323 
324 	/** typedef: mutable iterator for PluginList */
325 	typedef QMutableListIterator< KwavePluginPointer >
326 	    PluginListMutableIterator;
327 
328 	/** typedef: const iterator for PluginList */
329 	typedef QListIterator< KwavePluginPointer >
330 	    PluginListIterator;
331 
332     private:
333 
334 	/**
335 	 * Creates an instance of a plugin.
336 	 * @param name the name of the plugin (filename)
337 	 * @return pointer to the loaded plugin or zero if the
338 	 *         plugin was not found or invalid
339 	 */
340 	Kwave::Plugin *createPluginInstance(const QString &name);
341 
342 	/**
343 	 * Saves a plugin's default parameters to the user's configuration
344 	 * file. The whole section in the configuration file will be deleted
345 	 * before saving the new settings in order to wipe out invalid
346 	 * entries and settings that belong to an older version.
347 	 * @param name the name of the plugin
348 	 * @param params a list of configuration strings
349 	 */
350 	void savePluginDefaults(const QString &name,
351 	                        QStringList &params);
352 
353 	/** connects all signals of and for a plugin */
354 	void connectPlugin(Kwave::Plugin *plugin);
355 
356 	/** connects all signals from and to a plugin */
357 	void disconnectPlugin(Kwave::Plugin *plugin);
358 
359     private:
360 
361 	/** pointer to the currently active instance */
362 	static Kwave::PluginManager *m_active_instance;
363 
364 	/**
365 	 * map with plugin information: key = short name of the plugin,
366 	 * data = plugin info (description, author, version etc...)
367 	 */
368 	static QMap<QString, PluginModule> m_plugin_modules;
369 
370 	/** list of all plugins that were loaded by this instance */
371 	PluginList m_plugin_instances;
372 
373 	/** list of currently running plugins */
374 	PluginList m_running_plugins;
375 
376 	/** reference to our parent toplevel widget */
377 	QPointer<QWidget> m_parent_widget;
378 
379 	/** reference to our signal manager */
380 	Kwave::SignalManager &m_signal_manager;
381 
382 	/** interface for registering a SignalView */
383 	ViewManager *m_view_manager;
384 
385     };
386 }
387 
388 #endif /* PLUGIN_MANAGER_H */
389 
390 //***************************************************************************
391 //***************************************************************************
392