OSDN Git Service

LinGui: allow multiple instances of the gui to run
authorjstebbins <jstebbins@b64f7644-9d1e-0410-96f1-a4d463321fa5>
Fri, 9 Apr 2010 18:17:51 +0000 (18:17 +0000)
committerjstebbins <jstebbins@b64f7644-9d1e-0410-96f1-a4d463321fa5>
Fri, 9 Apr 2010 18:17:51 +0000 (18:17 +0000)
Each instance has a queue named "queue.<pid>".  On startup, the gui
opens and locks with lockf a file "ghb.pid.<pid>".  Then it searches
for any other ghb.pid.<pid> files that exist that are not locked.  If
it finds one, then some instance of ghb exited and may have left behind
a queue.  Try to reload it.  If there are no items in the queue, continue
looking for unlocked ghb.pid.<pid> files.

git-svn-id: svn://localhost/HandBrake/trunk@3212 b64f7644-9d1e-0410-96f1-a4d463321fa5

gtk/src/main.c
gtk/src/presets.c
gtk/src/presets.h
gtk/src/queuehandler.c

index a6a12fc..aade07e 100644 (file)
@@ -698,21 +698,7 @@ main (int argc, char *argv[])
        ghb_hal_init();
 #endif
 
-       if (!ghb_lock_file("queue_lock"))
-       {
-       const gchar *markup =
-               N_("<b><big>Another instance of HandBrake is already running.</big></b>\n"
-               "\n"
-               "Only one instance of HandBrake may run.\n");
-        GtkWidget *dialog = gtk_message_dialog_new_with_markup(NULL,
-            GTK_DIALOG_MODAL,
-            GTK_MESSAGE_ERROR,
-            GTK_BUTTONS_CLOSE,
-            _(markup));
-        gtk_dialog_run(GTK_DIALOG(dialog));
-        gtk_widget_destroy(dialog);
-        exit(EXIT_FAILURE);
-       }
+       ghb_write_pid_file();
        ud = g_malloc0(sizeof(signal_user_data_t));
        ud->debug = ghb_debug;
        g_log_set_handler (NULL, G_LOG_LEVEL_DEBUG, debug_log_handler, ud);
index d830387..7d7e844 100644 (file)
@@ -1151,6 +1151,104 @@ ghb_lock_file(const gchar *name)
 #endif
 }
 
+void
+ghb_write_pid_file()
+{
+#if !defined(_WIN32)
+       gchar *config, *path;
+       pid_t pid;
+       FILE *fp;
+       int fd, lock;
+
+       pid = getpid();
+
+       config = ghb_get_user_config_dir(NULL);
+       path = g_strdup_printf ("%s/ghb.pid.%d", config, pid);
+
+       fp = g_fopen(path, "w");
+       fprintf(fp, "%d\n", pid);
+       fclose(fp);
+
+       fd = open(path, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR);
+       lock = lockf(fd, F_TLOCK, 0);
+
+       g_free(config);
+       g_free(path);
+#endif
+}
+
+void
+ghb_unlink_pid_file(int pid)
+{
+       gchar *config, *path;
+
+       config = ghb_get_user_config_dir(NULL);
+       path = g_strdup_printf ("%s/ghb.pid.%d", config, pid);
+
+       if (g_file_test(path, G_FILE_TEST_IS_REGULAR))
+       {
+               g_unlink(path);
+       }
+
+       g_free(config);
+       g_free(path);
+}
+
+int
+ghb_find_pid_file()
+{
+       const gchar *file;
+       gchar *config;
+
+       config = ghb_get_user_config_dir(NULL);
+
+       if (g_file_test(config, G_FILE_TEST_IS_DIR))
+       {
+               GDir *gdir = g_dir_open(config, 0, NULL);
+               file = g_dir_read_name(gdir);
+               while (file)
+               {
+                       if (strncmp(file, "ghb.pid.", 8) == 0)
+                       {
+                               gchar *path;
+                               int fd, lock = 1;
+                               pid_t my_pid;
+                               int pid;
+
+                               sscanf(file, "ghb.pid.%d", &pid);
+                               my_pid = getpid();
+                               if (my_pid == pid)
+                               {
+                                       file = g_dir_read_name(gdir);
+                                       continue;
+                               }
+
+                               path = g_strdup_printf("%s/%s", config, file);
+                               fd = g_open(path, O_RDWR);
+                               if (fd >= 0)
+                               {
+                                       lock = lockf(fd, F_TLOCK, 0);
+                               }
+                               if (lock == 0)
+                               {
+                                       close(fd);
+                                       g_dir_close(gdir);
+                                       g_unlink(path);
+                                       g_free(path);
+                                       g_free(config);
+                                       return pid;
+                               }
+                               g_free(path);
+                               close(fd);
+                       }
+                       file = g_dir_read_name(gdir);
+               }
+               g_dir_close(gdir);
+       }
+       g_free(config);
+       return -1;
+}
+
 static void
 remove_plist(const gchar *name)
 {
@@ -1806,19 +1904,61 @@ remove_std_presets(signal_user_data_t *ud)
 void
 ghb_save_queue(GValue *queue)
 {
-       store_plist(queue, "queue");
+       pid_t pid;
+       char *path;
+
+       pid = getpid();
+       path = g_strdup_printf ("queue.%d", pid);
+       store_plist(queue, path);
+       g_free(path);
 }
 
 GValue*
 ghb_load_queue()
 {
-       return load_plist("queue");
+       GValue *queue;
+       pid_t pid;
+       char *path;
+
+       pid = getpid();
+       path = g_strdup_printf ("queue.%d", pid);
+       queue = load_plist(path);
+       g_free(path);
+       return queue;
+}
+
+GValue*
+ghb_load_old_queue(int pid)
+{
+       GValue *queue;
+       char *path;
+
+       path = g_strdup_printf ("queue.%d", pid);
+       queue = load_plist(path);
+       g_free(path);
+       return queue;
+}
+
+void
+ghb_remove_old_queue_file(int pid)
+{
+       char *path;
+
+       path = g_strdup_printf ("queue.%d", pid);
+       remove_plist(path);
+       g_free(path);
 }
 
 void
 ghb_remove_queue_file()
 {
-       remove_plist("queue");
+       pid_t pid;
+       char *path;
+
+       pid = getpid();
+       path = g_strdup_printf ("queue.%d", pid);
+       remove_plist(path);
+       g_free(path);
 }
 
 typedef struct
index a4da4ed..89f7780 100644 (file)
@@ -27,7 +27,9 @@ void ghb_prefs_save(GValue *settings);
 void ghb_pref_save(GValue *settings, const gchar *key);
 void ghb_save_queue(GValue *queue);
 GValue* ghb_load_queue();
-void ghb_remove_queue_file(void);;
+GValue* ghb_load_old_queue(int pid);
+void ghb_remove_queue_file(void);
+void ghb_remove_old_queue_file(int pid);
 gchar* ghb_get_user_config_dir(gchar *subdir);
 void ghb_settings_to_ui(signal_user_data_t *ud, GValue *dict);
 void ghb_clear_presets_selection(signal_user_data_t *ud);
@@ -42,5 +44,8 @@ void ghb_prefs_store(void);
 void ghb_pref_set(GValue *settings, const gchar *key);
 gboolean ghb_lock_file(const gchar *name);
 void ghb_refresh_preset(signal_user_data_t *ud);
+int ghb_find_pid_file();
+void ghb_unlink_pid_file(int pid);
+void ghb_write_pid_file();
 
 #endif // _GHB_PRESETS_H_
index 24eded5..3b91a24 100644 (file)
@@ -1259,13 +1259,20 @@ ghb_reload_queue(signal_user_data_t *ud)
        GValue *queue;
        gint unfinished = 0;
        gint count, ii;
+       gint pid;
        gint status;
        GValue *settings;
        gchar *message;
 
        g_debug("ghb_reload_queue");
 
-       queue = ghb_load_queue();
+find_pid:
+       pid = ghb_find_pid_file();
+       if (pid < 0)
+               return FALSE;
+
+       queue = ghb_load_old_queue(pid);
+       ghb_remove_old_queue_file(pid);
        // Look for unfinished entries
        count = ghb_array_len(queue);
        for (ii = 0; ii < count; ii++)
@@ -1277,6 +1284,9 @@ ghb_reload_queue(signal_user_data_t *ud)
                        unfinished++;
                }
        }
+       if (!unfinished)
+               goto find_pid;
+
        if (unfinished)
        {
                message = g_strdup_printf(
@@ -1314,11 +1324,11 @@ ghb_reload_queue(signal_user_data_t *ud)
                                add_to_queue_list(ud, settings, NULL);
                        }
                        ghb_queue_buttons_grey(ud);
+                       ghb_save_queue(ud->queue);
                }
                else
                {
                        ghb_value_free(queue);
-                       ghb_remove_queue_file();
                }
                g_free(message);
        }