diff --git a/daemon/cmd_load_studio.c b/daemon/cmd_load_studio.c index aad5cd06..ec0a079b 100644 --- a/daemon/cmd_load_studio.c +++ b/daemon/cmd_load_studio.c @@ -942,6 +942,8 @@ static bool run(void * command_context) ladish_graph_dump(g_studio.jack_graph); ladish_graph_dump(g_studio.studio_graph); + ladish_recent_store_use_item(g_studios_recent_store, g_studio.name); + ladish_studio_announce(); cmd_ptr->command.state = LADISH_COMMAND_STATE_DONE; diff --git a/daemon/recent_store.c b/daemon/recent_store.c index 659333c1..64b9cb32 100644 --- a/daemon/recent_store.c +++ b/daemon/recent_store.c @@ -269,6 +269,24 @@ reorder: ladish_recent_store_save(store_ptr); } +bool +ladish_recent_store_check_known( + ladish_recent_store_handle store_handle, + const char * item) +{ + unsigned int i; + + for (i = 0; i < store_ptr->max_items && store_ptr->items[i] != NULL; i++) + { + if (strcmp(store_ptr->items[i], item) == 0) + { + return true; + } + } + + return false; +} + void ladish_recent_store_iterate_items( ladish_recent_store_handle store_handle, diff --git a/daemon/recent_store.h b/daemon/recent_store.h index 042361e6..911a1014 100644 --- a/daemon/recent_store.h +++ b/daemon/recent_store.h @@ -46,6 +46,11 @@ ladish_recent_store_use_item( ladish_recent_store_handle store, const char * item); +bool +ladish_recent_store_check_known( + ladish_recent_store_handle store, + const char * item); + void ladish_recent_store_iterate_items( ladish_recent_store_handle store, diff --git a/daemon/studio.c b/daemon/studio.c index c31efb0e..9e9e7e9b 100644 --- a/daemon/studio.c +++ b/daemon/studio.c @@ -30,7 +30,6 @@ #include #include #include -#include #include "studio_internal.h" #include "../dbus_constants.h" @@ -43,7 +42,12 @@ #include "../proxies/notify_proxy.h" #define STUDIOS_DIR "/studios/" + +#define RECENT_STUDIOS_STORE_FILE "recent_studios" +#define RECENT_STUDIOS_STORE_MAX_ITEMS 50 + char * g_studios_dir; +ladish_recent_store_handle g_studios_recent_store; struct studio g_studio; @@ -530,6 +534,8 @@ static void ladish_studio_on_jack_server_disappeared(void) bool ladish_studio_init(void) { + char * studios_recent_store_path; + log_info("studio object construct"); g_studios_dir = catdup(g_base_dir, STUDIOS_DIR); @@ -544,6 +550,21 @@ bool ladish_studio_init(void) goto free_studios_dir; } + studios_recent_store_path = catdup(g_base_dir, "/" RECENT_STUDIOS_STORE_FILE); + if (studios_recent_store_path == NULL) + { + log_error("catdup failed for to compose recent studios store file path"); + goto free_studios_dir; + } + + if (!ladish_recent_store_create(studios_recent_store_path, 10, &g_studios_recent_store)) + { + free(studios_recent_store_path); + goto free_studios_dir; + } + + free(studios_recent_store_path); + INIT_LIST_HEAD(&g_studio.all_connections); INIT_LIST_HEAD(&g_studio.all_ports); INIT_LIST_HEAD(&g_studio.all_clients); @@ -567,7 +588,7 @@ bool ladish_studio_init(void) if (!ladish_graph_create(&g_studio.jack_graph, NULL)) { log_error("ladish_graph_create() failed to create jack graph object."); - goto free_studios_dir; + goto destroy_recent_store; } if (!ladish_graph_create(&g_studio.studio_graph, STUDIO_OBJECT_PATH)) @@ -603,6 +624,8 @@ studio_graph_destroy: ladish_graph_destroy(g_studio.studio_graph); jack_graph_destroy: ladish_graph_destroy(g_studio.jack_graph); +destroy_recent_store: + ladish_recent_store_destroy(g_studios_recent_store); free_studios_dir: free(g_studios_dir); fail: @@ -620,6 +643,8 @@ void ladish_studio_uninit(void) ladish_graph_destroy(g_studio.studio_graph); ladish_graph_destroy(g_studio.jack_graph); + ladish_recent_store_destroy(g_studios_recent_store); + free(g_studios_dir); log_info("studio object destroy"); @@ -781,75 +806,6 @@ ladish_app_supervisor_handle ladish_studio_find_app_supervisor(const char * opat return ctx.supervisor; } -bool ladish_studios_iterate(void * call_ptr, void * context, bool (* callback)(void * call_ptr, void * context, const char * studio, uint32_t modtime)) -{ - DIR * dir; - struct dirent * dentry; - size_t len; - struct stat st; - char * path; - char * name; - - dir = opendir(g_studios_dir); - if (dir == NULL) - { - lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "Cannot open directory '%s': %d (%s)", g_studios_dir, errno, strerror(errno)); - return false; - } - - while ((dentry = readdir(dir)) != NULL) - { - len = strlen(dentry->d_name); - if (len <= 4 || strcmp(dentry->d_name + (len - 4), ".xml") != 0) - continue; - - path = catdup(g_studios_dir, dentry->d_name); - if (path == NULL) - { - lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "catdup() failed"); - return false; - } - - if (stat(path, &st) != 0) - { - lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "failed to stat '%s': %d (%s)", path, errno, strerror(errno)); - free(path); - return false; - } - - free(path); - - if (!S_ISREG(st.st_mode)) - { - //log_info("Ignoring direntry that is not regular file. Mode is %07o", st.st_mode); - continue; - } - - name = malloc(len - 4 + 1); - if (name == NULL) - { - log_error("malloc() failed."); - closedir(dir); - return false; - } - - name[unescape(dentry->d_name, len - 4, name)] = 0; - //log_info("name = '%s'", name); - - if (!callback(call_ptr, context, name, st.st_mtime)) - { - free(name); - closedir(dir); - return false; - } - - free(name); - } - - closedir(dir); - return true; -} - bool ladish_studio_delete(void * call_ptr, const char * studio_name) { char * filename; diff --git a/daemon/studio_internal.h b/daemon/studio_internal.h index 2398beb1..e65d559c 100644 --- a/daemon/studio_internal.h +++ b/daemon/studio_internal.h @@ -34,6 +34,7 @@ #include "app_supervisor.h" #include "cmd.h" #include "studio.h" +#include "recent_store.h" #define JACK_CONF_MAX_ADDRESS_SIZE 1024 @@ -184,6 +185,8 @@ struct conf_callback_context }; extern struct studio g_studio; +extern char * g_studios_dir; +extern ladish_recent_store_handle g_studios_recent_store; extern const struct dbus_interface_descriptor g_interface_studio; diff --git a/daemon/studio_list.c b/daemon/studio_list.c new file mode 100644 index 00000000..613f8414 --- /dev/null +++ b/daemon/studio_list.c @@ -0,0 +1,163 @@ +/* -*- Mode: C ; c-basic-offset: 2 -*- */ +/* + * LADI Session Handler (ladish) + * + * Copyright (C) 2009, 2010 Nedko Arnaudov + * + ************************************************************************** + * This file contains studio list implementation + ************************************************************************** + * + * LADI Session Handler is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * LADI Session Handler 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with LADI Session Handler. If not, see + * or write to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "common.h" + +#include +#include +#include +#include + +#include "studio_internal.h" +#include "../common/catdup.h" +#include "escape.h" + +struct ladish_studios_iterate_context +{ + void * call_ptr; + void * context; + bool (* callback)(void * call_ptr, void * context, const char * studio, uint32_t modtime); + unsigned int counter; +}; + +#define ctx_ptr ((struct ladish_studios_iterate_context *)callback_context) + +bool recent_studio_callback(void * callback_context, const char * item) +{ + char * path; + struct stat st; + + if (!ladish_studio_compose_filename(item, &path, NULL)) + { + log_error("failed to compose path of (recent) studio \%s\" file", item); + return true; + } + + if (stat(path, &st) != 0) + { + if (errno != ENOENT) + { + log_error("failed to stat '%s': %d (%s)", path, errno, strerror(errno)); + } + + return true; + } + + if (!S_ISREG(st.st_mode)) + { + log_info("Ignoring recent studio that is not regular file. Mode is %07o", st.st_mode); + return true; + } + + ctx_ptr->callback(ctx_ptr->call_ptr, ctx_ptr->context, item, st.st_mtime); + ctx_ptr->counter++; + + return true; +} + +#undef ctx_ptr + +bool ladish_studios_iterate(void * call_ptr, void * context, bool (* callback)(void * call_ptr, void * context, const char * studio, uint32_t modtime)) +{ + DIR * dir; + struct dirent * dentry; + size_t len; + struct stat st; + char * path; + char * name; + struct ladish_studios_iterate_context ctx; + + ctx.call_ptr = call_ptr; + ctx.context = context; + ctx.callback = callback; + ctx.counter = 0; + + ladish_recent_store_iterate_items(g_studios_recent_store, &ctx, recent_studio_callback); + + /* TODO: smarter error handling based on ctx.counter (dbus error vs just logged error) */ + + dir = opendir(g_studios_dir); + if (dir == NULL) + { + lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "Cannot open directory '%s': %d (%s)", g_studios_dir, errno, strerror(errno)); + return false; + } + + while ((dentry = readdir(dir)) != NULL) + { + len = strlen(dentry->d_name); + if (len <= 4 || strcmp(dentry->d_name + (len - 4), ".xml") != 0) + continue; + + path = catdup(g_studios_dir, dentry->d_name); + if (path == NULL) + { + lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "catdup() failed"); + return false; + } + + if (stat(path, &st) != 0) + { + lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "failed to stat '%s': %d (%s)", path, errno, strerror(errno)); + free(path); + return false; + } + + free(path); + + if (!S_ISREG(st.st_mode)) + { + //log_info("Ignoring direntry that is not regular file. Mode is %07o", st.st_mode); + continue; + } + + name = malloc(len - 4 + 1); + if (name == NULL) + { + log_error("malloc() failed."); + closedir(dir); + return false; + } + + name[unescape(dentry->d_name, len - 4, name)] = 0; + //log_info("name = '%s'", name); + + if (!ladish_recent_store_check_known(g_studios_recent_store, name)) + { + if (!callback(call_ptr, context, name, st.st_mtime)) + { + free(name); + closedir(dir); + return false; + } + } + + free(name); + } + + closedir(dir); + return true; +} diff --git a/wscript b/wscript index e925f527..f386bc81 100644 --- a/wscript +++ b/wscript @@ -330,6 +330,7 @@ def build(bld): 'graph_dict.c', 'escape.c', 'studio_jack_conf.c', + 'studio_list.c', 'save.c', 'load.c', 'cmd_load_studio.c',