Logo Search packages:      
Sourcecode: ladcca version File versions  Download package

ladcca_control.c

/*
 *   LADCCA 
 *    
 *   Copyright (C) 2002 Robert Ham <rah@bash.sh>
 *    
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the Free Software
 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#define _GNU_SOURCE

#include "ac-config.h"

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <unistd.h>

#undef HAVE_CONFIG_H

#ifdef HAVE_LIBREADLINE
#  if defined(HAVE_READLINE_READLINE_H)
#    include <readline/readline.h>
#  elif defined(HAVE_READLINE_H)
#    include <readline.h>
#  else /* !defined(HAVE_READLINE_H) */
extern char *readline ();
#  endif /* !defined(HAVE_READLINE_H) */
char *cmdline = NULL;
#else /* !defined(HAVE_READLINE_READLINE_H) */
/* no readline */
#endif /* HAVE_LIBREADLINE */

#ifdef HAVE_READLINE_HISTORY
#  if defined(HAVE_READLINE_HISTORY_H)
#    include <readline/history.h>
#  elif defined(HAVE_HISTORY_H)
#    include <history.h>
#  else /* !defined(HAVE_HISTORY_H) */
extern void add_history ();
extern int write_history ();
extern int read_history ();
#  endif /* defined(HAVE_READLINE_HISTORY_H) */
/* no history */
#endif /* HAVE_READLINE_HISTORY */


#include <ladcca/ladcca.h>
#include <ladcca/debug.h>

#include "ladcca_control.h"
#include "client.h"

void
ladcca_control_init (ladcca_control_t * control)
{
  control->cur_project = NULL;
  control->client = NULL;
  control->projects = NULL;
  
  rl_initialize ();
  rl_prep_terminal (1); 
}

void
ladcca_control_free (ladcca_control_t * control)
{
  cca_list_t * node;

  for (node = control->projects; node; node = cca_list_next (node))
    project_destroy ((project_t *) node->data);

  cca_list_free (control->projects);
  
  rl_deprep_terminal ();
}

static void
command_help ()
{
  printf ("\n");
  printf ("  list              List projects\n");
  printf ("  project <name>    Select the project with name <name>\n");
  printf ("  dir <dir>         Set the selected project's directory to <dir>\n");
  printf ("  name <name>       Set the selected project's name to <name>\n");
  printf ("  remove <client>   Remove <client> from the selected project\n");
  printf ("  save              Save the selected project\n");
  printf ("  restore <dir>     Restore a project from <dir>\n");
  printf ("  close             Close the selected project\n");
/*  printf ("  tar  <tarball>    Pack the selected project into <tarball>\n");
  printf ("  untar <tarball>   Unpack and restore a project from <tarball>\n");*/ 
  printf ("  quit              Exit the program\n");
  printf ("\n");
  printf ("  It is only necessary to type enough characters of a command to\n");
  printf ("  disambiguate it from any other command\n");
  printf ("\n");
}

static void
command_list (ladcca_control_t * control)
{
  cca_list_t * pnode, * clnode;
  project_t * project;
  client_t * client;
  char client_jack_str[64];
  char client_alsa_str[32];
  
  if (!control->projects)
    {
      printf ("  No projects\n");
      return;
    }

  for (pnode = control->projects; pnode; pnode = cca_list_next (pnode))
    {
      project = (project_t *) pnode->data;

      printf ("  %s in directory %s, %s\n",
            project->name,
            project->dir,
            project->clients ? "clients:" : "no clients");

      for (clnode = project->clients; clnode; clnode = cca_list_next (clnode))
      {
        client = (client_t *) clnode->data;

        if (!client->alsa_client_id)
          client_alsa_str[0] = '\0';
        else
          sprintf (client_alsa_str, ", ALSA client ID: %u", (unsigned int) client->alsa_client_id);

        if (!client->jack_client_name)
          client_jack_str[0] = '\0';
        else
          sprintf (client_jack_str, ", JACK client name: %s", client->jack_client_name);

        printf ("    %s%s%s\n", client_get_identity (client), client_jack_str, client_alsa_str);
      }
    }
}

static void
command_project (ladcca_control_t * control, char * arg)
{
  cca_list_t * node;
  project_t * project;
  
  if (!arg || !strlen(arg))
    {
      if (control->cur_project)
        printf ("  Selected project: %s\n", control->cur_project->name);
      else
        printf ("  No project selected\n");
      return;
    }
  
  for (node = control->projects; node; node = cca_list_next (node))
    {
      project = (project_t *) node->data;

      if (strcmp (project->name, arg) == 0)
      {
        control->cur_project = project;
        return;
      }
    }
  
  printf ("  Unknown project '%s'\n", arg);
}

static void
command_dir (ladcca_control_t * control, char * arg)
{
  cca_event_t * event;
  size_t len;
  
  if (!control->cur_project)
    {
      printf ("  No project selected\n");
      return; 
    }

  if (!arg)
    {
      printf ("  %s\n", control->cur_project->dir);
      return;
    }

  len = strlen (arg);
  if (arg[len - 1] == '/')
    arg[len - 1] = '\0';

  event = cca_event_new_with_type (CCA_Project_Dir);
  cca_event_set_project (event, control->cur_project->name);
  cca_event_set_string (event, arg);
  cca_send_event (control->client, event);

  printf ("  Told server to change directory to %s\n", arg);
}

static void
command_remove (ladcca_control_t * control, char * arg)
{
  cca_event_t * event;
  cca_list_t * node;
  client_t * client;
  
  if (!control->cur_project)
    {
      printf ("  No project selected\n");
      return; 
    }

  if (!arg)
    {
      printf ("  Command requires an argument\n");
      return;
    }

  for (node = control->cur_project->clients; node; node = cca_list_next (node))
    {
      client = (client_t *) node->data;

      if (strcmp (client_get_identity (client), arg) == 0)
      break;
    }

  if (!node)
    {
      printf ("  Unknown client '%s' in project\n", arg);
      return;
    }

  
  event = cca_event_new_with_type (CCA_Client_Remove);
  cca_event_set_project (event, control->cur_project->name);
  cca_event_set_client_id (event, client->id);
  cca_send_event (control->client, event);


  printf ("  Told server to remove client '%s'\n", arg);
}

static void
command_restore (ladcca_control_t * control, char * arg)
{
  cca_event_t * event;
  
  if (!arg)
    {
      printf ("  Command requires an argument\n");
      return;
    }
  
  event = cca_event_new_with_type (CCA_Project_Add);
  cca_event_set_string (event, arg);
  cca_send_event (control->client, event);

  printf ("  Told server to restore project in dir '%s'\n", arg);
}

static void
command_name (ladcca_control_t * control, char * arg)
{
  cca_event_t * event;
  
  if (!control->cur_project)
    {
      printf ("  No project selected\n");
      return; 
    }
      
  if (!arg)
    {
      printf ("  Command requires an argument\n");
      return;
    }
  
  event = cca_event_new ();
  cca_event_set_type (event, CCA_Project_Name);
  cca_event_set_project (event, control->cur_project->name);
  cca_event_set_string (event, arg);
  cca_send_event (control->client, event);

  printf ("  Told server to set project name to '%s'\n", arg);
}

static void
command_save (ladcca_control_t * control)
{
  cca_event_t * event;
  
  if (!control->cur_project)
    {
      printf ("  No project selected\n");
      return;
    }

  event = cca_event_new_with_type (CCA_Save);
  cca_event_set_project (event, control->cur_project->name);
  cca_send_event (control->client, event);

  printf ("  Told server to save project\n");
}

static void
command_close (ladcca_control_t * control)
{
  cca_event_t * event;
  
  if (!control->cur_project)
    {
      printf ("  No project selected\n");
      return;
    }

  event = cca_event_new_with_type (CCA_Project_Remove);
  cca_event_set_project (event, control->cur_project->name);
  cca_send_event (control->client, event);

  printf ("  Told server to close project\n");
}

static int
deal_with_command (ladcca_control_t * control, char * command)
{
  char * ptr;
  char * arg;

  while (isspace (*command))
    command++;
  
  arg = strchr (command, ' ');
  if (arg)
    {
      while (isspace (*arg) && *arg != '\0')
      arg++;

      if (*arg == '\0')
      arg = NULL;
    }
    
  if (strncasecmp (command, "help", 1) == 0)
    {
      command_help ();
      return 0;
    }
  
  if (strncasecmp (command, "list", 1) == 0)
    {
      command_list (control);
      return 0;
    }
  
  if (strncasecmp (command, "project", 1) == 0)
    {
      command_project (control, arg);
      return 0;
    }

  if (strncasecmp (command, "dir", 1) == 0)
    {
      command_dir (control, arg);
      return 0;
    }

  if (strncasecmp (command, "name", 1) == 0)
    {
      command_name (control, arg);
      return 0;
    }

  if (strncasecmp (command, "remove", 3) == 0)
    {
      command_remove (control, arg);
      return 0;
    }

  
  if (strncasecmp (command, "save", 1) == 0)
    {
      command_save (control);
      return 0;
    }

  if (strncasecmp (command, "restore", 3) == 0)
    {
      command_restore (control, arg);
      return 0;
    }

  if (strncasecmp (command, "close", 1) == 0)
    {
      command_close (control);
      return 0;
    }

  if (strncasecmp (command, "quit", 1) == 0)
    {
      return 1;
    }
  
  ptr = strchr (command, ' ');
  if (ptr)
    *ptr = '\0';
  printf ("unknown command '%s'\n", command);
  if (ptr)
    *ptr = ' ';

  return 0;
}

static void
deal_with_events (ladcca_control_t * control)
{
  cca_event_t * event;
  const char * event_str;
  project_t * project;
  client_t * client;
  uuid_t client_id;
  cca_list_t * node, * clnode;

  if (cca_get_pending_event_count (control->client) == 0)
    return;

  while ( (event = cca_get_event (control->client)) )
    {
      event_str = cca_event_get_string (event);


      if (cca_event_get_project (event))
      {
        for (node = control->projects; node; node = cca_list_next (node))
          {
            project = (project_t *) node->data;

            if (strcmp (project->name, cca_event_get_project (event)) == 0)
            break;
            else
            project = NULL;
          }
      }
      else
      project = NULL;


      cca_event_get_client_id (event, client_id);
      if (!uuid_is_null (client_id) && cca_event_get_type (event) != CCA_Client_Add)
      {
        for (node = control->projects; node; node = cca_list_next (node))
          for (clnode = ((project_t *)node->data)->clients; clnode; clnode = cca_list_next (clnode))
            {
            client = (client_t *) clnode->data;

            if (uuid_compare (client->id, client_id) == 0)
              break;
            else
              client = NULL;
            }

        if (!client)
          {
            char id[37];
            uuid_unparse (client_id, id);
            printf ("unknown client %s\n", id);
            continue;
          }
      }
      else
      client = NULL;


      switch (cca_event_get_type (event))
      {
      case CCA_Project_Dir:
        printf ("* Project '%s' changed to directory %s\n", project->name, event_str);
        project_set_dir (project, event_str);
        break;

      case CCA_Project_Name:
        printf ("* Project '%s' changed name to '%s'\n", project->name, event_str);
        project_set_name (project, event_str);
        break;

      case CCA_Project_Add:
        printf ("* New project '%s'\n", event_str);
        control->projects = cca_list_append (control->projects, project_new (event_str));
        break;

      case CCA_Project_Remove:
        printf ("* Project '%s' removed\n", project->name);
        control->projects = cca_list_remove (control->projects, project);
        if (control->cur_project == project)
          control->cur_project = NULL;
        project_destroy (project);
        break;

      case CCA_Client_Add:
        client = client_new ();
        cca_event_get_client_id (event, client->id);
        printf ("* New client '%s' in project '%s'\n", client_get_identity (client), project->name);
        project->clients = cca_list_append (project->clients, client);
        break;

      case CCA_Client_Remove:
        printf ("* Client '%s' removed from project '%s'\n", client_get_identity (client), project->name);
        project->clients = cca_list_remove (project->clients, client);
        client_destroy (client);
        break;

        /*  case CCA_Client_Project:
        {
          project_t * new_project;

          printf ("* Client '%s' moved from project '%s' to project '%s'\n",
                client_get_identity (client), project->name, event_str);

          for (node = control->projects; node; node = cca_list_next (node))
            {
            new_project = (project_t *) node->data;

            if (strcmp (new_project->name, event_str) == 0)
              break;
            else
              new_project = NULL;
            }

          if (!new_project)
            {
            fprintf (stderr, "Unknown project '%s'; cannot move client", event_str);
            break;
            }

          new_project->clients = cca_list_append (new_project->clients, client);
          project->clients = cca_list_remove (project->clients, client);
          break;
          } */

      case CCA_Client_Name:
        printf ("* Client '%s' changed its name to '%s'\n",
              client_get_identity (client),
              event_str);
        client_set_name (client, event_str);
        break;

      case CCA_Jack_Client_Name:
        printf ("* Client '%s' set its JACK client name to '%s'\n",
              client_get_identity (client), event_str);
        client_set_jack_client_name (client, event_str);
        break;

      case CCA_Alsa_Client_ID:
        printf ("* Client '%s' set its ALSA client ID to '%u'\n",
              client_get_identity (client), cca_str_get_alsa_client_id (event_str));
        client->alsa_client_id = cca_str_get_alsa_client_id (event_str);
        break;

      case CCA_Server_Lost:
        printf ("* Server connection lost\n");
        exit (0);
        break;

      case CCA_Percentage:
        if (strcmp (event_str, "0") == 0)
          {
            if (project->saving)
            {
              printf ("* Operation complete\n");
              project->saving = 0;
            }
            else
            {
              printf ("* Operation commencing\n");
              project->saving = 1;
            }
          }
        else
          printf ("* Operation %s%% complete\n", event_str);
        break;
      }

      cca_event_destroy (event);
    }
}

void
ladcca_control_main (ladcca_control_t * control)
{
  char * prompt;
  size_t prompt_size = 32;
  size_t project_prompt_size;
  char * command;
  int done = 0;
  
  prompt = cca_malloc (prompt_size);
  
  printf ("\nLADCCA Control %s\n", PACKAGE_VERSION);
  printf ("\nConnected to server %s\n\n", cca_get_server_name (control->client));
  
  while (!done)
    {
      if (control->cur_project)
        {
        project_prompt_size = strlen (control->cur_project->name) + 4;

          if (project_prompt_size > prompt_size)
          {
            prompt_size = project_prompt_size;
            prompt = cca_realloc (prompt, prompt_size);
          }
          
          sprintf (prompt, "%s > ", control->cur_project->name);
        }
      else
        sprintf (prompt, "(no project) > ");
      
      command = readline (prompt);
      
      if (!command)
        {
          printf("\n");
          return;
        }
      
      deal_with_events (control);

      if (strlen (command))
        {
          done = deal_with_command (control, command);
          
#ifdef HAVE_READLINE_HISTORY
          add_history (command);
#endif
        }
      
      free (command);
    }
  
}


/* EOF */



Generated by  Doxygen 1.6.0   Back to index