[beast: 7/31] BSE: introduce Bse::Object IDL type, tied to BseObject
- From: Tim Janik <timj src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [beast: 7/31] BSE: introduce Bse::Object IDL type, tied to BseObject
- Date: Mon, 22 Jun 2015 14:38:44 +0000 (UTC)
commit d2d16a64097f934453abf425acdf3cc266ba635e
Author: Tim Janik <timj gnu org>
Date: Fri Jun 12 03:43:28 2015 +0200
BSE: introduce Bse::Object IDL type, tied to BseObject
beast-gtk/bstmain.cc | 5 +++-
bse/bseapi.idl | 9 ++++++-
bse/bseobject.cc | 63 +++++++++++++++++++++++++++++++++++++++++++++++--
bse/bseobject.hh | 49 +++++++++++++++++++++++++++++++++++---
bse/bseserver.cc | 21 +++++++++++++---
bse/bseserver.hh | 7 +++--
6 files changed, 138 insertions(+), 16 deletions(-)
---
diff --git a/beast-gtk/bstmain.cc b/beast-gtk/bstmain.cc
index eec1c84..737dfcf 100644
--- a/beast-gtk/bstmain.cc
+++ b/beast-gtk/bstmain.cc
@@ -440,14 +440,17 @@ bst_init_aida_idl()
// connect to BSE thread and fetch server handle
bse_server = Rapicorn::Aida::ObjectBroker::connect<Bse::ServerH> ("inproc://BSE-" BST_VERSION);
assert (bse_server != NULL);
+ assert (bse_server.proxy_id() == BSE_SERVER);
+ assert (bse_server.from_proxy (BSE_SERVER) == bse_server);
// hook Aida connection into our main loop
Bse::AidaGlibSource *source = Bse::AidaGlibSource::create (Bse::ServerH::__aida_connection__());
g_source_set_priority (source, G_PRIORITY_DEFAULT);
g_source_attach (source, g_main_context_default());
- // performa Bse Aida test
+ // perform Bse Aida tests
if (0)
{
+ Rapicorn::printerr ("bse_server: %s\n", bse_server.debug_name());
Bse::TestObjectH test = bse_server.get_test_object();
test.sig_echo_reply() += echo_test_handler;
const int test_result = test.echo_test ("foo");
diff --git a/bse/bseapi.idl b/bse/bseapi.idl
index 0206d4a..0f508bf 100644
--- a/bse/bseapi.idl
+++ b/bse/bseapi.idl
@@ -6,6 +6,12 @@
namespace Bse {
+/// Basic object type for all BSE objects.
+interface Object {
+ String debug_name () = 0; ///< Object name useful for debugging output.
+ int64 proxy_id () = 0; ///< Retrieve the BseObject proxy ID for an Object.
+};
+
/// Object to carry out IDL, API, signal, etc tests.
interface TestObject {
int32 echo_test (String msg) = 0; ///< Echo custom message to stdout.
@@ -33,9 +39,10 @@ record UserMessage {
* The Bse::Server object controls the main BSE thread and keeps track of all objects
* used in the BSE context.
*/
-interface Server {
+interface Server : Object {
signal void user_message (UserMessage umsg); ///< Notification signal for user messages from BSE.
TestObject get_test_object () = 0; ///< Retrieve object for API, signal, etc tests.
+ Object from_proxy (int64 proxyid) = 0; ///< Find an Object from its associated BseObject
proxy id.
};
} // Bse
diff --git a/bse/bseobject.cc b/bse/bseobject.cc
index 6fdc414..28a3d14 100644
--- a/bse/bseobject.cc
+++ b/bse/bseobject.cc
@@ -11,6 +11,40 @@
#define LDEBUG(...) BSE_KEY_DEBUG ("leaks", __VA_ARGS__)
+namespace Bse {
+ObjectImpl::ObjectImpl (BseObject *bobj) :
+ gobject_ (bobj)
+{
+ assert (gobject_);
+ assert (gobject_->cxxobject_ == NULL);
+ g_object_ref (gobject_);
+ gobject_->cxxobject_ = this;
+}
+
+ObjectImpl::~ObjectImpl ()
+{
+ assert (gobject_->cxxobject_ == this);
+ gobject_->cxxobject_ = NULL;
+ g_object_unref (gobject_);
+ // ObjectImpl keeps BseObject alive until it is destroyed
+ // BseObject keeps ObjectImpl alive until dispose()
+}
+
+std::string
+ObjectImpl::debug_name ()
+{
+ return bse_object_debug_name (this->as<BseObject*>());
+}
+
+int64_t
+ObjectImpl::proxy_id ()
+{
+ BseObject *bo = *this;
+ return bo->unique_id;
+}
+
+} // Bse
+
enum
{
PROP_0,
@@ -126,6 +160,8 @@ static void
bse_object_init (BseObject *object)
{
assert (in_bse_object_new);
+ object->cxxobject_ = NULL;
+ object->cxxobjref_ = NULL;
object->flags = 0;
object->lock_count = 0;
object->unique_id = bse_id_alloc ();
@@ -165,6 +201,13 @@ bse_object_do_dispose (GObject *gobject)
G_OBJECT_CLASS (parent_class)->dispose (gobject);
BSE_OBJECT_UNSET_FLAGS (object, BSE_OBJECT_FLAG_DISPOSING);
+
+ if (object->cxxobjref_)
+ {
+ object->cxxobjref_->reset();
+ delete object->cxxobjref_;
+ object->cxxobjref_ = NULL;
+ }
}
static void
@@ -447,10 +490,10 @@ bse_object_unlock (gpointer _object)
}
}
-gpointer
+BseObject*
bse_object_from_id (guint unique_id)
{
- return sfi_ustore_lookup (object_id_ustore, unique_id);
+ return (BseObject*) sfi_ustore_lookup (object_id_ustore, unique_id);
}
GList*
@@ -872,11 +915,25 @@ bse_object_new (GType object_type, const gchar *first_property_name, ...)
return object;
}
+#include "bseserver.hh"
+
GObject*
bse_object_new_valist (GType object_type, const gchar *first_property_name, va_list var_args)
{
in_bse_object_new++;
- GObject *object = g_object_new_valist (object_type, first_property_name, var_args);
+ BseObject *object = (BseObject*) g_object_new_valist (object_type, first_property_name, var_args);
in_bse_object_new--;
+ assert (object->cxxobject_ == NULL);
+ assert (object->cxxobjref_ == NULL);
+ Bse::ObjectImpl *cxxo;
+ if (object_type == BSE_TYPE_SERVER)
+ cxxo = new Bse::ServerImpl (object);
+ else // object_type == BSE_TYPE_OBJECT
+ cxxo = new Bse::ObjectImpl (object);
+ assert (object->cxxobject_ == cxxo);
+ assert (object->cxxobjref_ == NULL);
+ object->cxxobjref_ = new Bse::ObjectImplP (cxxo); // shared_ptr that allows enable_shared_from_this
+ assert (cxxo == *object);
+ assert (object == *cxxo);
return object;
}
diff --git a/bse/bseobject.hh b/bse/bseobject.hh
index 80c79d2..dbfaf6f 100644
--- a/bse/bseobject.hh
+++ b/bse/bseobject.hh
@@ -4,6 +4,30 @@
#include <bse/bseparam.hh>
+namespace Bse {
+
+class ObjectImpl : public virtual ObjectIface {
+ BseObject *gobject_;
+public:
+ explicit ObjectImpl (BseObject*);
+ virtual ~ObjectImpl ();
+ virtual std::string debug_name () override;
+ virtual int64_t proxy_id () override;
+ operator BseObject* () { return gobject_; }
+ template<class BseObjectPtr>
+ BseObjectPtr as ()
+ {
+ static_assert (std::is_pointer<BseObjectPtr>::value, "");
+ typedef typename std::remove_pointer<BseObjectPtr>::type BseObjectT;
+ static_assert (std::is_base_of<GObject, BseObjectT>::value, "");
+ return (BseObjectPtr) gobject_;
+ }
+};
+typedef std::shared_ptr<ObjectImpl> ObjectImplP;
+
+} // Bse
+
+
G_BEGIN_DECLS
/* --- BSE type macros --- */
@@ -35,12 +59,29 @@ typedef enum /*< skip >*/
} BseObjectFlags;
#define BSE_OBJECT_FLAGS_USHIFT (3)
#define BSE_OBJECT_FLAGS_MAX_SHIFT (16)
+
+G_END_DECLS // BseObject templates need C++ linkage
+
/* --- typedefs & structures --- */
struct BseObject : GObject {
- guint16 flags;
- guint16 lock_count;
- guint unique_id;
+ Bse::ObjectImpl *cxxobject_;
+ Bse::ObjectImplP *cxxobjref_; // shared_ptr that keeps a reference on cxxobject_ until dispose()
+ guint16 flags;
+ guint16 lock_count;
+ guint unique_id;
+ operator Bse::ObjectImpl* () { return cxxobject_; }
+ template<class ObjectImplPtr>
+ ObjectImplPtr as ()
+ {
+ static_assert (std::is_pointer<ObjectImplPtr>::value, "");
+ typedef typename std::remove_pointer<ObjectImplPtr>::type ObjectImplT;
+ static_assert (std::is_base_of<Rapicorn::Aida::ImplicitBase, ObjectImplT>::value, "");
+ return dynamic_cast<ObjectImplPtr> (cxxobject_);
+ }
};
+
+G_BEGIN_DECLS // BseObject templates need C++ linkage
+
struct BseObjectClass : GObjectClass {
gboolean (*editable_property) (BseObject *object, /* for set_property/get_property
implementations */
guint param_id,
@@ -100,7 +141,7 @@ gboolean bse_object_editable_property (gpointer object,
const gchar *property);
BseIcon* bse_object_get_icon (BseObject *object);
void bse_object_notify_icon_changed (BseObject *object);
-gpointer bse_object_from_id (guint unique_id);
+BseObject* bse_object_from_id (guint unique_id);
GList* bse_objects_list (GType type);
GList* bse_objects_list_by_uname (GType type,
const gchar *uname);
diff --git a/bse/bseserver.cc b/bse/bseserver.cc
index 4590f10..49b4234 100644
--- a/bse/bseserver.cc
+++ b/bse/bseserver.cc
@@ -350,8 +350,12 @@ bse_server_get (void)
if (!server)
{
- server = (BseServer*) bse_object_new (BSE_TYPE_SERVER, NULL);
+ server = (BseServer*) bse_object_new (BSE_TYPE_SERVER, "uname", "ServerImpl", NULL);
g_object_ref (server);
+ assert (server);
+ assert (server->cxxobject_);
+ assert (dynamic_cast<Bse::ObjectImpl*> (server->cxxobject_));
+ assert (dynamic_cast<Bse::ServerImpl*> (server->cxxobject_));
}
return server;
@@ -1123,7 +1127,8 @@ engine_shutdown (BseServer *server)
namespace Bse {
-ServerImpl::ServerImpl ()
+ServerImpl::ServerImpl (BseObject *bobj) :
+ ObjectImpl (bobj)
{}
ServerImpl::~ServerImpl ()
@@ -1137,11 +1142,19 @@ ServerImpl::get_test_object ()
return test_object_;
}
+ObjectIfaceP
+ServerImpl::from_proxy (int64_t proxyid)
+{
+ BseObject *bo = bse_object_from_id (proxyid);
+ if (!bo)
+ return ObjectIfaceP();
+ return shared_ptr_cast<ObjectIface> (bo->as<ObjectIface*>());
+}
+
ServerImpl&
ServerImpl::instance()
{
- static std::shared_ptr<ServerImpl> singleton = Rapicorn::FriendAllocator<ServerImpl>::make_shared();
- return *singleton;
+ return *bse_server_get()->as<ServerImpl*>();
}
void
diff --git a/bse/bseserver.hh b/bse/bseserver.hh
index ceb6819..5a6be2c 100644
--- a/bse/bseserver.hh
+++ b/bse/bseserver.hh
@@ -98,16 +98,17 @@ G_END_DECLS
namespace Bse {
-class ServerImpl : public ServerIface {
+class ServerImpl : public virtual ServerIface, public virtual ObjectImpl {
TestObjectImplP test_object_;
friend class FriendAllocator<ServerImpl>; // provide make_shared for non-public ctor
protected:
- explicit ServerImpl ();
virtual ~ServerImpl ();
public:
- virtual TestObjectIfaceP get_test_object ();
+ explicit ServerImpl (BseObject*);
+ virtual TestObjectIfaceP get_test_object () override;
static ServerImpl& instance ();
void send_user_message (const UserMessage &umsg);
+ virtual ObjectIfaceP from_proxy (int64_t proxyid) override;
};
} // Bse
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]