Compare commits
No commits in common. "4193fb72c2542227156af5c466129069326abb31" and "5e2d2807c1b81e3361a3e404a2b8887e512416ae" have entirely different histories.
4193fb72c2
...
5e2d2807c1
29 changed files with 17513 additions and 2643 deletions
|
@ -1,6 +1,6 @@
|
||||||
project(
|
project(
|
||||||
'audrey',
|
'audrey',
|
||||||
['c', 'vala'],
|
'c',
|
||||||
version: '0.1.0', # AUDREY_VERSION
|
version: '0.1.0', # AUDREY_VERSION
|
||||||
meson_version: '>= 1.0.0',
|
meson_version: '>= 1.0.0',
|
||||||
default_options: ['warning_level=0', 'werror=false'],
|
default_options: ['warning_level=0', 'werror=false'],
|
||||||
|
@ -10,7 +10,6 @@ i18n = import('i18n')
|
||||||
gnome = import('gnome')
|
gnome = import('gnome')
|
||||||
fs = import('fs')
|
fs = import('fs')
|
||||||
cc = meson.get_compiler('c')
|
cc = meson.get_compiler('c')
|
||||||
valac = meson.get_compiler('vala')
|
|
||||||
|
|
||||||
srcdir = meson.project_source_root() / 'src'
|
srcdir = meson.project_source_root() / 'src'
|
||||||
|
|
||||||
|
@ -20,7 +19,6 @@ config_h.set_quoted('GETTEXT_PACKAGE', 'audrey')
|
||||||
config_h.set_quoted('LOCALEDIR', get_option('prefix') / get_option('localedir'))
|
config_h.set_quoted('LOCALEDIR', get_option('prefix') / get_option('localedir'))
|
||||||
configure_file(output: 'config.h', configuration: config_h)
|
configure_file(output: 'config.h', configuration: config_h)
|
||||||
|
|
||||||
config_dep = valac.find_library('config', dirs: srcdir)
|
|
||||||
config_inc = include_directories('.')
|
config_inc = include_directories('.')
|
||||||
|
|
||||||
add_project_arguments(
|
add_project_arguments(
|
||||||
|
|
|
@ -10,5 +10,3 @@ blueprints = custom_target(
|
||||||
'@INPUT@',
|
'@INPUT@',
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
removeme = gnome.compile_resources('audrey-resources', 'audrey.gresource.xml', c_name: 'audrey', dependencies: blueprints)
|
|
||||||
|
|
515
src/application.c
Normal file
515
src/application.c
Normal file
|
@ -0,0 +1,515 @@
|
||||||
|
/* application.c generated by valac 0.56.16, the Vala compiler
|
||||||
|
* generated from application.vala, do not modify */
|
||||||
|
|
||||||
|
#include <adwaita.h>
|
||||||
|
#include <glib-object.h>
|
||||||
|
#include <gio/gio.h>
|
||||||
|
#include <glib.h>
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <glib/gi18n-lib.h>
|
||||||
|
|
||||||
|
#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
|
||||||
|
#if !defined(VALA_EXTERN)
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#define VALA_EXTERN __declspec(dllexport) extern
|
||||||
|
#elif __GNUC__ >= 4
|
||||||
|
#define VALA_EXTERN __attribute__((visibility("default"))) extern
|
||||||
|
#else
|
||||||
|
#define VALA_EXTERN extern
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define AUDREY_TYPE_APPLICATION (audrey_application_get_type ())
|
||||||
|
#define AUDREY_APPLICATION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), AUDREY_TYPE_APPLICATION, AudreyApplication))
|
||||||
|
#define AUDREY_APPLICATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), AUDREY_TYPE_APPLICATION, AudreyApplicationClass))
|
||||||
|
#define AUDREY_IS_APPLICATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), AUDREY_TYPE_APPLICATION))
|
||||||
|
#define AUDREY_IS_APPLICATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), AUDREY_TYPE_APPLICATION))
|
||||||
|
#define AUDREY_APPLICATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), AUDREY_TYPE_APPLICATION, AudreyApplicationClass))
|
||||||
|
|
||||||
|
typedef struct _AudreyApplication AudreyApplication;
|
||||||
|
typedef struct _AudreyApplicationClass AudreyApplicationClass;
|
||||||
|
typedef struct _AudreyApplicationPrivate AudreyApplicationPrivate;
|
||||||
|
enum {
|
||||||
|
AUDREY_APPLICATION_0_PROPERTY,
|
||||||
|
AUDREY_APPLICATION_NUM_PROPERTIES
|
||||||
|
};
|
||||||
|
static GParamSpec* audrey_application_properties[AUDREY_APPLICATION_NUM_PROPERTIES];
|
||||||
|
|
||||||
|
#define UI_TYPE_WINDOW (ui_window_get_type ())
|
||||||
|
#define UI_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), UI_TYPE_WINDOW, UiWindow))
|
||||||
|
#define UI_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), UI_TYPE_WINDOW, UiWindowClass))
|
||||||
|
#define UI_IS_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), UI_TYPE_WINDOW))
|
||||||
|
#define UI_IS_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), UI_TYPE_WINDOW))
|
||||||
|
#define UI_WINDOW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), UI_TYPE_WINDOW, UiWindowClass))
|
||||||
|
|
||||||
|
typedef struct _UiWindow UiWindow;
|
||||||
|
typedef struct _UiWindowClass UiWindowClass;
|
||||||
|
#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL)))
|
||||||
|
#define _g_free0(var) (var = (g_free (var), NULL))
|
||||||
|
typedef void (*GSimpleActionActivateCallback) (GSimpleAction* action, GVariant* parameter, gpointer user_data);
|
||||||
|
|
||||||
|
struct _AudreyApplication {
|
||||||
|
AdwApplication parent_instance;
|
||||||
|
AudreyApplicationPrivate * priv;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _AudreyApplicationClass {
|
||||||
|
AdwApplicationClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
static gpointer audrey_application_parent_class = NULL;
|
||||||
|
|
||||||
|
VALA_EXTERN GType audrey_application_get_type (void) G_GNUC_CONST ;
|
||||||
|
G_DEFINE_AUTOPTR_CLEANUP_FUNC (AudreyApplication, g_object_unref)
|
||||||
|
VALA_EXTERN AudreyApplication* audrey_application_new (void);
|
||||||
|
VALA_EXTERN AudreyApplication* audrey_application_construct (GType object_type);
|
||||||
|
static void audrey_application_real_activate (GApplication* base);
|
||||||
|
VALA_EXTERN UiWindow* ui_window_new (GtkApplication* app);
|
||||||
|
VALA_EXTERN UiWindow* ui_window_construct (GType object_type,
|
||||||
|
GtkApplication* app);
|
||||||
|
VALA_EXTERN GType ui_window_get_type (void) G_GNUC_CONST ;
|
||||||
|
G_DEFINE_AUTOPTR_CLEANUP_FUNC (UiWindow, g_object_unref)
|
||||||
|
static void audrey_application_on_about_action (AudreyApplication* self);
|
||||||
|
static gchar** _vala_array_dup1 (gchar** self,
|
||||||
|
gssize length);
|
||||||
|
static void audrey_application_on_preferences_action (AudreyApplication* self);
|
||||||
|
static GObject * audrey_application_constructor (GType type,
|
||||||
|
guint n_construct_properties,
|
||||||
|
GObjectConstructParam * construct_properties);
|
||||||
|
static void _audrey_application_on_about_action_gsimple_action_activate_callback (GSimpleAction* action,
|
||||||
|
GVariant* parameter,
|
||||||
|
gpointer self);
|
||||||
|
static void _audrey_application_on_preferences_action_gsimple_action_activate_callback (GSimpleAction* action,
|
||||||
|
GVariant* parameter,
|
||||||
|
gpointer self);
|
||||||
|
static void _g_application_quit_gsimple_action_activate_callback (GSimpleAction* action,
|
||||||
|
GVariant* parameter,
|
||||||
|
gpointer self);
|
||||||
|
static void audrey_application_finalize (GObject * obj);
|
||||||
|
static GType audrey_application_get_type_once (void);
|
||||||
|
static void _vala_array_destroy (gpointer array,
|
||||||
|
gssize array_length,
|
||||||
|
GDestroyNotify destroy_func);
|
||||||
|
static void _vala_array_free (gpointer array,
|
||||||
|
gssize array_length,
|
||||||
|
GDestroyNotify destroy_func);
|
||||||
|
|
||||||
|
AudreyApplication*
|
||||||
|
audrey_application_construct (GType object_type)
|
||||||
|
{
|
||||||
|
AudreyApplication * self = NULL;
|
||||||
|
#line 3 "../src/application.vala"
|
||||||
|
self = (AudreyApplication*) g_object_new (object_type, "application-id", "eu.callcc.audrey", "flags", G_APPLICATION_DEFAULT_FLAGS, NULL);
|
||||||
|
#line 2 "../src/application.vala"
|
||||||
|
return self;
|
||||||
|
#line 115 "application.c"
|
||||||
|
}
|
||||||
|
|
||||||
|
AudreyApplication*
|
||||||
|
audrey_application_new (void)
|
||||||
|
{
|
||||||
|
#line 2 "../src/application.vala"
|
||||||
|
return audrey_application_construct (AUDREY_TYPE_APPLICATION);
|
||||||
|
#line 123 "application.c"
|
||||||
|
}
|
||||||
|
|
||||||
|
static gpointer
|
||||||
|
_g_object_ref0 (gpointer self)
|
||||||
|
{
|
||||||
|
#line 22 "../src/application.vala"
|
||||||
|
return self ? g_object_ref (self) : NULL;
|
||||||
|
#line 131 "application.c"
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
audrey_application_real_activate (GApplication* base)
|
||||||
|
{
|
||||||
|
AudreyApplication * self;
|
||||||
|
GtkWindow* _tmp0_ = NULL;
|
||||||
|
GtkWindow* _tmp1_;
|
||||||
|
GtkWindow* _tmp2_;
|
||||||
|
GtkWindow* _tmp3_;
|
||||||
|
GtkWindow* win = NULL;
|
||||||
|
GtkWindow* _tmp5_;
|
||||||
|
#line 19 "../src/application.vala"
|
||||||
|
self = (AudreyApplication*) base;
|
||||||
|
#line 20 "../src/application.vala"
|
||||||
|
G_APPLICATION_CLASS (audrey_application_parent_class)->activate ((GApplication*) G_TYPE_CHECK_INSTANCE_CAST (self, adw_application_get_type (), AdwApplication));
|
||||||
|
#line 22 "../src/application.vala"
|
||||||
|
_tmp1_ = gtk_application_get_active_window ((GtkApplication*) self);
|
||||||
|
#line 22 "../src/application.vala"
|
||||||
|
_tmp2_ = _tmp1_;
|
||||||
|
#line 22 "../src/application.vala"
|
||||||
|
_tmp3_ = _g_object_ref0 (_tmp2_);
|
||||||
|
#line 22 "../src/application.vala"
|
||||||
|
_tmp0_ = _tmp3_;
|
||||||
|
#line 22 "../src/application.vala"
|
||||||
|
if (_tmp0_ == NULL) {
|
||||||
|
#line 158 "application.c"
|
||||||
|
UiWindow* _tmp4_;
|
||||||
|
#line 22 "../src/application.vala"
|
||||||
|
_tmp4_ = ui_window_new ((GtkApplication*) self);
|
||||||
|
#line 22 "../src/application.vala"
|
||||||
|
g_object_ref_sink (_tmp4_);
|
||||||
|
#line 22 "../src/application.vala"
|
||||||
|
_g_object_unref0 (_tmp0_);
|
||||||
|
#line 22 "../src/application.vala"
|
||||||
|
_tmp0_ = (GtkWindow*) _tmp4_;
|
||||||
|
#line 168 "application.c"
|
||||||
|
}
|
||||||
|
#line 22 "../src/application.vala"
|
||||||
|
_tmp5_ = _tmp0_;
|
||||||
|
#line 22 "../src/application.vala"
|
||||||
|
_tmp0_ = NULL;
|
||||||
|
#line 22 "../src/application.vala"
|
||||||
|
win = _tmp5_;
|
||||||
|
#line 23 "../src/application.vala"
|
||||||
|
gtk_window_present (win);
|
||||||
|
#line 19 "../src/application.vala"
|
||||||
|
_g_object_unref0 (win);
|
||||||
|
#line 19 "../src/application.vala"
|
||||||
|
_g_object_unref0 (_tmp0_);
|
||||||
|
#line 182 "application.c"
|
||||||
|
}
|
||||||
|
|
||||||
|
static gchar**
|
||||||
|
_vala_array_dup1 (gchar** self,
|
||||||
|
gssize length)
|
||||||
|
{
|
||||||
|
#line 28 "../src/application.vala"
|
||||||
|
if (length >= 0) {
|
||||||
|
#line 191 "application.c"
|
||||||
|
gchar** result;
|
||||||
|
gssize i;
|
||||||
|
#line 28 "../src/application.vala"
|
||||||
|
result = g_new0 (gchar*, length + 1);
|
||||||
|
#line 28 "../src/application.vala"
|
||||||
|
for (i = 0; i < length; i++) {
|
||||||
|
#line 198 "application.c"
|
||||||
|
gchar* _tmp0_;
|
||||||
|
#line 28 "../src/application.vala"
|
||||||
|
_tmp0_ = g_strdup (self[i]);
|
||||||
|
#line 28 "../src/application.vala"
|
||||||
|
result[i] = _tmp0_;
|
||||||
|
#line 204 "application.c"
|
||||||
|
}
|
||||||
|
#line 28 "../src/application.vala"
|
||||||
|
return result;
|
||||||
|
#line 208 "application.c"
|
||||||
|
}
|
||||||
|
#line 28 "../src/application.vala"
|
||||||
|
return NULL;
|
||||||
|
#line 212 "application.c"
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
audrey_application_on_about_action (AudreyApplication* self)
|
||||||
|
{
|
||||||
|
gchar** developers = NULL;
|
||||||
|
gchar* _tmp0_;
|
||||||
|
gchar** _tmp1_;
|
||||||
|
gint developers_length1;
|
||||||
|
gint _developers_size_;
|
||||||
|
AdwAboutDialog* about = NULL;
|
||||||
|
gchar* _tmp2_;
|
||||||
|
gchar* _tmp3_;
|
||||||
|
gchar* _tmp4_;
|
||||||
|
gchar* _tmp5_;
|
||||||
|
gchar* _tmp6_;
|
||||||
|
gchar** _tmp7_;
|
||||||
|
gint _tmp7__length1;
|
||||||
|
gchar* _tmp8_;
|
||||||
|
AdwAboutDialog* _tmp9_ = NULL;
|
||||||
|
GtkWindow* _tmp10_;
|
||||||
|
GtkWindow* _tmp11_;
|
||||||
|
#line 26 "../src/application.vala"
|
||||||
|
g_return_if_fail (self != NULL);
|
||||||
|
#line 27 "../src/application.vala"
|
||||||
|
_tmp0_ = g_strdup ("Erica Z");
|
||||||
|
#line 27 "../src/application.vala"
|
||||||
|
_tmp1_ = g_new0 (gchar*, 1 + 1);
|
||||||
|
#line 27 "../src/application.vala"
|
||||||
|
_tmp1_[0] = _tmp0_;
|
||||||
|
#line 27 "../src/application.vala"
|
||||||
|
developers = _tmp1_;
|
||||||
|
#line 27 "../src/application.vala"
|
||||||
|
developers_length1 = 1;
|
||||||
|
#line 27 "../src/application.vala"
|
||||||
|
_developers_size_ = developers_length1;
|
||||||
|
#line 28 "../src/application.vala"
|
||||||
|
_tmp2_ = g_strdup ("audrey");
|
||||||
|
#line 28 "../src/application.vala"
|
||||||
|
_tmp3_ = g_strdup ("eu.callcc.audrey");
|
||||||
|
#line 28 "../src/application.vala"
|
||||||
|
_tmp4_ = g_strdup ("Erica Z");
|
||||||
|
#line 28 "../src/application.vala"
|
||||||
|
_tmp5_ = g_strdup (_ ("translator-credits"));
|
||||||
|
#line 28 "../src/application.vala"
|
||||||
|
_tmp6_ = g_strdup ("0.1.0");
|
||||||
|
#line 28 "../src/application.vala"
|
||||||
|
_tmp7_ = (developers != NULL) ? _vala_array_dup1 (developers, developers_length1) : developers;
|
||||||
|
#line 28 "../src/application.vala"
|
||||||
|
_tmp7__length1 = developers_length1;
|
||||||
|
#line 28 "../src/application.vala"
|
||||||
|
_tmp8_ = g_strdup ("© 2024 Erica Z");
|
||||||
|
#line 28 "../src/application.vala"
|
||||||
|
_tmp9_ = (AdwAboutDialog*) adw_about_dialog_new ();
|
||||||
|
#line 28 "../src/application.vala"
|
||||||
|
adw_about_dialog_set_application_name (_tmp9_, _tmp2_);
|
||||||
|
#line 28 "../src/application.vala"
|
||||||
|
_g_free0 (_tmp2_);
|
||||||
|
#line 28 "../src/application.vala"
|
||||||
|
adw_about_dialog_set_application_icon (_tmp9_, _tmp3_);
|
||||||
|
#line 28 "../src/application.vala"
|
||||||
|
_g_free0 (_tmp3_);
|
||||||
|
#line 28 "../src/application.vala"
|
||||||
|
adw_about_dialog_set_developer_name (_tmp9_, _tmp4_);
|
||||||
|
#line 28 "../src/application.vala"
|
||||||
|
_g_free0 (_tmp4_);
|
||||||
|
#line 28 "../src/application.vala"
|
||||||
|
adw_about_dialog_set_translator_credits (_tmp9_, _tmp5_);
|
||||||
|
#line 28 "../src/application.vala"
|
||||||
|
_g_free0 (_tmp5_);
|
||||||
|
#line 28 "../src/application.vala"
|
||||||
|
adw_about_dialog_set_version (_tmp9_, _tmp6_);
|
||||||
|
#line 28 "../src/application.vala"
|
||||||
|
_g_free0 (_tmp6_);
|
||||||
|
#line 28 "../src/application.vala"
|
||||||
|
adw_about_dialog_set_developers (_tmp9_, _tmp7_);
|
||||||
|
#line 28 "../src/application.vala"
|
||||||
|
_tmp7_ = (_vala_array_free (_tmp7_, _tmp7__length1, (GDestroyNotify) g_free), NULL);
|
||||||
|
#line 28 "../src/application.vala"
|
||||||
|
adw_about_dialog_set_copyright (_tmp9_, _tmp8_);
|
||||||
|
#line 28 "../src/application.vala"
|
||||||
|
_g_free0 (_tmp8_);
|
||||||
|
#line 28 "../src/application.vala"
|
||||||
|
g_object_ref_sink (_tmp9_);
|
||||||
|
#line 28 "../src/application.vala"
|
||||||
|
about = _tmp9_;
|
||||||
|
#line 38 "../src/application.vala"
|
||||||
|
_tmp10_ = gtk_application_get_active_window ((GtkApplication*) self);
|
||||||
|
#line 38 "../src/application.vala"
|
||||||
|
_tmp11_ = _tmp10_;
|
||||||
|
#line 38 "../src/application.vala"
|
||||||
|
adw_dialog_present ((AdwDialog*) about, (GtkWidget*) _tmp11_);
|
||||||
|
#line 26 "../src/application.vala"
|
||||||
|
_g_object_unref0 (about);
|
||||||
|
#line 26 "../src/application.vala"
|
||||||
|
developers = (_vala_array_free (developers, developers_length1, (GDestroyNotify) g_free), NULL);
|
||||||
|
#line 309 "application.c"
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
audrey_application_on_preferences_action (AudreyApplication* self)
|
||||||
|
{
|
||||||
|
#line 41 "../src/application.vala"
|
||||||
|
g_return_if_fail (self != NULL);
|
||||||
|
#line 42 "../src/application.vala"
|
||||||
|
g_message ("application.vala:42: app.preferences action activated");
|
||||||
|
#line 319 "application.c"
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_audrey_application_on_about_action_gsimple_action_activate_callback (GSimpleAction* action,
|
||||||
|
GVariant* parameter,
|
||||||
|
gpointer self)
|
||||||
|
{
|
||||||
|
#line 10 "../src/application.vala"
|
||||||
|
audrey_application_on_about_action ((AudreyApplication*) self);
|
||||||
|
#line 329 "application.c"
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_audrey_application_on_preferences_action_gsimple_action_activate_callback (GSimpleAction* action,
|
||||||
|
GVariant* parameter,
|
||||||
|
gpointer self)
|
||||||
|
{
|
||||||
|
#line 10 "../src/application.vala"
|
||||||
|
audrey_application_on_preferences_action ((AudreyApplication*) self);
|
||||||
|
#line 339 "application.c"
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_g_application_quit_gsimple_action_activate_callback (GSimpleAction* action,
|
||||||
|
GVariant* parameter,
|
||||||
|
gpointer self)
|
||||||
|
{
|
||||||
|
#line 10 "../src/application.vala"
|
||||||
|
g_application_quit ((GApplication*) self);
|
||||||
|
#line 349 "application.c"
|
||||||
|
}
|
||||||
|
|
||||||
|
static GObject *
|
||||||
|
audrey_application_constructor (GType type,
|
||||||
|
guint n_construct_properties,
|
||||||
|
GObjectConstructParam * construct_properties)
|
||||||
|
{
|
||||||
|
GObject * obj;
|
||||||
|
GObjectClass * parent_class;
|
||||||
|
AudreyApplication * self;
|
||||||
|
GActionEntry* action_entries = NULL;
|
||||||
|
GActionEntry _tmp0_ = {0};
|
||||||
|
GActionEntry _tmp1_ = {0};
|
||||||
|
GActionEntry _tmp2_ = {0};
|
||||||
|
GActionEntry* _tmp3_;
|
||||||
|
gint action_entries_length1;
|
||||||
|
gint _action_entries_size_;
|
||||||
|
GActionEntry* _tmp4_;
|
||||||
|
gint _tmp4__length1;
|
||||||
|
gchar* _tmp5_;
|
||||||
|
gchar** _tmp6_;
|
||||||
|
gchar** _tmp7_;
|
||||||
|
gint _tmp7__length1;
|
||||||
|
#line 9 "../src/application.vala"
|
||||||
|
parent_class = G_OBJECT_CLASS (audrey_application_parent_class);
|
||||||
|
#line 9 "../src/application.vala"
|
||||||
|
obj = parent_class->constructor (type, n_construct_properties, construct_properties);
|
||||||
|
#line 9 "../src/application.vala"
|
||||||
|
self = G_TYPE_CHECK_INSTANCE_CAST (obj, AUDREY_TYPE_APPLICATION, AudreyApplication);
|
||||||
|
#line 10 "../src/application.vala"
|
||||||
|
memset (&_tmp0_, 0, sizeof (GActionEntry));
|
||||||
|
#line 10 "../src/application.vala"
|
||||||
|
_tmp0_.name = "about";
|
||||||
|
#line 10 "../src/application.vala"
|
||||||
|
_tmp0_.activate = _audrey_application_on_about_action_gsimple_action_activate_callback;
|
||||||
|
#line 10 "../src/application.vala"
|
||||||
|
memset (&_tmp1_, 0, sizeof (GActionEntry));
|
||||||
|
#line 10 "../src/application.vala"
|
||||||
|
_tmp1_.name = "preferences";
|
||||||
|
#line 10 "../src/application.vala"
|
||||||
|
_tmp1_.activate = _audrey_application_on_preferences_action_gsimple_action_activate_callback;
|
||||||
|
#line 10 "../src/application.vala"
|
||||||
|
memset (&_tmp2_, 0, sizeof (GActionEntry));
|
||||||
|
#line 10 "../src/application.vala"
|
||||||
|
_tmp2_.name = "quit";
|
||||||
|
#line 10 "../src/application.vala"
|
||||||
|
_tmp2_.activate = _g_application_quit_gsimple_action_activate_callback;
|
||||||
|
#line 10 "../src/application.vala"
|
||||||
|
_tmp3_ = g_new0 (GActionEntry, 3);
|
||||||
|
#line 10 "../src/application.vala"
|
||||||
|
_tmp3_[0] = _tmp0_;
|
||||||
|
#line 10 "../src/application.vala"
|
||||||
|
_tmp3_[1] = _tmp1_;
|
||||||
|
#line 10 "../src/application.vala"
|
||||||
|
_tmp3_[2] = _tmp2_;
|
||||||
|
#line 10 "../src/application.vala"
|
||||||
|
action_entries = _tmp3_;
|
||||||
|
#line 10 "../src/application.vala"
|
||||||
|
action_entries_length1 = 3;
|
||||||
|
#line 10 "../src/application.vala"
|
||||||
|
_action_entries_size_ = action_entries_length1;
|
||||||
|
#line 15 "../src/application.vala"
|
||||||
|
_tmp4_ = action_entries;
|
||||||
|
#line 15 "../src/application.vala"
|
||||||
|
_tmp4__length1 = action_entries_length1;
|
||||||
|
#line 15 "../src/application.vala"
|
||||||
|
g_action_map_add_action_entries ((GActionMap*) self, _tmp4_, (gint) _tmp4__length1, self);
|
||||||
|
#line 16 "../src/application.vala"
|
||||||
|
_tmp5_ = g_strdup ("<primary>q");
|
||||||
|
#line 16 "../src/application.vala"
|
||||||
|
_tmp6_ = g_new0 (gchar*, 1 + 1);
|
||||||
|
#line 16 "../src/application.vala"
|
||||||
|
_tmp6_[0] = _tmp5_;
|
||||||
|
#line 16 "../src/application.vala"
|
||||||
|
_tmp7_ = _tmp6_;
|
||||||
|
#line 16 "../src/application.vala"
|
||||||
|
_tmp7__length1 = 1;
|
||||||
|
#line 16 "../src/application.vala"
|
||||||
|
gtk_application_set_accels_for_action ((GtkApplication*) self, "app.quit", _tmp7_);
|
||||||
|
#line 16 "../src/application.vala"
|
||||||
|
_tmp7_ = (_vala_array_free (_tmp7_, _tmp7__length1, (GDestroyNotify) g_free), NULL);
|
||||||
|
#line 9 "../src/application.vala"
|
||||||
|
action_entries = (g_free (action_entries), NULL);
|
||||||
|
#line 9 "../src/application.vala"
|
||||||
|
return obj;
|
||||||
|
#line 435 "application.c"
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
audrey_application_class_init (AudreyApplicationClass * klass,
|
||||||
|
gpointer klass_data)
|
||||||
|
{
|
||||||
|
#line 1 "../src/application.vala"
|
||||||
|
audrey_application_parent_class = g_type_class_peek_parent (klass);
|
||||||
|
#line 1 "../src/application.vala"
|
||||||
|
((GApplicationClass *) klass)->activate = (void (*) (GApplication*)) audrey_application_real_activate;
|
||||||
|
#line 1 "../src/application.vala"
|
||||||
|
G_OBJECT_CLASS (klass)->constructor = audrey_application_constructor;
|
||||||
|
#line 1 "../src/application.vala"
|
||||||
|
G_OBJECT_CLASS (klass)->finalize = audrey_application_finalize;
|
||||||
|
#line 450 "application.c"
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
audrey_application_instance_init (AudreyApplication * self,
|
||||||
|
gpointer klass)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
audrey_application_finalize (GObject * obj)
|
||||||
|
{
|
||||||
|
AudreyApplication * self;
|
||||||
|
#line 1 "../src/application.vala"
|
||||||
|
self = G_TYPE_CHECK_INSTANCE_CAST (obj, AUDREY_TYPE_APPLICATION, AudreyApplication);
|
||||||
|
#line 46 "../src/application.vala"
|
||||||
|
g_debug ("application.vala:46: destroying application");
|
||||||
|
#line 1 "../src/application.vala"
|
||||||
|
G_OBJECT_CLASS (audrey_application_parent_class)->finalize (obj);
|
||||||
|
#line 469 "application.c"
|
||||||
|
}
|
||||||
|
|
||||||
|
static GType
|
||||||
|
audrey_application_get_type_once (void)
|
||||||
|
{
|
||||||
|
static const GTypeInfo g_define_type_info = { sizeof (AudreyApplicationClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) audrey_application_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (AudreyApplication), 0, (GInstanceInitFunc) audrey_application_instance_init, NULL };
|
||||||
|
GType audrey_application_type_id;
|
||||||
|
audrey_application_type_id = g_type_register_static (adw_application_get_type (), "AudreyApplication", &g_define_type_info, 0);
|
||||||
|
return audrey_application_type_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
GType
|
||||||
|
audrey_application_get_type (void)
|
||||||
|
{
|
||||||
|
static volatile gsize audrey_application_type_id__once = 0;
|
||||||
|
if (g_once_init_enter (&audrey_application_type_id__once)) {
|
||||||
|
GType audrey_application_type_id;
|
||||||
|
audrey_application_type_id = audrey_application_get_type_once ();
|
||||||
|
g_once_init_leave (&audrey_application_type_id__once, audrey_application_type_id);
|
||||||
|
}
|
||||||
|
return audrey_application_type_id__once;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_vala_array_destroy (gpointer array,
|
||||||
|
gssize array_length,
|
||||||
|
GDestroyNotify destroy_func)
|
||||||
|
{
|
||||||
|
if ((array != NULL) && (destroy_func != NULL)) {
|
||||||
|
gssize i;
|
||||||
|
for (i = 0; i < array_length; i = i + 1) {
|
||||||
|
if (((gpointer*) array)[i] != NULL) {
|
||||||
|
destroy_func (((gpointer*) array)[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_vala_array_free (gpointer array,
|
||||||
|
gssize array_length,
|
||||||
|
GDestroyNotify destroy_func)
|
||||||
|
{
|
||||||
|
_vala_array_destroy (array, array_length, destroy_func);
|
||||||
|
g_free (array);
|
||||||
|
}
|
||||||
|
|
|
@ -1,49 +1,36 @@
|
||||||
mod imp {
|
use gtk::{glib, gio};
|
||||||
use crate::ui;
|
|
||||||
use adw::prelude::*;
|
|
||||||
use adw::subclass::prelude::*;
|
|
||||||
use gtk::glib;
|
|
||||||
|
|
||||||
#[derive(Default)]
|
pub mod ffi {
|
||||||
pub struct Application;
|
#[repr(C)]
|
||||||
|
pub struct AudreyApplication {
|
||||||
#[glib::object_subclass]
|
pub parent_instance: adw::ffi::AdwApplication,
|
||||||
impl ObjectSubclass for Application {
|
|
||||||
const NAME: &'static str = "AudreyApplication";
|
|
||||||
type Type = super::Application;
|
|
||||||
type ParentType = adw::Application;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ObjectImpl for Application {}
|
#[repr(C)]
|
||||||
|
pub struct AudreyApplicationClass {
|
||||||
impl ApplicationImpl for Application {
|
pub parent_class: adw::ffi::AdwApplicationClass,
|
||||||
fn activate(&self) {
|
|
||||||
self.parent_activate();
|
|
||||||
match self.obj().active_window() {
|
|
||||||
None => ui::Window::new(self.obj().as_ref()).present(),
|
|
||||||
Some(win) => win.present(),
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GtkApplicationImpl for Application {}
|
|
||||||
|
|
||||||
impl AdwApplicationImpl for Application {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
use gtk::{gio, glib};
|
extern "C" {
|
||||||
|
fn audrey_application_get_type() -> glib::ffi::GType;
|
||||||
|
fn audrey_application_new() -> *mut ffi::AudreyApplication;
|
||||||
|
}
|
||||||
|
|
||||||
glib::wrapper! {
|
glib::wrapper! {
|
||||||
pub struct Application(ObjectSubclass<imp::Application>)
|
pub struct Application(Object<ffi::AudreyApplication, ffi::AudreyApplicationClass>)
|
||||||
@extends adw::Application, gtk::Application, gio::Application,
|
@extends adw::Application, gtk::Application, gio::Application,
|
||||||
@implements gio::ActionGroup, gio::ActionMap;
|
@implements gio::ActionGroup, gio::ActionMap;
|
||||||
|
|
||||||
|
match fn {
|
||||||
|
type_ => || audrey_application_get_type(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Application {
|
impl Application {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
glib::Object::builder()
|
unsafe {
|
||||||
.property("application-id", "eu.callcc.audrey")
|
glib::translate::from_glib_full(audrey_application_new())
|
||||||
.property("flags", gio::ApplicationFlags::default())
|
}
|
||||||
.build()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,48 +0,0 @@
|
||||||
public class Audrey.Application : Adw.Application {
|
|
||||||
public Application () {
|
|
||||||
Object (
|
|
||||||
application_id: "eu.callcc.audrey",
|
|
||||||
flags: ApplicationFlags.DEFAULT_FLAGS
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
construct {
|
|
||||||
GLib.ActionEntry[] action_entries = {
|
|
||||||
{ "about", this.on_about_action },
|
|
||||||
{ "preferences", this.on_preferences_action },
|
|
||||||
{ "quit", this.quit }
|
|
||||||
};
|
|
||||||
this.add_action_entries (action_entries, this);
|
|
||||||
this.set_accels_for_action ("app.quit", {"<primary>q"});
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void activate () {
|
|
||||||
base.activate ();
|
|
||||||
// if this.active_window not null, this isnt the primary instance
|
|
||||||
var win = this.active_window ?? new Ui.Window (this);
|
|
||||||
win.present ();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void on_about_action () {
|
|
||||||
string[] developers = { "Erica Z" };
|
|
||||||
var about = new Adw.AboutDialog () {
|
|
||||||
application_name = "audrey",
|
|
||||||
application_icon = "eu.callcc.audrey",
|
|
||||||
developer_name = "Erica Z",
|
|
||||||
translator_credits = _("translator-credits"),
|
|
||||||
version = "0.1.0", // AUDREY_VERSION
|
|
||||||
developers = developers,
|
|
||||||
copyright = "© 2024 Erica Z",
|
|
||||||
};
|
|
||||||
|
|
||||||
about.present (this.active_window);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void on_preferences_action () {
|
|
||||||
message ("app.preferences action activated");
|
|
||||||
}
|
|
||||||
|
|
||||||
~Application () {
|
|
||||||
debug ("destroying application");
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
[CCode (cprefix = "", lower_case_cprefix = "", cheader_filename = "config.h")]
|
|
||||||
namespace Audrey.Config {
|
|
||||||
public const string GETTEXT_PACKAGE;
|
|
||||||
public const string LOCALEDIR;
|
|
||||||
public const string PACKAGE_VERSION;
|
|
||||||
}
|
|
17
src/globalconf.c
Normal file
17
src/globalconf.c
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
/* globalconf.c generated by valac 0.56.16, the Vala compiler
|
||||||
|
* generated from globalconf.vala, do not modify */
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
#define AUDREY_CONST_user_agent "audrey/linux"
|
||||||
|
#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
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
namespace Audrey.Const {
|
|
||||||
public const string user_agent = "audrey/linux";
|
|
||||||
}
|
|
|
@ -1,10 +1,8 @@
|
||||||
mod application;
|
mod application;
|
||||||
pub use application::Application;
|
use application::{Application};
|
||||||
|
|
||||||
pub mod ui;
|
|
||||||
|
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
use gtk::{gio, glib};
|
use gtk::{glib, gio};
|
||||||
|
|
||||||
extern crate libsecret;
|
extern crate libsecret;
|
||||||
|
|
||||||
|
@ -13,7 +11,8 @@ extern crate libsecret;
|
||||||
#[link(name = "json-glib-1.0")]
|
#[link(name = "json-glib-1.0")]
|
||||||
#[link(name = "mpv")]
|
#[link(name = "mpv")]
|
||||||
#[link(name = "soup-3.0")]
|
#[link(name = "soup-3.0")]
|
||||||
extern "C" {}
|
extern "C" {
|
||||||
|
}
|
||||||
|
|
||||||
fn main() -> glib::ExitCode {
|
fn main() -> glib::ExitCode {
|
||||||
gio::resources_register_include!("audrey.gresource").expect("could not register resources");
|
gio::resources_register_include!("audrey.gresource").expect("could not register resources");
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
int main (string[] args) {
|
|
||||||
// do it ourselves or it's broken
|
|
||||||
Gtk.disable_setlocale ();
|
|
||||||
Intl.bindtextdomain (Audrey.Config.GETTEXT_PACKAGE, Audrey.Config.LOCALEDIR);
|
|
||||||
Intl.bind_textdomain_codeset (Audrey.Config.GETTEXT_PACKAGE, "UTF-8");
|
|
||||||
Intl.textdomain (Audrey.Config.GETTEXT_PACKAGE);
|
|
||||||
Intl.setlocale (LocaleCategory.ALL, "");
|
|
||||||
Intl.setlocale (LocaleCategory.NUMERIC, "C.UTF-8");
|
|
||||||
|
|
||||||
var app = new Audrey.Application ();
|
|
||||||
return app.run (args);
|
|
||||||
}
|
|
|
@ -1,13 +1,13 @@
|
||||||
audrey_sources = [
|
audrey_sources = [
|
||||||
'application.vala',
|
'application.c',
|
||||||
'globalconf.vala',
|
'globalconf.c',
|
||||||
'mpris.vala',
|
'mpris.c',
|
||||||
'playbin.vala',
|
'playbin.c',
|
||||||
'subsonic.vala',
|
'subsonic.c',
|
||||||
'ui/play_queue.vala',
|
'ui/play_queue.c',
|
||||||
'ui/playbar.vala',
|
'ui/playbar.c',
|
||||||
'ui/setup.vala',
|
'ui/setup.c',
|
||||||
'ui/window.vala',
|
'ui/window.c',
|
||||||
]
|
]
|
||||||
|
|
||||||
audrey_deps = [
|
audrey_deps = [
|
||||||
|
@ -20,18 +20,10 @@ audrey_deps = [
|
||||||
dependency('mpv', version: '>= 2.3'),
|
dependency('mpv', version: '>= 2.3'),
|
||||||
]
|
]
|
||||||
|
|
||||||
audrey_sources += removeme
|
|
||||||
|
|
||||||
audrey_c = static_library(
|
audrey_c = static_library(
|
||||||
'audrey',
|
'audrey',
|
||||||
audrey_sources,
|
audrey_sources,
|
||||||
dependencies: audrey_deps,
|
dependencies: audrey_deps,
|
||||||
include_directories: config_inc,
|
include_directories: config_inc,
|
||||||
install: true,
|
install: true,
|
||||||
vala_args: [
|
|
||||||
'--vapidir',
|
|
||||||
meson.current_source_dir() / 'vapi',
|
|
||||||
'--gresources',
|
|
||||||
meson.project_source_root() / 'resources/audrey.gresource.xml',
|
|
||||||
],
|
|
||||||
)
|
)
|
||||||
|
|
4735
src/mpris.c
Normal file
4735
src/mpris.c
Normal file
File diff suppressed because it is too large
Load diff
254
src/mpris.vala
254
src/mpris.vala
|
@ -1,254 +0,0 @@
|
||||||
[DBus (name = "org.mpris.MediaPlayer2")]
|
|
||||||
class Mpris : Object {
|
|
||||||
internal signal void on_raise ();
|
|
||||||
internal signal void on_quit ();
|
|
||||||
|
|
||||||
public bool can_raise { get { return true; } }
|
|
||||||
public void raise () throws Error {
|
|
||||||
this.on_raise ();
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool can_quit { get { return true; } }
|
|
||||||
public void quit () throws Error {
|
|
||||||
this.on_quit ();
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool can_set_fullscreen { get { return false; } }
|
|
||||||
public bool fullscreen { get { return false; } set { assert (false); } }
|
|
||||||
public bool has_track_list { get { return false; } }
|
|
||||||
public string identity { owned get { return "audrey"; } }
|
|
||||||
public string desktop_entry { owned get { return "eu.callcc.audrey"; } }
|
|
||||||
public string[] supported_uri_schemes { owned get { return {}; } }
|
|
||||||
public string[] supported_mime_types { owned get { return {}; } }
|
|
||||||
|
|
||||||
internal Mpris (Ui.Window window) {
|
|
||||||
this.on_raise.connect (() => window.present ());
|
|
||||||
this.on_quit.connect (() => window.close ());
|
|
||||||
}
|
|
||||||
|
|
||||||
~Mpris () {
|
|
||||||
debug ("destroying mpris");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[DBus (name = "org.mpris.MediaPlayer2.Player")]
|
|
||||||
class MprisPlayer : Object {
|
|
||||||
internal signal void on_next ();
|
|
||||||
internal signal void on_previous ();
|
|
||||||
internal signal void on_pause ();
|
|
||||||
internal signal void on_play_pause ();
|
|
||||||
internal signal void on_stop ();
|
|
||||||
internal signal void on_play ();
|
|
||||||
internal signal void on_seek (int64 offset);
|
|
||||||
internal signal void on_set_position (ObjectPath track_id, int64 position);
|
|
||||||
|
|
||||||
public void next () throws Error { this.on_next (); }
|
|
||||||
public void previous () throws Error { this.on_previous (); }
|
|
||||||
public void pause () throws Error { print("pause\n");this.on_pause (); }
|
|
||||||
public void play_pause () throws Error { this.on_play_pause (); }
|
|
||||||
public void stop () throws Error { this.on_stop (); }
|
|
||||||
public void play () throws Error { this.on_play (); }
|
|
||||||
public void seek (int64 offset) throws Error { this.on_seek (offset); }
|
|
||||||
public void set_position (ObjectPath track_id, int64 position) throws Error { this.on_set_position (track_id, position); }
|
|
||||||
public void open_uri (string uri) throws Error { assert (false); }
|
|
||||||
|
|
||||||
public signal void seeked (int64 position);
|
|
||||||
|
|
||||||
public string playback_status { owned get; internal set; default = "Stopped"; }
|
|
||||||
public string loop_status { owned get; /*set;*/ default = "None"; }
|
|
||||||
public double rate { get; /*set*/ default = 1.0; }
|
|
||||||
public bool shuffle { get; /*set*/ default = false; }
|
|
||||||
public HashTable<string, Variant> metadata { owned get; private set; default = new HashTable<string, Variant> (null, null); }
|
|
||||||
public double volume { get; set; default = 1.0; }
|
|
||||||
[CCode (notify = false)]
|
|
||||||
public int64 position { get; default = 0; }
|
|
||||||
public double minimum_rate { get { return 1.0; } }
|
|
||||||
public double maximum_rate { get { return 1.0; } }
|
|
||||||
public bool can_go_next { get; private set; default = false; }
|
|
||||||
public bool can_go_previous { get; private set; default = false; }
|
|
||||||
public bool can_play { get; private set; default = false; }
|
|
||||||
public bool can_pause { get; private set; default = false; }
|
|
||||||
public bool can_seek { get; private set; default = false; }
|
|
||||||
[CCode (notify = false)]
|
|
||||||
public bool can_control { get { return true; } }
|
|
||||||
|
|
||||||
internal Subsonic.Client api { get; set; }
|
|
||||||
|
|
||||||
internal MprisPlayer (DBusConnection conn, Playbin playbin) {
|
|
||||||
playbin.bind_property (
|
|
||||||
"state",
|
|
||||||
this,
|
|
||||||
"playback_status",
|
|
||||||
BindingFlags.DEFAULT,
|
|
||||||
(binding, from, ref to) => {
|
|
||||||
switch (from.get_enum ()) {
|
|
||||||
case PlaybinState.STOPPED:
|
|
||||||
to.set_string ("Stopped");
|
|
||||||
this.can_go_next = false;
|
|
||||||
this.can_go_previous = false;
|
|
||||||
this.can_play = false;
|
|
||||||
this.can_pause = false;
|
|
||||||
this.can_seek = false;
|
|
||||||
return true;
|
|
||||||
case PlaybinState.PAUSED:
|
|
||||||
to.set_string ("Paused");
|
|
||||||
this.can_go_next = true;
|
|
||||||
this.can_go_previous = true;
|
|
||||||
this.can_play = true;
|
|
||||||
this.can_pause = true;
|
|
||||||
this.can_seek = true;
|
|
||||||
return true;
|
|
||||||
case PlaybinState.PLAYING:
|
|
||||||
to.set_string ("Playing");
|
|
||||||
this.can_go_next = true;
|
|
||||||
this.can_go_previous = true;
|
|
||||||
this.can_play = true;
|
|
||||||
this.can_pause = true;
|
|
||||||
this.can_seek = true;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
playbin.bind_property (
|
|
||||||
"volume",
|
|
||||||
this,
|
|
||||||
"volume",
|
|
||||||
BindingFlags.BIDIRECTIONAL,
|
|
||||||
(binding, from, ref to) => {
|
|
||||||
to.set_double (from.get_int () / 100.0);
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
(binding, from, ref to) => {
|
|
||||||
to.set_int ((int) (from.get_double () * 100.0));
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
playbin.new_track.connect ((playbin) => {
|
|
||||||
PlaybinSong song = (PlaybinSong) playbin.play_queue.get_item (playbin.play_queue_position);
|
|
||||||
|
|
||||||
var metadata = new HashTable<string, Variant> (null, null);
|
|
||||||
metadata["mpris:trackid"] = new ObjectPath (@"/eu/callcc/audrey/track/$(song.id)");
|
|
||||||
metadata["mpris:length"] = (int64) song.duration * 1000000;
|
|
||||||
if (this.api != null) metadata["mpris:artUrl"] = this.api.cover_art_uri (song.id);
|
|
||||||
metadata["xesam:album"] = song.album;
|
|
||||||
metadata["xesam:artist"] = new string[] {song.artist};
|
|
||||||
if (song.genre != null) metadata["xesam:genre"] = song.genre;
|
|
||||||
metadata["xesam:title"] = song.title;
|
|
||||||
metadata["xesam:trackNumber"] = song.track;
|
|
||||||
metadata["xesam:useCount"] = song.play_count;
|
|
||||||
// TODO metadata["xesam:userRating"] = song.starred != null ? 1.0 : 0.0;
|
|
||||||
|
|
||||||
this.metadata = metadata;
|
|
||||||
});
|
|
||||||
|
|
||||||
playbin.stopped.connect (() => {
|
|
||||||
this.metadata = new HashTable<string, Variant> (null, null);
|
|
||||||
});
|
|
||||||
|
|
||||||
this.on_next.connect (() => playbin.go_to_next_track ());
|
|
||||||
this.on_previous.connect (() => playbin.go_to_prev_track ());
|
|
||||||
this.on_play.connect (() => playbin.play ());
|
|
||||||
this.on_pause.connect (() => playbin.pause ());
|
|
||||||
this.on_play_pause.connect (() => {
|
|
||||||
if (playbin.state == PlaybinState.PAUSED) playbin.play ();
|
|
||||||
else if (playbin.state == PlaybinState.PLAYING) playbin.pause ();
|
|
||||||
});
|
|
||||||
this.on_stop.connect (() => {
|
|
||||||
playbin.stop ();
|
|
||||||
});
|
|
||||||
|
|
||||||
// TODO: seeking from mpris
|
|
||||||
// TODO: trigger the seeked signal when applicable
|
|
||||||
|
|
||||||
this.notify.connect ((p) => {
|
|
||||||
var builder = new VariantBuilder (VariantType.ARRAY);
|
|
||||||
var invalid_builder = new VariantBuilder (new VariantType ("as"));
|
|
||||||
|
|
||||||
string dbus_name;
|
|
||||||
Variant dbus_value;
|
|
||||||
|
|
||||||
switch (p.name) {
|
|
||||||
case "playback-status":
|
|
||||||
dbus_name = "PlaybackStatus";
|
|
||||||
dbus_value = this.playback_status;
|
|
||||||
break;
|
|
||||||
case "loop-status":
|
|
||||||
dbus_name = "LoopStatus";
|
|
||||||
dbus_value = this.loop_status;
|
|
||||||
break;
|
|
||||||
case "rate":
|
|
||||||
dbus_name = "Rate";
|
|
||||||
dbus_value = this.rate;
|
|
||||||
break;
|
|
||||||
case "shuffle":
|
|
||||||
dbus_name = "Shuffle";
|
|
||||||
dbus_value = this.shuffle;
|
|
||||||
break;
|
|
||||||
case "metadata":
|
|
||||||
dbus_name = "Metadata";
|
|
||||||
dbus_value = this.metadata;
|
|
||||||
break;
|
|
||||||
case "volume":
|
|
||||||
dbus_name = "Volume";
|
|
||||||
dbus_value = this.volume;
|
|
||||||
break;
|
|
||||||
case "minimum-rate":
|
|
||||||
dbus_name = "MinimumRate";
|
|
||||||
dbus_value = this.minimum_rate;
|
|
||||||
break;
|
|
||||||
case "maximum-rate":
|
|
||||||
dbus_name = "MaximumRate";
|
|
||||||
dbus_value = this.maximum_rate;
|
|
||||||
break;
|
|
||||||
case "can-go-next":
|
|
||||||
dbus_name = "CanGoNext";
|
|
||||||
dbus_value = this.can_go_next;
|
|
||||||
break;
|
|
||||||
case "can-go-previous":
|
|
||||||
dbus_name = "CanGoPrevious";
|
|
||||||
dbus_value = this.can_go_previous;
|
|
||||||
break;
|
|
||||||
case "can-play":
|
|
||||||
dbus_name = "CanPlay";
|
|
||||||
dbus_value = this.can_play;
|
|
||||||
break;
|
|
||||||
case "can-pause":
|
|
||||||
dbus_name = "CanPause";
|
|
||||||
dbus_value = this.can_pause;
|
|
||||||
break;
|
|
||||||
case "can-seek":
|
|
||||||
dbus_name = "CanSeek";
|
|
||||||
dbus_value = this.can_seek;
|
|
||||||
break;
|
|
||||||
case "api":
|
|
||||||
// internal, ignored
|
|
||||||
return;
|
|
||||||
default:
|
|
||||||
warning (@"unknown mpris player property $(p.name)");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.add ("{sv}", dbus_name, dbus_value);
|
|
||||||
|
|
||||||
try {
|
|
||||||
conn.emit_signal (
|
|
||||||
null,
|
|
||||||
"/org/mpris/MediaPlayer2",
|
|
||||||
"org.freedesktop.DBus.Properties",
|
|
||||||
"PropertiesChanged",
|
|
||||||
new Variant (
|
|
||||||
"(sa{sv}as)",
|
|
||||||
"org.mpris.MediaPlayer2.Player",
|
|
||||||
builder,
|
|
||||||
invalid_builder));
|
|
||||||
} catch (Error e) {
|
|
||||||
error (@"could not notify of mpris property changes: $(e.message)");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
~MprisPlayer () {
|
|
||||||
debug ("destroying mpris player");
|
|
||||||
}
|
|
||||||
}
|
|
3647
src/playbin.c
Normal file
3647
src/playbin.c
Normal file
File diff suppressed because it is too large
Load diff
438
src/playbin.vala
438
src/playbin.vala
|
@ -1,438 +0,0 @@
|
||||||
public enum PlaybinState {
|
|
||||||
STOPPED,
|
|
||||||
PAUSED,
|
|
||||||
PLAYING,
|
|
||||||
}
|
|
||||||
|
|
||||||
private struct CommandCallback {
|
|
||||||
unowned SourceFunc callback;
|
|
||||||
int error;
|
|
||||||
}
|
|
||||||
|
|
||||||
public class PlaybinSong : Object {
|
|
||||||
private Subsonic.Song inner;
|
|
||||||
public string id { get { return inner.id; } }
|
|
||||||
public string title { get { return inner.title; } }
|
|
||||||
public string artist { get { return inner.artist; } }
|
|
||||||
public string album { get { return inner.album; } }
|
|
||||||
public string? genre { get { return inner.genre; } }
|
|
||||||
public int64 duration { get { return inner.duration; } }
|
|
||||||
public int64 track { get { return inner.track; } }
|
|
||||||
public int64 play_count { get { return inner.play_count; } }
|
|
||||||
|
|
||||||
public Gdk.Paintable? thumbnail { get; private set; }
|
|
||||||
|
|
||||||
private Cancellable cancel_loading_thumbnail;
|
|
||||||
|
|
||||||
public PlaybinSong (Subsonic.Client api, Subsonic.Song song) {
|
|
||||||
this.api = api;
|
|
||||||
this.inner = song;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Subsonic.Client api;
|
|
||||||
|
|
||||||
public void need_cover_art () {
|
|
||||||
/* TODO
|
|
||||||
if (this.cancel_loading_thumbnail != null) return;
|
|
||||||
if (this.thumbnail != null) return;
|
|
||||||
|
|
||||||
this.cancel_loading_thumbnail = new Cancellable ();
|
|
||||||
// TODO: dpi scaling maybe?? probably
|
|
||||||
api.cover_art.begin (this.id, 50, Priority.LOW, this.cancel_loading_thumbnail, (obj, res) => {
|
|
||||||
try {
|
|
||||||
var pixbuf = api.cover_art.end (res);
|
|
||||||
this.thumbnail = Gdk.Texture.for_pixbuf (pixbuf);
|
|
||||||
} catch (Error e) {
|
|
||||||
if (!(e is IOError.CANCELLED)) {
|
|
||||||
warning ("could not fetch cover art for song %s: %s", this.id, e.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.cancel_loading_thumbnail = null;
|
|
||||||
});
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
~PlaybinSong () {
|
|
||||||
if (this.cancel_loading_thumbnail != null) {
|
|
||||||
this.cancel_loading_thumbnail.cancel ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class Playbin : GLib.Object {
|
|
||||||
private Mpv.Handle mpv = new Mpv.Handle ();
|
|
||||||
private int _volume = 100;
|
|
||||||
private bool _mute = false;
|
|
||||||
private ListStore _play_queue = new ListStore (typeof (PlaybinSong));
|
|
||||||
|
|
||||||
// try to prevent wait_event to be called twice
|
|
||||||
private bool is_handling_event = false;
|
|
||||||
|
|
||||||
public PlaybinState state { get; private set; default = PlaybinState.STOPPED; }
|
|
||||||
|
|
||||||
public int volume {
|
|
||||||
get { return _volume; }
|
|
||||||
set {
|
|
||||||
var ret = mpv.set_property_int64 ("volume", value);
|
|
||||||
if (ret >= 0) {
|
|
||||||
_volume = value;
|
|
||||||
} else {
|
|
||||||
warning ("failed to set volume: %s", ret.to_string ());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool mute {
|
|
||||||
get { return _mute; }
|
|
||||||
set {
|
|
||||||
var ret = mpv.set_property_flag ("mute", value);
|
|
||||||
if (ret >= 0) {
|
|
||||||
_mute = value;
|
|
||||||
} else {
|
|
||||||
warning ("failed to set mute status: %s", ret.to_string ());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// invariant: negative iff stopped, otherwise < play queue length
|
|
||||||
public int play_queue_position { get; private set; default = -1; }
|
|
||||||
|
|
||||||
// signalled when a new track is current
|
|
||||||
public signal void new_track ();
|
|
||||||
// signalled when the last track is over
|
|
||||||
public signal void stopped ();
|
|
||||||
|
|
||||||
// these are mostly synced with mpv
|
|
||||||
public double position { get; private set; default = 0.0; }
|
|
||||||
public double duration { get; private set; default = 0.0; }
|
|
||||||
|
|
||||||
public weak Subsonic.Client api { get; set; default = null; }
|
|
||||||
|
|
||||||
public ListModel play_queue { get { return this._play_queue; } }
|
|
||||||
public uint play_queue_length { get; private set; default = 0; }
|
|
||||||
|
|
||||||
private async Mpv.Error mpv_command_async (string[] args) {
|
|
||||||
CommandCallback cc = {};
|
|
||||||
|
|
||||||
this.mpv.command_async ((uint64) &cc, args);
|
|
||||||
|
|
||||||
cc.callback = this.mpv_command_async.callback;
|
|
||||||
yield;
|
|
||||||
return cc.error;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Playbin () {
|
|
||||||
assert (this.mpv.initialize () >= 0);
|
|
||||||
assert (this.mpv.set_property_string ("audio-client-name", "audrey") >= 0);
|
|
||||||
assert (this.mpv.set_property_string ("user-agent", Audrey.Const.user_agent) >= 0);
|
|
||||||
assert (this.mpv.set_property_string ("video", "no") >= 0);
|
|
||||||
assert (this.mpv.set_property_string ("prefetch-playlist", "yes") >= 0);
|
|
||||||
assert (this.mpv.set_property_string ("gapless-audio", "yes") >= 0);
|
|
||||||
assert (this.mpv.observe_property (0, "time-pos", Mpv.Format.DOUBLE) >= 0);
|
|
||||||
assert (this.mpv.observe_property (1, "duration", Mpv.Format.DOUBLE) >= 0);
|
|
||||||
assert (this.mpv.observe_property (2, "playlist-pos", Mpv.Format.INT64) >= 0);
|
|
||||||
assert (this.mpv.observe_property (3, "pause", Mpv.Format.FLAG) >= 0);
|
|
||||||
|
|
||||||
this.mpv.wakeup_callback = () => {
|
|
||||||
Idle.add (() => {
|
|
||||||
if (this.is_handling_event) {
|
|
||||||
warning ("main thread mpv wakeup callback called twice");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
this.is_handling_event = true;
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
var event = this.mpv.wait_event (0.0);
|
|
||||||
if (event.event_id == Mpv.EventId.NONE) break;
|
|
||||||
|
|
||||||
switch (event.event_id) {
|
|
||||||
case Mpv.EventId.PROPERTY_CHANGE:
|
|
||||||
var data = event.parse_property ();
|
|
||||||
switch (event.reply_userdata) {
|
|
||||||
case 0:
|
|
||||||
assert (data.name == "time-pos");
|
|
||||||
if (data.format == Mpv.Format.NONE) {
|
|
||||||
this.position = 0.0;
|
|
||||||
} else {
|
|
||||||
this.position = data.parse_double ();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 1:
|
|
||||||
assert (data.name == "duration");
|
|
||||||
if (data.format == Mpv.Format.NONE) {
|
|
||||||
// this.duration = 0.0; i think this prevents the fallback below from working
|
|
||||||
} else {
|
|
||||||
this.duration = data.parse_double ();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
// here as a sanity check
|
|
||||||
// should always match our own play_queu_position/state
|
|
||||||
assert (data.name == "playlist-pos");
|
|
||||||
int64 playlist_pos = data.parse_int64 ();
|
|
||||||
if (playlist_pos < 0) {
|
|
||||||
if (this.state != PlaybinState.STOPPED) {
|
|
||||||
error ("mpv has no current playlist entry, but we think it's index %d", this.play_queue_position);
|
|
||||||
}
|
|
||||||
assert (this.play_queue_position < 0);
|
|
||||||
} else {
|
|
||||||
if (this.state == PlaybinState.STOPPED) {
|
|
||||||
error ("mpv is at playlist entry %d, but we're stopped", (int) playlist_pos);
|
|
||||||
}
|
|
||||||
if (this.play_queue_position != (int) playlist_pos) {
|
|
||||||
error ("mpv is at playlist entry %d, but we think it's %d", (int) playlist_pos, this.play_queue_position);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 3:
|
|
||||||
// also here as a sanity check
|
|
||||||
// should always match our own state
|
|
||||||
assert (data.name == "pause");
|
|
||||||
bool pause = data.parse_flag ();
|
|
||||||
if (pause && this.state != PlaybinState.PAUSED) {
|
|
||||||
error (@"mpv is paused, but we are @(this.state)");
|
|
||||||
}
|
|
||||||
if (!pause && this.state == PlaybinState.PAUSED) {
|
|
||||||
error ("mpv is not paused, but we are paused");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
assert (false);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Mpv.EventId.START_FILE:
|
|
||||||
debug ("START_FILE received");
|
|
||||||
|
|
||||||
// estimate duration from api data
|
|
||||||
// while mpv doesn't know it
|
|
||||||
this.duration = ((PlaybinSong) this._play_queue.get_item (this.play_queue_position)).duration;
|
|
||||||
|
|
||||||
this.new_track ();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Mpv.EventId.END_FILE:
|
|
||||||
var data = event.parse_end_file ();
|
|
||||||
debug (@"END_FILE received (reason: $(data.reason))");
|
|
||||||
|
|
||||||
if (data.error < 0) {
|
|
||||||
warning ("playback of track aborted: %s", data.error.to_string ());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.reason == Mpv.EndFileReason.EOF) {
|
|
||||||
// assume this is a proper transition
|
|
||||||
this.play_queue_position += 1;
|
|
||||||
|
|
||||||
if (this.play_queue_position == this._play_queue.get_n_items ()) {
|
|
||||||
// reached the end (?)
|
|
||||||
this.state = PlaybinState.STOPPED;
|
|
||||||
this.play_queue_position = -1;
|
|
||||||
this.stopped ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Mpv.EventId.COMMAND_REPLY:
|
|
||||||
unowned CommandCallback *cc = (CommandCallback *) event.reply_userdata;
|
|
||||||
cc.error = event.error;
|
|
||||||
cc.callback ();
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
// ignore by default
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.is_handling_event = false;
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public void seek (double position) {
|
|
||||||
var rc = this.mpv.command ({"seek", position.to_string (), "absolute"});
|
|
||||||
if (rc < 0) {
|
|
||||||
warning (@"could not seek to $position: $rc");
|
|
||||||
} else {
|
|
||||||
this.position = position;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// manually changes which track in the play queue to play
|
|
||||||
public void select_track (uint position)
|
|
||||||
requires (position < this.play_queue.get_n_items ())
|
|
||||||
{
|
|
||||||
assert (this.mpv.command ({"playlist-play-index", position.to_string ()}) >= 0);
|
|
||||||
this.play_queue_position = (int) position;
|
|
||||||
this.state = PlaybinState.PLAYING;
|
|
||||||
this.play (); // make sure mpv actually starts playing the track
|
|
||||||
}
|
|
||||||
|
|
||||||
public void pause () {
|
|
||||||
assert (this.state != PlaybinState.STOPPED);
|
|
||||||
this.state = PlaybinState.PAUSED;
|
|
||||||
debug ("setting state to paused");
|
|
||||||
// TODO: abstract away this handling around mpv api a bit for auto debug printing
|
|
||||||
var ret = this.mpv.set_property_flag("pause", true);
|
|
||||||
if (ret != 0) {
|
|
||||||
debug (@"failed to set state to paused ($(ret)): $(ret.to_string())");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void play () {
|
|
||||||
if (this.state == PlaybinState.STOPPED) {
|
|
||||||
// allow only when playlist is not empty
|
|
||||||
// and start from the top
|
|
||||||
assert (this._play_queue.get_n_items () > 0);
|
|
||||||
this.select_track (0);
|
|
||||||
} else {
|
|
||||||
this.state = PlaybinState.PLAYING;
|
|
||||||
debug ("setting state to playing");
|
|
||||||
var ret = this.mpv.set_property_flag("pause", false);
|
|
||||||
if (ret != 0) {
|
|
||||||
debug (@"failed to set state to playing ($(ret)): $(ret.to_string())");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void go_to_next_track ()
|
|
||||||
requires (this.state != PlaybinState.STOPPED)
|
|
||||||
{
|
|
||||||
if (this.play_queue_position+1 < this._play_queue.get_n_items ()) {
|
|
||||||
this.play_queue_position += 1;
|
|
||||||
assert (this.mpv.command ({"playlist-next-playlist"}) >= 0);
|
|
||||||
} else {
|
|
||||||
warning ("tried to skip forward at end of play queue, ignoring");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void go_to_prev_track ()
|
|
||||||
requires (this.state != PlaybinState.STOPPED)
|
|
||||||
{
|
|
||||||
if (this.play_queue_position > 0) {
|
|
||||||
this.play_queue_position -= 1;
|
|
||||||
assert (this.mpv.command ({"playlist-prev-playlist"}) >= 0);
|
|
||||||
} else {
|
|
||||||
warning ("tried to skip to prev track at start of play queue, ignoring");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void remove_track (uint position)
|
|
||||||
requires (position < this._play_queue.get_n_items ())
|
|
||||||
{
|
|
||||||
assert (this.mpv.command({"playlist-remove", position.to_string ()}) >= 0);
|
|
||||||
this._play_queue.remove (position);
|
|
||||||
this.play_queue_length -= 1;
|
|
||||||
if (this.play_queue_position > position) this.play_queue_position -= 1;
|
|
||||||
if (this.play_queue_position == this._play_queue.get_n_items ()) {
|
|
||||||
// we just killed the last track
|
|
||||||
this.state = PlaybinState.STOPPED;
|
|
||||||
this.play_queue_position = -1;
|
|
||||||
this.stopped ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clear () {
|
|
||||||
assert (this.mpv.command({"playlist-clear"}) >= 0);
|
|
||||||
if (this.state != PlaybinState.STOPPED) {
|
|
||||||
assert (this.mpv.command({"playlist-remove", "current"}) >= 0);
|
|
||||||
}
|
|
||||||
this.state = PlaybinState.STOPPED;
|
|
||||||
this._play_queue.remove_all ();
|
|
||||||
this.play_queue_length = 0;
|
|
||||||
this.play_queue_position = -1;
|
|
||||||
|
|
||||||
this.stopped ();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void append_track (Subsonic.Song song) {
|
|
||||||
assert (this.mpv.command ({
|
|
||||||
"loadfile",
|
|
||||||
this.api.stream_uri (song.id),
|
|
||||||
"append",
|
|
||||||
}) >= 0);
|
|
||||||
this._play_queue.append (new PlaybinSong (this.api, song));
|
|
||||||
this.play_queue_length += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async void append_track_async (Subsonic.Song song) {
|
|
||||||
var err = yield this.mpv_command_async ({
|
|
||||||
"loadfile",
|
|
||||||
this.api.stream_uri (song.id),
|
|
||||||
"append",
|
|
||||||
});
|
|
||||||
assert (err >= 0);
|
|
||||||
|
|
||||||
this._play_queue.append (new PlaybinSong (this.api, song));
|
|
||||||
this.play_queue_length += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void move_track (uint from, uint to)
|
|
||||||
requires (from < this._play_queue.get_n_items ())
|
|
||||||
requires (to < this._play_queue.get_n_items ())
|
|
||||||
{
|
|
||||||
debug (@"moving track $from to $to");
|
|
||||||
|
|
||||||
if (from < to) {
|
|
||||||
// why offset to? because if the playlist is 01234,
|
|
||||||
// mpv takes "move 1 to 3" to mean 02134, not 02314
|
|
||||||
// that is, the target is a "gap", not a playlist entry
|
|
||||||
// from -> 0 1 2 3 4 5
|
|
||||||
// to -> 0 1 2 3 4 5 6
|
|
||||||
assert(this.mpv.command({
|
|
||||||
"playlist-move",
|
|
||||||
from.to_string (),
|
|
||||||
(to+1).to_string (),
|
|
||||||
}) >= 0);
|
|
||||||
|
|
||||||
// F0123T -> 0123TF
|
|
||||||
var additions = new Object[to-from+1];
|
|
||||||
for (uint i = from+1; i < to; i += 1) {
|
|
||||||
additions[i-from-1] = this._play_queue.get_item (i);
|
|
||||||
}
|
|
||||||
additions[to-from-1] = this._play_queue.get_item (to);
|
|
||||||
additions[to-from] = this._play_queue.get_item (from);
|
|
||||||
this._play_queue.splice(from, to-from+1, additions);
|
|
||||||
|
|
||||||
if (this.play_queue_position == (int) from) this.play_queue_position = (int) to;
|
|
||||||
else if (this.play_queue_position > (int) from && this.play_queue_position <= (int) to) this.play_queue_position -= 1;
|
|
||||||
} else if (from > to) {
|
|
||||||
assert(this.mpv.command({
|
|
||||||
"playlist-move",
|
|
||||||
from.to_string (),
|
|
||||||
to.to_string (),
|
|
||||||
}) >= 0);
|
|
||||||
|
|
||||||
// T0123F -> FT0123
|
|
||||||
var additions = new Object[from-to+1];
|
|
||||||
additions[0] = this._play_queue.get_item (from);
|
|
||||||
for (uint i = to; i < from; i += 1) {
|
|
||||||
additions[i-to+1] = this._play_queue.get_item (i);
|
|
||||||
}
|
|
||||||
this._play_queue.splice (to, from-to+1, additions);
|
|
||||||
|
|
||||||
if (this.play_queue_position == (int) from) this.play_queue_position = (int) to;
|
|
||||||
else if (this.play_queue_position >= (int) to && this.play_queue_position < (int) from) this.play_queue_position += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void stop () {
|
|
||||||
debug ("stopping playback");
|
|
||||||
// don't clear the playlist, just in case (less state changes to sync)
|
|
||||||
assert(this.mpv.command({"stop", "keep-playlist"}) >= 0);
|
|
||||||
this.state = PlaybinState.STOPPED;
|
|
||||||
this.play_queue_position = -1;
|
|
||||||
this.stopped ();
|
|
||||||
}
|
|
||||||
|
|
||||||
~Playbin () {
|
|
||||||
debug ("destroying playbin");
|
|
||||||
}
|
|
||||||
}
|
|
2597
src/subsonic.c
Normal file
2597
src/subsonic.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,236 +0,0 @@
|
||||||
public errordomain Subsonic.Error {
|
|
||||||
BAD_AUTHN,
|
|
||||||
ERROR,
|
|
||||||
}
|
|
||||||
|
|
||||||
public delegate void Subsonic.SongCallback (Song song);
|
|
||||||
|
|
||||||
public class Subsonic.Artist : Object {
|
|
||||||
public string index;
|
|
||||||
public string id;
|
|
||||||
public string name { get; private set; }
|
|
||||||
public string? cover_art;
|
|
||||||
public string? artist_image_url;
|
|
||||||
public int64 album_count;
|
|
||||||
|
|
||||||
public Artist (string index, Json.Reader reader) {
|
|
||||||
this.index = index;
|
|
||||||
|
|
||||||
reader.read_member ("id");
|
|
||||||
this.id = reader.get_string_value ();
|
|
||||||
reader.end_member ();
|
|
||||||
|
|
||||||
reader.read_member ("name");
|
|
||||||
this.name = reader.get_string_value ();
|
|
||||||
reader.end_member ();
|
|
||||||
|
|
||||||
reader.read_member ("coverArt");
|
|
||||||
this.cover_art = reader.get_string_value ();
|
|
||||||
reader.end_member ();
|
|
||||||
|
|
||||||
reader.read_member ("artistImageUrl");
|
|
||||||
this.artist_image_url = reader.get_string_value ();
|
|
||||||
reader.end_member ();
|
|
||||||
|
|
||||||
reader.read_member ("albumCount");
|
|
||||||
this.album_count = reader.get_int_value ();
|
|
||||||
reader.end_member ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class Subsonic.Album : Object {
|
|
||||||
public string id;
|
|
||||||
public string name;
|
|
||||||
|
|
||||||
public Album (Json.Reader reader) {
|
|
||||||
reader.read_member ("id");
|
|
||||||
this.id = reader.get_string_value ();
|
|
||||||
reader.end_member ();
|
|
||||||
|
|
||||||
reader.read_member ("name");
|
|
||||||
this.name = reader.get_string_value ();
|
|
||||||
reader.end_member ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public struct Subsonic.Song {
|
|
||||||
public string id;
|
|
||||||
public string title;
|
|
||||||
public string album;
|
|
||||||
public string artist;
|
|
||||||
public int64 track;
|
|
||||||
public int64 year;
|
|
||||||
public DateTime? starred; // TODO
|
|
||||||
public int64 duration;
|
|
||||||
public int64 play_count;
|
|
||||||
public string? genre;
|
|
||||||
public string cover_art;
|
|
||||||
|
|
||||||
public Song (Json.Reader reader) {
|
|
||||||
reader.read_member ("id");
|
|
||||||
this.id = reader.get_string_value ();
|
|
||||||
reader.end_member ();
|
|
||||||
|
|
||||||
reader.read_member ("title");
|
|
||||||
this.title = reader.get_string_value ();
|
|
||||||
reader.end_member ();
|
|
||||||
|
|
||||||
reader.read_member ("album");
|
|
||||||
this.album = reader.get_string_value ();
|
|
||||||
reader.end_member ();
|
|
||||||
|
|
||||||
reader.read_member ("artist");
|
|
||||||
this.artist = reader.get_string_value ();
|
|
||||||
reader.end_member ();
|
|
||||||
|
|
||||||
reader.read_member ("track");
|
|
||||||
this.track = reader.get_int_value ();
|
|
||||||
reader.end_member ();
|
|
||||||
|
|
||||||
reader.read_member ("year");
|
|
||||||
this.year = reader.get_int_value ();
|
|
||||||
reader.end_member ();
|
|
||||||
|
|
||||||
reader.read_member ("duration");
|
|
||||||
this.duration = reader.get_int_value ();
|
|
||||||
reader.end_member ();
|
|
||||||
|
|
||||||
reader.read_member ("playCount");
|
|
||||||
this.play_count = reader.get_int_value ();
|
|
||||||
reader.end_member ();
|
|
||||||
|
|
||||||
reader.read_member ("genre");
|
|
||||||
this.genre = reader.get_string_value ();
|
|
||||||
reader.end_member ();
|
|
||||||
|
|
||||||
reader.read_member ("coverArt");
|
|
||||||
this.cover_art = reader.get_string_value ();
|
|
||||||
reader.end_member ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class Subsonic.Client : Object {
|
|
||||||
private Soup.Session session;
|
|
||||||
private string url;
|
|
||||||
private string parameters;
|
|
||||||
|
|
||||||
public Client.with_token (string url, string username, string token, string salt) {
|
|
||||||
this.url = url;
|
|
||||||
this.parameters = @"u=$(Uri.escape_string(username))&t=$(Uri.escape_string(token))&s=$(Uri.escape_string(salt))&v=1.16.1&c=eu.callcc.audrey";
|
|
||||||
|
|
||||||
this.session = new Soup.Session ();
|
|
||||||
this.session.user_agent = Audrey.Const.user_agent;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void unwrap_response (Json.Reader reader) throws GLib.Error {
|
|
||||||
reader.read_member ("subsonic-response");
|
|
||||||
|
|
||||||
reader.read_member ("status");
|
|
||||||
if (reader.get_string_value () != "ok") {
|
|
||||||
reader.end_member ();
|
|
||||||
reader.read_member ("error");
|
|
||||||
reader.read_member ("message");
|
|
||||||
throw new Subsonic.Error.ERROR (reader.get_string_value () ?? "???");
|
|
||||||
}
|
|
||||||
reader.end_member();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async void ping () throws GLib.Error {
|
|
||||||
var msg = new Soup.Message ("GET", @"$(this.url)/rest/ping?f=json&$(this.parameters)");
|
|
||||||
if (msg == null) {
|
|
||||||
throw new Subsonic.Error.BAD_AUTHN ("Bad message");
|
|
||||||
}
|
|
||||||
|
|
||||||
var bytes = yield this.session.send_and_read_async (msg, Priority.DEFAULT, null);
|
|
||||||
assert (msg.get_status () == Soup.Status.OK);
|
|
||||||
|
|
||||||
var parser = new Json.Parser ();
|
|
||||||
parser.load_from_data ((string) bytes.get_data ());
|
|
||||||
|
|
||||||
var reader = new Json.Reader (parser.get_root ());
|
|
||||||
this.unwrap_response (reader);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async void scrobble (string id) throws GLib.Error {
|
|
||||||
var msg = new Soup.Message ("GET", @"$(this.url)/rest/scrobble?id=$(Uri.escape_string (id))&f=json&$(this.parameters)");
|
|
||||||
assert (msg != null);
|
|
||||||
|
|
||||||
var bytes = yield this.session.send_and_read_async (msg, Priority.DEFAULT, null);
|
|
||||||
assert (msg.get_status () == Soup.Status.OK);
|
|
||||||
|
|
||||||
var parser = new Json.Parser ();
|
|
||||||
parser.load_from_data ((string) bytes.get_data ());
|
|
||||||
|
|
||||||
var reader = new Json.Reader (parser.get_root ());
|
|
||||||
this.unwrap_response (reader);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async void get_random_songs (string? parameters, SongCallback callback) throws GLib.Error {
|
|
||||||
string str_parameters;
|
|
||||||
if (parameters == null) {
|
|
||||||
str_parameters = "";
|
|
||||||
} else {
|
|
||||||
str_parameters = @"$parameters&";
|
|
||||||
}
|
|
||||||
|
|
||||||
var msg = new Soup.Message("GET", @"$(this.url)/rest/getRandomSongs?$(str_parameters)size=500&f=json&$(this.parameters)");
|
|
||||||
assert (msg != null);
|
|
||||||
|
|
||||||
var bytes = yield this.session.send_and_read_async (msg, Priority.DEFAULT, null);
|
|
||||||
assert (msg.get_status () == Soup.Status.OK);
|
|
||||||
|
|
||||||
var parser = new Json.Parser ();
|
|
||||||
parser.load_from_data ((string) bytes.get_data ());
|
|
||||||
|
|
||||||
var reader = new Json.Reader (parser.get_root ());
|
|
||||||
this.unwrap_response (reader);
|
|
||||||
|
|
||||||
reader.read_member ("randomSongs");
|
|
||||||
reader.read_member ("song");
|
|
||||||
|
|
||||||
for (int i = 0; i < reader.count_elements (); i += 1) {
|
|
||||||
reader.read_element (i);
|
|
||||||
callback (Song (reader));
|
|
||||||
reader.end_element ();
|
|
||||||
|
|
||||||
Idle.add (this.get_random_songs.callback);
|
|
||||||
yield;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert (reader.get_error () == null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public string stream_uri (string id) {
|
|
||||||
return @"$(this.url)/rest/stream?id=$(Uri.escape_string(id))&$(this.parameters)";
|
|
||||||
}
|
|
||||||
|
|
||||||
public string cover_art_uri (string id, int size = -1) {
|
|
||||||
if (size >= 0) {
|
|
||||||
return @"$(this.url)/rest/getCoverArt?id=$(Uri.escape_string(id))&$(this.parameters)";
|
|
||||||
} else {
|
|
||||||
return @"$(this.url)/rest/getCoverArt?size=$size&id=$(Uri.escape_string(id))&$(this.parameters)";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Gdk.Pixbuf cover_art (
|
|
||||||
string id,
|
|
||||||
int size = -1,
|
|
||||||
int priority = Priority.DEFAULT,
|
|
||||||
Cancellable? cancellable = null
|
|
||||||
)
|
|
||||||
throws GLib.Error
|
|
||||||
{
|
|
||||||
var msg = new Soup.Message("GET", this.cover_art_uri (id, size));
|
|
||||||
assert (msg != null);
|
|
||||||
|
|
||||||
var stream = yield this.session.send_async (msg, priority, cancellable);
|
|
||||||
if (msg.get_status () != Soup.Status.OK) {
|
|
||||||
warning ("could not load cover art for %s: %s", id, Soup.Status.get_phrase (msg.get_status ()));
|
|
||||||
}
|
|
||||||
return yield new Gdk.Pixbuf.from_stream_async (stream, cancellable);
|
|
||||||
}
|
|
||||||
|
|
||||||
~Client () {
|
|
||||||
debug ("destroying subsonic client");
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,2 +0,0 @@
|
||||||
mod window;
|
|
||||||
pub use window::Window;
|
|
1759
src/ui/play_queue.c
Normal file
1759
src/ui/play_queue.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,175 +0,0 @@
|
||||||
// song widget+drag behavior taken from gnome music
|
|
||||||
|
|
||||||
[GtkTemplate (ui = "/eu/callcc/audrey/play_queue_song.ui")]
|
|
||||||
class Ui.PlayQueueSong : Gtk.Box {
|
|
||||||
public bool draggable { get; set; default = false; }
|
|
||||||
public bool show_position { get; set; default = false; }
|
|
||||||
public bool show_artist { get; set; default = false; }
|
|
||||||
public bool show_cover { get; set; default = false; }
|
|
||||||
|
|
||||||
private bool _current = false;
|
|
||||||
public bool current {
|
|
||||||
get { return _current; }
|
|
||||||
set {
|
|
||||||
this._current = value;
|
|
||||||
if (value) {
|
|
||||||
this.add_css_class ("playing");
|
|
||||||
} else {
|
|
||||||
this.remove_css_class ("playing");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public uint displayed_position { get; set; }
|
|
||||||
public PlaybinSong song { get; set; }
|
|
||||||
|
|
||||||
private weak Playbin playbin;
|
|
||||||
public PlayQueueSong (Playbin playbin) {
|
|
||||||
this.playbin = playbin;
|
|
||||||
|
|
||||||
var action_group = new SimpleActionGroup ();
|
|
||||||
|
|
||||||
var remove = new SimpleAction ("remove", null);
|
|
||||||
remove.activate.connect (() => {
|
|
||||||
this.playbin.remove_track (this.displayed_position-1);
|
|
||||||
});
|
|
||||||
action_group.add_action (remove);
|
|
||||||
|
|
||||||
this.insert_action_group ("song", action_group);
|
|
||||||
}
|
|
||||||
|
|
||||||
private ulong connection;
|
|
||||||
public void bind (uint position, PlaybinSong song) {
|
|
||||||
this.displayed_position = position+1;
|
|
||||||
this.song = song;
|
|
||||||
this.current = this.playbin.play_queue_position == position;
|
|
||||||
this.connection = this.playbin.notify["play-queue-position"].connect (() => {
|
|
||||||
this.current = this.playbin.play_queue_position == position;
|
|
||||||
});
|
|
||||||
|
|
||||||
song.need_cover_art ();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void unbind () {
|
|
||||||
this.playbin.disconnect (this.connection);
|
|
||||||
}
|
|
||||||
|
|
||||||
[GtkCallback] private string format_duration (int duration) {
|
|
||||||
return "%02d:%02d".printf(duration/60, duration%60);
|
|
||||||
}
|
|
||||||
|
|
||||||
[GtkCallback] private string star_button_icon_name (DateTime? starred) {
|
|
||||||
return starred == null ? "non-starred" : "starred";
|
|
||||||
}
|
|
||||||
|
|
||||||
private double drag_x;
|
|
||||||
private double drag_y;
|
|
||||||
|
|
||||||
[GtkCallback] private Gdk.ContentProvider? on_drag_prepare (double x, double y) {
|
|
||||||
if (this.draggable) {
|
|
||||||
this.drag_x = x;
|
|
||||||
this.drag_y = y;
|
|
||||||
return new Gdk.ContentProvider.for_value (this);
|
|
||||||
}
|
|
||||||
else return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Gtk.ListBox? drag_widget;
|
|
||||||
|
|
||||||
[GtkCallback] private void on_drag_begin (Gtk.DragSource source, Gdk.Drag drag) {
|
|
||||||
this.drag_widget = new Gtk.ListBox ();
|
|
||||||
|
|
||||||
var drag_row = new PlayQueueSong (this.playbin);
|
|
||||||
drag_row.draggable = false;
|
|
||||||
drag_row.show_position = this.show_position;
|
|
||||||
drag_row.show_artist = this.show_artist;
|
|
||||||
drag_row.show_cover = this.show_cover;
|
|
||||||
drag_row.current = false;
|
|
||||||
drag_row.displayed_position = this.displayed_position;
|
|
||||||
drag_row.song = this.song;
|
|
||||||
drag_row.set_size_request (this.get_width (), this.get_height ());
|
|
||||||
|
|
||||||
var drag_row_real = new Gtk.ListBoxRow ();
|
|
||||||
drag_row_real.child = drag_row;
|
|
||||||
|
|
||||||
this.drag_widget.append (drag_row_real);
|
|
||||||
this.drag_widget.drag_highlight_row (drag_row_real);
|
|
||||||
|
|
||||||
var drag_icon = Gtk.DragIcon.get_for_drag (drag);
|
|
||||||
drag_icon.set("child", this.drag_widget);
|
|
||||||
drag.set_hotspot ((int) this.drag_x, (int) this.drag_y);
|
|
||||||
}
|
|
||||||
|
|
||||||
[GtkCallback] private bool on_drop (Value value, double x, double y) {
|
|
||||||
this.drag_widget = null;
|
|
||||||
this.drag_x = 0.0;
|
|
||||||
this.drag_y = 0.0;
|
|
||||||
|
|
||||||
var source = value as PlayQueueSong;
|
|
||||||
debug ("dropped %u on %u", source.displayed_position, this.displayed_position);
|
|
||||||
this.playbin.move_track (source.displayed_position-1, this.displayed_position-1);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[GtkTemplate (ui = "/eu/callcc/audrey/play_queue.ui")]
|
|
||||||
public class Ui.PlayQueue : Adw.Bin {
|
|
||||||
private weak Playbin _playbin;
|
|
||||||
public Playbin playbin {
|
|
||||||
get { return _playbin; }
|
|
||||||
set {
|
|
||||||
assert (_playbin == null); // only set once
|
|
||||||
_playbin = value;
|
|
||||||
|
|
||||||
_playbin.play_queue.items_changed.connect (this.on_store_items_changed);
|
|
||||||
this.can_clear_all = _playbin.play_queue.get_n_items () > 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool can_clear_all { get; private set; }
|
|
||||||
|
|
||||||
/*[GtkCallback] private void on_clear () {
|
|
||||||
this.playbin.clear ();
|
|
||||||
}*/
|
|
||||||
|
|
||||||
private void on_store_items_changed (GLib.ListModel store, uint position, uint removed, uint added) {
|
|
||||||
this.can_clear_all = store.get_n_items () > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
[GtkCallback] private void on_song_list_setup (Gtk.SignalListItemFactory factory, Object object) {
|
|
||||||
var item = object as Gtk.ListItem;
|
|
||||||
var child = new PlayQueueSong (this.playbin);
|
|
||||||
|
|
||||||
child.draggable = true;
|
|
||||||
child.show_position = true;
|
|
||||||
child.show_artist = true;
|
|
||||||
child.show_cover = true;
|
|
||||||
|
|
||||||
item.child = child;
|
|
||||||
}
|
|
||||||
|
|
||||||
[GtkCallback] private void on_song_list_bind (Gtk.SignalListItemFactory factory, Object object) {
|
|
||||||
var item = object as Gtk.ListItem;
|
|
||||||
var child = item.child as PlayQueueSong;
|
|
||||||
|
|
||||||
child.bind (item.position, item.item as PlaybinSong);
|
|
||||||
}
|
|
||||||
|
|
||||||
[GtkCallback] private void on_song_list_unbind (Gtk.SignalListItemFactory factory, Object object) {
|
|
||||||
var item = object as Gtk.ListItem;
|
|
||||||
var child = item.child as PlayQueueSong;
|
|
||||||
|
|
||||||
child.unbind ();
|
|
||||||
}
|
|
||||||
|
|
||||||
[GtkCallback] private void on_row_activated (uint position) {
|
|
||||||
playbin.select_track (position);
|
|
||||||
}
|
|
||||||
|
|
||||||
[GtkCallback] private string visible_child_name (uint n_items) {
|
|
||||||
return n_items > 0 ? "not-empty" : "empty";
|
|
||||||
}
|
|
||||||
|
|
||||||
~PlayQueue () {
|
|
||||||
debug ("destroying play queue widget");
|
|
||||||
}
|
|
||||||
}
|
|
1138
src/ui/playbar.c
Normal file
1138
src/ui/playbar.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,93 +0,0 @@
|
||||||
[GtkTemplate (ui = "/eu/callcc/audrey/playbar.ui")]
|
|
||||||
class Ui.Playbar : Adw.Bin {
|
|
||||||
public PlaybinSong? song { get; set; }
|
|
||||||
public Gdk.Paintable? playing_cover_art { get; set; }
|
|
||||||
public weak Playbin playbin { get; set; }
|
|
||||||
public bool show_cover_art { get; set; default = true; }
|
|
||||||
|
|
||||||
public int volume {
|
|
||||||
get { return playbin == null ? 100 : playbin.volume; }
|
|
||||||
set { playbin.volume = value; }
|
|
||||||
}
|
|
||||||
|
|
||||||
[GtkCallback] private string format_timestamp (double s) {
|
|
||||||
return "%02d:%02d".printf (((int) s)/60, ((int) s)%60);
|
|
||||||
}
|
|
||||||
|
|
||||||
[GtkCallback] private bool on_play_position_seek (Gtk.Range range, Gtk.ScrollType scroll_type, double value) {
|
|
||||||
if (range.adjustment.lower < range.adjustment.upper) {
|
|
||||||
this.playbin.seek ((int64) value);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
[GtkCallback] private void on_play_pause_clicked () {
|
|
||||||
if (this.playbin.state == PlaybinState.PLAYING) {
|
|
||||||
this.playbin.pause();
|
|
||||||
} else {
|
|
||||||
this.playbin.play();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[GtkCallback] private string play_pause_icon_name (PlaybinState state) {
|
|
||||||
if (state == PlaybinState.PLAYING) {
|
|
||||||
return "media-playback-pause";
|
|
||||||
} else {
|
|
||||||
return "media-playback-start";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[GtkCallback] private bool playbin_active (PlaybinState state) {
|
|
||||||
return state != PlaybinState.STOPPED;
|
|
||||||
}
|
|
||||||
|
|
||||||
[GtkCallback] private bool can_press_play (PlaybinState state, uint n_items) {
|
|
||||||
return !(state == PlaybinState.STOPPED && n_items == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
[GtkCallback] private string mute_button_icon_name (bool mute) {
|
|
||||||
return mute ? "audio-volume-muted" : "audio-volume-high";
|
|
||||||
}
|
|
||||||
|
|
||||||
[GtkCallback] private void on_mute_toggle () {
|
|
||||||
this.playbin.mute = !this.playbin.mute;
|
|
||||||
}
|
|
||||||
|
|
||||||
[GtkCallback] private void on_skip_forward_clicked () {
|
|
||||||
this.playbin.go_to_next_track ();
|
|
||||||
}
|
|
||||||
|
|
||||||
[GtkCallback] private void on_skip_backward_clicked () {
|
|
||||||
this.playbin.go_to_prev_track ();
|
|
||||||
}
|
|
||||||
|
|
||||||
[GtkCallback] private void seek_backward () {
|
|
||||||
// 10 seconds
|
|
||||||
double new_position = playbin.position - 10.0;
|
|
||||||
if (new_position < 0.0) new_position = 0.0;
|
|
||||||
this.playbin.seek (new_position);
|
|
||||||
}
|
|
||||||
|
|
||||||
[GtkCallback] private void seek_forward () {
|
|
||||||
// 10 seconds
|
|
||||||
double new_position = playbin.position + 10.0;
|
|
||||||
if (new_position > this.playbin.duration) new_position = this.playbin.duration;
|
|
||||||
this.playbin.seek (new_position);
|
|
||||||
}
|
|
||||||
|
|
||||||
[GtkCallback] private string song_title (PlaybinSong? song) {
|
|
||||||
return song == null ? "" : song.title;
|
|
||||||
}
|
|
||||||
|
|
||||||
[GtkCallback] private string song_artist (PlaybinSong? song) {
|
|
||||||
return song == null ? "" : song.artist;
|
|
||||||
}
|
|
||||||
|
|
||||||
[GtkCallback] private string song_album (PlaybinSong? song) {
|
|
||||||
return song == null ? "" : song.album;
|
|
||||||
}
|
|
||||||
|
|
||||||
~Playbar () {
|
|
||||||
debug ("destroying playbar widget");
|
|
||||||
}
|
|
||||||
}
|
|
1478
src/ui/setup.c
Normal file
1478
src/ui/setup.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,135 +0,0 @@
|
||||||
static void salt_password (string password, out string token, out string salt) {
|
|
||||||
const int SALT_BYTES = 8;
|
|
||||||
uchar salt_bytes[SALT_BYTES];
|
|
||||||
GCrypt.Random.randomize (salt_bytes, GCrypt.Random.Level.STRONG);
|
|
||||||
uchar salt_chars[2*SALT_BYTES+1];
|
|
||||||
for (int i = 0; i < SALT_BYTES; i += 1) {
|
|
||||||
salt_chars[2*i+0] = "0123456789abcdef"[(salt_bytes[i]>>4)&0xf];
|
|
||||||
salt_chars[2*i+1] = "0123456789abcdef"[(salt_bytes[i]>>0)&0xf];
|
|
||||||
}
|
|
||||||
salt_chars[2*SALT_BYTES] = 0;
|
|
||||||
var checksum = new GLib.Checksum (ChecksumType.MD5);
|
|
||||||
checksum.update ((uchar[]) password, -1);
|
|
||||||
checksum.update (salt_chars, -1);
|
|
||||||
|
|
||||||
token = checksum.get_string ();
|
|
||||||
salt = (string) salt_chars;
|
|
||||||
}
|
|
||||||
|
|
||||||
[GtkTemplate (ui = "/eu/callcc/audrey/setup.ui")]
|
|
||||||
public class Ui.Setup : Adw.PreferencesDialog {
|
|
||||||
public string status { get; private set; default = _("Not connected"); }
|
|
||||||
|
|
||||||
public bool authn_can_edit { get; private set; default = true; }
|
|
||||||
public bool authn_can_validate { get; private set; default = false; }
|
|
||||||
|
|
||||||
public string server_url { get; set; default = ""; }
|
|
||||||
public string username { get; set; default = ""; }
|
|
||||||
public string password { get; set; default = ""; }
|
|
||||||
public string token;
|
|
||||||
public string salt;
|
|
||||||
|
|
||||||
public signal void connected (Subsonic.Client api);
|
|
||||||
|
|
||||||
private static Secret.Schema secret_schema = new Secret.Schema (
|
|
||||||
"eu.callcc.audrey",
|
|
||||||
Secret.SchemaFlags.NONE,
|
|
||||||
"server-url", Secret.SchemaAttributeType.STRING,
|
|
||||||
"username", Secret.SchemaAttributeType.STRING
|
|
||||||
);
|
|
||||||
|
|
||||||
[GtkCallback] private void on_authn_changed () {
|
|
||||||
this.authn_can_validate = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
[GtkCallback] private void on_authn_validate_activated () {
|
|
||||||
this.authn_can_validate = false;
|
|
||||||
this.authn_can_edit = false;
|
|
||||||
this.status = _("Connecting...");
|
|
||||||
|
|
||||||
string new_token, new_salt;
|
|
||||||
salt_password (this.password, out new_token, out new_salt);
|
|
||||||
var api = new Subsonic.Client.with_token (
|
|
||||||
this.server_url,
|
|
||||||
this.username,
|
|
||||||
new_token,
|
|
||||||
new_salt);
|
|
||||||
|
|
||||||
api.ping.begin ((obj, res) => {
|
|
||||||
try {
|
|
||||||
api.ping.end (res);
|
|
||||||
this.status = _("Connected");
|
|
||||||
this.token = new_token;
|
|
||||||
this.salt = new_salt;
|
|
||||||
this.save ();
|
|
||||||
|
|
||||||
this.connected (api);
|
|
||||||
} catch (Error e) {
|
|
||||||
this.status = @"$(_("Ping failed")): $(e.message)";
|
|
||||||
this.authn_can_validate = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.authn_can_edit = true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void load () {
|
|
||||||
this.authn_can_edit = false;
|
|
||||||
Secret.password_searchv.begin (
|
|
||||||
secret_schema,
|
|
||||||
new HashTable<string, string> (null, null),
|
|
||||||
Secret.SearchFlags.UNLOCK,
|
|
||||||
null,
|
|
||||||
(obj, res) => {
|
|
||||||
try {
|
|
||||||
var list = Secret.password_searchv.end (res);
|
|
||||||
if (list == null) {
|
|
||||||
// didn't find shit, leave all empty
|
|
||||||
this.server_url = "";
|
|
||||||
this.username = "";
|
|
||||||
this.password = "";
|
|
||||||
// TODO: onboarding
|
|
||||||
this.authn_can_edit = true;
|
|
||||||
this.authn_can_validate = true;
|
|
||||||
} else {
|
|
||||||
var first = list.data;
|
|
||||||
assert (first != null);
|
|
||||||
|
|
||||||
this.server_url = first.attributes["server-url"];
|
|
||||||
this.username = first.attributes["username"];
|
|
||||||
|
|
||||||
first.retrieve_secret.begin (null, (obj, res) => {
|
|
||||||
try {
|
|
||||||
var value = first.retrieve_secret.end (res);
|
|
||||||
this.password = value.get_text () ?? "";
|
|
||||||
} catch (Error e) {
|
|
||||||
error ("could not retrieve password from credentials: %s", e.message);
|
|
||||||
}
|
|
||||||
|
|
||||||
// first connection
|
|
||||||
this.authn_can_validate = true;
|
|
||||||
this.on_authn_validate_activated ();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} catch (Error e) {
|
|
||||||
error ("could not search for password in keyring: %s", e.message);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void save () {
|
|
||||||
this.authn_can_edit = false;
|
|
||||||
Secret.password_store.begin (secret_schema, null, "Audrey Subsonic password", this.password, null, (obj, res) => {
|
|
||||||
try {
|
|
||||||
Secret.password_store.end (res);
|
|
||||||
} catch (Error e) {
|
|
||||||
error ("could not store password in keyring: %s", e.message);
|
|
||||||
}
|
|
||||||
this.authn_can_edit = true;
|
|
||||||
}, "server-url", this.server_url, "username", this.username);
|
|
||||||
}
|
|
||||||
|
|
||||||
~Setup () {
|
|
||||||
debug ("destroying setup dialog");
|
|
||||||
}
|
|
||||||
}
|
|
1593
src/ui/window.c
Normal file
1593
src/ui/window.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,39 +0,0 @@
|
||||||
mod ffi {
|
|
||||||
use gtk::glib;
|
|
||||||
|
|
||||||
#[repr(C)]
|
|
||||||
pub struct UiWindow {
|
|
||||||
parent_instance: adw::ffi::AdwApplicationWindow,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[repr(C)]
|
|
||||||
pub struct UiWindowClass {
|
|
||||||
parent_class: adw::ffi::AdwApplicationWindowClass,
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
pub fn ui_window_get_type() -> glib::ffi::GType;
|
|
||||||
pub fn ui_window_new(app: *mut gtk::ffi::GtkApplication) -> *mut UiWindow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
use adw::prelude::*;
|
|
||||||
use gtk::{gio, glib};
|
|
||||||
|
|
||||||
glib::wrapper! {
|
|
||||||
pub struct Window(Object<ffi::UiWindow, ffi::UiWindowClass>)
|
|
||||||
@extends adw::ApplicationWindow, gtk::ApplicationWindow, gtk::Window, gtk::Widget,
|
|
||||||
@implements gio::ActionGroup, gio::ActionMap, gtk::Accessible, gtk::Buildable, gtk::ConstraintTarget, gtk::Native, gtk::Root, gtk::ShortcutManager;
|
|
||||||
|
|
||||||
match fn {
|
|
||||||
type_ => || ffi::ui_window_get_type(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Window {
|
|
||||||
pub fn new(app: &impl IsA<gtk::Application>) -> Self {
|
|
||||||
use glib::translate::*;
|
|
||||||
|
|
||||||
unsafe { from_glib_none(ffi::ui_window_new(app.as_ref().to_glib_none().0)) }
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,136 +0,0 @@
|
||||||
[GtkTemplate (ui = "/eu/callcc/audrey/window.ui")]
|
|
||||||
class Ui.Window : Adw.ApplicationWindow {
|
|
||||||
[GtkChild] public unowned Ui.PlayQueue play_queue;
|
|
||||||
[GtkChild] public unowned Ui.Playbar playbar;
|
|
||||||
//[GtkChild] public unowned Adw.ButtonRow shuffle_all_tracks;
|
|
||||||
|
|
||||||
private Setup setup;
|
|
||||||
|
|
||||||
private Subsonic.Client api;
|
|
||||||
|
|
||||||
public int volume {
|
|
||||||
get { return this.playbin.volume; }
|
|
||||||
set { this.playbin.volume = value; }
|
|
||||||
}
|
|
||||||
public bool mute {
|
|
||||||
get { return this.playbin.mute; }
|
|
||||||
set { this.playbin.mute = value; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public PlaybinSong? song { get; private set; }
|
|
||||||
public Gdk.Paintable? playing_cover_art { get; set; default = null; }
|
|
||||||
|
|
||||||
private Cancellable cancel_loading_art;
|
|
||||||
public bool cover_art_loading { get; set; default = false; }
|
|
||||||
|
|
||||||
public Playbin playbin { get; private set; default = new Playbin (); }
|
|
||||||
|
|
||||||
public Window (Gtk.Application app) {
|
|
||||||
Object (application: app);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Mpris mpris;
|
|
||||||
private MprisPlayer mpris_player;
|
|
||||||
|
|
||||||
private void now_playing (PlaybinSong song) {
|
|
||||||
this.song = song;
|
|
||||||
// api.scrobble.begin (this.song.id); TODO
|
|
||||||
|
|
||||||
if (this.cancel_loading_art != null) {
|
|
||||||
this.cancel_loading_art.cancel ();
|
|
||||||
}
|
|
||||||
this.cancel_loading_art = new GLib.Cancellable ();
|
|
||||||
|
|
||||||
this.playing_cover_art = null; // TODO: preload next art somehow
|
|
||||||
this.cover_art_loading = true;
|
|
||||||
|
|
||||||
string song_id = this.song.id;
|
|
||||||
this.api.cover_art.begin (song_id, -1, Priority.DEFAULT, this.cancel_loading_art, (obj, res) => {
|
|
||||||
try {
|
|
||||||
this.playing_cover_art = Gdk.Texture.for_pixbuf (this.api.cover_art.end (res));
|
|
||||||
this.cover_art_loading = false;
|
|
||||||
} catch (Error e) {
|
|
||||||
if (!(e is IOError.CANCELLED)) {
|
|
||||||
warning ("could not load cover for %s: %s", song_id, e.message);
|
|
||||||
this.cover_art_loading = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
construct {
|
|
||||||
Bus.own_name (
|
|
||||||
BusType.SESSION,
|
|
||||||
"org.mpris.MediaPlayer2.audrey",
|
|
||||||
BusNameOwnerFlags.NONE,
|
|
||||||
(conn) => {
|
|
||||||
try {
|
|
||||||
this.mpris = new Mpris (this);
|
|
||||||
this.mpris_player = new MprisPlayer (conn, this.playbin);
|
|
||||||
|
|
||||||
conn.register_object ("/org/mpris/MediaPlayer2", this.mpris);
|
|
||||||
conn.register_object ("/org/mpris/MediaPlayer2", this.mpris_player);
|
|
||||||
} catch (IOError e) {
|
|
||||||
error ("could not register dbus service: %s", e.message);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
() => {},
|
|
||||||
() => { error ("could not acquire dbus name"); });
|
|
||||||
|
|
||||||
this.setup = new Setup ();
|
|
||||||
|
|
||||||
this.setup.connected.connect ((api) => {
|
|
||||||
this.api = api;
|
|
||||||
this.playbin.api = api;
|
|
||||||
this.mpris_player.api = api;
|
|
||||||
this.can_click_shuffle_all = true;
|
|
||||||
});
|
|
||||||
this.setup.load ();
|
|
||||||
|
|
||||||
this.playbin.new_track.connect (() => {
|
|
||||||
this.now_playing (this.playbin.play_queue.get_item (this.playbin.play_queue_position) as PlaybinSong);
|
|
||||||
});
|
|
||||||
|
|
||||||
this.playbin.stopped.connect (() => {
|
|
||||||
this.playing_cover_art = null;
|
|
||||||
this.song = null;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
[GtkCallback] private void show_setup_dialog () {
|
|
||||||
this.setup.present (this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool can_click_shuffle_all { get; private set; default = false; }
|
|
||||||
|
|
||||||
[GtkCallback] private void shuffle_all () {
|
|
||||||
this.can_click_shuffle_all = false;
|
|
||||||
this.playbin.clear ();
|
|
||||||
api.get_random_songs.begin (null, (song) => {
|
|
||||||
this.playbin.append_track (song);
|
|
||||||
}, (obj, res) => {
|
|
||||||
try {
|
|
||||||
api.get_random_songs.end (res);
|
|
||||||
} catch (Error e) {
|
|
||||||
error ("could not get random songs: %s", e.message);
|
|
||||||
}
|
|
||||||
this.can_click_shuffle_all = true;
|
|
||||||
|
|
||||||
this.playbin.select_track (0);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
[GtkCallback] private bool show_playbar_cover_art (string? stack_child) {
|
|
||||||
return stack_child != "play-queue";
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool close_request () {
|
|
||||||
// stop playback on close
|
|
||||||
this.playbin.stop ();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
~Window () {
|
|
||||||
debug ("destroying main window");
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,829 +0,0 @@
|
||||||
/* gcrypt.vapi
|
|
||||||
*
|
|
||||||
* Copyright:
|
|
||||||
* 2008 Jiqing Qiang
|
|
||||||
* 2008, 2010, 2012-2013 Evan Nemerson
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation; either
|
|
||||||
* version 2.1 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*
|
|
||||||
* Author:
|
|
||||||
* Jiqing Qiang <jiqing.qiang@gmail.com>
|
|
||||||
* Evan Nemerson <evan@coeus-group.com>
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
[CCode (cheader_filename = "gcrypt.h", lower_case_cprefix = "gcry_")]
|
|
||||||
namespace GCrypt {
|
|
||||||
[CCode (cname = "gpg_err_source_t", cprefix = "GPG_ERR_SOURCE_")]
|
|
||||||
public enum ErrorSource {
|
|
||||||
UNKNOWN,
|
|
||||||
GCRYPT,
|
|
||||||
GPG,
|
|
||||||
GPGSM,
|
|
||||||
GPGAGENT,
|
|
||||||
PINENTRY,
|
|
||||||
SCD,
|
|
||||||
GPGME,
|
|
||||||
KEYBOX,
|
|
||||||
KSBA,
|
|
||||||
DIRMNGR,
|
|
||||||
GSTI,
|
|
||||||
ANY,
|
|
||||||
USER_1,
|
|
||||||
USER_2,
|
|
||||||
USER_3,
|
|
||||||
USER_4,
|
|
||||||
|
|
||||||
/* This is one more than the largest allowed entry. */
|
|
||||||
DIM
|
|
||||||
}
|
|
||||||
|
|
||||||
[CCode (cname = "gpg_err_code_t", cprefix = "GPG_ERR_")]
|
|
||||||
public enum ErrorCode {
|
|
||||||
NO_ERROR,
|
|
||||||
GENERAL,
|
|
||||||
UNKNOWN_PACKET,
|
|
||||||
UNKNOWN_VERSION,
|
|
||||||
PUBKEY_ALGO,
|
|
||||||
DIGEST_ALGO,
|
|
||||||
BAD_PUBKEY,
|
|
||||||
BAD_SECKEY,
|
|
||||||
BAD_SIGNATURE,
|
|
||||||
NO_PUBKEY,
|
|
||||||
CHECKSUM,
|
|
||||||
BAD_PASSPHRASE,
|
|
||||||
CIPHER_ALGO,
|
|
||||||
KEYRING_OPEN,
|
|
||||||
INV_PACKET,
|
|
||||||
INV_ARMOR,
|
|
||||||
NO_USER_ID,
|
|
||||||
NO_SECKEY,
|
|
||||||
WRONG_SECKEY,
|
|
||||||
BAD_KEY,
|
|
||||||
COMPR_ALGO,
|
|
||||||
NO_PRIME,
|
|
||||||
NO_ENCODING_METHOD,
|
|
||||||
NO_ENCRYPTION_SCHEME,
|
|
||||||
NO_SIGNATURE_SCHEME,
|
|
||||||
INV_ATTR,
|
|
||||||
NO_VALUE,
|
|
||||||
NOT_FOUND,
|
|
||||||
VALUE_NOT_FOUND,
|
|
||||||
SYNTAX,
|
|
||||||
BAD_MPI,
|
|
||||||
INV_PASSPHRASE,
|
|
||||||
SIG_CLASS,
|
|
||||||
RESOURCE_LIMIT,
|
|
||||||
INV_KEYRING,
|
|
||||||
TRUSTDB,
|
|
||||||
BAD_CERT,
|
|
||||||
INV_USER_ID,
|
|
||||||
UNEXPECTED,
|
|
||||||
TIME_CONFLICT,
|
|
||||||
KEYSERVER,
|
|
||||||
WRONG_PUBKEY_ALGO,
|
|
||||||
TRIBUTE_TO_D_A,
|
|
||||||
WEAK_KEY,
|
|
||||||
INV_KEYLEN,
|
|
||||||
INV_ARG,
|
|
||||||
BAD_URI,
|
|
||||||
INV_URI,
|
|
||||||
NETWORK,
|
|
||||||
UNKNOWN_HOST,
|
|
||||||
SELFTEST_FAILED,
|
|
||||||
NOT_ENCRYPTED,
|
|
||||||
NOT_PROCESSED,
|
|
||||||
UNUSABLE_PUBKEY,
|
|
||||||
UNUSABLE_SECKEY,
|
|
||||||
INV_VALUE,
|
|
||||||
BAD_CERT_CHAIN,
|
|
||||||
MISSING_CERT,
|
|
||||||
NO_DATA,
|
|
||||||
BUG,
|
|
||||||
NOT_SUPPORTED,
|
|
||||||
INV_OP,
|
|
||||||
TIMEOUT,
|
|
||||||
INTERNAL,
|
|
||||||
EOF_GCRYPT,
|
|
||||||
INV_OBJ,
|
|
||||||
TOO_SHORT,
|
|
||||||
TOO_LARGE,
|
|
||||||
NO_OBJ,
|
|
||||||
NOT_IMPLEMENTED,
|
|
||||||
CONFLICT,
|
|
||||||
INV_CIPHER_MODE,
|
|
||||||
INV_FLAG,
|
|
||||||
INV_HANDLE,
|
|
||||||
TRUNCATED,
|
|
||||||
INCOMPLETE_LINE,
|
|
||||||
INV_RESPONSE,
|
|
||||||
NO_AGENT,
|
|
||||||
AGENT,
|
|
||||||
INV_DATA,
|
|
||||||
ASSUAN_SERVER_FAULT,
|
|
||||||
ASSUAN,
|
|
||||||
INV_SESSION_KEY,
|
|
||||||
INV_SEXP,
|
|
||||||
UNSUPPORTED_ALGORITHM,
|
|
||||||
NO_PIN_ENTRY,
|
|
||||||
PIN_ENTRY,
|
|
||||||
BAD_PIN,
|
|
||||||
INV_NAME,
|
|
||||||
BAD_DATA,
|
|
||||||
INV_PARAMETER,
|
|
||||||
WRONG_CARD,
|
|
||||||
NO_DIRMNGR,
|
|
||||||
DIRMNGR,
|
|
||||||
CERT_REVOKED,
|
|
||||||
NO_CRL_KNOWN,
|
|
||||||
CRL_TOO_OLD,
|
|
||||||
LINE_TOO_LONG,
|
|
||||||
NOT_TRUSTED,
|
|
||||||
CANCELED,
|
|
||||||
BAD_CA_CERT,
|
|
||||||
CERT_EXPIRED,
|
|
||||||
CERT_TOO_YOUNG,
|
|
||||||
UNSUPPORTED_CERT,
|
|
||||||
UNKNOWN_SEXP,
|
|
||||||
UNSUPPORTED_PROTECTION,
|
|
||||||
CORRUPTED_PROTECTION,
|
|
||||||
AMBIGUOUS_NAME,
|
|
||||||
CARD,
|
|
||||||
CARD_RESET,
|
|
||||||
CARD_REMOVED,
|
|
||||||
INV_CARD,
|
|
||||||
CARD_NOT_PRESENT,
|
|
||||||
NO_PKCS15_APP,
|
|
||||||
NOT_CONFIRMED,
|
|
||||||
CONFIGURATION,
|
|
||||||
NO_POLICY_MATCH,
|
|
||||||
INV_INDEX,
|
|
||||||
INV_ID,
|
|
||||||
NO_SCDAEMON,
|
|
||||||
SCDAEMON,
|
|
||||||
UNSUPPORTED_PROTOCOL,
|
|
||||||
BAD_PIN_METHOD,
|
|
||||||
CARD_NOT_INITIALIZED,
|
|
||||||
UNSUPPORTED_OPERATION,
|
|
||||||
WRONG_KEY_USAGE,
|
|
||||||
NOTHING_FOUND,
|
|
||||||
WRONG_BLOB_TYPE,
|
|
||||||
MISSING_VALUE,
|
|
||||||
HARDWARE,
|
|
||||||
PIN_BLOCKED,
|
|
||||||
USE_CONDITIONS,
|
|
||||||
PIN_NOT_SYNCED,
|
|
||||||
INV_CRL,
|
|
||||||
BAD_BER,
|
|
||||||
INV_BER,
|
|
||||||
ELEMENT_NOT_FOUND,
|
|
||||||
IDENTIFIER_NOT_FOUND,
|
|
||||||
INV_TAG,
|
|
||||||
INV_LENGTH,
|
|
||||||
INV_KEYINFO,
|
|
||||||
UNEXPECTED_TAG,
|
|
||||||
NOT_DER_ENCODED,
|
|
||||||
NO_CMS_OBJ,
|
|
||||||
INV_CMS_OBJ,
|
|
||||||
UNKNOWN_CMS_OBJ,
|
|
||||||
UNSUPPORTED_CMS_OBJ,
|
|
||||||
UNSUPPORTED_ENCODING,
|
|
||||||
UNSUPPORTED_CMS_VERSION,
|
|
||||||
UNKNOWN_ALGORITHM,
|
|
||||||
INV_ENGINE,
|
|
||||||
PUBKEY_NOT_TRUSTED,
|
|
||||||
DECRYPT_FAILED,
|
|
||||||
KEY_EXPIRED,
|
|
||||||
SIG_EXPIRED,
|
|
||||||
ENCODING_PROBLEM,
|
|
||||||
INV_STATE,
|
|
||||||
DUP_VALUE,
|
|
||||||
MISSING_ACTION,
|
|
||||||
MODULE_NOT_FOUND,
|
|
||||||
INV_OID_STRING,
|
|
||||||
INV_TIME,
|
|
||||||
INV_CRL_OBJ,
|
|
||||||
UNSUPPORTED_CRL_VERSION,
|
|
||||||
INV_CERT_OBJ,
|
|
||||||
UNKNOWN_NAME,
|
|
||||||
LOCALE_PROBLEM,
|
|
||||||
NOT_LOCKED,
|
|
||||||
PROTOCOL_VIOLATION,
|
|
||||||
INV_MAC,
|
|
||||||
INV_REQUEST,
|
|
||||||
UNKNOWN_EXTN,
|
|
||||||
UNKNOWN_CRIT_EXTN,
|
|
||||||
LOCKED,
|
|
||||||
UNKNOWN_OPTION,
|
|
||||||
UNKNOWN_COMMAND,
|
|
||||||
BUFFER_TOO_SHORT,
|
|
||||||
SEXP_INV_LEN_SPEC,
|
|
||||||
SEXP_STRING_TOO_LONG,
|
|
||||||
SEXP_UNMATCHED_PAREN,
|
|
||||||
SEXP_NOT_CANONICAL,
|
|
||||||
SEXP_BAD_CHARACTER,
|
|
||||||
SEXP_BAD_QUOTATION,
|
|
||||||
SEXP_ZERO_PREFIX,
|
|
||||||
SEXP_NESTED_DH,
|
|
||||||
SEXP_UNMATCHED_DH,
|
|
||||||
SEXP_UNEXPECTED_PUNC,
|
|
||||||
SEXP_BAD_HEX_CHAR,
|
|
||||||
SEXP_ODD_HEX_NUMBERS,
|
|
||||||
SEXP_BAD_OCT_CHAR,
|
|
||||||
ASS_GENERAL,
|
|
||||||
ASS_ACCEPT_FAILED,
|
|
||||||
ASS_CONNECT_FAILED,
|
|
||||||
ASS_INV_RESPONSE,
|
|
||||||
ASS_INV_VALUE,
|
|
||||||
ASS_INCOMPLETE_LINE,
|
|
||||||
ASS_LINE_TOO_LONG,
|
|
||||||
ASS_NESTED_COMMANDS,
|
|
||||||
ASS_NO_DATA_CB,
|
|
||||||
ASS_NO_INQUIRE_CB,
|
|
||||||
ASS_NOT_A_SERVER,
|
|
||||||
ASS_NOT_A_CLIENT,
|
|
||||||
ASS_SERVER_START,
|
|
||||||
ASS_READ_ERROR,
|
|
||||||
ASS_WRITE_ERROR,
|
|
||||||
ASS_TOO_MUCH_DATA,
|
|
||||||
ASS_UNEXPECTED_CMD,
|
|
||||||
ASS_UNKNOWN_CMD,
|
|
||||||
ASS_SYNTAX,
|
|
||||||
ASS_CANCELED,
|
|
||||||
ASS_NO_INPUT,
|
|
||||||
ASS_NO_OUTPUT,
|
|
||||||
ASS_PARAMETER,
|
|
||||||
ASS_UNKNOWN_INQUIRE,
|
|
||||||
USER_1,
|
|
||||||
USER_2,
|
|
||||||
USER_3,
|
|
||||||
USER_4,
|
|
||||||
USER_5,
|
|
||||||
USER_6,
|
|
||||||
USER_7,
|
|
||||||
USER_8,
|
|
||||||
USER_9,
|
|
||||||
USER_10,
|
|
||||||
USER_11,
|
|
||||||
USER_12,
|
|
||||||
USER_13,
|
|
||||||
USER_14,
|
|
||||||
USER_15,
|
|
||||||
USER_16,
|
|
||||||
MISSING_ERRNO,
|
|
||||||
UNKNOWN_ERRNO,
|
|
||||||
EOF,
|
|
||||||
|
|
||||||
E2BIG,
|
|
||||||
EACCES,
|
|
||||||
EADDRINUSE,
|
|
||||||
EADDRNOTAVAIL,
|
|
||||||
EADV,
|
|
||||||
EAFNOSUPPORT,
|
|
||||||
EAGAIN,
|
|
||||||
EALREADY,
|
|
||||||
EAUTH,
|
|
||||||
EBACKGROUND,
|
|
||||||
EBADE,
|
|
||||||
EBADF,
|
|
||||||
EBADFD,
|
|
||||||
EBADMSG,
|
|
||||||
EBADR,
|
|
||||||
EBADRPC,
|
|
||||||
EBADRQC,
|
|
||||||
EBADSLT,
|
|
||||||
EBFONT,
|
|
||||||
EBUSY,
|
|
||||||
ECANCELED,
|
|
||||||
ECHILD,
|
|
||||||
ECHRNG,
|
|
||||||
ECOMM,
|
|
||||||
ECONNABORTED,
|
|
||||||
ECONNREFUSED,
|
|
||||||
ECONNRESET,
|
|
||||||
ED,
|
|
||||||
EDEADLK,
|
|
||||||
EDEADLOCK,
|
|
||||||
EDESTADDRREQ,
|
|
||||||
EDIED,
|
|
||||||
EDOM,
|
|
||||||
EDOTDOT,
|
|
||||||
EDQUOT,
|
|
||||||
EEXIST,
|
|
||||||
EFAULT,
|
|
||||||
EFBIG,
|
|
||||||
EFTYPE,
|
|
||||||
EGRATUITOUS,
|
|
||||||
EGREGIOUS,
|
|
||||||
EHOSTDOWN,
|
|
||||||
EHOSTUNREACH,
|
|
||||||
EIDRM,
|
|
||||||
EIEIO,
|
|
||||||
EILSEQ,
|
|
||||||
EINPROGRESS,
|
|
||||||
EINTR,
|
|
||||||
EINVAL,
|
|
||||||
EIO,
|
|
||||||
EISCONN,
|
|
||||||
EISDIR,
|
|
||||||
EISNAM,
|
|
||||||
EL2HLT,
|
|
||||||
EL2NSYNC,
|
|
||||||
EL3HLT,
|
|
||||||
EL3RST,
|
|
||||||
ELIBACC,
|
|
||||||
ELIBBAD,
|
|
||||||
ELIBEXEC,
|
|
||||||
ELIBMAX,
|
|
||||||
ELIBSCN,
|
|
||||||
ELNRNG,
|
|
||||||
ELOOP,
|
|
||||||
EMEDIUMTYPE,
|
|
||||||
EMFILE,
|
|
||||||
EMLINK,
|
|
||||||
EMSGSIZE,
|
|
||||||
EMULTIHOP,
|
|
||||||
ENAMETOOLONG,
|
|
||||||
ENAVAIL,
|
|
||||||
ENEEDAUTH,
|
|
||||||
ENETDOWN,
|
|
||||||
ENETRESET,
|
|
||||||
ENETUNREACH,
|
|
||||||
ENFILE,
|
|
||||||
ENOANO,
|
|
||||||
ENOBUFS,
|
|
||||||
ENOCSI,
|
|
||||||
ENODATA,
|
|
||||||
ENODEV,
|
|
||||||
ENOENT,
|
|
||||||
ENOEXEC,
|
|
||||||
ENOLCK,
|
|
||||||
ENOLINK,
|
|
||||||
ENOMEDIUM,
|
|
||||||
ENOMEM,
|
|
||||||
ENOMSG,
|
|
||||||
ENONET,
|
|
||||||
ENOPKG,
|
|
||||||
ENOPROTOOPT,
|
|
||||||
ENOSPC,
|
|
||||||
ENOSR,
|
|
||||||
ENOSTR,
|
|
||||||
ENOSYS,
|
|
||||||
ENOTBLK,
|
|
||||||
ENOTCONN,
|
|
||||||
ENOTDIR,
|
|
||||||
ENOTEMPTY,
|
|
||||||
ENOTNAM,
|
|
||||||
ENOTSOCK,
|
|
||||||
ENOTSUP,
|
|
||||||
ENOTTY,
|
|
||||||
ENOTUNIQ,
|
|
||||||
ENXIO,
|
|
||||||
EOPNOTSUPP,
|
|
||||||
EOVERFLOW,
|
|
||||||
EPERM,
|
|
||||||
EPFNOSUPPORT,
|
|
||||||
EPIPE,
|
|
||||||
EPROCLIM,
|
|
||||||
EPROCUNAVAIL,
|
|
||||||
EPROGMISMATCH,
|
|
||||||
EPROGUNAVAIL,
|
|
||||||
EPROTO,
|
|
||||||
EPROTONOSUPPORT,
|
|
||||||
EPROTOTYPE,
|
|
||||||
ERANGE,
|
|
||||||
EREMCHG,
|
|
||||||
EREMOTE,
|
|
||||||
EREMOTEIO,
|
|
||||||
ERESTART,
|
|
||||||
EROFS,
|
|
||||||
ERPCMISMATCH,
|
|
||||||
ESHUTDOWN,
|
|
||||||
ESOCKTNOSUPPORT,
|
|
||||||
ESPIPE,
|
|
||||||
ESRCH,
|
|
||||||
ESRMNT,
|
|
||||||
ESTALE,
|
|
||||||
ESTRPIPE,
|
|
||||||
ETIME,
|
|
||||||
ETIMEDOUT,
|
|
||||||
ETOOMANYREFS,
|
|
||||||
ETXTBSY,
|
|
||||||
EUCLEAN,
|
|
||||||
EUNATCH,
|
|
||||||
EUSERS,
|
|
||||||
EWOULDBLOCK,
|
|
||||||
EXDEV,
|
|
||||||
EXFULL,
|
|
||||||
|
|
||||||
/* This is one more than the largest allowed entry. */
|
|
||||||
CODE_DIM
|
|
||||||
}
|
|
||||||
|
|
||||||
[CCode (cname = "gcry_error_t", cprefix = "gpg_err_")]
|
|
||||||
public struct Error : uint {
|
|
||||||
[CCode (cname = "gcry_err_make")]
|
|
||||||
public Error (ErrorSource source, ErrorCode code);
|
|
||||||
[CCode (cname = "gcry_err_make_from_errno")]
|
|
||||||
public Error.from_errno (ErrorSource source, int err);
|
|
||||||
public ErrorCode code ();
|
|
||||||
public ErrorSource source ();
|
|
||||||
|
|
||||||
[CCode (cname = "gcry_strerror")]
|
|
||||||
public unowned string to_string ();
|
|
||||||
|
|
||||||
[CCode (cname = "gcry_strsource")]
|
|
||||||
public unowned string source_to_string ();
|
|
||||||
}
|
|
||||||
|
|
||||||
[CCode (cname = "enum gcry_ctl_cmds", cprefix = "GCRYCTL_")]
|
|
||||||
public enum ControlCommand {
|
|
||||||
SET_KEY,
|
|
||||||
SET_IV,
|
|
||||||
CFB_SYNC,
|
|
||||||
RESET,
|
|
||||||
FINALIZE,
|
|
||||||
GET_KEYLEN,
|
|
||||||
GET_BLKLEN,
|
|
||||||
TEST_ALGO,
|
|
||||||
IS_SECURE,
|
|
||||||
GET_ASNOID,
|
|
||||||
ENABLE_ALGO,
|
|
||||||
DISABLE_ALGO,
|
|
||||||
DUMP_RANDOM_STATS,
|
|
||||||
DUMP_SECMEM_STATS,
|
|
||||||
GET_ALGO_NPKEY,
|
|
||||||
GET_ALGO_NSKEY,
|
|
||||||
GET_ALGO_NSIGN,
|
|
||||||
GET_ALGO_NENCR,
|
|
||||||
SET_VERBOSITY,
|
|
||||||
SET_DEBUG_FLAGS,
|
|
||||||
CLEAR_DEBUG_FLAGS,
|
|
||||||
USE_SECURE_RNDPOOL,
|
|
||||||
DUMP_MEMORY_STATS,
|
|
||||||
INIT_SECMEM,
|
|
||||||
TERM_SECMEM,
|
|
||||||
DISABLE_SECMEM_WARN,
|
|
||||||
SUSPEND_SECMEM_WARN,
|
|
||||||
RESUME_SECMEM_WARN,
|
|
||||||
DROP_PRIVS,
|
|
||||||
ENABLE_M_GUARD,
|
|
||||||
START_DUMP,
|
|
||||||
STOP_DUMP,
|
|
||||||
GET_ALGO_USAGE,
|
|
||||||
IS_ALGO_ENABLED,
|
|
||||||
DISABLE_INTERNAL_LOCKING,
|
|
||||||
DISABLE_SECMEM,
|
|
||||||
INITIALIZATION_FINISHED,
|
|
||||||
INITIALIZATION_FINISHED_P,
|
|
||||||
ANY_INITIALIZATION_P,
|
|
||||||
SET_CBC_CTS,
|
|
||||||
SET_CBC_MAC,
|
|
||||||
SET_CTR,
|
|
||||||
ENABLE_QUICK_RANDOM,
|
|
||||||
SET_RANDOM_SEED_FILE,
|
|
||||||
UPDATE_RANDOM_SEED_FILE,
|
|
||||||
SET_THREAD_CBS,
|
|
||||||
FAST_POLL
|
|
||||||
}
|
|
||||||
public Error control (ControlCommand cmd, ...);
|
|
||||||
|
|
||||||
namespace Cipher {
|
|
||||||
[CCode (cname = "enum gcry_cipher_algos", cprefix = "GCRY_CIPHER_")]
|
|
||||||
public enum Algorithm {
|
|
||||||
NONE,
|
|
||||||
IDEA,
|
|
||||||
3DES,
|
|
||||||
CAST5,
|
|
||||||
BLOWFISH,
|
|
||||||
SAFER_SK128,
|
|
||||||
DES_SK,
|
|
||||||
AES,
|
|
||||||
AES128,
|
|
||||||
RIJNDAEL,
|
|
||||||
RIJNDAEL128,
|
|
||||||
AES192,
|
|
||||||
RIJNDAEL192,
|
|
||||||
AES256,
|
|
||||||
RIJNDAEL256,
|
|
||||||
TWOFISH,
|
|
||||||
TWOFISH128,
|
|
||||||
ARCFOUR,
|
|
||||||
DES,
|
|
||||||
SERPENT128,
|
|
||||||
SERPENT192,
|
|
||||||
SERPENT256,
|
|
||||||
RFC2268_40,
|
|
||||||
RFC2268_128,
|
|
||||||
SEED,
|
|
||||||
CAMELLIA128,
|
|
||||||
CAMELLIA192,
|
|
||||||
CAMELLIA256,
|
|
||||||
SALSA20,
|
|
||||||
SALSA20R12,
|
|
||||||
GOST28147,
|
|
||||||
CHACHA20;
|
|
||||||
|
|
||||||
[CCode (cname = "gcry_cipher_algo_info")]
|
|
||||||
public Error info (ControlCommand what, [CCode (array_length_type = "size_t")] ref uchar[] buffer);
|
|
||||||
[CCode (cname = "gcry_cipher_algo_name")]
|
|
||||||
public unowned string to_string ();
|
|
||||||
[CCode (cname = "gcry_cipher_map_name")]
|
|
||||||
public static Algorithm from_string (string name);
|
|
||||||
[CCode (cname = "gcry_cipher_map_oid")]
|
|
||||||
public static Algorithm from_oid (string oid);
|
|
||||||
}
|
|
||||||
|
|
||||||
[CCode (cname = "enum gcry_cipher_modes", cprefix = "GCRY_CIPHER_MODE_")]
|
|
||||||
public enum Mode {
|
|
||||||
NONE, /* No mode specified */
|
|
||||||
ECB, /* Electronic Codebook */
|
|
||||||
CFB, /* Cipher Feedback */
|
|
||||||
CFB8, /* Cipher Feedback */
|
|
||||||
CBC, /* Cipher Block Chaining */
|
|
||||||
STREAM, /* Used with stream ciphers */
|
|
||||||
OFB, /* Output Feedback */
|
|
||||||
CTR, /* Counter */
|
|
||||||
AESWRAP,
|
|
||||||
CCM, /* Counter with CBC-MAC */
|
|
||||||
GCM, /* Galois/Counter Mode */
|
|
||||||
POLY1305,
|
|
||||||
OCB
|
|
||||||
}
|
|
||||||
|
|
||||||
[CCode (cname = "enum gcry_cipher_flags", cprefix = "GCRY_CIPHER_")]
|
|
||||||
public enum Flag {
|
|
||||||
SECURE, /* Allocate in secure memory. */
|
|
||||||
ENABLE_SYNC, /* Enable CFB sync mode. */
|
|
||||||
CBC_CTS, /* Enable CBC cipher text stealing (CTS). */
|
|
||||||
CBC_MAC /* Enable CBC message auth. code (MAC). */
|
|
||||||
}
|
|
||||||
[Compact]
|
|
||||||
[CCode (cname = "struct gcry_cipher_handle", lower_case_cprefix = "gcry_cipher_", free_function = "gcry_cipher_close")]
|
|
||||||
public class Cipher {
|
|
||||||
public static Error open (out Cipher cipher, Algorithm algo, Mode mode, Flag flags);
|
|
||||||
public void close ();
|
|
||||||
[CCode (cname = "gcry_cipher_ctl")]
|
|
||||||
public Error control (ControlCommand cmd, [CCode (array_length_type = "size_t")] uchar[] buffer);
|
|
||||||
public Error info (ControlCommand what, [CCode (array_length_type = "size_t")] ref uchar[] buffer);
|
|
||||||
|
|
||||||
public Error encrypt (uchar[] out_buffer, uchar[] in_buffer);
|
|
||||||
public Error decrypt (uchar[] out_buffer, uchar[] in_buffer);
|
|
||||||
|
|
||||||
[CCode (cname = "gcry_cipher_setkey")]
|
|
||||||
public Error set_key (uchar[] key_data);
|
|
||||||
[CCode (cname = "gcry_cipher_setiv")]
|
|
||||||
public Error set_iv (uchar[] iv_data);
|
|
||||||
[CCode (cname = "gcry_cipher_setctr")]
|
|
||||||
public Error set_counter_vector (uchar[] counter_vector);
|
|
||||||
public Error reset ();
|
|
||||||
public Error sync ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Compact, CCode (cname = "struct gcry_md_handle", cprefix = "gcry_md_", free_function = "gcry_md_close")]
|
|
||||||
public class Hash {
|
|
||||||
[CCode (cname = "enum gcry_md_algos", cprefix = "GCRY_MD_")]
|
|
||||||
public enum Algorithm {
|
|
||||||
NONE,
|
|
||||||
SHA1,
|
|
||||||
RMD160,
|
|
||||||
MD5,
|
|
||||||
MD4,
|
|
||||||
MD2,
|
|
||||||
TIGER,
|
|
||||||
TIGER1,
|
|
||||||
TIGER2,
|
|
||||||
HAVAL,
|
|
||||||
SHA224,
|
|
||||||
SHA256,
|
|
||||||
SHA384,
|
|
||||||
SHA512,
|
|
||||||
SHA3_224,
|
|
||||||
SHA3_256,
|
|
||||||
SHA3_384,
|
|
||||||
SHA3_512,
|
|
||||||
SHAKE128,
|
|
||||||
SHAKE256,
|
|
||||||
CRC32,
|
|
||||||
CRC32_RFC1510,
|
|
||||||
CRC24_RFC2440,
|
|
||||||
WHIRLPOOL,
|
|
||||||
GOSTR3411_94,
|
|
||||||
STRIBOG256,
|
|
||||||
STRIBOG512;
|
|
||||||
|
|
||||||
[CCode (cname = "gcry_md_get_algo_dlen")]
|
|
||||||
public size_t get_digest_length ();
|
|
||||||
[CCode (cname = "gcry_md_algo_info")]
|
|
||||||
public Error info (ControlCommand what, [CCode (array_length_type = "size_t")] ref uchar[] buffer);
|
|
||||||
[CCode (cname = "gcry_md_algo_name")]
|
|
||||||
public unowned string to_string ();
|
|
||||||
[CCode (cname = "gcry_md_map_name")]
|
|
||||||
public static Algorithm from_string (string name);
|
|
||||||
[CCode (cname = "gcry_md_test_algo")]
|
|
||||||
public Error is_available ();
|
|
||||||
[CCode (cname = "gcry_md_get_asnoid")]
|
|
||||||
public Error get_oid ([CCode (array_length_type = "size_t")] ref uchar[] buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
[CCode (cname = "enum gcry_md_flags", cprefix = "GCRY_MD_FLAG_")]
|
|
||||||
public enum Flag {
|
|
||||||
SECURE,
|
|
||||||
HMAC,
|
|
||||||
BUGEMU1
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Error open (out Hash hash, Algorithm algo, Flag flag);
|
|
||||||
public void close ();
|
|
||||||
public Error enable (Algorithm algo);
|
|
||||||
[CCode (instance_pos = -1)]
|
|
||||||
public Error copy (out Hash dst);
|
|
||||||
public void reset ();
|
|
||||||
[CCode (cname = "gcry_md_ctl")]
|
|
||||||
public Error control (ControlCommand cmd, [CCode (array_length_type = "size_t")] uchar[] buffer);
|
|
||||||
public void write (uchar[] buffer);
|
|
||||||
[CCode (array_length = false)]
|
|
||||||
public unowned uchar[] read (Algorithm algo);
|
|
||||||
public static void hash_buffer (Algorithm algo, [CCode (array_length = false)] uchar[] digest, uchar[] buffer);
|
|
||||||
public Algorithm get_algo ();
|
|
||||||
public bool is_enabled (Algorithm algo);
|
|
||||||
public bool is_secure ();
|
|
||||||
public Error info (ControlCommand what, [CCode (array_length_type = "size_t")] ref uchar[] buffer);
|
|
||||||
[CCode (cname = "gcry_md_setkey")]
|
|
||||||
public Error set_key (uchar[] key_data);
|
|
||||||
public void putc (char c);
|
|
||||||
public void final ();
|
|
||||||
public static Error list (ref Algorithm[] algos);
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Random {
|
|
||||||
[CCode (cname = "gcry_random_level_t")]
|
|
||||||
public enum Level {
|
|
||||||
[CCode (cname = "GCRY_WEAK_RANDOM")]
|
|
||||||
WEAK,
|
|
||||||
[CCode (cname = "GCRY_STRONG_RANDOM")]
|
|
||||||
STRONG,
|
|
||||||
[CCode (cname = "GCRY_VERY_STRONG_RANDOM")]
|
|
||||||
VERY_STRONG
|
|
||||||
}
|
|
||||||
|
|
||||||
[CCode (cname = "gcry_randomize")]
|
|
||||||
public static void randomize (uchar[] buffer, Level level = Level.VERY_STRONG);
|
|
||||||
[CCode (cname = "gcry_fast_random_poll")]
|
|
||||||
public static Error poll ();
|
|
||||||
[CCode (cname = "gcry_random_bytes", array_length = false)]
|
|
||||||
public static uchar[] random_bytes (size_t nbytes, Level level = Level.VERY_STRONG);
|
|
||||||
[CCode (cname = "gcry_random_bytes_secure", array_length = false)]
|
|
||||||
public static uchar[] random_bytes_secure (size_t nbytes, Level level = Level.VERY_STRONG);
|
|
||||||
[CCode (cname = "gcry_create_nonce")]
|
|
||||||
public static void nonce (uchar[] buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Compact, CCode (cname = "struct gcry_mpi", cprefix = "gcry_mpi_", free_function = "gcry_mpi_release")]
|
|
||||||
public class MPI {
|
|
||||||
[CCode (cname = "enum gcry_mpi_format", cprefix = "GCRYMPI_FMT_")]
|
|
||||||
public enum Format {
|
|
||||||
NONE,
|
|
||||||
STD,
|
|
||||||
PGP,
|
|
||||||
SSH,
|
|
||||||
HEX,
|
|
||||||
USG
|
|
||||||
}
|
|
||||||
|
|
||||||
[CCode (cname = "enum gcry_mpi_flag", cprefix = "GCRYMPI_FLAG_")]
|
|
||||||
public enum Flag {
|
|
||||||
SECURE,
|
|
||||||
OPAQUE
|
|
||||||
}
|
|
||||||
|
|
||||||
public MPI (uint nbits);
|
|
||||||
[CCode (cname = "gcry_mpi_snew")]
|
|
||||||
public MPI.secure (uint nbits);
|
|
||||||
public MPI copy ();
|
|
||||||
public void set (MPI u);
|
|
||||||
public void set_ui (ulong u);
|
|
||||||
public void swap (MPI b);
|
|
||||||
public int cmp (MPI v);
|
|
||||||
public int cmp_ui (ulong v);
|
|
||||||
|
|
||||||
public static Error scan (out MPI ret, MPI.Format format, [CCode (array_length = false)] uchar[] buffer, size_t buflen, out size_t nscanned);
|
|
||||||
[CCode (instance_pos = -1)]
|
|
||||||
public Error print (MPI.Format format, [CCode (array_length = false)] uchar[] buffer, size_t buflen, out size_t nwritter);
|
|
||||||
[CCode (instance_pos = -1)]
|
|
||||||
public Error aprint (MPI.Format format, [CCode (array_length_type = "size_t")] out uchar[] buffer);
|
|
||||||
|
|
||||||
public void add (MPI u, MPI v);
|
|
||||||
public void add_ui (MPI u, ulong v);
|
|
||||||
public void addm (MPI u, MPI v, MPI m);
|
|
||||||
public void sub (MPI u, MPI v);
|
|
||||||
public void sub_ui (MPI u, ulong v);
|
|
||||||
public void subm (MPI u, MPI v, MPI m);
|
|
||||||
public void mul (MPI u, MPI v);
|
|
||||||
public void mul_ui (MPI u, ulong v);
|
|
||||||
public void mulm (MPI u, MPI v, MPI m);
|
|
||||||
public void mul_2exp (MPI u, ulong cnt);
|
|
||||||
public void div (MPI r, MPI dividend, MPI divisor, int round);
|
|
||||||
public void mod (MPI dividend, MPI divisor);
|
|
||||||
public void powm (MPI b, MPI e, MPI m);
|
|
||||||
public int gcd (MPI a, MPI b);
|
|
||||||
public int invm (MPI a, MPI m);
|
|
||||||
|
|
||||||
public uint get_nbits ();
|
|
||||||
public int test_bit (uint n);
|
|
||||||
public void set_bit (uint n);
|
|
||||||
public void clear_bit (uint n);
|
|
||||||
public void set_highbit (uint n);
|
|
||||||
public void clear_highbit (uint n);
|
|
||||||
public void rshift (MPI a, uint n);
|
|
||||||
public void lshift (MPI a, uint n);
|
|
||||||
|
|
||||||
public void set_flag (MPI.Flag flag);
|
|
||||||
public void clear_flag (MPI.Flag flag);
|
|
||||||
public int get_flag (MPI.Flag flag);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Compact, CCode (cname = "struct gcry_sexp", free_function = "gcry_sexp_release")]
|
|
||||||
public class SExp {
|
|
||||||
[CCode (cname = "int", cprefix = "GCRYSEXP_FMT_")]
|
|
||||||
public enum Format {
|
|
||||||
DEFAULT,
|
|
||||||
CANON,
|
|
||||||
BASE64,
|
|
||||||
ADVANCED
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Error @new (out SExp retsexp, void * buffer, size_t length, int autodetect);
|
|
||||||
public static Error create (out SExp retsexp, void * buffer, size_t length, int autodetect, GLib.DestroyNotify free_function);
|
|
||||||
public static Error sscan (out SExp retsexp, out size_t erroff, char[] buffer);
|
|
||||||
public static Error build (out SExp retsexp, out size_t erroff, string format, ...);
|
|
||||||
public size_t sprint (Format mode, char[] buffer);
|
|
||||||
public static size_t canon_len (uchar[] buffer, out size_t erroff, out int errcode);
|
|
||||||
public SExp find_token (string token, size_t token_length = 0);
|
|
||||||
public int length ();
|
|
||||||
public SExp? nth (int number);
|
|
||||||
public SExp? car ();
|
|
||||||
public SExp? cdr ();
|
|
||||||
[CCode (array_length_type = "size_t")]
|
|
||||||
public unowned char[] nth_data (int number);
|
|
||||||
public gcry_string nth_string (int number);
|
|
||||||
public MPI nth_mpi (int number, MPI.Format mpifmt);
|
|
||||||
}
|
|
||||||
|
|
||||||
[CCode (cname = "char", free_function = "gcry_free")]
|
|
||||||
public class gcry_string : string { }
|
|
||||||
|
|
||||||
[CCode (lower_case_cprefix = "gcry_pk_")]
|
|
||||||
namespace PublicKey {
|
|
||||||
[CCode (cname = "enum gcry_pk_algos")]
|
|
||||||
public enum Algorithm {
|
|
||||||
RSA,
|
|
||||||
ELG_E,
|
|
||||||
DSA,
|
|
||||||
ELG,
|
|
||||||
ECDSA;
|
|
||||||
|
|
||||||
[CCode (cname = "gcry_pk_algo_name")]
|
|
||||||
public unowned string to_string ();
|
|
||||||
[CCode (cname = "gcry_pk_map_name")]
|
|
||||||
public static Algorithm map_name (string name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Error encrypt (out SExp ciphertext, SExp data, SExp pkey);
|
|
||||||
public static Error decrypt (out SExp plaintext, SExp data, SExp skey);
|
|
||||||
public static Error sign (out SExp signature, SExp data, SExp skey);
|
|
||||||
public static Error verify (SExp signature, SExp data, SExp pkey);
|
|
||||||
public static Error testkey (SExp key);
|
|
||||||
public static Error genkey (out SExp r_key, SExp s_params);
|
|
||||||
public static uint get_nbits (SExp key);
|
|
||||||
}
|
|
||||||
|
|
||||||
[CCode (lower_case_cprefix = "gcry_kdf_")]
|
|
||||||
namespace KeyDerivation {
|
|
||||||
[CCode (cname = "enum gcry_kdf_algos", cprefix = "GCRY_KDF_", has_type_id = false)]
|
|
||||||
public enum Algorithm {
|
|
||||||
NONE,
|
|
||||||
SIMPLE_S2K,
|
|
||||||
SALTED_S2K,
|
|
||||||
ITERSALTED_S2K,
|
|
||||||
PBKDF1,
|
|
||||||
PBKDF2,
|
|
||||||
SCRYPT
|
|
||||||
}
|
|
||||||
|
|
||||||
public GCrypt.Error derive ([CCode (type = "const void*", array_length_type = "size_t")] uint8[] passphrasse, GCrypt.KeyDerivation.Algorithm algo, GCrypt.Hash.Algorithm subalgo, [CCode (type = "const void*", array_length_type = "size_t")] uint8[] salt, ulong iterations, [CCode (type = "void*", array_length_type = "size_t", array_length_pos = 5.5)] uint8[] keybuffer);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,177 +0,0 @@
|
||||||
[CCode (cheader_filename = "mpv/client.h")]
|
|
||||||
namespace Mpv {
|
|
||||||
|
|
||||||
[CCode (cname = "mpv_error", cprefix = "MPV_ERROR_", has_type_id = false)]
|
|
||||||
public enum Error {
|
|
||||||
SUCCESS,
|
|
||||||
EVENT_QUEUE_FULL,
|
|
||||||
NOMEM,
|
|
||||||
UNINITIALIZED,
|
|
||||||
INVALID_PARAMETER,
|
|
||||||
OPTION_NOT_FOUND,
|
|
||||||
OPTION_FORMAT,
|
|
||||||
OPTION_ERROR,
|
|
||||||
PROPERTY_NOT_FOUND,
|
|
||||||
PROPERTY_FORMAT,
|
|
||||||
PROPERTY_UNAVAILABLE,
|
|
||||||
PROPERTY_ERROR,
|
|
||||||
COMMAND,
|
|
||||||
LOADING_FAILED,
|
|
||||||
AO_INIT_FAILED,
|
|
||||||
VO_INIT_FAILED,
|
|
||||||
NOTHING_TO_PLAY,
|
|
||||||
UNKNOWN_FORMAT,
|
|
||||||
UNSUPPORTED,
|
|
||||||
NOT_IMPLEMENTED,
|
|
||||||
GENERIC;
|
|
||||||
|
|
||||||
[CCode (cname = "mpv_error_string")]
|
|
||||||
public unowned string to_string ();
|
|
||||||
}
|
|
||||||
|
|
||||||
public delegate void WakeupCallback ();
|
|
||||||
|
|
||||||
[CCode (cname = "mpv_handle", free_function = "mpv_terminate_destroy")]
|
|
||||||
[Compact]
|
|
||||||
public class Handle {
|
|
||||||
[CCode (cname = "mpv_create")]
|
|
||||||
public Handle ();
|
|
||||||
|
|
||||||
[CCode (cname = "mpv_initialize")]
|
|
||||||
public Error initialize ();
|
|
||||||
|
|
||||||
[CCode (cname = "mpv_wait_event")]
|
|
||||||
public unowned Event? wait_event (double timeout);
|
|
||||||
|
|
||||||
public WakeupCallback wakeup_callback {
|
|
||||||
[CCode (cname = "mpv_set_wakeup_callback")] set;
|
|
||||||
}
|
|
||||||
|
|
||||||
[CCode (cname = "mpv_set_property")]
|
|
||||||
private Error set_property (string name, Format format, void *data);
|
|
||||||
|
|
||||||
[CCode (cname = "mpv_set_property_string")]
|
|
||||||
public Error set_property_string (string name, string value);
|
|
||||||
|
|
||||||
public Error set_property_int64 (string name, int64 value) {
|
|
||||||
return this.set_property (name, Format.INT64, &value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Error set_property_flag (string name, bool value) {
|
|
||||||
int flag = value ? 1 : 0;
|
|
||||||
return this.set_property (name, Format.FLAG, &flag);
|
|
||||||
}
|
|
||||||
|
|
||||||
[CCode (cname = "mpv_command")]
|
|
||||||
public Error command ([CCode (array_length = false)] string[] args);
|
|
||||||
|
|
||||||
[CCode (cname = "mpv_command_async")]
|
|
||||||
public Error command_async (uint64 reply_userdata, [CCode (array_length = false)] string[] args);
|
|
||||||
|
|
||||||
[CCode (cname = "mpv_observe_property")]
|
|
||||||
public Error observe_property (uint64 reply_userdata, string name, Format format);
|
|
||||||
}
|
|
||||||
|
|
||||||
[CCode (cname = "mpv_format", cprefix = "MPV_FORMAT_", has_type_id = false)]
|
|
||||||
public enum Format {
|
|
||||||
NONE,
|
|
||||||
STRING,
|
|
||||||
OSD_STRING,
|
|
||||||
FLAG,
|
|
||||||
INT64,
|
|
||||||
DOUBLE,
|
|
||||||
NODE,
|
|
||||||
NODE_ARRAY,
|
|
||||||
NODE_MAP,
|
|
||||||
BYTE_ARRAY,
|
|
||||||
}
|
|
||||||
|
|
||||||
[CCode (cname = "mpv_event_id", cprefix = "MPV_EVENT_", has_type_id = false)]
|
|
||||||
public enum EventId {
|
|
||||||
NONE,
|
|
||||||
SHUTDOWN,
|
|
||||||
LOG_MESSAGE,
|
|
||||||
GET_PROPERTY_REPLY,
|
|
||||||
SET_PROPERTY_REPLY,
|
|
||||||
COMMAND_REPLY,
|
|
||||||
START_FILE,
|
|
||||||
END_FILE,
|
|
||||||
FILE_LOADED,
|
|
||||||
CLIENT_MESSAGE,
|
|
||||||
VIDEO_RECONFIG,
|
|
||||||
AUDIO_RECONFIG,
|
|
||||||
SEEK,
|
|
||||||
PLAYBACK_RESTART,
|
|
||||||
PROPERTY_CHANGE,
|
|
||||||
QUEUE_OVERFLOW,
|
|
||||||
HOOK;
|
|
||||||
|
|
||||||
[CCode (cname = "mpv_event_name")]
|
|
||||||
public unowned string to_string ();
|
|
||||||
}
|
|
||||||
|
|
||||||
[CCode (cname = "mpv_event", destroy_function = "", has_type_id = false, has_copy_function = false)]
|
|
||||||
public struct Event {
|
|
||||||
EventId event_id;
|
|
||||||
Error error;
|
|
||||||
uint64 reply_userdata;
|
|
||||||
void *data;
|
|
||||||
|
|
||||||
public unowned EventProperty? parse_property ()
|
|
||||||
requires (event_id == EventId.PROPERTY_CHANGE)
|
|
||||||
requires (error >= 0)
|
|
||||||
{
|
|
||||||
return (EventProperty?) data;
|
|
||||||
}
|
|
||||||
|
|
||||||
public unowned EventEndFile? parse_end_file ()
|
|
||||||
requires (event_id == EventId.END_FILE)
|
|
||||||
requires (error >= 0)
|
|
||||||
{
|
|
||||||
return (EventEndFile?) data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[CCode (cname = "mpv_event_property", destroy_function = "", has_type_id = false, has_copy_function = false)]
|
|
||||||
public struct EventProperty {
|
|
||||||
unowned string name;
|
|
||||||
Format format;
|
|
||||||
void *data;
|
|
||||||
|
|
||||||
public int64 parse_int64 ()
|
|
||||||
requires (format == Format.INT64)
|
|
||||||
{
|
|
||||||
return * (int64 *) data;
|
|
||||||
}
|
|
||||||
|
|
||||||
public double parse_double ()
|
|
||||||
requires (format == Format.DOUBLE)
|
|
||||||
{
|
|
||||||
return * (double *) data;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool parse_flag ()
|
|
||||||
requires (format == Format.FLAG)
|
|
||||||
{
|
|
||||||
return (* (int *) data) == 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[CCode (cname = "mpv_event_end_file", destroy_function = "", has_type_id = false, has_copy_function = false)]
|
|
||||||
public struct EventEndFile {
|
|
||||||
EndFileReason reason;
|
|
||||||
Error error;
|
|
||||||
int64 playlist_entry_id;
|
|
||||||
int playlist_insert_num_entries;
|
|
||||||
}
|
|
||||||
|
|
||||||
[CCode (cname = "mpv_end_file_reason", cprefix = "MPV_END_FILE_REASON_", has_type_id = false)]
|
|
||||||
public enum EndFileReason {
|
|
||||||
EOF,
|
|
||||||
STOP,
|
|
||||||
QUIT,
|
|
||||||
ERROR,
|
|
||||||
REDIRECT,
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
Loading…
Reference in a new issue