Added config option so can force 'bad categories' into Other using freedesktop list
[pandora-libraries.git] / minimenu / mmenu.c
index d4b1438..83743bc 100644 (file)
@@ -58,6 +58,7 @@
 #include "mmcache.h"
 #include "mmcat.h"
 #include "mmui.h"
+#include "mmconf.h"
 
 pnd_box_handle g_active_apps = NULL;
 unsigned int g_active_appcount = 0;
@@ -79,6 +80,7 @@ char *g_skinpath = NULL; // where 'skin_selected' is located .. the fullpath inc
 pnd_conf_handle g_skinconf = NULL;
 
 void sigquit_handler ( int n );
+unsigned char app_is_visible ( pnd_conf_handle h, char *uniqueid );
 
 int main ( int argc, char *argv[] ) {
   int logall = -1; // -1 means normal logging rules; >=0 means log all!
@@ -167,8 +169,10 @@ int main ( int argc, char *argv[] ) {
   } // spin
   pnd_log ( pndn_rem, "Looks like user '%s' is in, continue.\n", g_username );
 
-  /* conf file
+  /* conf files
    */
+
+  // mmenu conf
   g_conf = pnd_conf_fetch_by_name ( MMENU_CONF, MMENU_CONF_SEARCHPATH );
 
   if ( ! g_conf ) {
@@ -176,6 +180,11 @@ int main ( int argc, char *argv[] ) {
     emit_and_quit ( MM_QUIT );
   }
 
+  // override mmenu conf via user preference conf
+  conf_merge_into ( conf_determine_location ( g_conf ), g_conf );
+  conf_setup_missing ( g_conf );
+
+  // desktop conf for app finding preferences
   g_desktopconf = pnd_conf_fetch_by_id ( pnd_conf_desktop, PND_CONF_SEARCHPATH );
 
   if ( ! g_desktopconf ) {
@@ -314,6 +323,17 @@ int main ( int argc, char *argv[] ) {
   // lets just merge the skin conf onto the regular conf, so it just magicly works
   pnd_box_append ( g_conf, g_skinconf );
 
+  // did user override the splash image?
+  char *splash = pnd_conf_get_as_char ( g_conf, "minimenu.force_wallpaper" );
+  if ( splash ) {
+    // we've got a filename, presumably; lets see if it exists
+    struct stat statbuf;
+    if ( stat ( splash, &statbuf ) == 0 ) {
+      // file seems to exist, lets set our override to that..
+      pnd_conf_set_char ( g_conf, "graphics.IMG_BACKGROUND_800480", splash );
+    }
+  }
+
   // attempt to set up UI
   if ( ! ui_setup() ) {
     pnd_log ( pndn_error, "ERROR: Couldn't set up the UI!\n" );
@@ -334,9 +354,12 @@ int main ( int argc, char *argv[] ) {
     emit_and_quit ( MM_QUIT );
   }
 
+  // init categories
+  category_init();
+
   // create all cat
   if ( pnd_conf_get_as_int_d ( g_conf, "categories.do_all_cat", 1 ) ) {
-    category_push ( g_x11_present ? CATEGORY_ALL "    (X11)" : CATEGORY_ALL "   (No X11)", NULL /*app*/, 0, NULL /* fspath */ );
+    category_push ( g_x11_present ? CATEGORY_ALL "    (X11)" : CATEGORY_ALL "   (No X11)", NULL /*app*/, 0, NULL /* fspath */, 1 /* visible */ );
   }
 
   // set up category mappings
@@ -362,6 +385,21 @@ int main ( int argc, char *argv[] ) {
 
   } // set up rescan
 
+  /* set speed to minimenu run-speed, now that we're all set up
+   */
+#if 0 /* something crashes at high speed image caching.. */
+  int use_mm_speed = pnd_conf_get_as_int_d ( g_conf, "minimenu.use_mm_speed", 0 );
+  if ( use_mm_speed > 0 ) {
+    int mm_speed = pnd_conf_get_as_int_d ( g_conf, "minimenu.mm_speed", -1 );
+    if ( mm_speed > 50 && mm_speed < 800 ) {
+      char buffer [ 512 ];
+      snprintf ( buffer, 500, "sudo /usr/pandora/scripts/op_cpuspeed.sh %d", mm_speed );
+      system ( buffer );
+    }
+  } // do speed change?
+#endif
+
+  // do it!
   while ( 1 ) { // forever!
 
     // show the menu, or changes thereof
@@ -393,7 +431,7 @@ int main ( int argc, char *argv[] ) {
     } // rescan?
 
     // sleep? block?
-    usleep ( 5000 );
+    usleep ( 100000 /*5000*/ );
 
   } // while
 
@@ -468,6 +506,11 @@ void applications_free ( void ) {
 
 void applications_scan ( void ) {
 
+  // has user disabled pnd scanning, by chance?
+  if ( ! pnd_conf_get_as_int_d ( g_conf, "filesystem.do_pnd_disco", 1 ) ) {
+    goto dirbrowser_scan; // skip pnd's
+  }
+
   // show disco screen
   ui_discoverscreen ( 1 /* clear screen */ );
 
@@ -626,21 +669,32 @@ void applications_scan ( void ) {
         ( pnd_pxml_get_x11 ( iter -> option_no_x11 ) == pnd_pxml_x11_required && g_x11_present == 1 )
        )
     {
+      if ( iter -> title_en == NULL || iter -> title_en [ 0 ] == '\0' ) {
+       // null title; just skip it.
+      } else {
+
+       // push to All category
+       // we do this first, so first category is always All
+       if ( pnd_conf_get_as_int_d ( g_conf, "categories.do_all_cat", 1 ) ) {
+         category_push ( g_x11_present ? CATEGORY_ALL "    (X11)" : CATEGORY_ALL "   (No X11)", iter, ovrh, NULL /* fspath */, 1 /* visible */ );
+       } // all?
+
+       // is this app suppressed? if not, show it in whatever categories the user is allowing
+       if ( iter -> unique_id && app_is_visible ( g_conf, iter -> unique_id ) ) {
 
-      // push to All category
-      // we do this first, so first category is always All
-      if ( pnd_conf_get_as_int_d ( g_conf, "categories.do_all_cat", 1 ) ) {
-       category_push ( g_x11_present ? CATEGORY_ALL "    (X11)" : CATEGORY_ALL "   (No X11)", iter, ovrh, NULL /* fspath */ );
-      } // all?
-
-      // main categories
-      category_meta_push ( iter -> main_category, NULL /* no parent cat */, iter, ovrh, pnd_conf_get_as_int_d ( g_conf, "tabs.top_maincat", 1 ) );
-      category_meta_push ( iter -> main_category1, iter -> main_category, iter, ovrh, pnd_conf_get_as_int_d ( g_conf, "tabs.top_maincat1", 0 ) );
-      category_meta_push ( iter -> main_category2, iter -> main_category, iter, ovrh, pnd_conf_get_as_int_d ( g_conf, "tabs.top_maincat2", 0 ) );
-      // alt categories
-      category_meta_push ( iter -> alt_category, NULL /* no parent cat */, iter, ovrh, pnd_conf_get_as_int_d ( g_conf, "tabs.top_altcat", 0 ) );
-      category_meta_push ( iter -> alt_category1, iter -> alt_category, iter, ovrh, pnd_conf_get_as_int_d ( g_conf, "tabs.top_altcat1", 0 ) );
-      category_meta_push ( iter -> alt_category2, iter -> alt_category, iter, ovrh, pnd_conf_get_as_int_d ( g_conf, "tabs.top_altcat2", 0 ) );
+         // main categories
+         category_meta_push ( iter -> main_category, NULL /* no parent cat */, iter, ovrh, cat_is_visible ( g_conf, iter -> main_category ) ); //pnd_conf_get_as_int_d ( g_conf, "tabs.top_maincat", 1 ) );
+         category_meta_push ( iter -> main_category1, iter -> main_category, iter, ovrh, cat_is_visible ( g_conf, iter -> main_category1 ) ); //pnd_conf_get_as_int_d ( g_conf, "tabs.top_maincat1", 0 ) );
+         category_meta_push ( iter -> main_category2, iter -> main_category, iter, ovrh, cat_is_visible ( g_conf, iter -> main_category2 ) ); //pnd_conf_get_as_int_d ( g_conf, "tabs.top_maincat2", 0 ) );
+         // alt categories
+         category_meta_push ( iter -> alt_category, NULL /* no parent cat */, iter, ovrh, cat_is_visible ( g_conf, iter -> alt_category ) ); //pnd_conf_get_as_int_d ( g_conf, "tabs.top_altcat", 0 ) );
+         category_meta_push ( iter -> alt_category1, iter -> alt_category, iter, ovrh, cat_is_visible ( g_conf, iter -> alt_category1 ) ); //pnd_conf_get_as_int_d ( g_conf, "tabs.top_altcat1", 0 ) );
+         category_meta_push ( iter -> alt_category2, iter -> alt_category, iter, ovrh, cat_is_visible ( g_conf, iter -> alt_category2 ) ); //pnd_conf_get_as_int_d ( g_conf, "tabs.top_altcat2", 0 ) );
+
+       } // app is visible?
+
+      } // has title?
 
     } // register with categories or filter out
 
@@ -649,8 +703,7 @@ void applications_scan ( void ) {
     itercount++;
   } // while
 
-  // sort (some) categories
-  category_sort();
+ dirbrowser_scan:
 
   // set up filesystem browser tabs
   if ( pnd_conf_get_as_int_d ( g_conf, "filesystem.do_browser", 0 ) ) {
@@ -668,7 +721,7 @@ void applications_scan ( void ) {
 
       // check if dir is empty; if so, skip it.
       if ( ! is_dir_empty ( buffer ) ) {
-       category_push ( tabname /* tab name */, NULL /* app */, 0 /* override */, buffer /* fspath */ );
+       category_push ( tabname /* tab name */, NULL /* app */, 0 /* override */, buffer /* fspath */, 1 /* visible */ );
       }
 
     }
@@ -679,12 +732,26 @@ void applications_scan ( void ) {
   // dump categories
   //category_dump();
 
+  // publish desired categories
+  category_publish ( CFNORMAL, NULL );
+
   // let deferred icon cache go now
   ui_post_scan();
 
   return;
 }
 
+static char _vbuf [ 512 ];
+unsigned char cat_is_visible ( pnd_conf_handle h, char *catname ) {
+  snprintf ( _vbuf, 500, "tabshow.%s", catname );
+  return ( pnd_conf_get_as_int_d ( g_conf, _vbuf, 1 ) ); // default to 'show' when unknown
+}
+
+unsigned char app_is_visible ( pnd_conf_handle h, char *uniqueid ) {
+  snprintf ( _vbuf, 500, "appshow.%s", uniqueid );
+  return ( pnd_conf_get_as_int_d ( g_conf, _vbuf, 1 ) ); // default to 'show' when unknown
+}
+
 void sigquit_handler ( int n ) {
   pnd_log ( pndn_rem, "SIGQUIT received; graceful exit.\n" );
   emit_and_quit ( MM_QUIT );
@@ -750,3 +817,51 @@ void setup_notifications ( void ) {
 
   return;
 }
+
+// for Pleng
+// Goal: normally menu will quit when an app is invoked, but there are cases when some folks
+// may configure their system and want mmenu to live instead (save on restart time, don't care
+// about RAM, using a multitasking tray/window manager setup...), so instead of 'exit and emit'
+// here we just run the app directly and cross fingers!
+void emit_and_run ( char *buffer ) {
+
+  // run the bloody thing
+  int f;
+
+  if ( ( f = fork() ) < 0 ) {
+    // error forking
+  } else if ( f > 0 ) {
+    // parent
+  } else {
+    // child, do it
+    execl ( "/bin/sh", "/bin/sh", "-c", buffer + strlen(MM_RUN) + 1, (char*) NULL );
+  } 
+
+  return;
+}
+
+// this code was swiped from pnd_utility pnd_exec_no_wait_1 as it became a little too minimenu-specific to remain there
+void exec_raw_binary ( char *fullpath ) {
+  int i;
+
+  if ( ( i = fork() ) < 0 ) {
+    printf ( "ERROR: Couldn't fork()\n" );
+    return;
+  }
+
+  if ( i ) {
+    return; // parent process, don't care
+  }
+
+  // child process, do something
+  execl ( "/bin/sh", "/bin/sh", "-c", fullpath, (char*) NULL );
+  //execl ( fullpath, fullpath, (char*) NULL );
+
+  // error invoking something, and we're the child process, so just die before all hell breaks lose with us thinking we're the (second!) parent on return!
+  exit ( -1 );
+
+  // getting here is an error
+  //printf ( "Error attempting to run %s\n", fullpath );
+
+  return;
+}