tasks.c File Reference

#include <glib.h>
#include <hal/libhal.h>
#include <stdio.h>
#include <signal.h>
#include <string.h>
#include "log.h"
#include "busy.h"
#include "devicelist.h"
#include "hal.h"
#include "ipc.h"
#include "process.h"
#include "system.h"
#include "tasks.h"
#include "xwindow.h"
Include dependency graph for tasks.c:

Go to the source code of this file.

Data Structures

struct  task_t
struct  request_t

Defines

#define FOLDER_XID   -1

Functions

static gboolean child_new (const char *command, const char *working_dir, const char *application, const char *document, const char *label, const char *image, eripc_context_t *context, const char *message_id)
static gboolean child_activate (task_t *task)
static gboolean child_close (task_t *task)
static gboolean child_window_open (task_t *task, request_t *request)
static gboolean child_window_close (task_t *task, request_t *request)
static void on_window_open_callback (eripc_context_t *context, const eripc_event_info_t *info, request_t *request)
static void on_window_close_callback (eripc_context_t *context, const eripc_event_info_t *info, request_t *request)
static gboolean on_check_child_window (gpointer data)
static gboolean on_child_new_timeout (gpointer data)
static gboolean on_child_term_timeout (gpointer data)
static task_ttasklist_add (proc_t *proc, const char *application, const char *document, const char *label, const char *image, Window window)
static gboolean tasklist_set_first (task_t *task)
static gboolean tasklist_remove_pid (GPid pid)
static gboolean tasklist_remove_window (Window window)
static task_tfind_valid_task (task_t *task)
static void free_task (task_t *task)
static task_tget_task (const char *application, const char *document)
static task_tget_task_by_xid (Window xid)
static gboolean parse_commandline (const gchar *command_line, gchar **application, gchar **document, gchar **arguments)
static request_tnew_request (task_t *task, eripc_context_t *context, const char *message_id)
static void free_request (request_t *request)
gboolean task_start (const char *command_line, const char *working_dir, const char *label, const char *image, eripc_context_t *context, const char *message_id)
 Start a task.
gboolean task_stop (const char *command_line, eripc_context_t *context, const char *message_id)
 Stop a running task.
gboolean task_rename (int xid, const char *new_document, const char *new_label)
void task_activate_by_xid (int xid)
gboolean task_activate (const char *command_line)
 Activate a running task.
void print_task_list ()
const gchar * task_service_by_window (Window xid)
 Get service of task with given window.
gboolean task_add (const char *application, const char *document, const char *label, const char *image, const char *ipc_service, gint pid, Window xid)
 Add a task which is already running.
gboolean task_cleanup_pid (GPid pid)
 Cleanup tasks for process.
gboolean task_cleanup_window (Window xid)
 Cleanup tasks for window.
gboolean task_startup_completed (proc_t *proc, Window window)
 Call when a task has finished starting.
char * testing_task_get_list ()
static void check_num_tasks ()

Variables

static const gint TIMEOUT_CHILD_NEW = 30
static const gint TIMEOUT_CHILD_CLOSE = 5
static const gint TIMEOUT_CHECK_RESTART_UDS = 5
static const gint TIMER_CHECK_WINDOW_MS = 500
static const guint MAX_TASKS = 4
static GSList * g_tasklist = NULL
static gboolean g_forced_close = FALSE
static gint g_child_terminate_source = 0
static gint g_check_child_window_source = 0
static gint g_task_pending_source = 0

Define Documentation

#define FOLDER_XID   -1

Definition at line 91 of file tasks.c.

Referenced by task_activate_by_xid(), and taskbar_select_folder().


Function Documentation

static void check_num_tasks (  )  [static]

Definition at line 718 of file tasks.c.

References child_close(), child_window_close(), g_forced_close, g_tasklist, proc_t::ipc_service, proc_t::is_multidoc, LOGPRINTF, MAX_TASKS, new_request(), and task_t::proc.

Referenced by on_check_child_window(), and on_window_open_callback().

00719 {
00720     if (g_slist_length(g_tasklist) > MAX_TASKS)
00721     {
00722         LOGPRINTF("maximum number of tasks reached, remove oldest");
00723         
00724         // get last task in list
00725         GSList *list_last_task = g_slist_last(g_tasklist);
00726         task_t *last_task = list_last_task->data;
00727 
00728         g_forced_close = TRUE;
00729         
00730         // close last task
00731         if (last_task->proc && last_task->proc->ipc_service
00732                 && last_task->proc->is_multidoc)
00733         {
00734             request_t *request = new_request(last_task, NULL, NULL);
00735             child_window_close(last_task, request);
00736         }
00737         else
00738         {
00739             child_close(last_task);
00740         }            
00741     }
00742 }

Here is the call graph for this function:

Here is the caller graph for this function:

static gboolean child_activate ( task_t task  )  [static]

Definition at line 646 of file tasks.c.

References LOGPRINTF, tasklist_set_first(), task_t::window, and window_activate().

Referenced by on_window_open_callback(), task_activate(), task_activate_by_xid(), and task_start().

00647 {
00648     LOGPRINTF("entry");
00649     
00650     // set task to head of list
00651     tasklist_set_first(task);
00652     
00653     // activate X11 window 
00654     window_activate(task->window);
00655 
00656     return TRUE;
00657 }

Here is the call graph for this function:

Here is the caller graph for this function:

static gboolean child_close ( task_t task  )  [static]

Definition at line 660 of file tasks.c.

References g_child_terminate_source, LOGPRINTF, on_child_term_timeout(), proc_t::pid, task_t::proc, and TIMEOUT_CHILD_CLOSE.

Referenced by check_num_tasks(), and task_stop().

00661 {
00662     LOGPRINTF("entry");
00663     
00664     if (task->proc)
00665     {
00666         // terminate child
00667         kill(task->proc->pid, SIGTERM);
00668     }
00669     
00670     // set maximum time to wait for child termination
00671     g_child_terminate_source = g_timeout_add_seconds(TIMEOUT_CHILD_CLOSE, on_child_term_timeout, task);
00672     
00673     return TRUE;
00674 }

Here is the call graph for this function:

Here is the caller graph for this function:

static gboolean child_new ( const char *  command,
const char *  working_dir,
const char *  application,
const char *  document,
const char *  label,
const char *  image,
eripc_context_t context,
const char *  message_id 
) [static]

Definition at line 526 of file tasks.c.

References busy_add_foreground(), BUSY_DIALOG_DELAYED, ERRORPRINTF, g_check_child_window_source, g_task_pending_source, LOGPRINTF, new_request(), on_check_child_window(), on_child_new_timeout(), process_start(), PS_WAIT_STARTED, tasklist_add(), TIMEOUT_CHILD_NEW, and TIMER_CHECK_WINDOW_MS.

Referenced by task_start().

00534 {
00535     LOGPRINTF("entry");
00536 
00537     gboolean retval = FALSE;
00538 
00539     if (   g_check_child_window_source == 0
00540         && g_task_pending_source       == 0 )
00541     {
00542      
00543         if (working_dir && working_dir[0]=='\0')
00544         {
00545             working_dir = NULL;
00546         }
00547         
00548         proc_t *proc = process_start(command, working_dir, NULL, NULL, PS_WAIT_STARTED);
00549         if (proc != NULL)
00550         {
00551             task_t    *task = tasklist_add(proc, application, document, label, image, 0);
00552             request_t *request = new_request(task, context, message_id);
00553 
00554             // show busy indication
00555             busy_add_foreground(0, BUSY_DIALOG_DELAYED, NULL);
00556 
00557             LOGPRINTF("pending task adding, wait for window id");
00558            
00559             // periodically check window list
00560             g_check_child_window_source = g_timeout_add(TIMER_CHECK_WINDOW_MS, on_check_child_window, request);            
00561             
00562             // set maximum time to wait for new window
00563             g_task_pending_source = g_timeout_add_seconds(TIMEOUT_CHILD_NEW, on_child_new_timeout, request);
00564             
00565             retval = TRUE;
00566         }
00567         else 
00568         {
00569             LOGPRINTF("error starting, return failure");
00570             // return FAILED immediately        
00571         }
00572     }
00573     else
00574     {
00575         ERRORPRINTF("still waiting for another task to be started, refusing task [%s]", label);
00576     }
00577     
00578     return retval;
00579 }

Here is the call graph for this function:

Here is the caller graph for this function:

static gboolean child_window_close ( task_t task,
request_t request 
) [static]

Definition at line 629 of file tasks.c.

References task_t::document, ipc_send_close(), proc_t::ipc_service, LOGPRINTF, on_window_close_callback(), and task_t::proc.

Referenced by check_num_tasks(), and task_stop().

00631 {
00632     LOGPRINTF("entry");
00633     
00634     gboolean retval = FALSE;
00635 
00636     if (task->proc && task->proc->ipc_service)
00637     {
00638         LOGPRINTF("wait for on_window_close_callback");
00639         retval = ipc_send_close(task->proc->ipc_service, task->document, on_window_close_callback, request);
00640     }
00641     
00642     return retval;
00643 }

Here is the call graph for this function:

Here is the caller graph for this function:

static gboolean child_window_open ( task_t task,
request_t request 
) [static]

Definition at line 582 of file tasks.c.

References task_t::document, ipc_send_open(), proc_t::ipc_service, LOGPRINTF, on_window_open_callback(), and task_t::proc.

Referenced by task_start().

00584 {
00585     LOGPRINTF("entry");
00586     
00587     gboolean retval = FALSE;
00588     
00589     if (task->proc && task->proc->ipc_service)
00590     {
00591         LOGPRINTF("pending task added, wait for on_window_open_callback");
00592         retval = ipc_send_open(task->proc->ipc_service, task->document, on_window_open_callback, request);
00593     }
00594 
00595     return retval;
00596 }

Here is the call graph for this function:

Here is the caller graph for this function:

static task_t * find_valid_task ( task_t task  )  [static]

Definition at line 1185 of file tasks.c.

References g_tasklist.

Referenced by on_check_child_window(), on_child_new_timeout(), on_window_close_callback(), and on_window_open_callback().

01186 {
01187     if (task == NULL) return NULL;
01188 
01189     task_t *task_data = NULL;
01190     GSList *cur_task = g_tasklist;
01191     
01192     while ( (cur_task != NULL) && (cur_task->data != NULL) )
01193     {
01194         task_data = cur_task->data;
01195         if (task_data == task)
01196         {
01197             return task_data;
01198         }
01199         cur_task = cur_task->next;
01200     }
01201     
01202     return NULL;
01203 }

Here is the caller graph for this function:

static void free_request ( request_t request  )  [static]

Definition at line 619 of file tasks.c.

References LOGPRINTF, and request_t::message_id.

Referenced by on_check_child_window(), on_child_new_timeout(), on_window_close_callback(), and on_window_open_callback().

00620 {
00621     LOGPRINTF("entry");
00622     
00623     g_free(request->message_id);
00624     g_free(request);
00625     request = NULL;
00626 }

Here is the caller graph for this function:

static void free_task ( task_t task  )  [static]

Definition at line 1048 of file tasks.c.

References task_t::application, task_t::document, task_t::image, and task_t::label.

Referenced by tasklist_remove_pid(), and tasklist_remove_window().

01049 {
01050     g_free(task->application);
01051     g_free(task->document);
01052     g_free(task->label);
01053     g_free(task->image);
01054     g_free(task);
01055     task = NULL;
01056 }

Here is the caller graph for this function:

static task_t * get_task ( const char *  application,
const char *  document 
) [static]

Definition at line 1221 of file tasks.c.

References task_t::application, task_t::document, g_tasklist, and LOGPRINTF.

Referenced by task_activate(), task_add(), task_start(), and task_stop().

01222 {
01223     LOGPRINTF("entry");
01224     
01225     GSList *task_ptr = g_tasklist;
01226     gchar  *baseapp  = g_path_get_basename(application);
01227     
01228     while (task_ptr)
01229     {
01230         task_t *cur_task = (task_t *) task_ptr->data;
01231 
01232         if (baseapp && cur_task->application && (strcmp(cur_task->application, baseapp) == 0) && 
01233             ((document == NULL) || (cur_task->document && (strcmp(cur_task->document, document) == 0))))
01234         {
01235             g_free(baseapp);
01236             return cur_task;
01237         }
01238         task_ptr = task_ptr->next;
01239     }
01240     
01241     g_free(baseapp);
01242     return NULL;
01243 }

Here is the caller graph for this function:

static task_t * get_task_by_xid ( Window  xid  )  [static]

Definition at line 1206 of file tasks.c.

References g_tasklist, and task_t::window.

Referenced by task_activate_by_xid(), task_rename(), and task_service_by_window().

01207 {
01208     GSList *task_ptr = g_tasklist;
01209     
01210     while (task_ptr)
01211     {
01212         task_t *cur_task = (task_t *) task_ptr->data;
01213 
01214         if (cur_task->window == xid) return cur_task;
01215         task_ptr = task_ptr->next;
01216     }
01217     return NULL;
01218 }

Here is the caller graph for this function:

static request_t * new_request ( task_t task,
eripc_context_t context,
const char *  message_id 
) [static]

Definition at line 599 of file tasks.c.

References request_t::context, ERRORPRINTF, LOGPRINTF, request_t::message_id, and request_t::task.

Referenced by check_num_tasks(), child_new(), task_start(), and task_stop().

00602 {
00603     LOGPRINTF("entry");
00604     
00605     request_t *request  = g_new0(request_t, 1);
00606     if (!request)
00607     {
00608         ERRORPRINTF("mem alloc failed");
00609         return FALSE;
00610     }
00611     request->task       = task;
00612     request->context    = context;
00613     request->message_id = g_strdup(message_id);
00614     
00615     return request;
00616 }

Here is the caller graph for this function:

static gboolean on_check_child_window ( gpointer  data  )  [static]

Definition at line 745 of file tasks.c.

References task_t::application, busy_remove_foreground(), check_num_tasks(), request_t::context, find_valid_task(), free_request(), g_check_child_window_source, g_task_pending_source, get_application_window(), ipc_send_reply_task_start(), LOGPRINTF, request_t::message_id, request_t::task, WARNPRINTF, and task_t::window.

Referenced by child_new().

00746 {
00747     LOGPRINTF("entry");
00748     
00749     request_t *request = data;
00750 
00751     if (request != NULL)
00752     {
00753         task_t *task = find_valid_task(request->task);
00754         if (task != NULL)
00755         {
00756             LOGPRINTF("looking for %s", task->application);
00757 
00758             Window child_window = get_application_window(task->application);
00759             if (child_window == 0)
00760             {
00761                 //  do nothing (wait for next call)
00762                 return TRUE;
00763             }
00764             else
00765             {
00766                 check_num_tasks();
00767 
00768                 // add window id to task info
00769                 if (task->window == 0) {
00770                     task->window = child_window;
00771                 }
00772 
00773                 if (request->context && request->message_id)
00774                 {
00775                     // return success to caller
00776                     ipc_send_reply_task_start(request->context, request->message_id, 0, NULL);
00777                 }
00778                 free_request(request);
00779             }
00780         }
00781         else
00782         {
00783             WARNPRINTF("task not found");
00784 
00785             if (request->context && request->message_id)
00786             {
00787                 // return failed to caller
00788                 ipc_send_reply_task_start(request->context, request->message_id, 3, NULL);
00789             }
00790             free_request(request);
00791         }
00792     }
00793     else
00794     {
00795         WARNPRINTF("request not found");
00796     }
00797 
00798     // stop and destroy timer
00799     g_check_child_window_source = 0;
00800     
00801     // stop pending timeout
00802     if (g_task_pending_source)
00803     {
00804         g_source_remove(g_task_pending_source);
00805         g_task_pending_source = 0;
00806     }
00807 
00808     // remove busy indication
00809     busy_remove_foreground(0);
00810 
00811     return FALSE;
00812 }

Here is the call graph for this function:

Here is the caller graph for this function:

static gboolean on_child_new_timeout ( gpointer  data  )  [static]

Definition at line 677 of file tasks.c.

References busy_remove_foreground(), request_t::context, find_valid_task(), free_request(), g_check_child_window_source, g_task_pending_source, ipc_send_reply_task_start(), LOGPRINTF, request_t::message_id, proc_t::pid, task_t::proc, request_t::task, and tasklist_remove_pid().

Referenced by child_new().

00678 {
00679     LOGPRINTF("entry");
00680     
00681     request_t *request = data;
00682     
00683     g_return_val_if_fail(request != NULL, FALSE);
00684     
00685     if (g_check_child_window_source)
00686     {
00687         g_source_remove(g_check_child_window_source);
00688         g_check_child_window_source = 0;
00689     }
00690     
00691     if (g_task_pending_source)
00692     {
00693         g_source_remove(g_task_pending_source);
00694         g_task_pending_source = 0;
00695     }    
00696     
00697     task_t *task = find_valid_task(request->task);
00698     if (task != NULL)
00699     {
00700         tasklist_remove_pid(request->task->proc->pid);
00701     }   
00702     
00703     // return result to caller
00704     if (request->context && request->message_id)
00705     {
00706         ipc_send_reply_task_start(request->context, request->message_id, 2, NULL);
00707     }
00708     free_request(request);
00709     
00710     // remove busy indication
00711     busy_remove_foreground(0);
00712 
00713     // stop and destroy this timer
00714     return FALSE; 
00715 }

Here is the call graph for this function:

Here is the caller graph for this function:

static gboolean on_child_term_timeout ( gpointer  data  )  [static]

Definition at line 1001 of file tasks.c.

References g_child_terminate_source, LOGPRINTF, proc_t::pid, and task_t::proc.

Referenced by child_close().

01002 {
01003     LOGPRINTF("entry");
01004     
01005     task_t *task = data;
01006     
01007     if (task->proc && (task->proc->pid > 0))
01008     {
01009         // termination timed out, now do it the really hard way
01010         kill(task->proc->pid, SIGKILL);
01011     }
01012     
01013     // reset terminated handler
01014     g_child_terminate_source = 0;
01015     
01016     // stop and destroy timer
01017     return FALSE;
01018 }

Here is the caller graph for this function:

static void on_window_close_callback ( eripc_context_t context,
const eripc_event_info_t info,
request_t request 
) [static]

Definition at line 948 of file tasks.c.

References eripc_event_info_t::args, eripc_arg_t::b, request_t::context, ERIPC_EVENT_REPLY, ERIPC_TYPE_BOOL, eripc_event_info_t::event_type, find_valid_task(), free_request(), ipc_send_reply(), LOGPRINTF, request_t::message_id, request_t::task, tasklist_remove_window(), WARNPRINTF, and task_t::window.

Referenced by child_window_close().

00951 {
00952     LOGPRINTF("entry request [%p]", request);
00953     
00954     gboolean retval = FALSE;
00955     const eripc_arg_t *arg_array = info->args;
00956     
00957     if (request == NULL)
00958     {
00959         WARNPRINTF("request is null");
00960     }
00961     if (find_valid_task(request->task) == NULL)
00962     {
00963         WARNPRINTF("task not found [%p]", request->task);
00964     }
00965     else if (info->event_type != ERIPC_EVENT_REPLY)
00966     {
00967         WARNPRINTF("invalid event: %d", info->event_type);
00968     }
00969     else if ((arg_array == NULL) || (arg_array[0].type != ERIPC_TYPE_BOOL))
00970     {
00971         WARNPRINTF("invalid arguments in reply");
00972     }
00973     else if (arg_array[0].value.b == FALSE)
00974     {
00975         LOGPRINTF("child returned failure");
00976     }
00977     else
00978     {
00979         // TODO
00980         // - check if window is really closed
00981         
00982         // remove task with this window from list
00983         tasklist_remove_window(request->task->window);
00984         retval = TRUE;
00985     }
00986     
00987     if (request != NULL)
00988     {
00989         if (request->message_id != NULL)
00990         {
00991             // return result to caller
00992             LOGPRINTF("return result to caller [%d], message_id [%s]", retval, request->message_id);
00993             ipc_send_reply(request->context, request->message_id, retval);
00994         }
00995         free_request(request);
00996     }
00997 }

Here is the call graph for this function:

Here is the caller graph for this function:

static void on_window_open_callback ( eripc_context_t context,
const eripc_event_info_t info,
request_t request 
) [static]

Definition at line 815 of file tasks.c.

References task_t::application, eripc_event_info_t::args, check_num_tasks(), child_activate(), request_t::context, task_t::document, ERIPC_EVENT_REPLY, ERIPC_TYPE_INT, ERIPC_TYPE_STRING, eripc_event_info_t::event_type, find_valid_task(), free_request(), g_tasklist, eripc_arg_t::i, ipc_menu_add_task(), ipc_send_reply_task_start(), task_t::label, LOGPRINTF, request_t::message_id, eripc_arg_t::s, request_t::task, tasklist_remove_window(), eripc_arg_t::value, WARNPRINTF, task_t::window, and window_activate().

Referenced by child_window_open().

00818 {
00819     LOGPRINTF("entry request [%p]", request);
00820     
00821     gboolean retval = FALSE;
00822     gchar *errmsg = NULL;
00823     const eripc_arg_t *arg_array = info->args;
00824     
00825     g_return_if_fail(request != NULL);
00826     
00827     if (info->event_type != ERIPC_EVENT_REPLY)
00828     {
00829         WARNPRINTF("invalid event: %d", info->event_type);
00830     }
00831     else if ((arg_array == NULL) || (arg_array[0].type != ERIPC_TYPE_INT))
00832     {
00833         WARNPRINTF("invalid arguments in reply, task not added");
00834     }
00835     else if (arg_array[0].value.i < 0)
00836     {
00837         LOGPRINTF("child returned failure, task not added");
00838         
00839         if (arg_array[1].type == ERIPC_TYPE_STRING)
00840         {
00841             LOGPRINTF("error message: %s", arg_array[1].value.s);
00842             errmsg = g_strdup(arg_array[1].value.s);
00843         }
00844         
00845         task_t *new_task = find_valid_task(request->task);
00846         if (new_task)
00847         {
00848             tasklist_remove_window(new_task->window);
00849         }
00850     }
00851     else    
00852     {
00853         task_t *old_task  = NULL;
00854         task_t *task_data = NULL;
00855         GSList *task      = g_tasklist;
00856         
00857         Window child_window = arg_array[0].value.i;
00858     
00859         // TODO
00860         // - add check if window exists in windowlist
00861         
00862         LOGPRINTF("task started in window: %d", (int) child_window);
00863 
00864         // check if window is already in tasklist
00865         //
00866         while ( (task != NULL) && (task->data != NULL) )
00867         {
00868             task_data = task->data;
00869 
00870             LOGPRINTF("check %s, %s; window %d", task_data->application, task_data->document, (int) task_data->window);
00871 
00872             if (task_data->window == child_window)
00873             {
00874                 // task with this window found
00875                 old_task = task_data;
00876                 break;
00877             }
00878             
00879             task = task->next;
00880         }
00881 
00882         task_t *new_task = find_valid_task(request->task);
00883         if (new_task && (child_window > 0))
00884         {
00885             LOGPRINTF("task %s, %s; window %d", new_task->application, new_task->document, (int) child_window);
00886             
00887             if (old_task == new_task)
00888             {
00889                 // task is already in task manager, activate it
00890                 child_activate(old_task);
00891             }
00892             else
00893             {
00894                 if (old_task)
00895                 {
00896                     // new task will replace old task
00897                     LOGPRINTF("remove old task %s, %s: window %d", old_task->application, old_task->document, (int) old_task->window);
00898                     tasklist_remove_window(old_task->window);
00899                 }
00900                 else
00901                 {
00902                     // task is new, check current number of tasks
00903                     check_num_tasks();
00904                 }
00905 
00906                 // add to task manager
00907                 ipc_menu_add_task(child_window, new_task->label);
00908 
00909                 // save new window
00910                 new_task->window = child_window;
00911 
00912                 if (old_task)
00913                 {
00914                     // activate existing window 
00915                     LOGPRINTF("reactivate existing window");
00916                     window_activate(child_window);
00917                 }
00918             }
00919         }
00920             
00921         // set success
00922         retval = TRUE;
00923     }
00924 
00925     if (request != NULL)
00926     {
00927         if (request->message_id != NULL)
00928         {
00929             // return result to caller
00930             if (retval == TRUE)
00931             {
00932                 LOGPRINTF("return result to caller [%d], message_id [%s]", 0, request->message_id);
00933                 ipc_send_reply_task_start(request->context, request->message_id, 0, NULL);
00934             }
00935             else
00936             {
00937                 LOGPRINTF("return result to caller [%d], message_id [%s]", 4, request->message_id);
00938                 ipc_send_reply_task_start(request->context, request->message_id, 4, errmsg);            
00939             }
00940         }
00941         free_request(request);
00942     }
00943     
00944     g_free(errmsg);
00945 }

Here is the call graph for this function:

Here is the caller graph for this function:

gboolean parse_commandline ( const gchar *  command_line,
gchar **  application,
gchar **  document,
gchar **  arguments 
) [static]

Definition at line 1246 of file tasks.c.

References LOGPRINTF, and WARNPRINTF.

Referenced by task_activate(), task_start(), and task_stop().

01247 {
01248     char   **argv_ptr   = NULL;
01249     GError *error       = NULL;
01250     gchar  *app         = NULL;
01251     gchar  *doc         = NULL;
01252     gchar  *arg         = NULL;
01253     gint   argc         = 0;
01254     
01255     LOGPRINTF("enter");
01256     
01257     g_shell_parse_argv(command_line, &argc, &argv_ptr, &error);
01258     if (error)
01259     {
01260         WARNPRINTF("Execution of '%s' failed with error: %s", command_line, error->message);
01261         g_error_free(error);
01262         return FALSE;
01263     }
01264     
01265     // split command line
01266     //
01267     app = g_path_get_basename(argv_ptr[0]);
01268     
01269     if (argc > 1)
01270     {
01271         doc  = g_strdup(argv_ptr[argc-1]);
01272         
01273         // join all arguments except application
01274         arg = g_strjoinv(" ", &argv_ptr[1]); 
01275     }
01276     
01277     // return arguments
01278     //
01279     if (application != NULL)
01280     {
01281         LOGPRINTF("app `%s`", app);
01282         *application = app;
01283     }
01284     else 
01285     {
01286         g_free(app);
01287     }
01288         
01289     if (document != NULL)
01290     {
01291         LOGPRINTF("doc `%s`", doc);
01292         *document = doc;
01293     }
01294     else 
01295     {
01296         g_free(doc);
01297     }
01298         
01299     if (arguments != NULL)
01300     {
01301         LOGPRINTF("arg `%s`", arg);
01302         *arguments = arg;
01303     }
01304     else 
01305     {
01306         g_free(arg);
01307     }
01308 
01309     g_strfreev(argv_ptr);
01310     
01311     return TRUE;
01312 }

Here is the caller graph for this function:

void print_task_list (  ) 

Definition at line 363 of file tasks.c.

References task_t::application, task_t::document, g_tasklist, proc_t::pid, task_t::proc, and task_t::window.

Referenced by testing_list_tasks().

00364 {
00365     GSList *task_ptr = g_tasklist;
00366     
00367     int i = 0;
00368     printf("%s() TASKS\n", __func__);
00369     while (task_ptr)
00370     {
00371         task_t *task = (task_t *) task_ptr->data;
00372         int pid = (task->proc) ? task->proc->pid : 0;
00373         printf("  [%d] proc_pid=%d  window=%d  app=%s  doc=%s\n", i, pid,
00374                 (guint)task->window, task->application, task->document);
00375 
00376         task_ptr = task_ptr->next;
00377         i++;
00378     }
00379 }

Here is the caller graph for this function:

gboolean task_activate ( const char *  command_line  ) 

Activate a running task.

---------------------------------------------------------------------------

Name : task_activate

Parameters:
command_line Full command line of task, quoted as g_shell_quote
Returns:
Returns TRUE on success, FALSE on failure

--------------------------------------------------------------------------

Definition at line 331 of file tasks.c.

References child_activate(), get_task(), LOGPRINTF, parse_commandline(), WARNPRINTF, and task_t::window.

Referenced by cb_menu_item_activated(), and cb_status_item_activated().

00332 {
00333     LOGPRINTF("entry: `%s`", command_line);
00334 
00335     gboolean retval       = FALSE;
00336     gchar    *application = NULL;
00337     gchar    *document    = NULL;
00338     
00339     parse_commandline(command_line, &application, &document, NULL);
00340                      
00341     task_t *task = get_task(application, document);
00342     if (task)
00343     {
00344         LOGPRINTF("found task, activate window %d", (gint) task->window);
00345         retval = child_activate(task);
00346     }
00347     else 
00348     {
00349         WARNPRINTF("task not found cmdline='%s'", command_line);
00350     }
00351 
00352     // free allocated memory
00353     g_free(application);
00354     g_free(document);
00355     
00356     LOGPRINTF("leave: retval %d", retval);
00357     
00358     return retval;
00359 }

Here is the call graph for this function:

Here is the caller graph for this function:

void task_activate_by_xid ( int  xid  ) 

Definition at line 310 of file tasks.c.

References child_activate(), FOLDER_XID, get_task_by_xid(), LOGPRINTF, process_activate_ctb(), WARNPRINTF, and task_t::window.

Referenced by cb_task_activate().

00311 {
00312     LOGPRINTF("entry xid=%d", xid);
00313     if (xid == FOLDER_XID) 
00314     {
00315         process_activate_ctb();
00316         return; 
00317     }
00318     task_t *task = get_task_by_xid(xid);
00319     if (task)
00320     {
00321         LOGPRINTF("found task, activate window %d", (gint) task->window);
00322         child_activate(task);
00323     } 
00324     else 
00325     {
00326         WARNPRINTF("task not found, xid=%d", xid);
00327     }
00328 }

Here is the call graph for this function:

Here is the caller graph for this function:

gboolean task_add ( const char *  application,
const char *  document,
const char *  label,
const char *  image,
const char *  ipc_service,
gint  pid,
Window  xid 
)

Add a task which is already running.

---------------------------------------------------------------------------

Name : task_add

Parameters:
application Basename of the application
document Full path of the document
label Text label shown under icon in popup menu
image Full path to icon shown in popup menu
ipc_service IPC service name of the application
pid Process ID
xid Window ID
Returns:
Returns TRUE on success, FALSE on failure

--------------------------------------------------------------------------

Definition at line 396 of file tasks.c.

References get_task(), LOGPRINTF, process_get_by_pid(), and tasklist_add().

Referenced by cb_opened_window().

00403 {
00404     LOGPRINTF("entry");
00405     
00406     gboolean retval = FALSE;
00407     
00408     task_t *task = get_task(application, document);
00409     proc_t *proc = process_get_by_pid(pid);
00410     if (proc && !task)
00411     {
00412         LOGPRINTF("task %s, %s, not found, add it...", application, document);
00413         task = tasklist_add(proc, application, document, label, image, xid);
00414         if (task)
00415         {
00416             retval = TRUE;
00417         }
00418     }
00419 
00420     return retval;
00421 }

Here is the call graph for this function:

Here is the caller graph for this function:

gboolean task_cleanup_pid ( GPid  pid  ) 

Cleanup tasks for process.

---------------------------------------------------------------------------

Name : task_cleanup_pid

Parameters:
pid Process that has exited
Returns:
Returns TRUE on success, FALSE on failure

--------------------------------------------------------------------------

Definition at line 424 of file tasks.c.

References g_forced_close, LOGPRINTF, process_activate_ctb(), and tasklist_remove_pid().

Referenced by on_process_exit().

00425 {
00426     LOGPRINTF("entry: forced %d", g_forced_close);
00427 
00428     gboolean result = tasklist_remove_pid(pid);
00429 
00430     if (result && !g_forced_close)
00431     {
00432 #if MACHINE_IS_DR800SG || MACHINE_IS_DR800S || MACHINE_IS_DR800SW
00433         // automatically return to application that was on top in the stack
00434 #elif MACHINE_IS_DR1000S || MACHINE_IS_DR1000SW
00435         // return to folder in content browser
00436         process_activate_ctb();
00437 #endif
00438     }
00439     
00440     g_forced_close = FALSE;
00441     
00442     return result;
00443 }

Here is the call graph for this function:

Here is the caller graph for this function:

gboolean task_cleanup_window ( Window  xid  ) 

Cleanup tasks for window.

---------------------------------------------------------------------------

Name : task_cleanup_window

Parameters:
xid Window that was closed
Returns:
Returns TRUE on success, FALSE on failure

--------------------------------------------------------------------------

Definition at line 446 of file tasks.c.

References g_forced_close, LOGPRINTF, process_activate_ctb(), and tasklist_remove_window().

Referenced by cb_closed_window().

00447 {
00448     LOGPRINTF("entry: xid %d, forced %d", (int) xid, g_forced_close);
00449  
00450     gboolean result = tasklist_remove_window(xid);
00451 
00452     if (result && !g_forced_close)
00453     {
00454 #if MACHINE_IS_DR800SG || MACHINE_IS_DR800S || MACHINE_IS_DR800SW
00455         // automatically return to application that was on top in the stack
00456 #elif MACHINE_IS_DR1000S || MACHINE_IS_DR1000SW
00457         // return to folder in content browser
00458         process_activate_ctb();
00459 #endif
00460     }
00461     
00462     g_forced_close = FALSE;
00463     
00464     return result;
00465 }

Here is the call graph for this function:

Here is the caller graph for this function:

gboolean task_rename ( int  xid,
const char *  new_document,
const char *  new_label 
)

Definition at line 293 of file tasks.c.

References task_t::document, ERRORPRINTF, get_task_by_xid(), ipc_menu_rename_task(), task_t::label, and LOGPRINTF.

Referenced by cb_task_rename().

00294 {
00295     LOGPRINTF("[%d] %s '%s'", xid, new_document, new_label);
00296     task_t *task = get_task_by_xid(xid);
00297     if (task == NULL) {
00298         ERRORPRINTF("unknown task: xid=%d", xid);
00299         return FALSE;
00300     }
00301     g_free(task->document);
00302     task->document = g_strdup(new_document);
00303     g_free(task->label);
00304     task->label = g_strdup(new_label);
00305     ipc_menu_rename_task(xid, task->label);
00306     return TRUE;
00307 }

Here is the call graph for this function:

Here is the caller graph for this function:

const gchar* task_service_by_window ( Window  xid  ) 

Get service of task with given window.

---------------------------------------------------------------------------

Name : task_service_by_window

Parameters:
xid Window ID
Returns:
Returns IPC service

--------------------------------------------------------------------------

Definition at line 383 of file tasks.c.

References get_task_by_xid(), proc_t::ipc_service, LOGPRINTF, and task_t::proc.

Referenced by parse_wm_messages().

00384 {
00385     LOGPRINTF("entry: %d", (gint) xid);
00386 
00387     task_t *task = get_task_by_xid(xid);
00388     if (task && task->proc && task->proc->ipc_service) 
00389     {
00390         return task->proc->ipc_service;
00391     }
00392     return NULL;
00393 }

Here is the call graph for this function:

Here is the caller graph for this function:

gboolean task_start ( const char *  command_line,
const char *  working_dir,
const char *  label,
const char *  image,
eripc_context_t context,
const char *  message_id 
)

Start a task.

File Name : tasks.h

Description: Task list handling functions Copyright (C) 2008 iRex Technologies B.V. All rights reserved.---------------------------------------------------------------------------

Name : task_start

Parameters:
command_line Full command line to spawn, quoted as g_shell_quote
working_dir Working directory or NULL to inherit from sysd
label Text label shown under icon in popup menu
image Full path to icon shown in popup menu
Returns:
Window ID

--------------------------------------------------------------------------

Definition at line 168 of file tasks.c.

References child_activate(), child_new(), child_window_open(), get_task(), ipc_send_reply_task_start(), proc_t::ipc_service, proc_t::is_multidoc, LOGPRINTF, new_request(), parse_commandline(), task_t::proc, process_get_by_name(), and tasklist_add().

Referenced by cb_open_url(), cb_status_item_activated(), cb_task_start(), and start_demo_mode().

00174 {
00175     LOGPRINTF("entry: `%s`", command_line);
00176     
00177     gboolean retval       = FALSE;
00178     gchar    *application = NULL;
00179     gchar    *document    = NULL;
00180 
00181     parse_commandline(command_line, &application, &document, NULL);
00182 
00183     LOGPRINTF("app [%s] wd [%s] doc [%s] label [%s] image [%s]", application, working_dir, document, label, image);
00184     
00185     task_t *task = get_task(application, document);
00186     if (task)
00187     {
00188         LOGPRINTF("task exists, reopen or activate");
00189         // task already exists, reopen or activate
00190         //
00191         if (task->proc && task->proc->ipc_service && task->proc->is_multidoc)
00192         {
00193             request_t *request = new_request(task, context, message_id);
00194             retval = child_window_open(task, request);
00195         }
00196         else
00197         {
00198             retval = child_activate(task);
00199             if (context && message_id)
00200             {
00201                 // return result to caller
00202                 ipc_send_reply_task_start(context, message_id, 0, NULL);
00203             }
00204         }
00205     }
00206     else
00207     {
00208         proc_t *proc = process_get_by_name(application);
00209         if (proc)
00210         {
00211             // process is running but no task yet, create new
00212             //
00213             if (proc->ipc_service && proc->is_multidoc)
00214             {
00215                 LOGPRINTF("task %s, %s not found, create it...", application, document);
00216                 task_t *task = tasklist_add(proc, application, document, label, image, 0);
00217                 request_t *request = new_request(task, context, message_id);
00218                 retval = child_window_open(task, request);
00219             }
00220             else
00221             {
00222                 if (proc->is_multidoc) {
00223                     LOGPRINTF("%s, %s is currently running but is not a task, ignored.", application, document);
00224                     // process running, singledoc and no task found for it
00225                     // this is either a window-less process or a system process
00226                     // in either case; we ignore this start command.
00227                 } else {
00228                     // TODO REFACTOR (common code)
00229                     // process not running, create new
00230                     LOGPRINTF("process %s running, but not for current doc, start new", application);
00231                     retval = child_new(command_line, working_dir, application, document, label, image, context, message_id);
00232                 }
00233             }
00234         }
00235         else
00236         {
00237             // process not running, create new
00238             //
00239             LOGPRINTF("process %s, not currently running start new", application);
00240             retval = child_new(command_line, working_dir, application, document, label, image, context, message_id);
00241         }
00242     }
00243 
00244     // free allocated memory
00245     g_free(application);
00246     g_free(document);
00247 
00248     LOGPRINTF("leave: retval %d", retval);
00249     
00250     return retval;
00251 }

Here is the call graph for this function:

Here is the caller graph for this function:

gboolean task_startup_completed ( proc_t proc,
Window  xid 
)

Call when a task has finished starting.

---------------------------------------------------------------------------

Name : task_startup_completed

Parameters:
proc Process
xid Window id
Returns:
Returns TRUE on success, FALSE on failure

--------------------------------------------------------------------------

Definition at line 468 of file tasks.c.

References task_t::application, task_t::document, g_tasklist, ipc_menu_add_task(), task_t::label, LOGPRINTF, task_t::proc, and task_t::window.

Referenced by post_process_startup().

00469 {
00470     LOGPRINTF("entry");
00471     
00472     GSList *task_ptr = g_tasklist;
00473     while (task_ptr)
00474     {
00475         task_t *task = (task_t *) task_ptr->data;
00476 
00477         if (task->proc == proc)
00478         {
00479             if (window != 0)
00480             {
00481                 task->window = window;
00482                LOGPRINTF("assigned window %d to %s, %s", (gint) task->window, task->application, task->document);
00483             }
00484 
00485             // add to task manager
00486             ipc_menu_add_task((gint)task->window, task->label);
00487 
00488             return TRUE;
00489         }
00490         task_ptr = task_ptr->next;
00491     }
00492     return FALSE;
00493 }

Here is the call graph for this function:

Here is the caller graph for this function:

gboolean task_stop ( const char *  command_line,
eripc_context_t context,
const char *  message_id 
)

Stop a running task.

---------------------------------------------------------------------------

Name : task_stop

Parameters:
command_line Full command line of task, quoted as g_shell_quote
Returns:
Returns TRUE on success, FALSE on failure

--------------------------------------------------------------------------

Definition at line 254 of file tasks.c.

References child_close(), child_window_close(), get_task(), ipc_send_reply(), proc_t::ipc_service, proc_t::is_multidoc, LOGPRINTF, new_request(), parse_commandline(), and task_t::proc.

Referenced by cb_task_stop().

00257 {
00258     LOGPRINTF("entry: `%s`", command_line);
00259 
00260     gboolean retval       = FALSE;
00261     gchar    *application = NULL;
00262     gchar    *document    = NULL;
00263     
00264     parse_commandline(command_line, &application, &document, NULL);
00265                      
00266     task_t *task = get_task(application, document);
00267     if (task)
00268     {
00269         if (task->proc && task->proc->ipc_service && task->proc->is_multidoc)
00270         {
00271             request_t *request = new_request(task, context, message_id);
00272             LOGPRINTF("found multidoc window, close child window");
00273             retval = child_window_close(task, request);
00274         }
00275         else
00276         {
00277             LOGPRINTF("found singledoc window, close child");
00278             retval = child_close(task);
00279             ipc_send_reply(context, message_id, retval);
00280         }
00281     }
00282 
00283     // free allocated memory
00284     g_free(application);
00285     g_free(document);
00286     
00287     LOGPRINTF("leave: retval %d", retval);
00288     
00289     return retval;
00290 }

Here is the call graph for this function:

Here is the caller graph for this function:

static task_t * tasklist_add ( proc_t proc,
const char *  application,
const char *  document,
const char *  label,
const char *  image,
Window  window 
) [static]

Definition at line 1021 of file tasks.c.

References task_t::application, task_t::document, ERRORPRINTF, g_tasklist, task_t::image, task_t::label, LOGPRINTF, task_t::proc, and task_t::window.

Referenced by child_new(), task_add(), and task_start().

01023 {
01024     LOGPRINTF("entry");
01025    
01026     task_t *task = g_new0 (task_t, 1);
01027     if (!task)
01028     {
01029         ERRORPRINTF("mem alloc failed");
01030         return NULL;
01031     }
01032     
01033     task->proc        = proc;
01034     task->application = g_strdup(application);
01035     task->document    = g_strdup(document);
01036     task->label       = g_strdup(label);
01037     task->image       = g_strdup(image);
01038     task->window      = window;
01039     
01040     g_tasklist = g_slist_prepend(g_tasklist, task);
01041 
01042     LOGPRINTF("done. task %p [#tasks: %d]", task, g_slist_length(g_tasklist));
01043     
01044     return task;
01045 }

Here is the caller graph for this function:

static gboolean tasklist_remove_pid ( GPid  pid  )  [static]

Definition at line 1087 of file tasks.c.

References free_task(), g_tasklist, ipc_menu_remove_task(), LOGPRINTF, proc_t::pid, task_t::proc, and task_t::window.

Referenced by on_child_new_timeout(), and task_cleanup_pid().

01088 {
01089     LOGPRINTF("entry");
01090     
01091     GSList *task = g_tasklist;
01092     gint    npre = g_slist_length(g_tasklist);
01093     
01094     while ( (task != NULL) && (task->data != NULL) )
01095     {
01096         task_t *task_data = task->data;
01097 
01098         if (task_data->proc && (task_data->proc->pid == pid))
01099         {
01100             ipc_menu_remove_task(task_data->window);
01101             free_task(task_data);
01102     
01103             g_tasklist = g_slist_delete_link(g_tasklist, task);
01104             
01105             // start over iteration
01106             task = g_tasklist;
01107         }
01108         else
01109         {
01110             task = task->next;
01111         }
01112     }
01113     
01114     gint npost = g_slist_length(g_tasklist);
01115     
01116     if (npre != npost)
01117     {
01118         LOGPRINTF("removed %d tasks, %d remaining", npre-npost, npost);
01119         return TRUE;
01120     }
01121     else
01122     {
01123         LOGPRINTF("no tasks found for pid %d", pid);
01124         return FALSE;
01125     }
01126 }

Here is the call graph for this function:

Here is the caller graph for this function:

static gboolean tasklist_remove_window ( Window  window  )  [static]

Definition at line 1129 of file tasks.c.

References task_t::application, free_task(), g_tasklist, ipc_menu_remove_task(), LOGPRINTF, and task_t::window.

Referenced by on_window_close_callback(), on_window_open_callback(), and task_cleanup_window().

01130 {
01131     LOGPRINTF("entry: xid %d", (int) window);
01132     
01133     GSList *task = g_tasklist;
01134     gint    npre = g_slist_length(g_tasklist);
01135     gboolean is_uds_task = FALSE;
01136     
01137     while ( (task != NULL) && (task->data != NULL) )
01138     {
01139         task_t *task_data = task->data;
01140 
01141         if (task_data->window == window)
01142         {
01143             ipc_menu_remove_task(task_data->window);
01144              
01145             if (strcmp(task_data->application, "uds") == 0)
01146             {
01147                 is_uds_task = TRUE;
01148             }
01149             free_task(task_data);
01150             
01151             g_tasklist = g_slist_delete_link(g_tasklist, task);
01152             
01153             // start over iteration
01154             task = g_tasklist;
01155         }
01156         else
01157         {
01158             task = task->next;
01159         }
01160     }
01161     
01162     gint npost = g_slist_length(g_tasklist);
01163 /*    
01164     if (is_uds_task && !is_uds_in_use())
01165     {
01166         // start timer to check if any windows for UDS remain
01167         LOGPRINTF("no task found for UDS, start timer");
01168         g_timeout_add_seconds(TIMEOUT_CHECK_RESTART_UDS, on_check_restart_uds, NULL);
01169     }
01170 */
01171 
01172     if (npre != npost)
01173     {
01174         LOGPRINTF("removed %d tasks, %d remaining", npre-npost, npost);
01175         return TRUE;
01176     }
01177     else
01178     {
01179         LOGPRINTF("no tasks found for window %d", (int) window);
01180         return FALSE;
01181     }
01182 }

Here is the call graph for this function:

Here is the caller graph for this function:

static gboolean tasklist_set_first ( task_t task  )  [static]

Definition at line 1059 of file tasks.c.

References g_tasklist, ipc_menu_set_first_task(), LOGPRINTF, and task_t::window.

Referenced by child_activate().

01060 {
01061     LOGPRINTF("entry");
01062    
01063     task_t *task_data = NULL;
01064     GSList *cur_task = g_tasklist;
01065     
01066     while ( (cur_task != NULL) && (cur_task->data != NULL) )
01067     {
01068         task_data = cur_task->data;
01069         if (task_data == task)
01070         {
01071             ipc_menu_set_first_task(task->window);
01072 
01073             g_tasklist = g_slist_delete_link(g_tasklist, cur_task);
01074             g_tasklist = g_slist_prepend(g_tasklist, task);
01075             LOGPRINTF("task set to first [#tasks: %d]", g_slist_length(g_tasklist));
01076             return TRUE;
01077         }
01078         
01079         cur_task = cur_task->next;
01080     }
01081     
01082     LOGPRINTF("no first task found [#tasks: %d]", g_slist_length(g_tasklist));
01083     return FALSE;
01084 }

Here is the call graph for this function:

Here is the caller graph for this function:

char* testing_task_get_list (  ) 

Definition at line 496 of file tasks.c.

References task_t::application, buffer, cp, task_t::document, and g_tasklist.

Referenced by testing_list_tasks().

00497 {
00498 #if (TESTING_ON)
00499     char buffer[1000];
00500     char* cp = buffer;
00501     GSList *iter = g_tasklist;
00502     while (iter)
00503     {
00504         task_t* task = (task_t*) iter->data;
00505         strcpy(cp, task->application);
00506         cp += strlen(task->application);
00507         *cp++ = '|';
00508         strcpy(cp, task->document);
00509         cp += strlen(task->document);
00510         *cp++ = '\n';
00511 
00512         iter = g_slist_next(iter);
00513     }
00514     *cp = 0;
00515     char* result = g_strdup(buffer);
00516     return result;
00517 #endif
00518     return g_strdup("no debug");
00519 }

Here is the caller graph for this function:


Variable Documentation

gint g_check_child_window_source = 0 [static]

Definition at line 96 of file tasks.c.

Referenced by child_new(), on_check_child_window(), and on_child_new_timeout().

gint g_child_terminate_source = 0 [static]

Definition at line 95 of file tasks.c.

Referenced by child_close(), and on_child_term_timeout().

gboolean g_forced_close = FALSE [static]

Definition at line 94 of file tasks.c.

Referenced by check_num_tasks(), task_cleanup_pid(), and task_cleanup_window().

gint g_task_pending_source = 0 [static]

Definition at line 97 of file tasks.c.

Referenced by child_new(), on_check_child_window(), and on_child_new_timeout().

GSList* g_tasklist = NULL [static]
const guint MAX_TASKS = 4 [static]

Definition at line 84 of file tasks.c.

Referenced by check_num_tasks().

const gint TIMEOUT_CHECK_RESTART_UDS = 5 [static]

Definition at line 81 of file tasks.c.

const gint TIMEOUT_CHILD_CLOSE = 5 [static]

Definition at line 80 of file tasks.c.

Referenced by child_close().

const gint TIMEOUT_CHILD_NEW = 30 [static]

Definition at line 79 of file tasks.c.

Referenced by child_new().

const gint TIMER_CHECK_WINDOW_MS = 500 [static]

Definition at line 83 of file tasks.c.

Referenced by child_new().

Generated by  doxygen 1.6.2-20100208