summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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_