// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "interface.h"

namespace speech_synthesis {
namespace gobject {

// Register with the glib type system.
// This macro automatically defines a number of functions and variables
// which are required to make speech_synthesizer functional as a GObject:
// - speech_synthesizer_parent_class
// - speech_synthesizer_get_type()
// - dbus_glib_speech_synthesizer_object_info
// It also ensures that the structs are setup so that the initialization
// functions are called in the appropriate way by g_object_new().
G_DEFINE_TYPE(SpeechSynthesizer, speech_synthesizer, G_TYPE_OBJECT);

GObject* speech_synthesizer_constructor(GType gtype,
                                        guint n_properties,
                                        GObjectConstructParam *properties) {
  GObject* obj;
  GObjectClass* parent_class;
  // Instantiate using the parent class, then extend for local properties.
  parent_class = G_OBJECT_CLASS(speech_synthesizer_parent_class);
  obj = parent_class->constructor(gtype, n_properties, properties);

  SpeechSynthesizer* speech_synthesizer = reinterpret_cast<SpeechSynthesizer*>(obj);
  speech_synthesizer->service = NULL;

  // We don't have any thing we care to expose to the glib class system.
  return obj;
}

void speech_synthesizer_class_init(SpeechSynthesizerClass *real_class) {
  // Called once to configure the "class" structure.
  GObjectClass* gobject_class = G_OBJECT_CLASS(real_class);
  gobject_class->constructor = speech_synthesizer_constructor;
}

void speech_synthesizer_init(SpeechSynthesizer *self) { }

// TODO(wad) add error messaging
#define SPEECH_SYNTHESIZER_WRAP_METHOD(_NAME, s, e, args...) \
  if (!s->service) { \
    return FALSE; \
  } \
  return s->service->_NAME(args, e);

#define SPEECH_SYNTHESIZER_WRAP_METHOD0(_NAME, s, e) \
  if (!s->service) { \
    return FALSE; \
  } \
  return s->service->_NAME(e);

gboolean speech_synthesizer_speak(SpeechSynthesizer* self,
                                  gchar *text,
                                  GError** error) {
  SPEECH_SYNTHESIZER_WRAP_METHOD(Speak, self, error, text);
}
gboolean speech_synthesizer_set_properties(SpeechSynthesizer* self,
                                           gchar *properties,
                                           GError** error) {
  SPEECH_SYNTHESIZER_WRAP_METHOD(SetProperties, self, error, properties);
}
gboolean speech_synthesizer_stop(SpeechSynthesizer* self,
                                 GError** error) {
  SPEECH_SYNTHESIZER_WRAP_METHOD0(Stop, self, error);
}
gboolean speech_synthesizer_is_speaking(SpeechSynthesizer* self,
                                        gboolean* OUT_isSpeaking_requested,
                                        GError** error) {
  SPEECH_SYNTHESIZER_WRAP_METHOD(IsSpeaking, self, error,
      OUT_isSpeaking_requested);
}
#undef SPEECH_SYNTHESIZER_WRAP_METHOD

}  // namespace gobject
}  // namespace speech_synthesis

