/* sound-manager.c generated by valac 0.56.19, the Vala compiler
 * generated from sound-manager.vala, do not modify */

/*
 * Copyright (c) 2024-2025 focus-timer contributors
 *
 * SPDX-License-Identifier: GPL-3.0-or-later
 *
 * Authors: Kamil Prusko <kamilprusko@gmail.com>
 */

#include "ft_core.h"
#include <glib.h>
#include <gio/gio.h>
#include <glib-object.h>
#include <string.h>

#define FT_SOUND_MANAGER_SHORT_FADE_DURATION (300 * FT_INTERVAL_MILLISECOND)
#define FT_SOUND_MANAGER_LONG_FADE_DURATION FT_INTERVAL_SECOND
#define FT_SOUND_MANAGER_ABOUT_TO_END_TIME (10 * FT_INTERVAL_SECOND)
#if !defined(VALA_STRICT_C)
#if !defined(__clang__) && defined(__GNUC__) && (__GNUC__ >= 14)
#pragma GCC diagnostic warning "-Wincompatible-pointer-types"
#elif defined(__clang__) && (__clang_major__ >= 16)
#pragma clang diagnostic ignored "-Wincompatible-function-pointer-types"
#pragma clang diagnostic ignored "-Wincompatible-pointer-types"
#endif
#endif

enum  {
	FT_SOUND_MANAGER_0_PROPERTY,
	FT_SOUND_MANAGER_NUM_PROPERTIES
};
static GParamSpec* ft_sound_manager_properties[FT_SOUND_MANAGER_NUM_PROPERTIES];
#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL)))
#define _vala_assert(expr, msg) if G_LIKELY (expr) ; else g_assertion_message_expr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg);
#define _vala_return_if_fail(expr, msg) if G_LIKELY (expr) ; else { g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, msg); return; }
#define _vala_return_val_if_fail(expr, msg, val) if G_LIKELY (expr) ; else { g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, msg); return val; }
#define _vala_warn_if_fail(expr, msg) if G_LIKELY (expr) ; else g_warn_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg);

struct _FtSoundManagerPrivate {
	FtAlertSound* pomodoro_finished_sound;
	FtAlertSound* break_finished_sound;
	FtBackgroundSound* background_sound;
	guint background_sound_inhibit_count;
	GSettings* settings;
	FtTimer* timer;
	gulong timer_state_changed_id;
	guint fade_out_timeout_id;
};

static gint FtSoundManager_private_offset;
static gpointer ft_sound_manager_parent_class = NULL;

static void ft_sound_manager_schedule_fade_out (FtSoundManager* self,
                                         gint64 timeout);
static gboolean ft_sound_manager_on_fade_out_timeout (FtSoundManager* self);
static gboolean _ft_sound_manager_on_fade_out_timeout_gsource_func (gpointer self);
static void ft_sound_manager_unschedule_fade_out (FtSoundManager* self);
static void ft_sound_manager_update_background_sound (FtSoundManager* self);
static void ft_sound_manager_on_timer_state_changed (FtSoundManager* self,
                                              const FtTimerState* current_state,
                                              const FtTimerState* previous_state);
static void ft_sound_manager_real_dispose (GObject* base);
static GObject * ft_sound_manager_constructor (GType type,
                                        guint n_construct_properties,
                                        GObjectConstructParam * construct_properties);
static void _ft_sound_manager_on_timer_state_changed_ft_timer_state_changed (FtTimer* _sender,
                                                                      const FtTimerState* current_state,
                                                                      const FtTimerState* previous_state,
                                                                      gpointer self);
static void ft_sound_manager_finalize (GObject * obj);
static GType ft_sound_manager_get_type_once (void);
static inline gpointer _vala_memdup2 (gconstpointer mem,
                        gsize byte_size);

static inline gpointer
ft_sound_manager_get_instance_private (FtSoundManager* self)
{
	return G_STRUCT_MEMBER_P (self, FtSoundManager_private_offset);
}

static gboolean
_ft_sound_manager_on_fade_out_timeout_gsource_func (gpointer self)
{
	gboolean result;
	result = ft_sound_manager_on_fade_out_timeout ((FtSoundManager*) self);
	return result;
}

static void
ft_sound_manager_schedule_fade_out (FtSoundManager* self,
                                    gint64 timeout)
{
	g_return_if_fail (self != NULL);
	_vala_return_if_fail (self->priv->fade_out_timeout_id == ((guint) 0), "this.fade_out_timeout_id == 0");
	self->priv->fade_out_timeout_id = g_timeout_add_full (G_PRIORITY_DEFAULT, ft_timestamp_to_milliseconds_uint (timeout), _ft_sound_manager_on_fade_out_timeout_gsource_func, g_object_ref (self), g_object_unref);
	g_source_set_name_by_id (self->priv->fade_out_timeout_id, "Ft.SoundManager.on_fade_out_timeout");
}

static void
ft_sound_manager_unschedule_fade_out (FtSoundManager* self)
{
	g_return_if_fail (self != NULL);
	if (self->priv->fade_out_timeout_id != ((guint) 0)) {
		g_source_remove (self->priv->fade_out_timeout_id);
		self->priv->fade_out_timeout_id = (guint) 0;
	}
}

static gpointer
_g_object_ref0 (gpointer self)
{
	return self ? g_object_ref (self) : NULL;
}

static void
ft_sound_manager_update_background_sound (FtSoundManager* self)
{
	FtBackgroundSound* _tmp1_;
	FtTimeBlock* current_time_block = NULL;
	FtTimer* _tmp2_;
	void* _tmp3_;
	void* _tmp4_;
	FtTimeBlock* _tmp5_;
	FtState _tmp6_ = 0;
	FtTimeBlock* _tmp7_;
	FtState current_state = 0;
	gboolean _tmp11_ = FALSE;
	g_return_if_fail (self != NULL);
	ft_sound_manager_unschedule_fade_out (self);
	if (self->priv->background_sound_inhibit_count != ((guint) 0)) {
		FtBackgroundSound* _tmp0_;
		_tmp0_ = self->priv->background_sound;
		ft_background_sound_fade_out (_tmp0_, FT_SOUND_MANAGER_LONG_FADE_DURATION);
		return;
	}
	_tmp1_ = self->priv->background_sound;
	if (!ft_sound_can_play ((FtSound*) _tmp1_)) {
		return;
	}
	_tmp2_ = self->priv->timer;
	_tmp3_ = ft_timer_get_user_data (_tmp2_);
	_tmp4_ = _tmp3_;
	_tmp5_ = _g_object_ref0 (FT_IS_TIME_BLOCK (_tmp4_) ? ((FtTimeBlock*) _tmp4_) : NULL);
	current_time_block = _tmp5_;
	_tmp7_ = current_time_block;
	if (_tmp7_ != NULL) {
		FtTimeBlock* _tmp8_;
		FtState _tmp9_;
		FtState _tmp10_;
		_tmp8_ = current_time_block;
		_tmp9_ = ft_time_block_get_state (_tmp8_);
		_tmp10_ = _tmp9_;
		_tmp6_ = _tmp10_;
	} else {
		_tmp6_ = FT_STATE_STOPPED;
	}
	current_state = _tmp6_;
	if (current_state == FT_STATE_POMODORO) {
		FtTimer* _tmp12_;
		_tmp12_ = self->priv->timer;
		_tmp11_ = ft_timer_is_running (_tmp12_);
	} else {
		_tmp11_ = FALSE;
	}
	if (_tmp11_) {
		gint64 remaining = 0LL;
		FtTimer* _tmp13_;
		gint64 fade_duration = 0LL;
		_tmp13_ = self->priv->timer;
		remaining = ft_timer_calculate_remaining (_tmp13_, FT_TIMESTAMP_UNDEFINED);
		fade_duration = FT_SOUND_MANAGER_LONG_FADE_DURATION;
		if (remaining > FT_SOUND_MANAGER_ABOUT_TO_END_TIME) {
			FtBackgroundSound* _tmp14_;
			_tmp14_ = self->priv->background_sound;
			ft_background_sound_fade_in (_tmp14_, fade_duration);
			ft_sound_manager_schedule_fade_out (self, remaining - FT_SOUND_MANAGER_ABOUT_TO_END_TIME);
		} else {
			FtBackgroundSound* _tmp15_;
			fade_duration = MAX (remaining - FT_INTERVAL_SECOND, FT_SOUND_MANAGER_SHORT_FADE_DURATION);
			_tmp15_ = self->priv->background_sound;
			ft_background_sound_fade_out (_tmp15_, fade_duration);
		}
	} else {
		FtBackgroundSound* _tmp16_;
		_tmp16_ = self->priv->background_sound;
		ft_background_sound_fade_out (_tmp16_, FT_SOUND_MANAGER_SHORT_FADE_DURATION);
	}
	_g_object_unref0 (current_time_block);
}

void
ft_sound_manager_inhibit_background_sound (FtSoundManager* self)
{
	guint _tmp0_;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->priv->background_sound_inhibit_count;
	self->priv->background_sound_inhibit_count = _tmp0_ + 1;
	if (self->priv->background_sound_inhibit_count == ((guint) 1)) {
		ft_sound_manager_update_background_sound (self);
	}
}

void
ft_sound_manager_uninhibit_background_sound (FtSoundManager* self)
{
	guint _tmp0_;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->priv->background_sound_inhibit_count;
	self->priv->background_sound_inhibit_count = _tmp0_ - 1;
	if (self->priv->background_sound_inhibit_count == ((guint) 0)) {
		ft_sound_manager_update_background_sound (self);
	}
}

static void
ft_sound_manager_on_timer_state_changed (FtSoundManager* self,
                                         const FtTimerState* current_state,
                                         const FtTimerState* previous_state)
{
	gboolean _tmp0_ = FALSE;
	gboolean _tmp1_ = FALSE;
	g_return_if_fail (self != NULL);
	g_return_if_fail (current_state != NULL);
	g_return_if_fail (previous_state != NULL);
	if (ft_timer_state_is_finished (current_state)) {
		_tmp1_ = !ft_timer_state_is_finished (previous_state);
	} else {
		_tmp1_ = FALSE;
	}
	if (_tmp1_) {
		FtTimerState _tmp2_;
		void* _tmp3_;
		_tmp2_ = *previous_state;
		_tmp3_ = _tmp2_.user_data;
		_tmp0_ = _tmp3_ != NULL;
	} else {
		_tmp0_ = FALSE;
	}
	if (_tmp0_) {
		FtTimeBlock* current_time_block = NULL;
		FtTimerState _tmp4_;
		void* _tmp5_;
		FtTimeBlock* _tmp6_;
		FtTimeBlock* _tmp7_;
		FtState _tmp8_;
		FtState _tmp9_;
		_tmp4_ = *current_state;
		_tmp5_ = _tmp4_.user_data;
		_tmp6_ = _g_object_ref0 (FT_IS_TIME_BLOCK (_tmp5_) ? ((FtTimeBlock*) _tmp5_) : NULL);
		current_time_block = _tmp6_;
		_tmp7_ = current_time_block;
		_tmp8_ = ft_time_block_get_state (_tmp7_);
		_tmp9_ = _tmp8_;
		if (_tmp9_ == FT_STATE_POMODORO) {
			FtAlertSound* _tmp10_;
			_tmp10_ = self->priv->pomodoro_finished_sound;
			ft_sound_play ((FtSound*) _tmp10_);
		} else {
			FtTimeBlock* _tmp11_;
			FtState _tmp12_;
			FtState _tmp13_;
			_tmp11_ = current_time_block;
			_tmp12_ = ft_time_block_get_state (_tmp11_);
			_tmp13_ = _tmp12_;
			if (ft_state_is_break (_tmp13_)) {
				FtAlertSound* _tmp14_;
				_tmp14_ = self->priv->break_finished_sound;
				ft_sound_play ((FtSound*) _tmp14_);
			}
		}
		_g_object_unref0 (current_time_block);
	}
	ft_sound_manager_update_background_sound (self);
}

static gboolean
ft_sound_manager_on_fade_out_timeout (FtSoundManager* self)
{
	FtTimer* _tmp0_;
	gint64 current_time = 0LL;
	FtTimer* _tmp1_;
	GSource* _tmp2_;
	gint64 remaining = 0LL;
	FtTimer* _tmp3_;
	gint64 fade_out_duration = 0LL;
	FtBackgroundSound* _tmp4_;
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	_tmp0_ = self->priv->timer;
	_vala_return_val_if_fail (ft_timer_is_running (_tmp0_), "this.timer.is_running ()", FALSE);
	_tmp1_ = self->priv->timer;
	_tmp2_ = g_main_current_source ();
	current_time = ft_timer_get_current_time (_tmp1_, g_source_get_time (_tmp2_));
	_tmp3_ = self->priv->timer;
	remaining = ft_timer_calculate_remaining (_tmp3_, current_time);
	fade_out_duration = MAX (remaining - FT_INTERVAL_SECOND, FT_SOUND_MANAGER_SHORT_FADE_DURATION);
	self->priv->fade_out_timeout_id = (guint) 0;
	_tmp4_ = self->priv->background_sound;
	ft_background_sound_fade_out (_tmp4_, fade_out_duration);
	result = G_SOURCE_REMOVE;
	return result;
}

static void
ft_sound_manager_real_dispose (GObject* base)
{
	FtSoundManager * self;
	FtAlertSound* _tmp1_;
	FtAlertSound* _tmp3_;
	FtBackgroundSound* _tmp5_;
	self = (FtSoundManager*) base;
	ft_sound_manager_unschedule_fade_out (self);
	if (self->priv->timer_state_changed_id != ((gulong) 0)) {
		FtTimer* _tmp0_;
		_tmp0_ = self->priv->timer;
		g_signal_handler_disconnect ((GObject*) _tmp0_, self->priv->timer_state_changed_id);
		self->priv->timer_state_changed_id = (gulong) 0;
	}
	_tmp1_ = self->priv->pomodoro_finished_sound;
	if (_tmp1_ != NULL) {
		FtAlertSound* _tmp2_;
		_tmp2_ = self->priv->pomodoro_finished_sound;
		ft_sound_stop ((FtSound*) _tmp2_);
		_g_object_unref0 (self->priv->pomodoro_finished_sound);
		self->priv->pomodoro_finished_sound = NULL;
	}
	_tmp3_ = self->priv->break_finished_sound;
	if (_tmp3_ != NULL) {
		FtAlertSound* _tmp4_;
		_tmp4_ = self->priv->break_finished_sound;
		ft_sound_stop ((FtSound*) _tmp4_);
		_g_object_unref0 (self->priv->break_finished_sound);
		self->priv->break_finished_sound = NULL;
	}
	_tmp5_ = self->priv->background_sound;
	if (_tmp5_ != NULL) {
		FtBackgroundSound* _tmp6_;
		_tmp6_ = self->priv->background_sound;
		ft_sound_stop ((FtSound*) _tmp6_);
		_g_object_unref0 (self->priv->background_sound);
		self->priv->background_sound = NULL;
	}
	_g_object_unref0 (self->priv->timer);
	self->priv->timer = NULL;
	_g_object_unref0 (self->priv->settings);
	self->priv->settings = NULL;
	G_OBJECT_CLASS (ft_sound_manager_parent_class)->dispose (G_TYPE_CHECK_INSTANCE_CAST (self, G_TYPE_OBJECT, GObject));
}

FtSoundManager*
ft_sound_manager_construct (GType object_type)
{
	FtSoundManager * self = NULL;
	self = (FtSoundManager*) g_object_new (object_type, NULL);
	return self;
}

FtSoundManager*
ft_sound_manager_new (void)
{
	return ft_sound_manager_construct (FT_TYPE_SOUND_MANAGER);
}

static void
_ft_sound_manager_on_timer_state_changed_ft_timer_state_changed (FtTimer* _sender,
                                                                 const FtTimerState* current_state,
                                                                 const FtTimerState* previous_state,
                                                                 gpointer self)
{
	ft_sound_manager_on_timer_state_changed ((FtSoundManager*) self, current_state, previous_state);
}

static GObject *
ft_sound_manager_constructor (GType type,
                              guint n_construct_properties,
                              GObjectConstructParam * construct_properties)
{
	GObject * obj;
	GObjectClass * parent_class;
	static GWeakRef FtSoundManager_singleton__ref;
	static GMutex FtSoundManager_singleton__lock;
	FtSoundManager * self;
	FtTimer* _tmp0_;
	FtTimer* _tmp1_;
	FtTimer* _tmp2_;
	gulong _tmp3_;
	FtAlertSound* _tmp4_;
	FtAlertSound* _tmp5_;
	FtBackgroundSound* _tmp6_;
	FtBackgroundSound* _tmp7_;
	FtBackgroundSound* _tmp8_;
	GSettings* _tmp9_;
	GSettings* _tmp10_;
	GSettings* _tmp11_;
	FtAlertSound* _tmp12_;
	GSettings* _tmp13_;
	FtAlertSound* _tmp14_;
	GSettings* _tmp15_;
	FtAlertSound* _tmp16_;
	GSettings* _tmp17_;
	FtAlertSound* _tmp18_;
	GSettings* _tmp19_;
	FtBackgroundSound* _tmp20_;
	GSettings* _tmp21_;
	FtBackgroundSound* _tmp22_;
	g_mutex_lock (&FtSoundManager_singleton__lock);
	obj = g_weak_ref_get (&FtSoundManager_singleton__ref);
	if (obj != NULL) {
		g_mutex_unlock (&FtSoundManager_singleton__lock);
		return obj;
	}
	parent_class = G_OBJECT_CLASS (ft_sound_manager_parent_class);
	obj = parent_class->constructor (type, n_construct_properties, construct_properties);
	self = G_TYPE_CHECK_INSTANCE_CAST (obj, FT_TYPE_SOUND_MANAGER, FtSoundManager);
	_tmp0_ = ft_timer_get_default ();
	_tmp1_ = _g_object_ref0 (_tmp0_);
	_g_object_unref0 (self->priv->timer);
	self->priv->timer = _tmp1_;
	_tmp2_ = self->priv->timer;
	_tmp3_ = g_signal_connect_object (_tmp2_, "state-changed", (GCallback) _ft_sound_manager_on_timer_state_changed_ft_timer_state_changed, self, G_CONNECT_AFTER);
	self->priv->timer_state_changed_id = _tmp3_;
	_tmp4_ = ft_alert_sound_new ("pomodoro-finished");
	_g_object_unref0 (self->priv->pomodoro_finished_sound);
	self->priv->pomodoro_finished_sound = _tmp4_;
	_tmp5_ = ft_alert_sound_new ("break-finished");
	_g_object_unref0 (self->priv->break_finished_sound);
	self->priv->break_finished_sound = _tmp5_;
	_tmp6_ = ft_background_sound_new ();
	_g_object_unref0 (self->priv->background_sound);
	self->priv->background_sound = _tmp6_;
	_tmp7_ = self->priv->background_sound;
	ft_background_sound_set_loop (_tmp7_, TRUE);
	_tmp8_ = self->priv->background_sound;
	ft_background_sound_fade_out (_tmp8_, (gint64) 0);
	_tmp9_ = ft_get_settings ();
	_tmp10_ = _g_object_ref0 (_tmp9_);
	_g_object_unref0 (self->priv->settings);
	self->priv->settings = _tmp10_;
	_tmp11_ = self->priv->settings;
	_tmp12_ = self->priv->pomodoro_finished_sound;
	g_settings_bind (_tmp11_, "pomodoro-finished-sound", (GObject*) _tmp12_, "uri", G_SETTINGS_BIND_DEFAULT);
	_tmp13_ = self->priv->settings;
	_tmp14_ = self->priv->pomodoro_finished_sound;
	g_settings_bind (_tmp13_, "pomodoro-finished-sound-volume", (GObject*) _tmp14_, "volume", G_SETTINGS_BIND_DEFAULT);
	_tmp15_ = self->priv->settings;
	_tmp16_ = self->priv->break_finished_sound;
	g_settings_bind (_tmp15_, "break-finished-sound", (GObject*) _tmp16_, "uri", G_SETTINGS_BIND_DEFAULT);
	_tmp17_ = self->priv->settings;
	_tmp18_ = self->priv->break_finished_sound;
	g_settings_bind (_tmp17_, "break-finished-sound-volume", (GObject*) _tmp18_, "volume", G_SETTINGS_BIND_DEFAULT);
	_tmp19_ = self->priv->settings;
	_tmp20_ = self->priv->background_sound;
	g_settings_bind (_tmp19_, "background-sound", (GObject*) _tmp20_, "uri", G_SETTINGS_BIND_DEFAULT);
	_tmp21_ = self->priv->settings;
	_tmp22_ = self->priv->background_sound;
	g_settings_bind (_tmp21_, "background-sound-volume", (GObject*) _tmp22_, "volume", G_SETTINGS_BIND_DEFAULT);
	ft_sound_manager_update_background_sound (self);
	g_weak_ref_set (&FtSoundManager_singleton__ref, obj);
	g_mutex_unlock (&FtSoundManager_singleton__lock);
	return obj;
}

static void
ft_sound_manager_class_init (FtSoundManagerClass * klass,
                             gpointer klass_data)
{
	ft_sound_manager_parent_class = g_type_class_peek_parent (klass);
	g_type_class_adjust_private_offset (klass, &FtSoundManager_private_offset);
	((GObjectClass *) klass)->dispose = (void (*) (GObject*)) ft_sound_manager_real_dispose;
	G_OBJECT_CLASS (klass)->constructor = ft_sound_manager_constructor;
	G_OBJECT_CLASS (klass)->finalize = ft_sound_manager_finalize;
}

static void
ft_sound_manager_instance_init (FtSoundManager * self,
                                gpointer klass)
{
	self->priv = ft_sound_manager_get_instance_private (self);
	self->priv->pomodoro_finished_sound = NULL;
	self->priv->break_finished_sound = NULL;
	self->priv->background_sound = NULL;
	self->priv->background_sound_inhibit_count = (guint) 0;
	self->priv->settings = NULL;
	self->priv->timer = NULL;
	self->priv->timer_state_changed_id = (gulong) 0;
	self->priv->fade_out_timeout_id = (guint) 0;
}

static void
ft_sound_manager_finalize (GObject * obj)
{
	FtSoundManager * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (obj, FT_TYPE_SOUND_MANAGER, FtSoundManager);
	_g_object_unref0 (self->priv->pomodoro_finished_sound);
	_g_object_unref0 (self->priv->break_finished_sound);
	_g_object_unref0 (self->priv->background_sound);
	_g_object_unref0 (self->priv->settings);
	_g_object_unref0 (self->priv->timer);
	G_OBJECT_CLASS (ft_sound_manager_parent_class)->finalize (obj);
}

static GType
ft_sound_manager_get_type_once (void)
{
	static const GTypeInfo g_define_type_info = { sizeof (FtSoundManagerClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) ft_sound_manager_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (FtSoundManager), 0, (GInstanceInitFunc) ft_sound_manager_instance_init, NULL };
	GType ft_sound_manager_type_id;
	ft_sound_manager_type_id = g_type_register_static (G_TYPE_OBJECT, "FtSoundManager", &g_define_type_info, 0);
	FtSoundManager_private_offset = g_type_add_instance_private (ft_sound_manager_type_id, sizeof (FtSoundManagerPrivate));
	return ft_sound_manager_type_id;
}

GType
ft_sound_manager_get_type (void)
{
	static volatile gsize ft_sound_manager_type_id__once = 0;
	if (g_once_init_enter (&ft_sound_manager_type_id__once)) {
		GType ft_sound_manager_type_id;
		ft_sound_manager_type_id = ft_sound_manager_get_type_once ();
		g_once_init_leave (&ft_sound_manager_type_id__once, ft_sound_manager_type_id);
	}
	return ft_sound_manager_type_id__once;
}

static inline gpointer
_vala_memdup2 (gconstpointer mem,
               gsize byte_size)
{
	gpointer new_mem;
	if (mem && byte_size != 0) {
		new_mem = g_malloc (byte_size);
		memcpy (new_mem, mem, byte_size);
	} else {
		new_mem = NULL;
	}
	return new_mem;
}

