Shotwell Plugins, Part I – Setup

Here’s a quick overview on how to start writing a custom publishing plugin. This is being done on Ubuntu 14.04, so no promises it will function on any other version.

  1. Install valac-0.22, libgphoto2-dev, gnome-doc-utils,libgstreamer-plugins-base1.0-dev, libgee-0.8-dev libsqlite3-dev libraw-dev librest-dev libwebkitgtk-3.0-dev libgexiv2-dev libgudev-1.0-dev libgtk-3-dev libjson-glib-dev
  2. Download the shotwell 0.20.2 sources and not the current version from github. The current version in get uses some new gtk features which are not available in ubuntu 14.04.
  3. Copy the shotwell/samples/simple-plugin from the shotwell git repo to a new directory
  4. Build/install shotwell 0.20
    $ ./configure --install-headers
    $ sudo make -j6 install

     

  5. In your new plugin, run ‘make; make install’ to ensure the basic build works.
  6. Rename simple-plugin.vala to your publishing plugin name (ie, OnedrivePublishing.vala)
  7. Modify the Makefile and set the PROGRAM to your plugin name (ie, OnedrivePublishing)
  8. Running make should compile your new empty plugin.

Now that that’s done we can start creating out publishing plugin.

The plugin sample implements the Spit.Pluggable interface, in order to create a publishing plugin, we’ll need to use that to return our publishing module and create a new class to implement the Spit.Pluggable and Spit.Publishing.Service interface as well. Rename that class and include all the necessary interfaces. We’ll use the ShotwellPublishingCoreServices as a template for how to bootstrap out publishing service.

The basic do-nothing module which compiles w/ one warning (the return null) now contains the following:

extern const string _VERSION;
private class OnedriveModule : Object, Spit.Module {
    private Spit.Pluggable[] pluggables = new Spit.Pluggable[0];

    public OnedriveModule() {
        pluggables += new OnedriveService();
    }
    
    public unowned string get_module_name() {
        return _("OneDrive Publishing Services");
    }
    
    public unowned string get_version() {
        return _VERSION;
    }
    
    public unowned string get_id() {
        return "org.yorba.shotwell.publishing.onedrive";
    }
    
    public unowned Spit.Pluggable[]? get_pluggables() {
        return pluggables;
    }
}
// This is our new publishing class
private class OnedriveService : Object, Spit.Pluggable, Spit.Publishing.Service {
        

    public OnedriveService() {
    }

    public unowned string get_id() {
        return "org.yorba.shotwell.publishing.onedrive";
    }
    
    public Spit.Publishing.Publisher.MediaType get_supported_media() {
        return (Spit.Publishing.Publisher.MediaType.PHOTO |
            Spit.Publishing.Publisher.MediaType.VIDEO);
    }
    public Spit.Publishing.Publisher create_publisher(Spit.Publishing.PluginHost host) {
        //TODO
        return null;
    }

    public void get_info(ref Spit.PluggableInfo info) {
        info.authors = "Mike Smorul";
        info.version = _VERSION;
        info.is_license_wordwrapped = false;
        
    }    
    public unowned string get_pluggable_name() {
        return "OneDrive";
    }

    public int get_pluggable_interface(int min_host_interface, int max_host_interface) {
        return Spit.negotiate_interfaces(min_host_interface, max_host_interface,
            Spit.Publishing.CURRENT_INTERFACE);
    }
    
    public void activation(bool enabled) {
    }
}
// This entry point is required for all SPIT modules.
public Spit.Module? spit_entry_point(Spit.EntryPointParams *params) {
    params->module_spit_interface = Spit.negotiate_interfaces(params->host_min_spit_interface,
        params->host_max_spit_interface, Spit.CURRENT_INTERFACE);

    return (params->module_spit_interface != Spit.UNSUPPORTED_INTERFACE)
        ? new OnedriveModule() : null;
}

private void dummy_main() {
}

You can now compile this by:

$ make clean; make ; make install

This will install your new module into your local modules directory. To make sure it works, open up shotwell, go to Edit -> Preferences -> Plugins and you should see your new plugin listed under the Publishing section with a generic graphic next to it. If you enable the module you’ll notice the following error that will be fixed when we start implementing functionality

 GSettingsEngine.vala:457: GSettingsConfigurationEngine: error: schema 'org.yorba.shotwell.plugins.enable-state' does not define key 'publishing-onedrive'

Useful Links