Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve/initialization #131

Merged
merged 5 commits into from
Nov 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion examples/python/stepping.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from gi.repository import Psy, GLib
import psy_operators

initializer = Psy.Initializer() # initialize psylib
initializer = Psy.Initializer(gstreamer=False, portaudio=False) # initialize psylib

window: Psy.Canvas
_NUM_ITERATIONS = 10
Expand Down
2 changes: 1 addition & 1 deletion examples/python/timers.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from gi.repository import Psy, GLib
import psy_operators

psy_init = Psy.Initializer()
psy_init = Psy.Initializer(gstreamer=False, portaudio=False)

cmd_parser = ap.ArgumentParser(
"timers", description="An example using Psy.Timers with python"
Expand Down
73 changes: 50 additions & 23 deletions psy/psy-init.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ static GMutex init_mutex;

typedef struct _PsyInitializer {
GObject parent;
guint all : 1;
#ifdef HAVE_GSTREAMER
guint gstreamer : 1;
guint gstreamer : 1;
guint gstreamer_force_unload : 1;
#endif
#ifdef HAVE_PORTAUDIO
guint portaudio : 1;
Expand All @@ -29,9 +29,9 @@ G_DEFINE_TYPE(PsyInitializer, psy_initializer, G_TYPE_OBJECT)

typedef enum {
PROP_NULL, // GObject internal use
PROP_ALL, // Turn everything on.
#ifdef HAVE_GSTREAMER
PROP_GSTREAMER,
PROP_GSTREAMER_FORCE_UNLOAD,
#endif
#ifdef HAVE_PORTAUDIO
PROP_PORTAUDIO,
Expand Down Expand Up @@ -100,7 +100,10 @@ initializer_finalize(GObject *obj)

// specific libs
if (self->gstreamer) {
gst_deinit();
// You are not allowed to deinit gstreamer twice. So only unload
// gstreamer when you are really sure.
if (self->gstreamer_force_unload)
gst_deinit();
}

if (self->portaudio) {
Expand All @@ -124,15 +127,19 @@ initializer_get_property(GObject *obj,
PsyInitializer *self = PSY_INITIALIZER(obj);

switch (id) {
case PROP_ALL:
g_value_set_boolean(value, self->all != 0);
break;
#ifdef HAVE_GSTREAMER
case PROP_GSTREAMER:
g_value_set_boolean(value, self->gstreamer != 0);
break;
case PROP_GSTREAMER_FORCE_UNLOAD:
g_value_set_boolean(value, self->gstreamer != 0);
break;
#endif
#ifdef HAVE_PORTAUDIO
case PROP_PORTAUDIO:
g_value_set_boolean(value, self->portaudio != 0);
break;
#endif
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, id, pspec);
}
Expand All @@ -147,19 +154,21 @@ initializer_set_property(GObject *obj,
PsyInitializer *self = PSY_INITIALIZER(obj);

switch (id) {
case PROP_ALL:
self->all = g_value_get_boolean(value);
if (self->all) {
self->gstreamer = TRUE;
self->portaudio = TRUE;
}
break;
#ifdef HAVE_GSTREAMER
case PROP_GSTREAMER:
self->gstreamer = g_value_get_boolean(value);
g_info("use gstreamer = %d", self->gstreamer == 1);
break;
case PROP_GSTREAMER_FORCE_UNLOAD:
self->gstreamer_force_unload = g_value_get_boolean(value);
break;
#endif
#ifdef HAVE_PORTAUDIO
case PROP_PORTAUDIO:
self->portaudio = g_value_get_boolean(value);
g_info("use portaudio = %d", self->portaudio == 1);
break;
#endif
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, id, pspec);
}
Expand All @@ -174,28 +183,46 @@ psy_initializer_class_init(PsyInitializerClass *klass)
obj_class->finalize = initializer_finalize;
obj_class->constructed = initializer_constructed;

initializer_properties[PROP_ALL]
= g_param_spec_boolean("all",
"All",
"Initialize all libs psylib uses",
TRUE,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);

#ifdef HAVE_GSTREAMER
/**
* Initializer:gstreamer
*
* If set to true psylib will init gstreamer on your behalf
*/
initializer_properties[PROP_GSTREAMER] = g_param_spec_boolean(
"gstreamer",
"GStreamer",
"Initialize gstreamer along with the rest of psylib",
FALSE,
TRUE,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);

/**
* Initializer:gstreamer-force-unload
*
* If set to true psylib will deinit gstreamer on your behalf. You'll have
* to notice that doing this twice WILL crash your program, so you'll
* probably want to keep this off, as that doesn't hurt.
*/
initializer_properties[PROP_GSTREAMER_FORCE_UNLOAD]
= g_param_spec_boolean("gstreamer-force-unload",
"GStreamerForceUnload",
"deinit gstreamer when done. Keep it FALSE.",
FALSE,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
#endif

#ifdef HAVE_PORTAUDIO

/**
* Initializer:portaudio
*
* If set to true psylib will init portaudio on your behalf
*/
initializer_properties[PROP_PORTAUDIO] = g_param_spec_boolean(
"portaudio",
"PortAudio",
"Initialize portaudio along with the rest of psylib",
FALSE,
TRUE,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
#endif

Expand Down
10 changes: 10 additions & 0 deletions tests/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,16 @@ if buildtype != 'debug' and buildtype != 'debugoptimized'
UNIT_PP_ARGS += '-DNDEBUG=1'
endif

test_init = executable(
'test_init',
files('test-init.c', 'munit.c', 'unit-test-utilities.c'),
dependencies: psy_dep,
c_args : UNIT_PP_ARGS,
cpp_args : UNIT_PP_ARGS,
)
test('test_init', test_init)


test_gtk_window = executable(
'test_gtk_window',
files('test-gtk-window.c'),
Expand Down
4 changes: 2 additions & 2 deletions tests/test-gtk-window.c
Original file line number Diff line number Diff line change
Expand Up @@ -232,8 +232,8 @@ main(int argc, char **argv)
gint window_style;
const gchar *text_content = NULL;

PsyInitializer *initializer
= g_object_new(PSY_TYPE_INITIALIZER, "all", FALSE, NULL);
PsyInitializer *initializer = g_object_new(
PSY_TYPE_INITIALIZER, "gstreamer", FALSE, "portaudio", FALSE, NULL);

PsyColor *circle_color = psy_color_new_rgb(1.0, 0, 0);
PsyColor *cross_color = psy_color_new_rgb(1.0, 1.0, 0);
Expand Down
110 changes: 110 additions & 0 deletions tests/test-init.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@

#include "unit-test-utilities.h"

#include <munit.h>
#include <psylib.h>
#include <signal.h>

static int
initializer_setup(void)
{
install_log_handler();
set_log_handler_level(G_LOG_LEVEL_DEBUG);
set_log_handler_file("test-init.txt");
return 0;
}

static int
initializer_teardown(void)
{
set_log_handler_file(NULL);
remove_log_handler();
return 0;
}

static MunitResult
test_initializer_default(const MunitParameter params[], void *user_data)
{
(void) params;
(void) user_data;
gboolean gst, portaudio;
PsyInitializer *initialzer = g_object_new(PSY_TYPE_INITIALIZER, NULL);

g_object_get(initialzer, "gstreamer", &gst, "portaudio", &portaudio, NULL);

munit_assert_int(gst, ==, TRUE);
munit_assert_int(portaudio, ==, TRUE);

g_object_unref(initialzer);

return MUNIT_OK;
}

static MunitResult
test_initializer_specific(const MunitParameter params[], void *user_data)
{
(void) params;
(void) user_data;
gboolean gst, portaudio;

// No need to say we do "need" gstreamer. Initialization is everything
// unless explictly turned off as portaudio here below.
PsyInitializer *initialzer
= g_object_new(PSY_TYPE_INITIALIZER, "portaudio", FALSE, NULL);

g_object_get(initialzer, "gstreamer", &gst, "portaudio", &portaudio, NULL);

munit_assert_int(gst, ==, TRUE);
munit_assert_int(portaudio, ==, FALSE);

g_object_unref(initialzer);

return MUNIT_OK;
}

// clang-format off
MunitTest tests[] = {
{"default",test_initializer_default, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL},
{"specific", test_initializer_specific, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL},
{0}
};
// clang-format on

MunitSuite suite = {"initializer/", tests, NULL, 1, MUNIT_SUITE_OPTION_NONE};

static void
signal_handler(int sig)
{
switch (sig) {
case SIGINT:
case SIGABRT:
case SIGSEGV:
remove_log_handler();
g_print("Received signal %d\nquitting\n", sig);
exit(sig);
}
}

static void
setup_signal_handlers(void)
{
if (signal(SIGINT, signal_handler) == SIG_ERR) {
g_printerr("Unable to catch SIGINT");
}
if (signal(SIGABRT, signal_handler) == SIG_ERR) {
g_printerr("Unable to catch SIGABRT");
}
if (signal(SIGSEGV, signal_handler) == SIG_ERR) {
g_printerr("Unable to catch SIGABRT");
}
}

int
main(int argc, char **argv)
{
initializer_setup();
setup_signal_handlers();
int ret = munit_suite_main(&suite, NULL, argc, argv);
initializer_teardown();
return ret;
}
2 changes: 1 addition & 1 deletion tests/test-timer2.c
Original file line number Diff line number Diff line change
Expand Up @@ -520,7 +520,7 @@ MunitTest tests[] = {
};
// clang-format on

MunitSuite suite = {"psy-timer/", tests, NULL, 1, MUNIT_SUITE_OPTION_NONE};
MunitSuite suite = {"timer/", tests, NULL, 1, MUNIT_SUITE_OPTION_NONE};

static void
signal_handler(int sig)
Expand Down
Loading