Main Page | Modules | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals | Examples

program-handler.c

Go to the documentation of this file.
00001 /**
00002  * \file
00003  * The program handler, used for loading programs and starting the
00004  * screensaver. 
00005  * \author Adam Dunkels <adam@dunkels.com>
00006  *
00007  * The Contiki program handler is responsible for the Contiki menu and
00008  * the desktop icons, as well as for loading programs and displaying a
00009  * dialog with a message telling which program that is loading.
00010  *
00011  * The program handler also is responsible for starting the
00012  * screensaver when the CTK detects that it should be started.
00013  */
00014  
00015 /*
00016  * Copyright (c) 2003, Adam Dunkels.
00017  * All rights reserved. 
00018  *
00019  * Redistribution and use in source and binary forms, with or without 
00020  * modification, are permitted provided that the following conditions 
00021  * are met: 
00022  * 1. Redistributions of source code must retain the above copyright 
00023  *    notice, this list of conditions and the following disclaimer. 
00024  * 2. Redistributions in binary form must reproduce the above
00025  *    copyright notice, this list of conditions and the following
00026  *    disclaimer in the documentation and/or other materials provided
00027  *    with the distribution. 
00028  * 3. The name of the author may not be used to endorse or promote
00029  *    products derived from this software without specific prior
00030  *    written permission.  
00031  *
00032  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
00033  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00034  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00035  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
00036  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00037  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
00038  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00039  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
00040  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00041  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00042  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  
00043  *
00044  * This file is part of the Contiki desktop OS
00045  *
00046  * $Id: program-handler.c,v 1.1 2006/06/17 22:41:12 adamdunkels Exp $
00047  *
00048  */
00049 
00050 #include <string.h>
00051 
00052 #include "contiki.h"
00053 #include "ctk/ctk.h"
00054 #include "ctk/ctk-draw.h"
00055 
00056 #include "program-handler.h"
00057 
00058 
00059 /* Menus */
00060 static struct ctk_menu contikimenu;
00061 
00062 #ifndef PROGRAM_HANDLER_CONF_MAX_NUMDSCS
00063 #define MAX_NUMDSCS 10
00064 #else /* PROGRAM_HANDLER_CONF_MAX_NUMDSCS */
00065 #define MAX_NUMDSCS PROGRAM_HANDLER_CONF_MAX_NUMDSCS
00066 #endif /* PROGRAM_HANDLER_CONF_MAX_NUMDSCS */
00067 
00068 static struct dsc *contikidsc[MAX_NUMDSCS];
00069 static unsigned char contikidsclast = 0;
00070 
00071 #if WITH_LOADER_ARCH
00072 /* "Run..." window */
00073 static struct ctk_window runwindow;
00074 static unsigned char runmenuitem;
00075 static struct ctk_label namelabel =
00076   {CTK_LABEL(0, 0, 13, 1, "Program name:")};
00077 static char name[31];
00078 static struct ctk_textentry nameentry =
00079   {CTK_TEXTENTRY(0, 1, 14, 1, name, 30)};
00080 static struct ctk_button loadbutton =
00081   {CTK_BUTTON(10, 2, 4, "Load")};
00082 
00083 static struct ctk_window loadingdialog;
00084 static struct ctk_label loadingmsg =
00085   {CTK_LABEL(0, 0, 8, 1, "Starting")};
00086 static struct ctk_label loadingname =
00087   {CTK_LABEL(9, 0, 16, 1, name)};
00088 
00089 static struct ctk_window errordialog;
00090 static struct ctk_label errormsg =
00091   {CTK_LABEL(0, 1, 22, 1, "Error loading program:")};
00092 static char errorfilename[22];
00093 static struct ctk_label errorfilelabel =
00094   {CTK_LABEL(0, 3, 22, 1, errorfilename)};
00095 static struct ctk_label errortype =
00096   {CTK_LABEL(4, 5, 16, 1, "")};
00097 static struct ctk_button errorokbutton =
00098   {CTK_BUTTON(9, 7, 2, "Ok")};
00099 
00100 
00101 #endif /* WITH_LOADER_ARCH */
00102 
00103 PROCESS(program_handler_process, "Program handler");
00104 
00105 static const char * const errormsgs[] = {
00106   "Ok",
00107   "Read error",
00108   "Header error",
00109   "OS error",
00110   "Data format error",
00111   "Out of memory",
00112   "File not found",
00113   "No loader"
00114 };
00115 
00116 #define LOADER_EVENT_LOAD 1
00117 #define LOADER_EVENT_DISPLAY_NAME 2
00118 
00119 static char *displayname;
00120 
00121 #if CTK_CONF_SCREENSAVER
00122 char program_handler_screensaver[20];
00123 #endif /* CTK_CONF_SCREENSAVER */
00124 
00125 /*-----------------------------------------------------------------------------------*/
00126 /**
00127  * Add a program to the program handler.
00128  *
00129  * \param dsc The DSC description structure for the program to be added.
00130  *
00131  * \param menuname The name that the program should have in the
00132  * Contiki menu.
00133  *
00134  * \param desktop Flag which specifies if the program should show up
00135  * as an icon on the desktop or not.
00136  */
00137 /*-----------------------------------------------------------------------------------*/
00138 void
00139 program_handler_add(struct dsc *dsc, char *menuname,
00140                     unsigned char desktop)
00141 {
00142   contikidsc[contikidsclast++] = dsc;
00143   ctk_menuitem_add(&contikimenu, menuname);
00144   if(desktop) {
00145     CTK_ICON_ADD(dsc->icon, &program_handler_process);
00146   }
00147 }
00148 /*-----------------------------------------------------------------------------------*/
00149 /**
00150  * Initializes the program handler.
00151  *
00152  * Is called by the initialization before any programs have been added
00153  * with program_handler_add().
00154  *
00155  */
00156 /*-----------------------------------------------------------------------------------*/
00157 #ifdef WITH_LOADER_ARCH
00158 #define NUM_PNARGS 6
00159 #define NAMELEN 32
00160 struct pnarg {
00161   char name[NAMELEN];
00162   char *arg;
00163 };
00164 static struct pnarg pnargs[NUM_PNARGS];
00165 static struct pnarg *
00166 pnarg_copy(char *name, char *arg)
00167 {
00168   char i;
00169   struct pnarg *pnargsptr;
00170 
00171   pnargsptr = pnargs;
00172   /* Allocate a place in the loadernames table. */
00173   for(i = 0; i < NUM_PNARGS; ++i) {
00174     if(*(pnargsptr->name) == 0) {
00175       strncpy(pnargsptr->name, name, NAMELEN);
00176       pnargsptr->arg = arg;
00177       return pnargsptr;
00178     }
00179     ++pnargsptr;
00180   }
00181   return NULL;
00182 }
00183 
00184 static void
00185 pnarg_free(struct pnarg *pn)
00186 {
00187   *(pn->name) = 0;
00188 }
00189 #endif /* WITH_LOADER_ARCH */
00190 /*-----------------------------------------------------------------------------------*/
00191 /**
00192  * Loads a program and displays a dialog telling the user about it.
00193  *
00194  * \param name The name of the program to be loaded.
00195  *
00196  * \param arg An argument which is passed to the new process when it
00197  * is loaded.
00198  */
00199 /*-----------------------------------------------------------------------------------*/
00200 void
00201 program_handler_load(char *name, char *arg)
00202 {
00203 #ifdef WITH_LOADER_ARCH
00204   struct pnarg *pnarg;
00205   
00206   pnarg = pnarg_copy(name, arg);
00207   if(pnarg != NULL) {
00208     process_post(&program_handler_process, LOADER_EVENT_DISPLAY_NAME, pnarg);
00209   } else {
00210     ctk_label_set_text(&errortype, "Out of memory");
00211     ctk_dialog_open(&errordialog);
00212   }
00213   /*  ctk_redraw(); */
00214   /*  ctk_window_redraw(&loadingdialog);*/
00215 #endif /* WITH_LOADER_ARCH */
00216 }
00217 
00218 #ifdef WITH_LOADER_ARCH
00219 #define RUN(prg, name, arg) program_handler_load(prg, arg)
00220 #else /* WITH_LOADER_ARCH */
00221 #define RUN(prg, process, arg) process_start(process, arg)
00222 #endif /* WITH_LOADER_ARCH */
00223 /*-----------------------------------------------------------------------------------*/
00224 /**
00225  * Configures the name of the screensaver to be loaded when
00226  * appropriate.
00227  *
00228  * \param name The name of the screensaver or NULL if no screensaver
00229  * should be used.
00230  */
00231 /*-----------------------------------------------------------------------------------*/
00232 #if CTK_CONF_SCREENSAVER
00233 void
00234 program_handler_setscreensaver(char *name)
00235 {
00236   if(name == NULL) {
00237     program_handler_screensaver[0] = 0;
00238   } else {
00239     strncpy(program_handler_screensaver, name, sizeof(program_handler_screensaver));
00240   }
00241 }
00242 #endif /* CTK_CONF_SCREENSAVER */
00243 /*-----------------------------------------------------------------------------------*/
00244 static void
00245 make_windows(void)
00246 {
00247 #ifdef WITH_LOADER_ARCH
00248   ctk_window_new(&runwindow, 16, 3, "Run");
00249   
00250   CTK_WIDGET_ADD(&runwindow, &namelabel);
00251   CTK_WIDGET_ADD(&runwindow, &nameentry);
00252   CTK_WIDGET_ADD(&runwindow, &loadbutton);
00253   
00254   CTK_WIDGET_FOCUS(&runwindow, &nameentry);
00255   
00256   ctk_dialog_new(&loadingdialog, 25, 1);
00257   CTK_WIDGET_ADD(&loadingdialog, &loadingmsg);
00258   CTK_WIDGET_ADD(&loadingdialog, &loadingname);
00259   
00260   ctk_dialog_new(&errordialog, 22, 8);
00261   CTK_WIDGET_ADD(&errordialog, &errormsg);
00262   CTK_WIDGET_ADD(&errordialog, &errorfilelabel);
00263   CTK_WIDGET_ADD(&errordialog, &errortype);
00264   CTK_WIDGET_ADD(&errordialog, &errorokbutton);
00265   CTK_WIDGET_FOCUS(&errordialog, &errorokbutton);
00266 #endif /* WITH_LOADER_ARCH */
00267 }
00268 /*-----------------------------------------------------------------------------------*/
00269 PROCESS_THREAD(program_handler_process, ev, data)
00270 {
00271 #ifdef WITH_LOADER_ARCH
00272   unsigned char err;
00273   struct dsc *dsc;
00274 #endif /* WITH_LOADER_ARCH */
00275   unsigned char i;
00276   struct dsc **dscp;
00277 
00278   PROCESS_BEGIN();
00279   
00280   /* Create the menus */
00281   ctk_menu_new(&contikimenu, "Contiki");
00282   ctk_menu_add(&contikimenu);
00283 #if WITH_LOADER_ARCH
00284   runmenuitem = ctk_menuitem_add(&contikimenu, "Run program...");
00285   
00286   make_windows();
00287 #endif /* WITH_LOADER_ARCH */
00288   
00289   displayname = NULL;
00290   
00291 #if CTK_CONF_SCREENSAVER
00292   program_handler_screensaver[0] = 0;
00293 #endif /* CTK_CONF_SCREENSAVER */
00294 
00295   while(1) {
00296     PROCESS_WAIT_EVENT();
00297     if(ev == ctk_signal_button_activate) {
00298 #ifdef WITH_LOADER_ARCH
00299       if(data == (process_data_t)&loadbutton) {
00300         ctk_window_close(&runwindow);
00301         program_handler_load(name, NULL);
00302       } else if(data == (process_data_t)&errorokbutton) {
00303         ctk_dialog_close();
00304       }
00305 #endif /* WITH_LOADER_ARCH */
00306       dscp = &contikidsc[0];
00307       for(i = 0; i < CTK_CONF_MAXMENUITEMS; ++i) {    
00308         if(*dscp != NULL &&
00309            data == (process_data_t)(*dscp)->icon) {
00310           RUN((*dscp)->prgname, (*dscp)->process, NULL);
00311           break;
00312         }
00313         ++dscp;
00314       }
00315     } else if(ev == ctk_signal_menu_activate) {
00316       if((struct ctk_menu *)data == &contikimenu) {
00317 #if WITH_LOADER_ARCH
00318         dsc = contikidsc[contikimenu.active];
00319         if(dsc != NULL) {
00320           RUN(dsc->prgname, dsc->process, NULL);
00321         } else if(contikimenu.active == runmenuitem) {
00322           make_windows();
00323           ctk_window_close(&runwindow);
00324           ctk_window_open(&runwindow);
00325           CTK_WIDGET_FOCUS(&runwindow, &nameentry);
00326         }
00327 #else /* WITH_LOADER_ARCH */
00328         if(contikidsc[contikimenu.active] != NULL) {
00329           RUN(contikidsc[contikimenu.active]->prgname,
00330               contikidsc[contikimenu.active]->process,
00331               NULL);
00332         }
00333 #endif /* WITH_LOADER_ARCH */
00334       }
00335 #if CTK_CONF_SCREENSAVER
00336     } else if(ev == ctk_signal_screensaver_start) {
00337 #if WITH_LOADER_ARCH
00338       if(program_handler_screensaver[0] != 0) {
00339         program_handler_load(program_handler_screensaver, NULL);
00340       }
00341 #endif /* WITH_LOADER_ARCH */
00342 #endif /* CTK_CONF_SCREENSAVER */
00343     } else if(ev == LOADER_EVENT_DISPLAY_NAME) {
00344 #if WITH_LOADER_ARCH
00345       if(displayname == NULL) {
00346         make_windows();
00347         
00348         ctk_label_set_text(&loadingname, ((struct pnarg *)data)->name);
00349         ctk_dialog_open(&loadingdialog);
00350         process_post(&program_handler_process, LOADER_EVENT_LOAD, data);
00351         displayname = data;
00352       } else {
00353         /* Try again. */
00354         process_post(&program_handler_process, LOADER_EVENT_DISPLAY_NAME, data);
00355       }
00356 #endif /* WITH_LOADER_ARCH */
00357     } else if(ev == LOADER_EVENT_LOAD) {
00358 #if WITH_LOADER_ARCH
00359       if(displayname == data) {
00360         ctk_dialog_close();
00361         displayname = NULL;
00362         log_message("Loading ", ((struct pnarg *)data)->name);
00363         err = LOADER_LOAD(((struct pnarg *)data)->name,
00364                           ((struct pnarg *)data)->arg);
00365         if(err != LOADER_OK) {
00366           make_windows();
00367           errorfilename[0] = '"';
00368           strncpy(errorfilename + 1, ((struct pnarg *)data)->name,
00369                   sizeof(errorfilename) - 2);
00370           errorfilename[1 + strlen(((struct pnarg *)data)->name)] = '"';
00371           ctk_label_set_text(&errortype, (char *)errormsgs[err]);
00372           ctk_dialog_open(&errordialog);
00373           log_message((char *)errormsgs[err], errorfilename);
00374         }
00375         pnarg_free(data);
00376       } else {
00377         /* Try again. */
00378         process_post(&program_handler_process, LOADER_EVENT_DISPLAY_NAME, data);
00379       }
00380 #endif /* WITH_LOADEER_ARCH */
00381     }
00382   }
00383   PROCESS_END();
00384 }
00385 /*-----------------------------------------------------------------------------------*/

Generated on Thu Jun 22 17:45:42 2006 for Contiki 2.x by  doxygen 1.4.4