Changeset f42b4fbef76944dc292983208ef62e144ab7031f

Show
Ignore:
Timestamp:
10/02/11 00:47:50 (20 months ago)
Author:
Nedko Arnaudov <nedko@…>
Children:
36ef11202b7e4345f2402d8ea9cf6395ac857081
Parents:
5483a52daf9dca6aa6cbfafc7d6d050456d49dd3
git-committer:
Nedko Arnaudov <nedko@arnaudov.name> / 2011-10-02T00:47:50Z+0300
Message:

operational jack session implementation

Files:
10 modified

Legend:

Unmodified
Added
Removed
  • common/dirhelpers.c

    r0266594 rf42b4fb  
    2626 
    2727#include "../common.h" 
     28#include "catdup.h" 
    2829 
    2930#include <sys/types.h> 
     
    3233#include <errno.h> 
    3334#include <stdarg.h> 
     35#include <dirent.h> 
    3436 
    3537bool check_dir_exists(const char * dirname) 
     
    241243  return ret; 
    242244} 
     245 
     246bool ladish_rmdir_recursive(const char * dirpath) 
     247{ 
     248  DIR * dir; 
     249  struct dirent * dentry_ptr; 
     250  char * entry_fullpath; 
     251  struct stat st; 
     252  bool success; 
     253 
     254  success = false; 
     255 
     256  dir = opendir(dirpath); 
     257  if (dir == NULL) 
     258  { 
     259    log_error("Cannot open directory '%s': %d (%s)", dirpath, errno, strerror(errno)); 
     260    goto exit; 
     261  } 
     262 
     263  while ((dentry_ptr = readdir(dir)) != NULL) 
     264  { 
     265    if (strcmp(dentry_ptr->d_name, ".") == 0 || 
     266        strcmp(dentry_ptr->d_name, "..") == 0) 
     267    { 
     268      continue; 
     269    } 
     270 
     271    entry_fullpath = catdup3(dirpath, "/", dentry_ptr->d_name); 
     272    if (entry_fullpath == NULL) 
     273    { 
     274      log_error("catdup() failed"); 
     275      goto close; 
     276    } 
     277 
     278    if (stat(entry_fullpath, &st) != 0) 
     279    { 
     280      log_error("failed to stat '%s': %d (%s)", entry_fullpath, errno, strerror(errno)); 
     281    } 
     282    else 
     283    { 
     284      if (S_ISDIR(st.st_mode)) 
     285      { 
     286        if (!ladish_rmdir_recursive(entry_fullpath)) 
     287        { 
     288          goto free; 
     289        } 
     290      } 
     291      else 
     292      { 
     293        if (unlink(entry_fullpath) < 0) 
     294        { 
     295          log_error("unlink('%s') failed. errno = %d (%s)", dirpath, errno, strerror(errno)); 
     296          goto free; 
     297        } 
     298      } 
     299    } 
     300 
     301    free(entry_fullpath); 
     302  } 
     303 
     304  if (rmdir(dirpath) < 0) 
     305  { 
     306    log_error("rmdir('%s') failed. errno = %d (%s)", dirpath, errno, strerror(errno)); 
     307  } 
     308  else 
     309  { 
     310    success = true; 
     311  } 
     312 
     313  goto close; 
     314 
     315free: 
     316  free(entry_fullpath); 
     317close: 
     318  closedir(dir); 
     319exit: 
     320  return success; 
     321} 
     322 
     323bool ladish_rotate(const char * src, const char * dst, unsigned int max_backups) 
     324{ 
     325  size_t len = strlen(dst) + 100; 
     326  char paths[2][len]; 
     327  struct stat st; 
     328  char * path; 
     329  const char * older_path; 
     330  bool oldest_found; 
     331  unsigned int backup; 
     332 
     333  oldest_found = false; 
     334  older_path = NULL; 
     335  backup = max_backups; 
     336  while (backup > 0) 
     337  { 
     338    path = paths[backup % 2]; 
     339    snprintf(path, len, "%s.%u", dst, backup); 
     340 
     341    if (stat(path, &st) != 0) 
     342    { 
     343      if (!oldest_found && errno == ENOENT) 
     344      { 
     345        log_info("\"%s\" does not exist", path); 
     346        goto next; 
     347      } 
     348 
     349      log_error("Failed to stat \"%s\": %d (%s)", path, errno, strerror(errno)); 
     350      return false; 
     351    } 
     352 
     353    if (!S_ISDIR(st.st_mode)) 
     354    { 
     355      log_error("\"%s\" exists but is not directory.", path); 
     356      return false; 
     357    } 
     358 
     359    oldest_found = true; 
     360 
     361    if (backup < max_backups) 
     362    { 
     363      ASSERT(older_path != NULL); 
     364      log_info("rename '%s' -> '%s'", path, older_path); 
     365      if (rename(path, older_path) != 0) 
     366      { 
     367        log_error("rename('%s' -> '%s') failed. errno = %d (%s)", path, older_path, errno, strerror(errno)); 
     368        return false; 
     369      } 
     370    } 
     371    else 
     372    { 
     373      /* try to remove dst.max_backups */ 
     374      log_info("rmdir '%s'", path); 
     375      if (!ladish_rmdir_recursive(path)) 
     376      { 
     377        return false; 
     378      } 
     379    } 
     380 
     381  next: 
     382    older_path = path; 
     383    backup--; 
     384  } 
     385 
     386  log_info("rename '%s' -> '%s'", dst, path); 
     387  if (rename(dst, path) != 0 && errno != ENOENT) 
     388  { 
     389    log_error("rename('%s' -> '%s') failed. errno = %d (%s)", dst, path, errno, strerror(errno)); 
     390    return false; 
     391  } 
     392 
     393  log_info("rename '%s' -> '%s'", src, dst); 
     394  if (rename(src, dst) != 0) 
     395  { 
     396    log_error("rename('%s' -> '%s') failed. errno = %d (%s)", src, dst, errno, strerror(errno)); 
     397    return false; 
     398  } 
     399 
     400  return true; 
     401} 
  • common/dirhelpers.h

    r0266594 rf42b4fb  
    3131bool ensure_dir_exist(const char * dirname, int mode); 
    3232bool ensure_dir_exist_varg(int mode, ...); 
     33bool ladish_rmdir_recursive(const char * dirname); 
     34bool ladish_rotate(const char * src, const char * dst, unsigned int max_backups); 
    3335 
    3436#endif /* #ifndef DIRHELPERS_H__805193D2_2662_40FA_8814_AF8A4E08F4B0__INCLUDED */ 
  • daemon/app_supervisor.c

    r5483a52 rf42b4fb  
    4141#include "../common/catdup.h" 
    4242#include "../common/dirhelpers.h" 
     43#include "jack_session.h" 
    4344 
    4445struct ladish_app 
     
    4950  char * name; 
    5051  char * commandline; 
     52  char * js_commandline; 
    5153  bool terminal; 
    5254  char level[MAX_LEVEL_CHARCOUNT]; 
     
    6870  char * opath; 
    6971  char * dir; 
     72 
     73  char * js_dir; 
     74  char * js_temp_dir; 
     75  unsigned int pending_js_saves; 
     76  void * save_callback_context; 
     77  ladish_save_complete_callback save_callback; 
     78 
    7079  char * project_name; 
    7180  uint64_t version; 
     
    8695 
    8796  if (strcmp(level, LADISH_APP_LEVEL_0) != 0 && 
    88       strcmp(level, LADISH_APP_LEVEL_1) != 0&& 
    89       strcmp(level, LADISH_APP_LEVEL_LASH) != 0) 
     97      strcmp(level, LADISH_APP_LEVEL_1) != 0 && 
     98      strcmp(level, LADISH_APP_LEVEL_LASH) != 0 && 
     99      strcmp(level, LADISH_APP_LEVEL_JACKSESSION) != 0) 
    90100  { 
    91101    return false; 
     
    155165 
    156166  supervisor_ptr->dir = NULL; 
     167 
     168  supervisor_ptr->js_temp_dir = NULL; 
     169  supervisor_ptr->js_dir = NULL; 
     170  supervisor_ptr->pending_js_saves = 0; 
     171  supervisor_ptr->save_callback_context = NULL; 
     172  supervisor_ptr->save_callback = NULL; 
     173 
    157174  supervisor_ptr->project_name = NULL; 
    158175 
     
    207224  free(app_ptr->name); 
    208225  free(app_ptr->commandline); 
     226  free(app_ptr->js_commandline); 
    209227  free(app_ptr); 
    210228} 
     
    251269} 
    252270 
     271static void ladish_js_save_complete(struct ladish_app_supervisor * supervisor_ptr) 
     272{ 
     273  struct list_head * node_ptr; 
     274  struct ladish_app * app_ptr; 
     275  bool success; 
     276 
     277  ASSERT(supervisor_ptr->js_temp_dir != NULL); 
     278  ASSERT(supervisor_ptr->js_dir != NULL); 
     279  ASSERT(supervisor_ptr->pending_js_saves == 0); 
     280 
     281  /* find whether all strdup() calls for new commandlines succeeded */ 
     282  list_for_each(node_ptr, &supervisor_ptr->applist) 
     283  { 
     284    app_ptr = list_entry(node_ptr, struct ladish_app, siblings); 
     285    if (app_ptr->state == LADISH_APP_STATE_STARTED && 
     286        strcmp(app_ptr->level, LADISH_APP_LEVEL_JACKSESSION) == 0 && 
     287        app_ptr->js_commandline == NULL) 
     288    { /* a strdup() call has failed, free js commandline buffers allocated by succeeded strdup() calls */ 
     289      list_for_each(node_ptr, &supervisor_ptr->applist) 
     290      { 
     291        app_ptr = list_entry(node_ptr, struct ladish_app, siblings); 
     292        free(app_ptr->js_commandline); 
     293        app_ptr->js_commandline = NULL; 
     294      } 
     295      goto fail_rm_temp_dir; 
     296    } 
     297  } 
     298 
     299  /* move js_dir to js_dir.1; move js_temp_dir to js_dir  */ 
     300  success = ladish_rotate(supervisor_ptr->js_temp_dir, supervisor_ptr->js_dir, 10); 
     301  if (!success) 
     302  { 
     303    goto fail_rm_temp_dir; 
     304  } 
     305 
     306  list_for_each(node_ptr, &supervisor_ptr->applist) 
     307  { 
     308    app_ptr = list_entry(node_ptr, struct ladish_app, siblings); 
     309    if (app_ptr->state == LADISH_APP_STATE_STARTED && 
     310        strcmp(app_ptr->level, LADISH_APP_LEVEL_JACKSESSION) == 0) 
     311    { 
     312      ASSERT(app_ptr->commandline != NULL); 
     313      ASSERT(app_ptr->js_commandline != NULL); 
     314      free(app_ptr->commandline); 
     315      app_ptr->commandline = app_ptr->js_commandline; 
     316      app_ptr->js_commandline = NULL; 
     317    } 
     318  } 
     319 
     320  goto done; 
     321 
     322fail_rm_temp_dir: 
     323  if (!ladish_rmdir_recursive(supervisor_ptr->js_temp_dir)) 
     324  { 
     325    log_error("Cannot remove JS temp dir '%s'", supervisor_ptr->js_temp_dir); 
     326  } 
     327 
     328done: 
     329  free(supervisor_ptr->js_temp_dir); 
     330  supervisor_ptr->js_temp_dir = NULL; 
     331 
     332  supervisor_ptr->save_callback(supervisor_ptr->save_callback_context, success); 
     333  supervisor_ptr->save_callback = NULL; 
     334  supervisor_ptr->save_callback_context = NULL; 
     335} 
     336 
    253337#define supervisor_ptr ((struct ladish_app_supervisor *)supervisor_handle) 
    254338 
     
    334418  { 
    335419    log_error("invalid level '%s'", level); 
    336     return NULL; 
     420    goto fail; 
     421  } 
     422 
     423  if (strcmp(level, LADISH_APP_LEVEL_JACKSESSION) == 0 && 
     424      supervisor_ptr->dir == NULL) 
     425  { 
     426    log_error("jack session apps need directory"); 
     427    goto fail; 
    337428  } 
    338429 
     
    341432  { 
    342433    log_error("malloc of struct ladish_app failed"); 
    343     return NULL; 
     434    goto fail; 
    344435  } 
    345436 
     
    348439  { 
    349440    log_error("strdup() failed for app name"); 
    350     free(app_ptr); 
    351     return NULL; 
     441    goto free_app; 
    352442  } 
    353443 
     
    356446  { 
    357447    log_error("strdup() failed for app commandline"); 
    358     free(app_ptr->name); 
    359     free(app_ptr); 
    360     return NULL; 
    361   } 
     448    goto free_name; 
     449  } 
     450 
     451  app_ptr->js_commandline = NULL; 
    362452 
    363453  app_ptr->dbus_name = NULL; 
     
    419509 
    420510  return (ladish_app_handle)app_ptr; 
     511 
     512free_name: 
     513  free(app_ptr->name); 
     514free_app: 
     515  free(app_ptr); 
     516fail: 
     517  return NULL; 
    421518} 
    422519 
     
    623720} 
    624721 
     722#define app_ptr ((struct ladish_app *)context) 
     723 
     724static void ladish_js_app_save_complete(void * context, const char * commandline) 
     725{ 
     726  log_info("JS app saved, commandline '%s'", commandline); 
     727  ASSERT(app_ptr->supervisor->js_temp_dir != NULL); 
     728 
     729  ASSERT(app_ptr->js_commandline == NULL); 
     730  app_ptr->js_commandline = strdup(commandline); 
     731  if (app_ptr->js_commandline == NULL) 
     732  { 
     733    log_error("strdup() failed for JS app '%s' commandline '%s'", app_ptr->name, commandline); 
     734  } 
     735 
     736  if (app_ptr->supervisor->pending_js_saves != 1) 
     737  { 
     738    ASSERT(app_ptr->supervisor->pending_js_saves > 1); 
     739    app_ptr->supervisor->pending_js_saves--; 
     740    log_info("%u more JS apps are still saving", app_ptr->supervisor->pending_js_saves); 
     741    return; 
     742  } 
     743 
     744  log_info("Last JS app saved"); 
     745  app_ptr->supervisor->pending_js_saves = 0; 
     746 
     747  ladish_js_save_complete(app_ptr->supervisor); 
     748} 
     749 
     750#undef app_ptr 
     751 
    625752static inline void ladish_app_initiate_save(struct ladish_app * app_ptr) 
    626753{ 
     
    629756  { 
    630757    ladish_app_initiate_lash_save(app_ptr, app_ptr->supervisor->dir != NULL ? app_ptr->supervisor->dir : g_base_dir); 
     758  } 
     759  else if (strcmp(app_ptr->level, LADISH_APP_LEVEL_JACKSESSION) == 0) 
     760  { 
     761    log_info("Initiating JACK session save for '%s'", app_ptr->name); 
     762    ladish_js_save_app(app_ptr->uuid, app_ptr->supervisor->js_temp_dir, app_ptr, ladish_js_app_save_complete); 
    631763  } 
    632764  else if (strcmp(app_ptr->level, LADISH_APP_LEVEL_1) == 0) 
     
    659791  bool lifeless; 
    660792 
     793  free(supervisor_ptr->js_temp_dir); 
     794  supervisor_ptr->js_temp_dir = NULL; 
     795  free(supervisor_ptr->js_dir); 
     796  supervisor_ptr->js_dir = NULL; 
    661797  free(supervisor_ptr->dir); 
    662798  supervisor_ptr->dir = NULL; 
     
    701837{ 
    702838  char * dup; 
     839  char * js_dir; 
     840 
     841  ASSERT(supervisor_ptr->pending_js_saves == 0); 
    703842 
    704843  dup = strdup(dir); 
     
    709848  } 
    710849 
    711   if (supervisor_ptr->dir != NULL) 
    712   { 
    713     free(supervisor_ptr->dir); 
    714   } 
    715  
     850  js_dir = catdup(dir, "/js_apps"); 
     851  if (js_dir == NULL) 
     852  { 
     853    log_error("catdup() failed to compose supervisor js dir path"); 
     854    free(dup); 
     855    return false; 
     856  } 
     857 
     858  free(supervisor_ptr->dir); 
    716859  supervisor_ptr->dir = dup; 
     860 
     861  free(supervisor_ptr->js_dir); 
     862  supervisor_ptr->js_dir = js_dir; 
    717863 
    718864  return true; 
     
    812958bool ladish_app_supervisor_start_app(ladish_app_supervisor_handle supervisor_handle, ladish_app_handle app_handle) 
    813959{ 
     960  char uuid_str[37]; 
     961  char * js_dir; 
     962  bool ret; 
     963 
    814964  app_ptr->zombie = false; 
    815965 
    816966  ASSERT(app_ptr->pid == 0); 
    817967 
    818   if (!loader_execute( 
    819         supervisor_ptr->name, 
    820         supervisor_ptr->project_name, 
    821         app_ptr->name, 
    822         supervisor_ptr->dir != NULL ? supervisor_ptr->dir : "/", 
    823         app_ptr->terminal, 
    824         app_ptr->commandline, 
    825         &app_ptr->pid)) 
     968  if (strcmp(app_ptr->level, LADISH_APP_LEVEL_JACKSESSION) == 0) 
     969  { 
     970    uuid_unparse(app_ptr->uuid, uuid_str); 
     971    js_dir = catdup4(supervisor_ptr->js_dir, "/", uuid_str, "/"); 
     972    if (js_dir == NULL) 
     973    { 
     974      log_error("catdup4() failed to compose app jack session dir"); 
     975      return false; 
     976    } 
     977  } 
     978  else 
     979  { 
     980    js_dir = NULL; 
     981  } 
     982 
     983  ret = loader_execute( 
     984    supervisor_ptr->name, 
     985    supervisor_ptr->project_name, 
     986    app_ptr->name, 
     987    supervisor_ptr->dir != NULL ? supervisor_ptr->dir : "/", 
     988    js_dir, 
     989    app_ptr->terminal, 
     990    app_ptr->commandline, 
     991    &app_ptr->pid); 
     992 
     993  free(js_dir); 
     994 
     995  if (!ret) 
    826996  { 
    827997    return false; 
     
    8691039  ladish_app_send_signal(app_ptr, SIGKILL, false); 
    8701040  app_ptr->state = LADISH_APP_STATE_KILL; 
    871 } 
    872  
    873 void ladish_app_save(ladish_app_handle app_handle) 
    874 { 
    875   ladish_app_initiate_save(app_ptr); 
    8761041} 
    8771042 
     
    10071172  struct list_head * node_ptr; 
    10081173  struct ladish_app * app_ptr; 
     1174  bool success; 
     1175 
     1176  ASSERT(supervisor_ptr->js_temp_dir == NULL); 
     1177  ASSERT(supervisor_ptr->pending_js_saves == 0); 
     1178  list_for_each(node_ptr, &supervisor_ptr->applist) 
     1179  { 
     1180    app_ptr = list_entry(node_ptr, struct ladish_app, siblings); 
     1181    if (app_ptr->state == LADISH_APP_STATE_STARTED && 
     1182        strcmp(app_ptr->level, LADISH_APP_LEVEL_JACKSESSION) == 0) 
     1183    { 
     1184      ASSERT(app_ptr->js_commandline == NULL); 
     1185      supervisor_ptr->pending_js_saves++; 
     1186    } 
     1187  } 
     1188 
     1189  if (supervisor_ptr->pending_js_saves > 0) 
     1190  { 
     1191    ASSERT(supervisor_ptr->dir != NULL); 
     1192    supervisor_ptr->js_temp_dir = catdup(supervisor_ptr->dir, "/js_apps.tmpXXXXXX"); 
     1193    if (supervisor_ptr->js_temp_dir == NULL) 
     1194    { 
     1195      log_error("catdup() failed to compose supervisor js temp dir path template"); 
     1196      goto reset_js_pending_saves; 
     1197    } 
     1198 
     1199    if (mkdtemp(supervisor_ptr->js_temp_dir) == NULL) 
     1200    { 
     1201      log_error("mkdtemp('%s') failed. errno = %d (%s)", supervisor_ptr->js_temp_dir, errno, strerror(errno)); 
     1202      goto free_js_temp_dir; 
     1203    } 
     1204 
     1205    log_info("saving %u JACK session apps to '%s'", supervisor_ptr->pending_js_saves, supervisor_ptr->js_temp_dir); 
     1206 
     1207    supervisor_ptr->save_callback_context = context; 
     1208    supervisor_ptr->save_callback = callback; 
     1209  } 
     1210  else 
     1211  { 
     1212    ASSERT(supervisor_ptr->save_callback_context == NULL); 
     1213    ASSERT(supervisor_ptr->save_callback == NULL); 
     1214  } 
    10091215 
    10101216  list_for_each(node_ptr, &supervisor_ptr->applist) 
     
    10251231  } 
    10261232 
    1027   callback(context, true); 
     1233  success = true; 
     1234  goto exit; 
     1235 
     1236free_js_temp_dir: 
     1237  free(supervisor_ptr->js_temp_dir); 
     1238  supervisor_ptr->js_temp_dir = NULL; 
     1239reset_js_pending_saves: 
     1240  supervisor_ptr->pending_js_saves = 0; 
     1241  success = false; 
     1242exit: 
     1243  if (supervisor_ptr->pending_js_saves == 0) 
     1244  { 
     1245    ASSERT(supervisor_ptr->save_callback == NULL); 
     1246    ASSERT(callback != NULL); 
     1247    callback(context, success); 
     1248  } 
    10281249} 
    10291250 
  • daemon/app_supervisor.h

    r5483a52 rf42b4fb  
    3636#define LADISH_APP_STATE_KILL       3 /**< @brief app is being force killed */ 
    3737 
    38 #define MAX_LEVEL_CHARCOUNT 10  /* includes terminating nul char */ 
     38#define MAX_LEVEL_CHARCOUNT 12  /* includes terminating nul char */ 
    3939 
    4040/** 
     
    427427 
    428428/** 
    429  * Initiate save of app internal state. The app must be in started state. 
    430  * 
    431  * @param[in] app_handle Handle of app 
    432  */ 
    433 void ladish_app_save(ladish_app_handle app_handle); 
    434  
    435 /** 
    436429 * Initiate restore of app internal state. The app must be in started state. 
    437430 * 
  • daemon/loader.c

    r60aaa49 rf42b4fb  
    264264  const char * commandline, 
    265265  const char * working_dir, 
     266  const char * session_dir, 
    266267  bool run_in_terminal, 
    267268  const char * vgraph_name, 
     
    295296  { 
    296297    setenv("LADISH_PROJECT_NAME", project_name, true); 
     298  } 
     299 
     300  if (session_dir != NULL) 
     301  { 
     302    setenv("SESSION_DIR", session_dir, true); 
    297303  } 
    298304 
     
    522528  const char * app_name, 
    523529  const char * working_dir, 
     530  const char * session_dir, 
    524531  bool run_in_terminal, 
    525532  const char * commandline, 
     
    635642    set_ldpreload(); 
    636643 
    637     loader_exec_program(commandline, working_dir, run_in_terminal, vgraph_name, project_name, app_name); 
     644    loader_exec_program(commandline, working_dir, session_dir, run_in_terminal, vgraph_name, project_name, app_name); 
    638645 
    639646    return false;  /* We should never get here */ 
  • daemon/loader.h

    r99b1ab0 rf42b4fb  
    33 * LADI Session Handler (ladish) 
    44 * 
    5  * Copyright (C) 2009, 2010 Nedko Arnaudov <nedko@arnaudov.name> 
     5 * Copyright (C) 2009, 2010, 2011 Nedko Arnaudov <nedko@arnaudov.name> 
    66 * 
    77 ************************************************************************** 
     
    3636  const char * app_name, 
    3737  const char * working_dir, 
     38  const char * session_dir, 
    3839  bool run_in_terminal, 
    3940  const char * commandline, 
  • daemon/room_load.c

    r68716ee rf42b4fb  
    872872  XML_SetUserData(parser, &parse_context); 
    873873 
     874  ladish_app_supervisor_set_directory(room_ptr->app_supervisor, project_dir); 
     875  if (!ladish_app_supervisor_set_project_name(room_ptr->app_supervisor, room_ptr->project_name)) 
     876  { 
     877    ladish_app_supervisor_set_project_name(room_ptr->app_supervisor, NULL); 
     878  } 
     879 
    874880  xmls = XML_ParseBuffer(parser, bytes_read, XML_TRUE); 
    875881  if (xmls == XML_STATUS_ERROR && !parse_context.error) 
     
    886892  ladish_graph_dump(room_ptr->graph); 
    887893  ladish_app_supervisor_dump(room_ptr->app_supervisor); 
    888  
    889   ladish_app_supervisor_set_directory(room_ptr->app_supervisor, project_dir); 
    890   if (!ladish_app_supervisor_set_project_name(room_ptr->app_supervisor, room_ptr->project_name)) 
    891   { 
    892     ladish_app_supervisor_set_project_name(room_ptr->app_supervisor, NULL); 
    893   } 
    894894 
    895895  ladish_graph_trick_dicts(room_ptr->graph); 
  • gui/dialogs.c

    r4f7a90a rf42b4fb  
    5656  gtk_widget_set_sensitive(GTK_WIDGET(level1_button), TRUE); 
    5757  gtk_widget_set_sensitive(GTK_WIDGET(level2lash_button), TRUE); 
     58  gtk_widget_set_sensitive(GTK_WIDGET(level2js_button), is_room_view(view)); 
    5859 
    5960  gtk_window_set_focus(GTK_WINDOW(g_app_dialog), GTK_WIDGET(command_entry)); 
  • gui/gladish.ui

    re2b9461 rf42b4fb  
    12591259                <property name="group">app_level0</property> 
    12601260                <property name="receives_default">False</property> 
    1261                 <property name="sensitive">False</property> 
     1261                <property name="sensitive">True</property> 
    12621262                <property name="visible">True</property> 
    12631263              </object> 
  • gui/world_tree.c

    r4f7a90a rf42b4fb  
    268268  gtk_widget_set_sensitive(GTK_WIDGET(level1_button), !running); 
    269269  gtk_widget_set_sensitive(GTK_WIDGET(level2lash_button), !running); 
     270  gtk_widget_set_sensitive(GTK_WIDGET(level2js_button), !running && is_room_view(view)); 
    270271 
    271272  /* comparing pointers here is ok, because ladish_map_app_level_constant() was called by ladish_app_supervisor_get_app_properties() */