summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Stebbins <[email protected]>2017-06-20 14:52:19 -0700
committerJohn Stebbins <[email protected]>2017-06-20 14:52:19 -0700
commit707b0a1cfab212f9a6f1d087fb654fd7490e1828 (patch)
tree3f539a0bbcc02bb79227c64e92c703333257e087
parent148591c7223ead48f1b2498e689ede7c789a2997 (diff)
LinGui: Make disk warning limit configurable
Allow disabling and setting disk warning limit in preferences. When enabled checks disk fullness every 10 seconds during encoding. If disk full condition is detected, pauses the encode and gives a popup with options "Resume, I've fixed the problem", "Resume, Don't tell me again", and "Cancel Current and Stop".
-rw-r--r--gtk/src/callbacks.c52
-rw-r--r--gtk/src/ghb.m493
-rw-r--r--gtk/src/hb-backend.c20
-rw-r--r--gtk/src/hb-backend.h2
-rw-r--r--gtk/src/internal_defaults.json3
-rw-r--r--gtk/src/queuehandler.c189
-rw-r--r--gtk/src/queuehandler.h2
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_