浏览代码

fill in rest of signal/callback/proc

jp9000 12 年之前
父节点
当前提交
6ac6256ac5

+ 3 - 0
libobs/CMakeLists.txt

@@ -67,6 +67,9 @@ add_library(libobs SHARED
 		graphics/vec2.c
 		graphics/vec3.c
 		graphics/vec4.c
+		callback/calldata.c
+		callback/proc.c
+		callback/signal.c
 		${libobs_platform_src})
 
 set_target_properties(libobs

+ 1 - 1
libobs/callback/calldata.h

@@ -178,7 +178,7 @@ EXPORT bool calldata_getstring(calldata_t data, const char *name,
 
 /* ------------------------------------------------------------------------- */
 
-void calldata_setchar  (calldata_t data, const char *name, char val)
+static void calldata_setchar  (calldata_t data, const char *name, char val)
 {
 	calldata_setdata(data, name, &val, sizeof(val));
 }

+ 59 - 0
libobs/callback/proc.c

@@ -14,4 +14,63 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#include "../util/darray.h"
 
+#include "proc.h"
+
+struct proc_info {
+	char *name;
+	void (*proc)(calldata_t, void*);
+};
+
+static inline void proc_info_free(struct proc_info *pi)
+{
+	bfree(pi->name);
+}
+
+struct proc_handler {
+	void                     *data;
+
+	/* TODO: replace with hash table lookup? */
+	DARRAY(struct proc_info) procs;
+};
+
+proc_handler_t proc_handler_create(void *data)
+{
+	struct proc_handler *handler = bmalloc(sizeof(struct proc_handler));
+	handler->data = data;
+	da_init(handler->procs);
+	return handler;
+}
+
+void proc_handler_destroy(proc_handler_t handler)
+{
+	if (handler) {
+		for (size_t i = 0; i < handler->procs.num; i++)
+			proc_info_free(handler->procs.array+i);
+		da_free(handler->procs);
+		bfree(handler);
+	}
+}
+
+void proc_handler_add(proc_handler_t handler, const char *name,
+		void (*proc)(calldata_t, void*))
+{
+	struct proc_info pi = {bstrdup(name), proc};
+	da_push_back(handler->procs, &pi);
+}
+
+bool proc_handler_call(proc_handler_t handler, const char *name,
+		calldata_t params)
+{
+	for (size_t i = 0; i < handler->procs.num; i++) {
+		struct proc_info *info = handler->procs.array+i;
+
+		if (strcmp(info->name, name) == 0) {
+			info->proc(params, handler->data);
+			return true;
+		}
+	}
+
+	return false;
+}

+ 1 - 1
libobs/callback/proc.h

@@ -34,7 +34,7 @@ typedef struct proc_handler *proc_handler_t;
 proc_handler_t proc_handler_create(void *data);
 void proc_handler_destroy(proc_handler_t handler);
 
-void proc_handler_add(proc_handler_t handler, const char *declaration,
+void proc_handler_add(proc_handler_t handler, const char *name,
 		void (*proc)(calldata_t, void*));
 
 bool proc_handler_call(proc_handler_t handler, const char *name,

+ 186 - 0
libobs/callback/signal.c

@@ -14,4 +14,190 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#include "../util/darray.h"
+#include "../util/threading.h"
 
+#include "signal.h"
+
+struct signal_callback {
+	void (*callback)(calldata_t, void*);
+	void *data;
+};
+
+struct signal_info {
+	char                           *name;
+	DARRAY(struct signal_callback) callbacks;
+	pthread_mutex_t                mutex;
+
+	struct signal_info             *next;
+};
+
+static inline struct signal_info *signal_info_create(const char *name)
+{
+	struct signal_info *si = bmalloc(sizeof(struct signal_info));
+	si->name = bstrdup(name);
+	si->next = NULL;
+	da_init(si->callbacks);
+
+	if (!pthread_mutex_init(&si->mutex, NULL) != 0) {
+		blog(LOG_ERROR, "Could not create signal!");
+		bfree(si->name);
+		bfree(si);
+		return NULL;
+	}
+
+	return si;
+}
+
+static inline void signal_info_destroy(struct signal_info *si)
+{
+	if (si) {
+		pthread_mutex_destroy(&si->mutex);
+		bfree(si->name);
+		da_free(si->callbacks);
+		bfree(si);
+	}
+}
+
+static inline size_t signal_get_callback_idx(struct signal_info *si,
+		void (*callback)(calldata_t, void*), void *data)
+{
+	for (size_t i = 0; i < si->callbacks.num; i++) {
+		struct signal_callback *sc = si->callbacks.array+i;
+
+		if (sc->callback == callback && sc->data == data)
+			return i;
+	}
+
+	return DARRAY_INVALID;
+}
+
+struct signal_handler {
+	/* TODO: might be good to use hash table instead */
+	struct signal_info *first;
+	pthread_mutex_t    mutex;
+};
+
+static struct signal_info *getsignal(signal_handler_t handler,
+		const char *name, struct signal_info **p_last)
+{
+	struct signal_info *signal, *last= NULL;
+
+	signal = handler->first;
+	while (signal != NULL) {
+		if (strcmp(signal->name, name) == 0)
+			break;
+
+		last = signal;
+		signal = signal->next;
+	}
+
+	if (p_last)
+		*p_last = last;
+	return signal;
+}
+
+/* ------------------------------------------------------------------------- */
+
+signal_handler_t signal_handler_create(void)
+{
+	struct signal_handler *handler = bmalloc(sizeof(struct signal_handler));
+	handler->first = NULL;
+
+	if (pthread_mutex_init(&handler->mutex, NULL) != 0) {
+		bfree(handler);
+		return NULL;
+	}
+
+	return handler;
+}
+
+void signal_handler_destroy(signal_handler_t handler)
+{
+	if (handler) {
+		struct signal_info *sig = handler->first;
+		while (sig != NULL) {
+			struct signal_info *next = sig->next;
+			signal_info_destroy(sig);
+			sig = next;
+		}
+
+		pthread_mutex_destroy(&handler->mutex);
+		bfree(handler);
+	}
+}
+
+void signal_handler_connect(signal_handler_t handler, const char *signal,
+		void (*callback)(calldata_t, void*), void *data)
+{
+	struct signal_info *sig, *last;
+	struct signal_callback cb_data = {callback, data};
+	size_t idx;
+
+	pthread_mutex_lock(&handler->mutex);
+	sig = getsignal(handler, signal, &last);
+	if (!sig) {
+		sig = signal_info_create(signal);
+		if (!last)
+			handler->first = sig;
+		else
+			last->next = sig;
+
+		if (!sig)
+			return;
+	}
+
+	pthread_mutex_unlock(&handler->mutex);
+
+	/* -------------- */
+
+	pthread_mutex_lock(&sig->mutex);
+
+	idx = signal_get_callback_idx(sig, callback, data);
+	if (idx == DARRAY_INVALID)
+		da_push_back(sig->callbacks, &cb_data);
+	
+	pthread_mutex_unlock(&sig->mutex);
+}
+
+static inline struct signal_info *getsignal_locked(signal_handler_t handler,
+		const char *name)
+{
+	struct signal_info *sig;
+
+	pthread_mutex_lock(&handler->mutex);
+	sig = getsignal(handler, name, NULL);
+	pthread_mutex_unlock(&handler->mutex);
+
+	return sig;
+}
+
+void signal_handler_disconnect(signal_handler_t handler, const char *signal,
+		void (*callback)(calldata_t, void*), void *data)
+{
+	struct signal_info *sig = getsignal_locked(handler, signal);
+	size_t idx;
+
+	pthread_mutex_lock(&sig->mutex);
+
+	idx = signal_get_callback_idx(sig, callback, data);
+	if (idx == DARRAY_INVALID)
+		da_erase(sig->callbacks, idx);
+	
+	pthread_mutex_unlock(&sig->mutex);
+}
+
+void signal_handler_signal(signal_handler_t handler, const char *signal,
+		calldata_t params)
+{
+	struct signal_info *sig = getsignal_locked(handler, signal);
+
+	pthread_mutex_lock(&sig->mutex);
+
+	for (size_t i = 0; i < sig->callbacks.num; i++) {
+		struct signal_callback *cb = sig->callbacks.array+i;
+		cb->callback(params, cb->data);
+	}
+
+	pthread_mutex_unlock(&sig->mutex);
+}

+ 3 - 3
libobs/callback/signal.h

@@ -34,9 +34,9 @@ signal_handler_t signal_handler_create(void);
 void signal_handler_destroy(signal_handler_t handler);
 
 void signal_handler_connect(signal_handler_t handler, const char *signal,
-		void (*callback)(calldata_t, void*), void *param);
+		void (*callback)(calldata_t, void*), void *data);
 void signal_handler_disconnect(signal_handler_t handler, const char *signal,
-		void (*callback)(calldata_t. void*), void *param);
+		void (*callback)(calldata_t, void*), void *data);
 
-void signal_handler_signal(signal_handler_t handler, const char *name,
+void signal_handler_signal(signal_handler_t handler, const char *signal,
 		calldata_t params);

+ 4 - 1
libobs/makefile.am

@@ -52,7 +52,10 @@ libobs_la_SOURCES = obs.c \
 		    graphics/texture-render.c \
 		    graphics/vec2.c \
 		    graphics/vec3.c \
-		    graphics/vec4.c
+		    graphics/vec4.c \
+		    callback/calldata.c \
+		    callback/proc.c \
+		    callback/signal.c
 
 if OS_WIN
 libobs_la_SOURCES += util/platform-windows.c obs-windows.c

+ 4 - 0
obs/window-main-basic.cpp

@@ -67,6 +67,10 @@ bool OBSBasic::InitGraphics()
 	return true;
 }
 
+void OBSBasic::AddScene(const char *name)
+{
+}
+
 void OBSBasic::OnClose(wxCloseEvent &event)
 {
 	wxGetApp().ExitMainLoop();

+ 2 - 2
obs/window-main-basic.hpp

@@ -25,8 +25,6 @@
 using namespace std;
 
 class OBSBasic : public OBSBasicBase {
-	vector<OBSSource> scenes;
-
 	bool InitGraphics();
 
 	void NewProject();
@@ -62,6 +60,8 @@ public:
 
 	bool Init();
 
+	bool AddScene(const char *name);
+
 	inline wxPanel *GetPreviewPanel() {return previewPanel;}
 	inline wxSizer *GetPreviewContainer() {return previewContainer;}
 };

+ 4 - 0
vs/2013/libobs/libobs.vcxproj

@@ -20,6 +20,8 @@
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\..\..\libobs\callback\calldata.h" />
+    <ClInclude Include="..\..\..\libobs\callback\proc.h" />
+    <ClInclude Include="..\..\..\libobs\callback\signal.h" />
     <ClInclude Include="..\..\..\libobs\graphics\axisang.h" />
     <ClInclude Include="..\..\..\libobs\graphics\bounds.h" />
     <ClInclude Include="..\..\..\libobs\graphics\effect-parser.h" />
@@ -67,6 +69,8 @@
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="..\..\..\libobs\callback\calldata.c" />
+    <ClCompile Include="..\..\..\libobs\callback\proc.c" />
+    <ClCompile Include="..\..\..\libobs\callback\signal.c" />
     <ClCompile Include="..\..\..\libobs\graphics\axisang.c" />
     <ClCompile Include="..\..\..\libobs\graphics\bounds.c" />
     <ClCompile Include="..\..\..\libobs\graphics\effect-parser.c" />

+ 12 - 0
vs/2013/libobs/libobs.vcxproj.filters

@@ -195,6 +195,12 @@
     <ClInclude Include="..\..\..\libobs\callback\calldata.h">
       <Filter>callback\Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\..\libobs\callback\proc.h">
+      <Filter>callback\Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\..\libobs\callback\signal.h">
+      <Filter>callback\Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="..\..\..\libobs\obs-output.c">
@@ -320,5 +326,11 @@
     <ClCompile Include="..\..\..\libobs\callback\calldata.c">
       <Filter>callback\Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\..\libobs\callback\signal.c">
+      <Filter>callback\Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\..\libobs\callback\proc.c">
+      <Filter>callback\Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>