Initial revision
This commit is contained in:
203
src/file.c
Normal file
203
src/file.c
Normal file
@@ -0,0 +1,203 @@
|
||||
// SPDX-FileCopyrightText: 2022 Geoffrey D. Bennett <g@b4.vu>
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include "alsa.h"
|
||||
#include "alsa-sim.h"
|
||||
#include "error.h"
|
||||
#include "file.h"
|
||||
#include "stringhelper.h"
|
||||
|
||||
static void run_alsactl(
|
||||
struct alsa_card *card,
|
||||
char *cmd,
|
||||
char *fn
|
||||
) {
|
||||
GtkWindow *w = GTK_WINDOW(card->window_main);
|
||||
|
||||
gchar *argv[] = {
|
||||
"alsactl", cmd, card->device, "-f", fn, NULL
|
||||
};
|
||||
gchar *stdout;
|
||||
gchar *stderr;
|
||||
gint exit_status;
|
||||
GError *error = NULL;
|
||||
|
||||
gboolean result = g_spawn_sync(
|
||||
NULL,
|
||||
argv,
|
||||
NULL,
|
||||
G_SPAWN_SEARCH_PATH,
|
||||
NULL,
|
||||
NULL,
|
||||
&stdout,
|
||||
&stderr,
|
||||
&exit_status,
|
||||
&error
|
||||
);
|
||||
|
||||
if (result && WIFEXITED(exit_status) && WEXITSTATUS(exit_status) == 0)
|
||||
goto done;
|
||||
|
||||
char *error_message =
|
||||
result
|
||||
? g_strdup_printf("%s\n%s", stdout, stderr)
|
||||
: g_strdup_printf("%s", error->message);
|
||||
|
||||
char *msg = g_strdup_printf(
|
||||
"Error running “alsactl %s %s -f %s”: %s",
|
||||
cmd, card->device, fn, error_message
|
||||
);
|
||||
show_error(w, msg);
|
||||
g_free(msg);
|
||||
g_free(error_message);
|
||||
|
||||
done:
|
||||
g_free(stdout);
|
||||
g_free(stderr);
|
||||
if (error)
|
||||
g_error_free(error);
|
||||
}
|
||||
|
||||
static void add_state_filter(GtkFileChooserNative *native) {
|
||||
GtkFileFilter *filter = gtk_file_filter_new();
|
||||
gtk_file_filter_set_name(filter, "alsactl state file (.state)");
|
||||
gtk_file_filter_add_pattern(filter, "*.state");
|
||||
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(native), filter);
|
||||
}
|
||||
|
||||
static void load_response(
|
||||
GtkNativeDialog *native,
|
||||
int response,
|
||||
gpointer data
|
||||
) {
|
||||
struct alsa_card *card = data;
|
||||
|
||||
if (response != GTK_RESPONSE_ACCEPT)
|
||||
goto done;
|
||||
|
||||
GFile *file = gtk_file_chooser_get_file(GTK_FILE_CHOOSER(native));
|
||||
char *fn = g_file_get_path(file);
|
||||
|
||||
run_alsactl(card, "restore", fn);
|
||||
|
||||
g_free(fn);
|
||||
g_object_unref(file);
|
||||
|
||||
done:
|
||||
g_object_unref(native);
|
||||
}
|
||||
|
||||
void activate_load(
|
||||
GSimpleAction *action,
|
||||
GVariant *parameter,
|
||||
gpointer data
|
||||
) {
|
||||
struct alsa_card *card = data;
|
||||
|
||||
GtkFileChooserNative *native = gtk_file_chooser_native_new(
|
||||
"Load Configuration",
|
||||
GTK_WINDOW(card->window_main),
|
||||
GTK_FILE_CHOOSER_ACTION_OPEN,
|
||||
"_Load",
|
||||
"_Cancel"
|
||||
);
|
||||
|
||||
add_state_filter(native);
|
||||
|
||||
g_signal_connect(native, "response", G_CALLBACK(load_response), card);
|
||||
gtk_native_dialog_show(GTK_NATIVE_DIALOG(native));
|
||||
}
|
||||
|
||||
static void save_response(
|
||||
GtkNativeDialog *native,
|
||||
int response,
|
||||
gpointer data
|
||||
) {
|
||||
struct alsa_card *card = data;
|
||||
|
||||
if (response != GTK_RESPONSE_ACCEPT)
|
||||
goto done;
|
||||
|
||||
GFile *file = gtk_file_chooser_get_file(GTK_FILE_CHOOSER(native));
|
||||
char *fn = g_file_get_path(file);
|
||||
|
||||
// append .state if not present
|
||||
char *fn_with_ext;
|
||||
if (string_ends_with(fn, ".state"))
|
||||
fn_with_ext = g_strdup_printf("%s", fn);
|
||||
else
|
||||
fn_with_ext = g_strdup_printf("%s.state", fn);
|
||||
|
||||
run_alsactl(card, "store", fn_with_ext);
|
||||
|
||||
g_free(fn);
|
||||
g_free(fn_with_ext);
|
||||
g_object_unref(file);
|
||||
|
||||
done:
|
||||
g_object_unref(native);
|
||||
}
|
||||
|
||||
void activate_save(
|
||||
GSimpleAction *action,
|
||||
GVariant *parameter,
|
||||
gpointer data
|
||||
) {
|
||||
struct alsa_card *card = data;
|
||||
|
||||
GtkFileChooserNative *native = gtk_file_chooser_native_new(
|
||||
"Save Configuration",
|
||||
GTK_WINDOW(card->window_main),
|
||||
GTK_FILE_CHOOSER_ACTION_SAVE,
|
||||
"_Save",
|
||||
"_Cancel"
|
||||
);
|
||||
|
||||
add_state_filter(native);
|
||||
|
||||
g_signal_connect(native, "response", G_CALLBACK(save_response), card);
|
||||
gtk_native_dialog_show(GTK_NATIVE_DIALOG(native));
|
||||
}
|
||||
|
||||
static void sim_response(
|
||||
GtkNativeDialog *native,
|
||||
int response,
|
||||
gpointer data
|
||||
) {
|
||||
GtkWindow *w = data;
|
||||
|
||||
if (response != GTK_RESPONSE_ACCEPT)
|
||||
goto done;
|
||||
|
||||
GFile *file = gtk_file_chooser_get_file(GTK_FILE_CHOOSER(native));
|
||||
char *fn = g_file_get_path(file);
|
||||
|
||||
create_sim_from_file(w, fn);
|
||||
|
||||
g_free(fn);
|
||||
g_object_unref(file);
|
||||
|
||||
done:
|
||||
g_object_unref(native);
|
||||
}
|
||||
|
||||
void activate_sim(
|
||||
GSimpleAction *action,
|
||||
GVariant *parameter,
|
||||
gpointer data
|
||||
) {
|
||||
GtkWidget *w = data;
|
||||
|
||||
GtkFileChooserNative *native = gtk_file_chooser_native_new(
|
||||
"Load Configuration File for Interface Simulation",
|
||||
GTK_WINDOW(w),
|
||||
GTK_FILE_CHOOSER_ACTION_OPEN,
|
||||
"_Load",
|
||||
"_Cancel"
|
||||
);
|
||||
|
||||
add_state_filter(native);
|
||||
|
||||
g_signal_connect(native, "response", G_CALLBACK(sim_response), w);
|
||||
gtk_native_dialog_show(GTK_NATIVE_DIALOG(native));
|
||||
}
|
||||
Reference in New Issue
Block a user