diff --git a/data/usbbootgui.ui b/data/usbbootgui.ui
index 11a6d49..b581ab3 100644
--- a/data/usbbootgui.ui
+++ b/data/usbbootgui.ui
@@ -17,16 +17,6 @@
-
- gpio.png
- GPIO expansion board
- gpioexpand
-
-
- sdcard.png
- eMMC / SD card reader
- msd
-
document-open.png
Custom application
@@ -78,7 +68,7 @@
- True
+ False
True
0
@@ -142,43 +132,45 @@ Type:
-
@@ -189,7 +181,7 @@ Type:
True
- True
+ False
True
3
diff --git a/src/usbbootgui.c b/src/usbbootgui.c
index d8dcfd2..a2d78c0 100644
--- a/src/usbbootgui.c
+++ b/src/usbbootgui.c
@@ -29,9 +29,6 @@
#define MODEL_IDX_NAME 1 /* Friendly name */
#define MODEL_IDX_IMAGE 2 /* Image folder name */
-/* Prefix to image folders */
-#define IMAGE_PREFIX "/usr/share/rpiboot"
-
#define SETTINGS_FILE "/etc/usbbootgui.conf"
/* USB device ids of interest */
@@ -79,7 +76,7 @@ static gchar *promptForFolder()
gtk_widget_destroy (dialog);
- bootcodepath = g_strdup_printf ("%s/bootcode.bin", folder);
+ bootcodepath = g_build_filename (folder, "bootcode.bin", NULL);
if (!g_file_test (bootcodepath, G_FILE_TEST_EXISTS))
{
@@ -303,13 +300,13 @@ static void showDialog()
}
else
{
- imagepath = g_strdup_printf ("%s/%s", IMAGE_PREFIX, image);
+ imagepath = g_strdup(image);
}
if (imagepath)
{
/* Sanity check: check that image folder is present, and contains at least bootcode.bin */
- bootcodepath = g_strdup_printf ("%s/bootcode.bin", imagepath);
+ bootcodepath = g_build_filename (imagepath, "bootcode.bin", NULL);
if (!g_file_test (imagepath, G_FILE_TEST_EXISTS))
{
@@ -441,14 +438,7 @@ static gboolean pollForPi()
showDialog();
else
{
- if (image[0] == '/')
- success = usbboot (image);
- else
- {
- imagepath = g_strdup_printf ("%s/%s", IMAGE_PREFIX, image);
- success = usbboot (imagepath);
- g_free (imagepath);
- }
+ success = usbboot (image);
if (!success)
{
@@ -477,8 +467,117 @@ static void showTrayIcon()
}
}
+static void addImage(const gchar *name, const gchar *folder)
+{
+ GtkListStore *store = GTK_LIST_STORE (gtk_builder_get_object (builder, "liststore"));
+ GtkTreeIter iter;
+ gchar *description, *descpath, *iconpath;
+ GdkPixbuf *icon;
+
+ gchar format[] = "%s\n\n%s";
+
+ descpath = g_build_filename (folder, "description.txt", NULL);
+ if (g_file_test (descpath, G_FILE_TEST_EXISTS))
+ {
+ gchar *desc;
+ g_file_get_contents (descpath, &desc, NULL, NULL);
+ description = g_strdup_printf (format, g_strstrip (desc), folder);
+ g_free (desc);
+ } else {
+ if (g_strcmp0 (name, "gpioexpand") == 0)
+ description = g_strdup_printf (format, _("GPIO expansion board"), folder);
+ else if (g_strcmp0 (name, "msd") == 0)
+ description = g_strdup_printf (format, _("eMMC / SD card reader"), folder);
+ else
+ description = g_strdup_printf (format, name, folder);
+ }
+ g_free (descpath);
+
+ iconpath = g_build_filename (folder, "icon.png", NULL);
+ if (g_file_test (iconpath, G_FILE_TEST_EXISTS)) {
+ icon = gdk_pixbuf_new_from_file(iconpath, NULL);
+ } else {
+ if (g_strcmp0 (name, "gpioexpand") == 0)
+ icon = gdk_pixbuf_new_from_file(PACKAGE_DATA_DIR "/gpio.png", NULL);
+ else if (g_strcmp0 (name, "msd") == 0)
+ icon = gdk_pixbuf_new_from_file(PACKAGE_DATA_DIR "/sdcard.png", NULL);
+ else
+ icon = gdk_pixbuf_new_from_file(PACKAGE_DATA_DIR "/document-open.png", NULL); // TODO: make an "unknown" icon
+ }
+ g_free (iconpath);
+
+ gtk_list_store_append(store, &iter);
+
+ gtk_list_store_set(store, &iter,
+ MODEL_IDX_ICON, icon,
+ MODEL_IDX_NAME, description,
+ MODEL_IDX_IMAGE, g_strdup (folder),
+ -1);
+}
+
+static void scanDirectory(const gchar *path)
+{
+ gchar *rpibootpath, *imagepath, *bootcodepath;
+ const gchar *name;
+ GDir *rpibootdir;
+
+ rpibootpath = g_build_filename (path, "rpiboot", NULL);
+ rpibootdir = g_dir_open(rpibootpath, 0, NULL);
+ if (!rpibootdir)
+ return;
+
+ while(name = g_dir_read_name(rpibootdir)) {
+ imagepath = g_build_filename (rpibootpath, name, NULL);
+ if (g_file_test (imagepath, G_FILE_TEST_IS_DIR)) {
+ bootcodepath = g_build_filename (imagepath, "bootcode.bin", NULL);
+ if (g_file_test (bootcodepath, G_FILE_TEST_EXISTS)) {
+ addImage(name, imagepath);
+ }
+ g_free (bootcodepath);
+ }
+ g_free(imagepath);
+ }
+ g_dir_close (rpibootdir);
+ g_free (rpibootpath);
+}
+
+gboolean stringInList(GList *list, const gchar *string)
+{
+ GList *l;
+ for (l=list; l!=NULL; l = l->next)
+ if (g_strcmp0 (string, l->data) == 0)
+ return TRUE;
+ return FALSE;
+}
+
+static void populateImageList()
+{
+ const gchar *path;
+ const gchar *var;
+ const gchar * const *xdg_data_dirs;
+ gint i;
+
+ GList *scanned_dirs = NULL;
+ GList *l;
+
+ xdg_data_dirs = g_get_system_data_dirs ();
+ for (i = 0; xdg_data_dirs[i]; i++) {
+ if (stringInList(scanned_dirs, xdg_data_dirs[i]))
+ continue;
+ scanned_dirs = g_list_prepend(scanned_dirs, (gpointer)xdg_data_dirs[i]);
+ scanDirectory(xdg_data_dirs[i]);
+ }
+ path = g_get_user_data_dir ();
+ if (stringInList(scanned_dirs, path))
+ return;
+ scanDirectory(path);
+}
+
int main(int argc, char *argv[])
{
+ GtkListStore *store;
+ GtkTreeIter iter;
+
#ifdef ENABLE_NLS
bindtextdomain (GETTEXT_PACKAGE, LOCALE_DIR);
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
@@ -498,6 +597,13 @@ int main(int argc, char *argv[])
builder = gtk_builder_new();
gtk_builder_add_from_file (builder, PACKAGE_DATA_DIR "/usbbootgui.ui", NULL);
+ populateImageList();
+
+ /* Move "Custom application" to the end of the list. */
+ store = GTK_LIST_STORE (gtk_builder_get_object (builder, "liststore"));
+ gtk_tree_model_get_iter_first(GTK_TREE_MODEL (store), &iter);
+ gtk_list_store_move_before(store, &iter, NULL);
+
if ( !hasAlwaysUseImage() )
showDialog();
if ( hasAlwaysUseImage() )