Plugins for non tag-based modifications (e.g. "Normalize") are also thinkable but not focus of the project. Tags for other types of files (non-audio) may also be provided but are not focus of the project.
Object names should start with a capitol letter. Function/method names and variables will use only lowercase letters.
Types (typedef) should have at least one capitol letter.
class Controller : public SigC::Object { protected: // Prevent copys. Controller(Controller &c) { g_assert_not_reached(); } // Prevent assignments. Controller& operator=(Controller &c) { g_assert_not_reached(); } public: Controller(); ~Controller(); /* Loads the preferences from the configfile. */ int configfile_load(void); /* Saves the preferences to the configfile. */ int configfile_save(void); PluginHandler *pluginhandler; FileInfoManager *fileinfomanager; Preferences *preferences; ConfigFile *configfile; EventBus *eventbus; private: /* Triggers eventbus events and queues the files to the FileInfoManager. */ void on_filelist_selection_changed(void *filenames); /* Whenever a new plugin has been registered, this updates the * FileInfoManager. */ void on_plugins_registered(Plugin *plugin); /* This signal indicates that some file's data needs to be written to the * filesystem. May, for example, be triggered by a plugin when a "save" button * has been pressed. */ void on_filelist_save_request(void *list); /* Emits an eventbus event. */ void emit_file_read_finished_event(FileInfo *info); /* Emits an eventbus event. */ void emit_filenames_read_finished_event(void); /* Emits an eventbus event. */ void emit_preferences_changed_event(std::string key); };
Groups of events are selectable through patterns by the use of wildcards.
It is expected that events will be namespaced. Events emitted by the GUI have "GUI" as their toplevel namespace. E.g.: GUI:Filelist:SelectionChanged, File:Read:Finished, Preferences:Changed, Plugin:Registered, Plugin:Unregistered etc.. The event names need to be specified as a part of the Cantus 3 API too.
Events can be registered either as GClosure, or using a SigC slot.
Event emission is synchronous.
enum EVENTBUS_SIG_TYPES { EVENTBUS_SIG_SIGC, EVENTBUS_SIG_GCLOSURE }; typedef struct { glong id; // A unique identifier for the listener. gboolean invalid; // Whether or not the listener is invalid. const gchar *pattern; // An event pattern (glob). gshort type; // SigC-Slot or Closure? GClosure *closure; // The function (closure) to be called when the event // pattern matches. SigC::Slot1<void, void*> sigcslot; // The function (sigc) to be called when // the event pattern matches. } EventBusListener; class EventBus : public SigC::Object { protected: // Prevent copys. EventBus(EventBus &e) { g_assert_not_reached(); } // Prevent assignments. EventBus& operator=(EventBus &e) { g_assert_not_reached(); } public: EventBus(); ~EventBus(); /* Registers a listener for a specific event pattern; use the returned */ /* id to unregister the listener. */ glong add_listener(const gchar *event_pattern, GClosure *closure); /* Registers a listener for a specific event pattern; use the returned * id to unregister the listener. The function to be called is a SigC slot. */ glong add_listener_sigc(const gchar *event_pattern, SigC::Slot1<void, void*> slot); /* Invalidate the listener with the given id. */ void remove_listener(glong id); /* Unregister all invalid listeners. */ void delete_invalid_listeners(void); /* Emits an event in the bus. */ void emit_event(const gchar *event, const GValue *values); /* Emits an event in the bus, convenience wrapper. */ void emit_event_with_pointer(const gchar *event, gpointer value); /* Emits an event in the bus, convenience wrapper. */ void emit_event_with_char(const gchar *event, const gchar *value); /* Emits an event in the bus, convenience wrapper. */ void emit_event_with_int(const gchar *event, gint value); private: glong idpool; // Holds the id of the listener registered last. GList *listeners; // Holds all listeners. };
Cantus 3 provides the following events:
Filelist:Read:Start Filelist:Read:Finished Filelist:Save:Request File:Read:Finished Preferences:Changed Plugin:Responsibility:Changed GUI:Filelist:Selection:Changed GUI:PluginWidget:Destroyed
This object holds two data structures (hashes): One representing the file as its contents currently are (refered to as the "real hash") (e.g. the current tag fields), while a second structure holds the same information as it is currently being edited (refered to as the "edited hash").
In addition, this object holds a history of the structure, needed for the "Undo" process, plus a future of the structure, needed for the "Redo" process.
The hash key names should be namespaced, e.g. ID3V2:DCOM, File:Name etc..
The object guarantees to be threadsafe.
class FileInfo { protected: // Prevent copies. FileInfo(FileInfo &f) { g_assert_not_reached(); } // Prevent assignments. FileInfo& operator=(FileInfo &s) { g_assert_not_reached(); } public: /* Triggered whenever a file has been read. */ SigC::Signal1<void, FileInfo*> signal_read_finished; /* Triggered whenever a file has been written. */ SigC::Signal1<void, FileInfo*> signal_write_finished; /* The filename is being stored in the real hash and the edited hash as * well. */ FileInfo(const gchar *filename); ~FileInfo(); /* Returns the inode number of the file, or < 0 on an error. */ glong get_inode(void); /* Read all file informations into the real hash using the given Input * Plugin. * Returns an errorcode or 0. */ gint read(const ReadFunc func); /* Write all file informations from the real hash to the filesystem, using * the given output plugin. * Returns an errorcode or 0. */ gint write(const WriteFunc func); /* Returns a pointer to the file's "edited_hash". Make sure to "lock()" when * you do this! */ CantusHash *get_edited_hash(void); /* Lock the object from being accessed. */ void lock(void); /* Unlock the object so that it can be accessed. */ void unlock(void); /* Returns the filename from the real hash. Make sure to lock() before you * use this! */ const gchar *get_filename(void); /* Returns the filename from the edited hash. Make sure to lock() before you * use this! */ const gchar *get_edited_filename(void); /* Move the "real hash" onto an "UNDO" stack. Then, copy the edited hash into * the new real hash. Also, clear the "REDO" stack. */ void commit(void); /* Copy the real hash into the edited hash. */ void revert(void); /* Push the edited hash onto the "REDO" stack. Then, pop the last item from * the "UNDO" stack into the edited hash. * Returns FALSE when the "UNDO" list was empty so nothing has been changed. */ gboolean undo(void); /* Push the edited hash onto the "UNDO" stack. Then, pop the last item from * the "REDO" stack into the edited hash. * Returns FALSE when the "REDO" list was empty so nothing has been changed. */ gboolean redo(void); private: /* Push something to the history (for UNDO). */ void history_push(CantusHash *hash); /* Get something from the history (for UNDO). */ CantusHash *history_pop(void); /* Get something to the future (for REDO). */ void future_push(CantusHash *hash); /* Get something from the future (for REDO). */ CantusHash *future_pop(void); /* Clear the future (for REDO). */ void future_clear(void); CantusHash *real_hash; // The file's data as on the filesystem. CantusHash *edited_hash; // The file's data as edited. std::list<CantusHash *> history; // The history of the data for UNDO. std::list<CantusHash *> future; // The future of the data for REDO. Glib::Mutex mutex; // One mutex to lock the whole object. };
The FileInfoManager is implemented using glibmm's thread implementations, having (in addition to the main thread) two worker threads: One writer thread and one reader thread, both locking each other. The signals sent by the worker threads must be emitted by the main thread, because the GUI toolkit is not threadsafe. Thus, an (asynchronous) dispatcher sends a signal to the main thread, which is emitting the standard GSignal.
Caching is done by hashing the filename to the inode number and the inode number to the file's data.
Since the FileInfoManager also needs to trigger the read() function of the FileInfo object, it needs to know which plugins to invoke. Thus, it holds a list of all Plugins available.
class FileInfoManager : public SigC::Object { protected: // Prevent copies. FileInfoManager(FileInfoManager &f) { g_assert_not_reached(); } // Prevent assignments. FileInfoManager& operator=(FileInfoManager &f) { g_assert_not_reached(); } public: FileInfoManager(); ~FileInfoManager(); /* Triggered whenever a file has been read. */ SigC::Signal1<void, FileInfo*> signal_file_read_finished; /* Triggered whenever a file could not be read (e.g. wrong permissions). */ SigC::Signal1<void, FileInfo*> signal_file_read_failed; /* Triggered whenever a file has been written. */ SigC::Signal1<void, FileInfo*> signal_file_write_finished; /* Triggered whenever a file could not be written (e.g. wrong permissions). */ SigC::Signal1<void, FileInfo*> signal_file_write_failed; /* Triggered whenever a file could not be renamed. (e.g. file exists). */ SigC::Signal1<void, FileInfo*> signal_file_rename_failed; /* Triggered whenever the read queue has been finished. */ SigC::Signal0<void> signal_queue_read_finished; /* Triggered whenever the write queue has been finished. */ SigC::Signal0<void> signal_queue_write_finished; /* Stores a copy of the pluginlist in the object. * This is required because the object invokes the FileInfo read function, * which needs a plugin as an argument. */ void register_plugins(std::list<Plugin*> *pluginlist); /* Replaces the list of files that still need to be read. (read queue) * (filenames == NULL is allowed). */ void readqueue_set(GList *filenames); /* Clear the read queue. (=Abort read). */ void readqueue_clear(void); /* Appends stuff to the list of files that still need to be * written. (write queue) */ void writequeue_append(GList *filenames); /* Clear the write queue. (=Abort write) */ void writequeue_clear(void); /* This function locks the fileinfo object with the given name and returns * the hash containing all file data from the fileinfo object. * The FileInfo object will remain locked, so make sure to unlock!! */ CantusHash *get_info_locked(const gchar *filename); /* Unlocks the FileInfo object with the given name. */ void unlock(const gchar *filename); /* Returns the progress in percent as a float. */ float get_progress(void); private: /* Unregisters all plugins. */ void unregister_plugins(void); /* A worker thread doing all read operations. */ void reader_func(void); /* A worker thread doing all write operations. */ void writer_func(void); /* Receives one fileinfo object from the cache. If the item is not in the * cache yet, it will try to read it using all apropriate plugins. */ FileInfo *read(const gchar *filename); /* Receives one fileinfo object from the cache. If the item is not in the * cache yet, read it. Then try to write it using all apropriate plugins. */ void write(gint inode); /* Checks whether the filename has been edited and renames the file. * Returns TRUE on success, FALSE otherwise. */ gboolean try_rename(FileInfo *info); /* This dispatcher is called via an asynchronous pipe. * Once called, it emits all queued events via a synchronous SigC signal. */ void signal_dispatcher(void); Glib::Mutex mutex; // One mutex for parent, reader and writer. Glib::Cond readcond; // Pushed whenever there is something to read. Glib::Cond writecond; // Pushed whenever there is something to write. gboolean stopthreads; // When true, the threads will terminate themself. Glib::Thread *reader; // The reader_func() thread. Glib::Thread *writer; // The writer_func() thread. std::deque<FileInfoManagerEvent*> eventqueue; // The event-dispatcher's queue. Glib::Dispatcher signal_dispatch; // Triggered asynchronously to // call the dispatcher. std::list<Plugin*> *plugins; // A list of all available plugins. std::deque<const gchar *> readqueue; // The read queue (list of filenames). std::deque<glong> writequeue; // The write queue (list of inodes). // A hash mapping filename to inode. __gnu_cxx::hash_map<std::string, glong> inodemap; // A hash mapping inode to FileInfo object. __gnu_cxx::hash_map<glong, FileInfo*> cache; int queued_read; // The number of files currently queued for reading. int processed_read; // The number of files read. int queued_write; // The number of files currently queued for writing. int processed_write; // The number of files written. };
class Preferences : public SigC::Object { protected: // Prevent copys. Preferences(Preferences &p) { g_assert_not_reached(); } // Prevent assignments. Preferences& operator=(Preferences &p) { g_assert_not_reached(); } public: Preferences(void); ~Preferences(void); /* Triggered whenever something has been changed. */ SigC::Signal1<void, std::string> signal_changed; /* Tests all edited preferences for sanity. */ bool check_commit(void); /* Tests the preference with the given key for sanity. */ bool check_commit(std::string key); /* Confirms all preferences. This also triggers a Preferences:Changed event. */ bool commit(void); /* Confirms the preference with the given key. This also triggers a * Preferences:Changed event. */ bool commit(std::string key); /* Set one preference value. Returns always TRUE. */ bool set(std::string key, int type, void *value); /* Set one preference value (integer). */ void set_int(std::string key, int value); /* Get one preference value (int). */ int get_int(std::string key); /* Set one preference value (boolean). */ void set_bool(std::string key, bool value); /* Get one preference value (char). */ bool get_bool(std::string key); /* Set one preference value (char). */ void set_char(std::string key, std::string value); /* Get one preference value (char). */ std::string get_char(std::string key); /* Walks through all preferences calling the given slot. * Args passed to the slot are: The preference name, type (e.g. G_TYPE_INT) * and its value. * If the slot returns FALSE, list evaluation will be stopped. */ void foreach(SigC::Slot3<bool, std::string, int, void*> slot); protected: std::map<std::string, CantusHashValue*> prefs; std::map<std::string, CantusHashValue*> editedprefs; };
class ConfigFile : public SigC::Object { public: ConfigFile(); ~ConfigFile(); /* Defines which file to read/write from. */ void set_filename(std::string newfilename); /* Check, whether or not the file exists and is read-/writable. * Returns 0 if the file is read/writeable. * -1 if no filename has been set yet or the file does not exist. * -2 if the file is not readable. * -3 if the file is not writeable. */ int check(void); /* This function opens the configfile and saves all option/value pairs in the * given map. Returns an errorcode, or 0 on success. */ int load(void); /* This function writes the configfile contents from the memory to the * configfile. Returns an errorcode, or 0 on success. */ int save(void); /* Clear the configfile content (only in the memory). */ void clear(void); /* Appends one key/value pair to the configfile (only in the memory). * Args passed to the method are: The key name, the value type (e.g. * G_TYPE_INT) and the value. * Returns always TRUE. */ bool append(std::string key, int type, void *value); /* Walks through all lines of the file, passing every option to the slot. * Args passed to the slot are: The key name, the value type (e.g. * G_TYPE_INT) and the value. */ void foreach_line(SigC::Slot3<bool, std::string, int, void*> slot); protected: /* Given one line of a file, this function returns the extracted key/value * pair. */ std::pair<std::string, std::string> get_pair(const gchar *pline); /* Given one value string, this function extracts the value in the right data * type. */ std::pair<int, void*> grab_value(std::string value); std::list<std::pair<std::string, std::string> > content; // The file content. std::string filename; // The file name. };
The plugin can set several options (like its name etc.) by filling the C-compatible hash passed to its initializer.
class Plugin : public SigC::Object { public: Plugin(); ~Plugin(); /* Triggered directly before the plugin will be deleted (= when the */ /* refcounter has reached a value <= 0). */ SigC::Signal1<void, Plugin*> signal_plugin_deleted; /* Loads a plugin and all its symbols into the object. */ gint load(const gchar *filename); /* Increase a plugin's refcounter. When the refcounter is <= 0 the plugin will * be unloaded. On object creation, the refcounter is 1. */ void ref(void); /* Decrease a plugin's refcounter. */ void unref(void); /* Define the plugin's priority. */ void set_priority(gint priority); /* Returns the plugin's priority. */ gint get_priority(void); /* Returns the plugin name. */ const gchar *get_name(void); /* Returns the name of the tags handled by this plugin. */ const gchar *get_tagname(void); /* Returns the title for the plugin's notebook tab label. */ const gchar *get_label(void); /* Returns the the plugin description (should be 200 chars max.). */ const gchar *get_description(void); /* Returns the plugin's major version number. */ gint get_majorversion(void); /* Returns the plugin's minor version number. */ gint get_minorversion(void); /* Returns a function pointer to the plugin's read() function. */ const ReadFunc get_readfunc(void); /* Returns a function pointer to the plugin's write() function. */ const WriteFunc get_writefunc(void); /* Calls the plugin's uiwidget() function. */ void *get_uiwidget(gboolean vertical); /* Given a file name, this function returns TRUE if the plugin is responsible * for handling this filetype, otherwise FALSE. */ gboolean handles(const gchar *filename); private: /* Checks, whether the plugin meets all mandatory requirements. Returns TRUE * if the plugin is valid, otherwise FALSE. */ gboolean check_plugin(void); void *dlhandle; // The handle for dl_open. CantusHash *plugindata; // A pointer to the C-compatible plugin data. gint refct; // A refcounter indicating whether the plugin is // still needed. gint priority; // A priority, to be used by the backend only. };
Plugins are stored in two maps: One map is mapping filename to plugin, while the second hash is ordered by a numerical id to provide a priority mechanism.
class PluginHandler : public SigC::Object { protected: // Prevent copys. PluginHandler(PluginHandler &p) { g_assert_not_reached(); } // Prevent assignments. PluginHandler& operator=(PluginHandler &p) { g_assert_not_reached(); } public: PluginHandler(); ~PluginHandler(); /* Triggered whenever a plugin has successfully been loaded. */ SigC::Signal1<void, Plugin*> signal_plugin_loaded; /* Triggered whenever a plugin has been removed (= when the refcounter has */ /* been decreased). */ SigC::Signal1<void, Plugin*> signal_plugin_removed; /* Triggered straight before a plugin is being deleted (= when the */ /* refcounter has reached a value <= 0). */ SigC::Signal1<void, Plugin*> signal_plugin_deleted; /* Register a new input plugin. * Returns 0 on success, an errorcode < 0 otherwise. * Emits the Plugin::Registered signal. */ gint reg(const gchar *filename, gint priority); /* Unregister an input plugin (=decrease the plugin's refcounter). * Emits the Plugin::Unregistered signal. */ void unreg(const gchar *filename); /* Return an std::list of all plugins responsible for the given file type. * Don't forget to delete the list AND UNREF EVERY PLUGIN!! */ std::list<Plugin*> *get_responsible_plugins(const gchar *filename); /* Given a list of filenames, this function returns a std::list of all * responsible plugins for the given filetypes. * Don't forget to delete the list AND UNREF EVERY PLUGIN!! */ std::list<Plugin*> *get_responsible_plugins_from_list(GList *filenames); /* This function returns a list of all plugins. Don't forget to delete the * list AND UNREF EVERY PLUGIN!! */ std::list<Plugin*> *get_plugins(void); protected: // Holds mappings between plugin filenames and "Plugin" objects. std::map<std::string, Plugin*> plugins_str; std::map<int, Plugin*> plugins_int; };
class Mainwindow : public SigC::Object { public: Mainwindow(); ~Mainwindow(); /* Triggered whenever the filebrowser selection changed. * The GList contains a list of all filenames currently selected. * Warning: The GList is only valid for the duration of the signal. */ SigC::Signal1<void, GList*> signal_filebrowser_selection_changed; /* Triggered whenever the "save" menu has been activated. */ SigC::Signal0<void> signal_menu_file_save_activate; /* Triggered whenever the "preferences" item has been clicked. */ SigC::Signal0<void> signal_menu_edit_preferences_activate; /* Triggered whenever the pluginarea1 visibility changed. */ SigC::Signal1<void, gboolean> signal_pluginarea1_visibility_changed; /* Triggered whenever the pluginarea2 visibility changed. */ SigC::Signal1<void, gboolean> signal_pluginarea2_visibility_changed; /* Triggered whenever a widget has been removed from any pluginarea. */ SigC::Signal1<void, Plugin*> signal_pluginarea_widget_removed; /* Builds the complete mainwindow. */ Gtk::Window *create(void); /* Update the plugins to be shown in the pluginarea. */ void pluginarea_update(std::list<Plugin*> *plugins); /* Updates the progressbar. */ void set_progress(double percent); /* Make the pluginarea visible or invisible. */ void pluginarea1_set_active(gboolean active); /* Make the pluginarea visible or invisible. */ void pluginarea2_set_active(gboolean active); FileBrowser *filebrowser; private: void connect_signals(void); void on_menu_help_about_activate(void); void on_menu_view_pluginarea1_activate(void); void on_menu_view_pluginarea2_activate(void); Glib::RefPtr<Gnome::Glade::Xml> refXml; gboolean lockevents; Gtk::Window *pwindow; Gtk::Viewport *viewport; Gtk::Table *table; Gtk::ProgressBar *progressbar; Gtk::HPaned *hpaned; Gtk::Notebook *notebook; PluginArea *pluginarea1; PluginArea *pluginarea2; AboutBox *aboutbox; };
class PluginArea : public Gtk::Notebook { public: PluginArea(gboolean is_vertical); ~PluginArea(); /* Triggered whenever a widget has been removed. */ SigC::Signal1<void, Plugin *> signal_widget_removed; // Operates on single plugins. void plugin_attach(Plugin *plugin); void plugin_remove(Plugin *plugin); gboolean plugin_is_visible(Plugin *plugin); // Operates on a list of plugins. void plugins_set(std::list<Plugin*> *plugins); void plugins_attach(std::list<Plugin*> *plugins); void plugins_remove(std::list<Plugin*> *plugins); protected: std::map<Plugin*, Gtk::Widget*> visibleplugins; gboolean vertical; // Whether or not the plugin is shown in vertical pos. void remove_unneeded(std::list<Plugin*> *required); gboolean in_list(Plugin *plugin, std::list<Plugin*> *required); };
class FileBrowser : public Gtk::HPaned { public: FileBrowser(); ~FileBrowser(); /* Triggered when the filelist selection has changed. */ SigC::Signal1<void, GList*> signal_filelist_selection_changed; /* Jump to the given directory. */ void set_dir(std::string dir); /* Specify a list of patterns that represent filenames to be shown in the * filelist. */ void set_filepattern(const gchar **pfilepattern); /* Specify a comma-sperated list of patterns that represent filenames to be * shown in the filelist. */ void set_filepattern(std::string str); /* Specify whether or not hidden files and directories should be visible. */ void set_showhidden(gboolean show_hidden); /* Manually trigger a re-read of the current directory. */ void update(void); private: void _on_dirtree_row_activated( const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn *column); void _on_dirtree_row_expanded( const Gtk::TreeModel::iterator& iter, const Gtk::TreeModel::Path& path); void _on_dirtree_row_collapsed( const Gtk::TreeModel::iterator& iter, const Gtk::TreeModel::Path& path); void _on_dirtree_selection_changed(void); void _on_filelist_selection_changed(void); Gtk::TreeView *dirtree_view; GtkTreeStore *dirtree; Gtk::TreeView *filelist_view; GtkListStore *filelist; std::string curdir; const gchar **filepattern; std::string filepattern_str; gboolean showhidden; };
class AboutBox : public Gtk::Dialog { public: AboutBox(); ~AboutBox(); void create(void); protected: Gtk::Image *image; };
class PreferencesWindow : public SigC::Object { public: PreferencesWindow(std::string gladefile, std::string gladedomain); ~PreferencesWindow(); /* Triggered whenever the CLOSE button has been clicked. */ SigC::Signal0<void> signal_button_close_clicked; /* Triggered whenever any preference has been changed. */ /* Emits the preference name, type (e.g. G_TYPE_BOOL) and its value. */ SigC::Signal3<void, std::string, gint, void *> signal_preference_changed; /* Make the window visible. If it does not exist yet, it will be created. */ void show(void); /* Hide the window. */ void hide(void); /* Updates one widget according to the given value. */ bool update_widget(std::string name, int type, void *value); private: /* Builds the complete preferences window and makes it visible. */ void create(void); /* Adds all categories by iterating through the notebook tab labels. */ void fill_tree(void); /* Connects all signals. */ void connect_signals(void); /* Callback handler, triggered whenever another preferences category has been * selected. */ void on_preftree_selection_changed(Gtk::TreeIter iter); /* Callback handler, triggered whenever the "close" button has been clicked. */ void on_button_close_clicked(void); /* Callback handler, triggered whenever any of the preferences has been * edited. */ void on_widget_changed(Gtk::Widget *widget); /* Given a container, this function returns a list of all children. * Other than "Gtk::Object::get_children()", this function works recursive. */ void get_children_recursive( Gtk::Container *container, std::list<Gtk::Widget*> *children); Glib::RefPtr<Gnome::Glade::Xml> refXml; // Glade's XML-structure. std::string glade_file; // The .glade filename. std::string glade_domain; // The .glade file domain. Gtk::Window *window; // The toplevel window. Gtk::Notebook *notebook; // The notebook holding prefs. Gtk::Viewport *viewport; // Preftree parent. PreferencesTree preftree; // Preftree. };
class PreferencesTree : public Gtk::TreeView { public: PreferencesTree(); ~PreferencesTree(); /* Triggered whenever an item has been selected. */ SigC::Signal1<void, Gtk::TreeIter> signal_selection_changed; /* Add a category with an icon. */ void add(std::string catname, std::string pixmapfile); private: void on_selection_changed(void); // List model columns. class ModelColumns : public Gtk::TreeModel::ColumnRecord { public: //Gtk::TreeModelColumn<Glib::RefPtr<Gdk::Pixbuf> > pixbuf; Gtk::TreeModelColumn<Glib::ustring> caption; ModelColumns() { //add(pixbuf); add(caption); } }; Glib::RefPtr<Gtk::ListStore> store; Gtk::CellRendererText renderer_text; ModelColumns columns; };
class GUIController : public SigC::Object { protected: // Prevent copys. GUIController(GUIController &c) { g_assert_not_reached(); } // Prevent assignments. GUIController& operator=(GUIController &c) { g_assert_not_reached(); } public: GUIController(); ~GUIController(); void init(void); private: void on_preferences_preference_changed(std::string key, gint type, void *data); void on_menu_file_save_clicked(void); void on_menu_edit_preferences_clicked(void); void on_preferences_changed(void *key); void on_plugin_responsibility_changed(void *data); void on_filebrowser_selection_changed(GList *selection); void on_pluginarea_widget_removed(Plugin *plugin); void on_pluginarea1_visibility_changed(gboolean visible); void on_pluginarea2_visibility_changed(gboolean visible); bool on_progressbar_update_poll(void); PreferencesWindow *preferences; bool lock_on_preferences_changed; };
Plugins can be written in C++ and C as well. Thus, the initializer arguments (including the function pointers) are passed in a C-compatible g_hash_table. Plugins store their name (and other specifications) in that hash during the initialisation so that the engine is informed.
Beneath the initializer (InitFunc) and the destroyer (DestroyFunc) there are optional symbols that the plugin can supply. Refer to the list below.
// Functions provided by plugins. typedef void *(*AnyFunc) (void); typedef gint (*InitFunc) (CantusHash *specs); typedef gint (*DestroyFunc) (void); typedef gboolean (*HandlesFunc) (const gchar *filename); typedef gint (*ReadFunc) (const gchar *filename, CantusHash *data); typedef gint (*WriteFunc) (const gchar *filename, CantusHash *data); typedef void *(*UIPrefsFunc) (void); typedef void *(*UIWidgetFunc) (gboolean vertical); typedef void *(*UIIconFunc) (void); // EventBus functions, provided by Cantus. typedef void *(*CantusPrefGetFunc) (const gchar *); // FIXME. typedef glong (*CantusAddListenerFunc) (const gchar *, GClosure *); #ifdef _CPLUSPLUS_ typedef glong (*CantusAddListenerSigCFunc)(const gchar *, SigC::Slot1<void, void*>); #endif typedef glong (*CantusRemoveListenerFunc) (glong id); typedef glong (*CantusEmitFunc) (const gchar *, const GValue *); // Preferences functions, provided by Cantus. typedef void (*CantusPrefSet_intFunc) (const gchar *key, gint value); typedef gint (*CantusPrefGet_intFunc) (const gchar *key); typedef void (*CantusPrefSet_boolFunc) (const gchar *key, gboolean value); typedef gboolean (*CantusPrefGet_boolFunc) (const gchar *key); typedef void (*CantusPrefSet_charFunc) (const gchar *key, const gchar *value); typedef const gchar* (*CantusPrefGet_charFunc) (const gchar *key); // FileInfoManager functions, provided by Cantus. typedef CantusHash *(*CantusFileInfoGetFunc) (const gchar *filename); typedef void (*CantusFileInfoUnlockFunc)(const gchar *filename);
Current Revision: 1.0