Commit fbecc673 authored by Yuanle Song's avatar Yuanle Song
Browse files

v0.4.0 renamed dbus services; use code gen.

parent 0816351b
Loading
Loading
Loading
Loading
+30 −0
Original line number Diff line number Diff line
<!DOCTYPE node PUBLIC
"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd" >
<node>
  <interface name="com.emacsos.zero.ZeroPinyinService1.ZeroPinyinServiceInterface">
    <!--
	GetCandidates:
	@preedit_str: the preedit string
	@fetch_size: how many candidates to fetch
	@candidates: the candidates
	@matched_preedit_str_lengths: the matched str length in preedit str for
	                              each candidate

	Get candidates for a preedit string. This method will fetch at least
	fetch_size candidates if they exists. However, this method is allowed to
	return more candidates than fetch_size.

    -->
    <method name="GetCandidates">
      <arg type="s" name="preedit_str"/>
      <arg type="u" name="fetch_size"/>
      <arg type="as" name="candidates" direction="out"/>
      <arg type="au" name="matched_preedit_str_lengths" direction="out"/>
    </method>

    <method name="Quit"/>

    <annotation name="org.gtk.GDBus.C.Name" value="ZeroPinyinService"/>
  </interface>
</node>
+1 −1
Original line number Diff line number Diff line
[D-BUS Service]
Name=com.emacsos.zero.ZeroPinyinService
Name=com.emacsos.zero.ZeroPinyinService1
Exec=/home/sylecn/bin/sbin/zero-pinyin-service
+66 −156
Original line number Diff line number Diff line
#include <gio/gio.h>
#include <glib-unix.h>
#include "zero-pinyin-service.h"
#include "zero-pinyin-service-generated.h"
#include "../sqlite3_util.h"
#include <sqlite3.h>

typedef struct {
	GApplication *app;
	GDBusNodeInfo *introspection_data;
	guint owner_id;
	ZeroPinyinService *interface;
	sqlite3 *db;
	gboolean init_done;
} AppData;

static AppData appdata;

static const gchar introspection_xml[] =
  "<node>"
  "  <interface name='com.emacsos.zero.ZeroPinyinService'>"
  "    <method name='GetCandidates'>"
  "      <arg type='s' name='preedit_str'/>"
  "      <arg type='u' name='fetch_size'/>"
  "      <arg type='as' name='candidates' direction='out'/>"
  "      <arg type='au' name='matched_preedit_str_lengths' direction='out'/>"
  "    </method>"
  "    <method name='Quit'/>"
  "  </interface>"
  "</node>";

static void
handle_method_get_candidates (GDBusMethodInvocation *invocation,
			      AppData *appdata,
			      GVariant *parameters)
static gboolean
on_handle_get_candidates (ZeroPinyinService *object,
			  GDBusMethodInvocation *invocation,
			  const gchar *preedit_str,
			  guint fetch_size,
			  AppData *appdata)
{
	gchar *preedit_str = NULL;
	guint fetch_size = 0;
	GVariant *result = NULL;
	GVariantBuilder *candidates_builder = NULL;
	GVariantBuilder *matched_lengths_builder = NULL;

	g_variant_get (parameters, "(su)", &preedit_str, &fetch_size);
	g_return_if_fail (preedit_str != NULL);
	g_return_if_fail (fetch_size > 0);
	if (preedit_str == NULL || fetch_size == 0) {
		g_dbus_method_invocation_return_dbus_error (
			invocation,
			"org.gtk.GDBus.Failed",
			"Bad param");
		if (preedit_str)
			g_free (preedit_str);
		return;
		return TRUE;
	}

	g_message ("get_candidates for preedit_str=%s fetch_size=%u",
		   preedit_str, fetch_size);

	candidates_builder = g_variant_builder_new (G_VARIANT_TYPE ("as"));
	matched_lengths_builder = g_variant_builder_new (G_VARIANT_TYPE ("au"));
	GVariant *result = NULL;
	GVariantBuilder *candidates_builder = NULL;
	GVariantBuilder *matched_lengths_builder = NULL;

        /* test data */
	/* get_candidates_test (preedit_str, fetch_size, candidates_builder, matched_lengths_builder); */
	candidates_builder = g_variant_builder_new (G_VARIANT_TYPE ("as"));
	matched_lengths_builder = g_variant_builder_new (G_VARIANT_TYPE ("au"));
	get_candidates (appdata->db, preedit_str, fetch_size, candidates_builder, matched_lengths_builder);

	result = g_variant_new ("(asau)", candidates_builder, matched_lengths_builder);
@@ -69,102 +47,51 @@ handle_method_get_candidates (GDBusMethodInvocation *invocation,

	g_variant_builder_unref (candidates_builder);
	g_variant_builder_unref (matched_lengths_builder);
	g_free (preedit_str);
}

static void
handle_method_call (GDBusConnection       *connection,
                    const gchar           *sender,
                    const gchar           *object_path,
                    const gchar           *interface_name,
                    const gchar           *method_name,
                    GVariant              *parameters,
                    GDBusMethodInvocation *invocation,
                    gpointer               user_data)
{
	AppData *appdata;
	gchar *errmsg = NULL;

	appdata = (AppData*) user_data;

	g_message ("got method call: %s", method_name);
	if (g_strcmp0 (method_name, "GetCandidates") == 0) {
		handle_method_get_candidates (invocation, appdata, parameters);
	} else if (g_strcmp0 (method_name, "Quit") == 0) {
		g_application_quit (appdata->app);
	} else {
		g_warning ("method not found: %s", method_name);

		errmsg = g_strdup_printf ("Method not found: %s", method_name);
		g_dbus_method_invocation_return_dbus_error (
			invocation,
			"org.gtk.GDBus.Failed",
			errmsg);
		g_free (errmsg);
	}
}

static GVariant *
handle_get_property (GDBusConnection  *connection,
                     const gchar      *sender,
                     const gchar      *object_path,
                     const gchar      *interface_name,
                     const gchar      *property_name,
                     GError          **error,
                     gpointer          user_data)
{
	return NULL;
	return TRUE;
}

static gboolean
handle_set_property (GDBusConnection  *connection,
                     const gchar      *sender,
                     const gchar      *object_path,
                     const gchar      *interface_name,
                     const gchar      *property_name,
                     GVariant         *value,
                     GError          **error,
                     gpointer          user_data)
on_handle_quit (ZeroPinyinService *object,
		GDBusMethodInvocation *invocation,
		AppData *appdata)
{
	g_application_quit (appdata->app);
	return TRUE;
}

static const GDBusInterfaceVTable interface_vtable = {
	handle_method_call,
	handle_get_property,
	handle_set_property
};

static void
on_bus_acquired (GDBusConnection *connection,
		 const gchar *name,
		 gpointer user_data)
{
	AppData *appdata = NULL;
	AppData *appdata = (AppData*) user_data;
	GError *err = NULL;
	guint registration_id = 0;
	static const gchar* object_path = "/com/emacsos/zero/ZeroPinyinService";

	g_message ("on_bus_acquired() name=%s", name);
	appdata = (AppData*) user_data;
	registration_id = g_dbus_connection_register_object (

	appdata->interface = zero_pinyin_service_skeleton_new ();
	g_signal_connect (appdata->interface,
			  "handle-get-candidates",
			  G_CALLBACK (on_handle_get_candidates),
			  appdata);
	g_signal_connect (appdata->interface,
			  "handle-quit",
			  G_CALLBACK (on_handle_quit),
			  appdata);
	g_dbus_interface_skeleton_export (
		G_DBUS_INTERFACE_SKELETON (appdata->interface),
		connection,
		object_path,
		appdata->introspection_data->interfaces[0],
		&interface_vtable,
		appdata,  /* user_data */
		NULL,  /* user_data_free_func */
		&err); /* GError** */
	if (err != NULL) {
		g_warning ("object register failed: %s. exiting now", err->message);
		ZERO_PINYIN_OBJECT_PATH,
		&err);
	if (err) {
		g_warning ("export interface at %s failed: %s",
			   ZERO_PINYIN_OBJECT_PATH, err->message);
		g_error_free (err);
		g_application_quit (appdata->app);
		g_application_quit (G_APPLICATION (appdata->app));
		return;
	}
	if (registration_id > 0) {
		g_message ("object registered at %s", object_path);
	}
	g_assert_cmpint (registration_id, >, 0);
	g_message ("interface exported at %s", ZERO_PINYIN_OBJECT_PATH);
}

static void
@@ -186,11 +113,9 @@ on_name_lost (GDBusConnection *connection,
static void
config_dbus_service (AppData *appdata)
{
	appdata->introspection_data = g_dbus_node_info_new_for_xml (
		introspection_xml, NULL);
	g_assert (appdata->introspection_data != NULL);
	appdata->owner_id = g_bus_own_name (G_BUS_TYPE_SESSION,
					    "com.emacsos.zero.ZeroPinyinService",
	appdata->owner_id = g_bus_own_name (
		G_BUS_TYPE_SESSION,
		ZERO_PINYIN_WELL_KNOWN_NAME,
		G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT|G_BUS_NAME_OWNER_FLAGS_REPLACE,
		on_bus_acquired,
		on_name_acquired,
@@ -211,6 +136,9 @@ on_sigterm_received (gpointer user_data)
	return G_SOURCE_REMOVE;
}

/**
 * init appdata->db
 */
static void
config_db (AppData* appdata)
{
@@ -253,18 +181,6 @@ db_fail:
	appdata->db = NULL;
}

static void
zero_pinyin_service_init (GApplication *app,
			  AppData *appdata)
{
	appdata->introspection_data = NULL;
	appdata->owner_id = 0;
	appdata->db = NULL;
	config_dbus_service (appdata);
	config_db (appdata);
	appdata->init_done = TRUE;
}

/**
 * allow graceful shutdown by Ctrl-C and SIGTERM.
 */
@@ -284,27 +200,25 @@ setup_sigint_sigterm_handler (AppData *appdata)
}

static void
startup (GApplication* app,
on_startup (GApplication* app,
	    AppData* appdata)
{
	g_message ("zero-pinyin-service startup()");
	config_db (appdata);
	config_dbus_service (appdata);
	setup_sigint_sigterm_handler (appdata);

	g_assert_false (appdata->init_done);
	zero_pinyin_service_init (app, appdata);
	g_application_hold (app);
}

static void
activate (GApplication *app,
on_activate (GApplication *app,
	     AppData *appdata)
{
	g_message ("zero-pinyin-service activate()");
	/* as a pure service, activate is a no-op. */
}

static void
shutdown (GApplication *app,
on_shutdown (GApplication *app,
	     AppData *appdata)
{
	g_message ("zero-pinyin-service shutdown()");
@@ -312,10 +226,6 @@ shutdown (GApplication *app,
		g_bus_unown_name (appdata->owner_id);
		appdata->owner_id = 0;
	}
	if (appdata->introspection_data != NULL) {
		g_dbus_node_info_unref (appdata->introspection_data);
		appdata->introspection_data = NULL;
	}
	if (appdata->db != NULL) {
		sqlite3_close (appdata->db);
		appdata->db = NULL;
@@ -323,12 +233,13 @@ shutdown (GApplication *app,
}

/**
 * provide zero-pinyin-service dbus service.
 * it's a console app based on glib and gio.
 * provides zero-pinyin-service dbus service.
 * it's a console app (GApplication) based on glib and gio.
 */
int
main (int argc, char *argv[])
{
	static AppData appdata = {0};
	GApplication *app = NULL;
	int status = 0;

@@ -336,11 +247,10 @@ main (int argc, char *argv[])
				 G_APPLICATION_FLAGS_NONE);
	g_assert_nonnull (app);
	appdata.app = app;
	appdata.init_done = FALSE;

	g_signal_connect (app, "startup", G_CALLBACK (startup), &appdata);
	g_signal_connect (app, "activate", G_CALLBACK (activate), &appdata);
	g_signal_connect (app, "shutdown", G_CALLBACK (shutdown), &appdata);
	g_signal_connect (app, "startup", G_CALLBACK (on_startup), &appdata);
	g_signal_connect (app, "activate", G_CALLBACK (on_activate), &appdata);
	g_signal_connect (app, "shutdown", G_CALLBACK (on_shutdown), &appdata);

	status = g_application_run (G_APPLICATION (app), argc, argv);
	g_object_unref (app);
+16 −1
Original line number Diff line number Diff line
# -*- mode: conf -*-
project('zero-pinyin-service', ['c', 'cpp'],
  version: '0.3.2',
  version: '0.4.0',
  license: 'GPL',
  default_options: [
    'warning_level=2',
@@ -30,19 +30,34 @@ if get_option('buildtype').startswith('release')
    language: ['c', 'cpp'])
endif

install_data('com.emacsos.zero.ZeroPinyinService1.ZeroPinyinServiceInterface.xml',
  install_dir: '/usr/share/dbus-1/interfaces/')
install_data('com.emacsos.zero.ZeroPinyinService1.service',
  install_dir: '/usr/share/dbus-1/services/')

glib = dependency('glib-2.0')
gio = dependency('gio-unix-2.0')
uuid = dependency('uuid')
sqlite3 = dependency('sqlite3')
shared_dep = [glib, gio, uuid, sqlite3]

gen_inc = include_directories('.')

gdbus_codegen = find_program('gdbus-codegen')
zero_panel_generated = custom_target('zero-panel-generated',
  input: 'com.emacsos.zero.ZeroPinyinService1.ZeroPinyinServiceInterface.xml',
  output: ['zero-pinyin-service-generated.h', 'zero-pinyin-service-generated.c'],
  command: [gdbus_codegen, '--generate-c-code', 'zero-pinyin-service-generated', '@INPUT@'])

src = [
  '../PinyinParser.cc',
  '../sqlite3_util.c',
  'parse-pinyin.cpp',
  'zero-pinyin-service.c',
  zero_panel_generated,
  'main.c']
executable('zero-pinyin-service', src,
  include_directories: gen_inc,
  dependencies: shared_dep,
  install: true, install_dir: '/home/sylecn/bin/sbin/')

+6 −7
Original line number Diff line number Diff line
@@ -5,10 +5,11 @@
#include <string.h>
#include <sqlite3.h>

#ifdef __cplusplus
extern "C"
{
#endif
G_BEGIN_DECLS

#define ZERO_PINYIN_WELL_KNOWN_NAME "com.emacsos.zero.ZeroPinyinService1"
#define ZERO_PINYIN_OBJECT_PATH "/com/emacsos/zero/ZeroPinyinService1"
#define ZERO_PINYIN_INTERFACE_NAME "com.emacsos.zero.ZeroPinyinService1.ZeroPinyinServiceInterface"

typedef struct {
	gint shengmu_i;
@@ -45,8 +46,6 @@ void get_candidates (sqlite3* db,
		     GVariantBuilder *candidates_builder,
		     GVariantBuilder *matched_lengths_builder);

#ifdef __cplusplus
}
#endif
G_END_DECLS

#endif /* _ZERO_PINYIN_SERVICE_H_ */