diff options
-rw-r--r-- | gtk/src/callbacks.c | 52 | ||||
-rw-r--r-- | gtk/src/ghb.m4 | 93 | ||||
-rw-r--r-- | gtk/src/hb-backend.c | 20 | ||||
-rw-r--r-- | gtk/src/hb-backend.h | 2 | ||||
-rw-r--r-- | gtk/src/internal_defaults.json | 3 | ||||
-rw-r--r-- | gtk/src/queuehandler.c | 189 | ||||
-rw-r--r-- | gtk/src/queuehandler.h | 2 |
7 files changed, 274 insertions, 87 deletions
diff --git a/gtk/src/callbacks.c b/gtk/src/callbacks.c index 469eb2b3b..2ee6431f5 100644 --- a/gtk/src/callbacks.c +++ b/gtk/src/callbacks.c @@ -2955,39 +2955,6 @@ ghb_cancel_encode2(signal_user_data_t *ud, const gchar *extra_msg) return FALSE; } -static gint -find_queue_job(GhbValue *queue, gint unique_id, GhbValue **job) -{ - GhbValue *queueDict, *uiDict; - gint ii, count; - gint job_unique_id; - - g_debug("find_queue_job"); - if (job != NULL) - { - *job = NULL; - } - if (unique_id == 0) // Invalid Id - return -1; - - count = ghb_array_len(queue); - for (ii = 0; ii < count; ii++) - { - queueDict = ghb_array_get(queue, ii); - uiDict = ghb_dict_get(queueDict, "uiSettings"); - job_unique_id = ghb_dict_get_int(uiDict, "job_unique_id"); - if (job_unique_id == unique_id) - { - if (job != NULL) - { - *job = queueDict; - } - return ii; - } - } - return -1; -} - static void start_new_log(signal_user_data_t *ud, GhbValue *uiDict) { @@ -3061,7 +3028,7 @@ submit_job(signal_user_data_t *ud, GhbValue *queueDict) ghb_start_queue(); // Start queue activity spinner - int index = find_queue_job(ud->queue, unique_id, NULL); + int index = ghb_find_queue_job(ud->queue, unique_id, NULL); if (index >= 0) { GtkTreeView *treeview; @@ -3207,6 +3174,7 @@ ghb_start_next_job(signal_user_data_t *ud) ghb_notify_done(ud); ghb_update_pending(ud); gtk_widget_hide(progress); + ghb_dict_set_bool(ud->globals, "SkipDiskFreeCheck", FALSE); } gchar* @@ -3217,7 +3185,7 @@ working_status_string(signal_user_data_t *ud, ghb_instance_status_t *status) gint index; qcount = ghb_array_len(ud->queue); - index = find_queue_job(ud->queue, status->unique_id, NULL); + index = ghb_find_queue_job(ud->queue, status->unique_id, NULL); if (qcount > 1) { job_str = g_strdup_printf(_("job %d of %d, "), index+1, qcount); @@ -3285,7 +3253,7 @@ searching_status_string(signal_user_data_t *ud, ghb_instance_status_t *status) gint index; qcount = ghb_array_len(ud->queue); - index = find_queue_job(ud->queue, status->unique_id, NULL); + index = ghb_find_queue_job(ud->queue, status->unique_id, NULL); if (qcount > 1) { job_str = g_strdup_printf(_("job %d of %d, "), index+1, qcount); @@ -3330,7 +3298,9 @@ ghb_backend_events(signal_user_data_t *ud) GtkTreeIter iter; static gint prev_scan_state = -1; static gint prev_queue_state = -1; + static gint event_sequence = 0; + event_sequence++; ghb_track_status(); ghb_get_status(&status); if (prev_scan_state != status.scan.state || @@ -3451,7 +3421,7 @@ ghb_backend_events(signal_user_data_t *ud) if (status.queue.unique_id != 0) { - index = find_queue_job(ud->queue, status.queue.unique_id, NULL); + index = ghb_find_queue_job(ud->queue, status.queue.unique_id, NULL); if (index >= 0) { treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "queue_list")); @@ -3476,6 +3446,11 @@ ghb_backend_events(signal_user_data_t *ud) } } g_free(path); + if ((status.queue.state & GHB_STATE_WORKING) && + (event_sequence % 50 == 0)) // check every 10 seconds + { + ghb_low_disk_check(ud); + } } } @@ -3517,7 +3492,7 @@ ghb_backend_events(signal_user_data_t *ud) gint qstatus; const gchar *status_icon; - index = find_queue_job(ud->queue, status.queue.unique_id, &queueDict); + index = ghb_find_queue_job(ud->queue, status.queue.unique_id, &queueDict); treeview = GTK_TREE_VIEW(GHB_WIDGET(ud->builder, "queue_list")); store = gtk_tree_view_get_model(treeview); switch( status.queue.error ) @@ -3572,6 +3547,7 @@ ghb_backend_events(signal_user_data_t *ud) { ghb_uninhibit_gsm(); gtk_widget_hide(GTK_WIDGET(progress)); + ghb_dict_set_bool(ud->globals, "SkipDiskFreeCheck", FALSE); } ghb_save_queue(ud->queue); ud->cancel_encode = GHB_CANCEL_NONE; diff --git a/gtk/src/ghb.m4 b/gtk/src/ghb.m4 index 73577af35..ed0319cdc 100644 --- a/gtk/src/ghb.m4 +++ b/gtk/src/ghb.m4 @@ -346,6 +346,11 @@ conjunction with the "Forced" option.</property> <property name="step_increment">0.1</property> <property name="page_increment">1</property> </object> + <object class="GtkAdjustment" id="DiskFreeLimitAdjustment"> + <property name="upper">1000000</property> + <property name="step_increment">500</property> + <property name="page_increment">1000</property> + </object> <object class="GtkAboutDialog" id="hb_about"> <property name="transient_for">hb_window</property> <property name="can_focus">False</property> @@ -7681,6 +7686,84 @@ This file may be reloaded at a later time to edit your jobs and re-encode.</prop </packing> </child> <child> + <object class="GtkBox" id="DiskFreeBox"> + <property name="orientation">vertical</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="spacing">2</property> + <child> + <object class="GtkCheckButton" id="DiskFreeCheck"> + <property name="label" translatable="yes">Monitor destination disk free space</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="tooltip_text" translatable="yes">Pause encoding if free disk space drops below limit</property> + <property name="halign">start</property> + <property name="draw_indicator">True</property> + <signal name="toggled" handler="pref_changed_cb" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkBox" id="DiskFreeLimitBox"> + <property name="orientation">horizontal</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="spacing">4</property> + <property name="margin-start">21</property> + <child> + <object class="GtkSpinButton" id="DiskFreeLimit"> + <property name="width-chars">7</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="tooltip_text" translatable="yes">Pause encoding if free disk space drops below limit</property> + <property name="primary_icon_activatable">False</property> + <property name="secondary_icon_activatable">False</property> + <property name="valign">GTK_ALIGN_CENTER</property> + <property name="adjustment">DiskFreeLimitAdjustment</property> + <property name="width_request">55</property> + <signal name="value-changed" handler="pref_changed_cb" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="DiskFreeLimitLabel"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="halign">start</property> + <property name="label" translatable="yes">MB Limit</property> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="top_attach">2</property> + <property name="left_attach">0</property> + <property name="width">1</property> + <property name="height">1</property> + </packing> + </child> + <child> <object class="GtkBox" id="vbox2"> <property name="orientation">vertical</property> <property name="visible">True</property> @@ -7785,7 +7868,7 @@ This file may be reloaded at a later time to edit your jobs and re-encode.</prop </child> </object> <packing> - <property name="top_attach">2</property> + <property name="top_attach">3</property> <property name="left_attach">0</property> <property name="width">1</property> <property name="height">1</property> @@ -7802,7 +7885,7 @@ This file may be reloaded at a later time to edit your jobs and re-encode.</prop <signal name="toggled" handler="pref_changed_cb" swapped="no"/> </object> <packing> - <property name="top_attach">3</property> + <property name="top_attach">4</property> <property name="left_attach">0</property> <property name="width">1</property> <property name="height">1</property> @@ -7820,7 +7903,7 @@ This file may be reloaded at a later time to edit your jobs and re-encode.</prop <signal name="toggled" handler="pref_changed_cb" swapped="no"/> </object> <packing> - <property name="top_attach">4</property> + <property name="top_attach">5</property> <property name="left_attach">0</property> <property name="width">1</property> <property name="height">1</property> @@ -7840,7 +7923,7 @@ on the Video tab instead.</property> <signal name="toggled" handler="advanced_video_changed_cb" swapped="no"/> </object> <packing> - <property name="top_attach">5</property> + <property name="top_attach">6</property> <property name="left_attach">0</property> <property name="width">1</property> <property name="height">1</property> @@ -7859,7 +7942,7 @@ Check this if you want the queue to clean itself up by deleting completed jobs.< <signal name="toggled" handler="pref_changed_cb" swapped="no"/> </object> <packing> - <property name="top_attach">6</property> + <property name="top_attach">7</property> <property name="left_attach">0</property> <property name="width">1</property> <property name="height">1</property> diff --git a/gtk/src/hb-backend.c b/gtk/src/hb-backend.c index ab8b8ef89..07f3a7248 100644 --- a/gtk/src/hb-backend.c +++ b/gtk/src/hb-backend.c @@ -4275,18 +4275,30 @@ ghb_stop_live_encode() void ghb_pause_queue() { + hb_status.queue.state |= GHB_STATE_PAUSED; + hb_pause( h_queue ); +} + +void +ghb_resume_queue() +{ + hb_status.queue.state &= ~GHB_STATE_PAUSED; + hb_resume( h_queue ); +} + +void +ghb_pause_resume_queue() +{ hb_state_t s; hb_get_state2( h_queue, &s ); if( s.state == HB_STATE_PAUSED ) { - hb_status.queue.state &= ~GHB_STATE_PAUSED; - hb_resume( h_queue ); + ghb_resume_queue(); } else { - hb_status.queue.state |= GHB_STATE_PAUSED; - hb_pause( h_queue ); + ghb_pause_queue(); } } diff --git a/gtk/src/hb-backend.h b/gtk/src/hb-backend.h index 47627c71d..450989a06 100644 --- a/gtk/src/hb-backend.h +++ b/gtk/src/hb-backend.h @@ -103,6 +103,8 @@ void ghb_remove_job(gint unique_id); void ghb_start_queue(void); void ghb_stop_queue(void); void ghb_pause_queue(void); +void ghb_resume_queue(void); +void ghb_pause_resume_queue(void); void ghb_start_live_encode(); void ghb_stop_live_encode(); diff --git a/gtk/src/internal_defaults.json b/gtk/src/internal_defaults.json index f0ba22bad..7d70db5fa 100644 --- a/gtk/src/internal_defaults.json +++ b/gtk/src/internal_defaults.json @@ -1,5 +1,6 @@ { "Globals": { + "SkipDiskFreeCheck": false, "show_preview": false, "scan_source": "", "volume_label": "New Video" @@ -68,6 +69,8 @@ "x264FastDecode": false }, "Preferences": { + "DiskFreeCheck": true, + "DiskFreeLimit": 10000, "RemoveFinishedJobs": false, "HideAdvancedVideoSettings": true, "AutoScan": false, diff --git a/gtk/src/queuehandler.c b/gtk/src/queuehandler.c index 6d8718c83..a708598fa 100644 --- a/gtk/src/queuehandler.c +++ b/gtk/src/queuehandler.c @@ -984,6 +984,154 @@ queue_reload_clicked_cb(GtkWidget *widget, signal_user_data_t *ud) } } +gint64 +ghb_dest_free_space(GhbValue *settings) +{ + GFile *gfile; + GFileInfo *info; + guint64 size; + const gchar *dest = ghb_dict_get_string(settings, "destination"); + gchar *destdir = g_path_get_dirname(dest); + gchar *resolved = ghb_resolve_symlink(destdir); + + gfile = g_file_new_for_path(resolved); + info = g_file_query_filesystem_info(gfile, + G_FILE_ATTRIBUTE_FILESYSTEM_FREE, NULL, NULL); + if (info != NULL) + { + if (g_file_info_has_attribute(info, G_FILE_ATTRIBUTE_FILESYSTEM_FREE)) + { + size = g_file_info_get_attribute_uint64(info, + G_FILE_ATTRIBUTE_FILESYSTEM_FREE); + return size; + } + g_object_unref(info); + } + g_object_unref(gfile); + g_free(resolved); + g_free(destdir); + + return -1; +} + +gint +ghb_find_queue_job(GhbValue *queue, gint unique_id, GhbValue **job) +{ + GhbValue *queueDict, *uiDict; + gint ii, count; + gint job_unique_id; + + if (job != NULL) + { + *job = NULL; + } + if (unique_id == 0) // Invalid Id + return -1; + + count = ghb_array_len(queue); + for (ii = 0; ii < count; ii++) + { + queueDict = ghb_array_get(queue, ii); + uiDict = ghb_dict_get(queueDict, "uiSettings"); + job_unique_id = ghb_dict_get_int(uiDict, "job_unique_id"); + if (job_unique_id == unique_id) + { + if (job != NULL) + { + *job = queueDict; + } + return ii; + } + } + return -1; +} + +void +ghb_low_disk_check(signal_user_data_t *ud) +{ + GtkWindow *hb_window; + GtkWidget *dialog; + GtkResponseType response; + ghb_status_t status; + const char *paused_msg = ""; + const char *dest; + gint64 free_size; + gint64 free_limit; + GhbValue *qDict; + GhbValue *settings; + + if (ghb_dict_get_bool(ud->globals, "SkipDiskFreeCheck") || + !ghb_dict_get_bool(ud->prefs, "DiskFreeCheck")) + { + return; + } + + ghb_get_status(&status); + if (status.queue.unique_id <= 0) + { + // No current job + return; + } + ghb_find_queue_job(ud->queue, status.queue.unique_id, &qDict); + if (qDict == NULL) + { + // Failed to find queue setting! + return; + } + settings = ghb_dict_get(qDict, "uiSettings"); + free_size = ghb_dest_free_space(settings); + if (free_size < 0) + { + // Failed to read free space + return; + } + // limit is in MB + free_limit = ghb_dict_get_int(ud->prefs, "DiskFreeLimit") * 1024 * 1024; + if (free_size > free_limit) + { + return; + } + + if ((status.queue.state & GHB_STATE_WORKING) && + !(status.queue.state & GHB_STATE_PAUSED)) + { + paused_msg = "Encoding has been paused.\n\n"; + ghb_pause_queue(); + } + dest = ghb_dict_get_string(settings, "destination"); + hb_window = GTK_WINDOW(GHB_WIDGET(ud->builder, "hb_window")); + dialog = gtk_message_dialog_new(hb_window, GTK_DIALOG_MODAL, + GTK_MESSAGE_WARNING, GTK_BUTTONS_NONE, + _("%sThe destination filesystem is almost full: %"PRIu64"MB free.\n" + "Destination: %s\n" + "Encode may be incomplete if you proceed.\n"), + paused_msg, free_size / (1024 * 1024), dest); + gtk_dialog_add_buttons( GTK_DIALOG(dialog), + _("Resume, I've fixed the problem"), 1, + _("Resume, Don't tell me again"), 2, + _("Cancel Current and Stop"), 3, + NULL); + response = gtk_dialog_run(GTK_DIALOG(dialog)); + gtk_widget_destroy(dialog); + switch ((int)response) + { + case 1: + ghb_resume_queue(); + break; + case 2: + ghb_dict_set_bool(ud->globals, "SkipDiskFreeCheck", TRUE); + ghb_resume_queue(); + break; + case 3: + ghb_stop_queue(); + ud->cancel_encode = GHB_CANCEL_ALL; + break; + default: + ghb_resume_queue(); + break; + } +} + static gboolean validate_settings(signal_user_data_t *ud, GhbValue *settings, gint batch) { @@ -1056,45 +1204,6 @@ validate_settings(signal_user_data_t *ud, GhbValue *settings, gint batch) return FALSE; } #endif - if (!batch) - { - GFile *gfile; - GFileInfo *info; - guint64 size; - gchar *resolved = ghb_resolve_symlink(destdir); - - gfile = g_file_new_for_path(resolved); - info = g_file_query_filesystem_info(gfile, - G_FILE_ATTRIBUTE_FILESYSTEM_FREE, NULL, NULL); - if (info != NULL) - { - if (g_file_info_has_attribute(info, G_FILE_ATTRIBUTE_FILESYSTEM_FREE)) - { - size = g_file_info_get_attribute_uint64(info, - G_FILE_ATTRIBUTE_FILESYSTEM_FREE); - - gint64 fsize = (guint64)10 * 1024 * 1024 * 1024; - if (size < fsize) - { - message = g_strdup_printf( - _("Destination filesystem is almost full: %uM free\n\n" - "Encode may be incomplete if you proceed.\n"), - (guint)(size / (1024L*1024L))); - if (!ghb_message_dialog(hb_window, GTK_MESSAGE_QUESTION, - message, _("Cancel"), _("Proceed"))) - { - g_free(message); - g_free(destdir); - return FALSE; - } - g_free(message); - } - } - g_object_unref(info); - } - g_object_unref(gfile); - g_free(resolved); - } g_free(destdir); if (g_file_test(dest, G_FILE_TEST_EXISTS)) { @@ -2277,7 +2386,7 @@ queue_start_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud) G_MODULE_EXPORT void queue_pause_clicked_cb(GtkWidget *xwidget, signal_user_data_t *ud) { - ghb_pause_queue(); + ghb_pause_resume_queue(); } gboolean diff --git a/gtk/src/queuehandler.h b/gtk/src/queuehandler.h index 50f6cc250..34b052d0f 100644 --- a/gtk/src/queuehandler.h +++ b/gtk/src/queuehandler.h @@ -32,5 +32,7 @@ void ghb_queue_buttons_grey(signal_user_data_t *ud); gboolean ghb_reload_queue(signal_user_data_t *ud); void ghb_queue_remove_row(signal_user_data_t *ud, int row); void ghb_finalize_job(GhbValue *settings); +gint ghb_find_queue_job(GhbValue *queue, gint unique_id, GhbValue **job); +void ghb_low_disk_check(signal_user_data_t *ud); #endif // _QUEUEHANDLER_H_ |