//------------------------------------------------------------------------------
// Pd Spectral Toolkit
//
// terminal.c
//
// Accepts a command line shell instruction and outputs the result
//
// Created by Cooper Baker on 3/29/12.
// Updated for 64 Bit Support in September 2019.
// Copyright (C) 2019 Cooper Baker. All Rights Reserved.
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// m_pd.h - main header for Pd
//------------------------------------------------------------------------------
#include "m_pd.h"
#include "stdio.h"
#include "string.h"
// utility header for Pd Spectral Toolkit project
#include "utility.h"
#define STRING_MAX 65535
//------------------------------------------------------------------------------
// terminal_class - pointer to this object's definition
//------------------------------------------------------------------------------
t_class* terminal_class;
//------------------------------------------------------------------------------
// terminal - data structure holding this object's data
//------------------------------------------------------------------------------
typedef struct terminal
{
// this object - must always be first variable in struct
t_object object;
// pointer to the outlet
t_outlet* outlet;
// character string to hold a terminal command
char* terminal_command[ 1024 ];
} t_terminal;
//------------------------------------------------------------------------------
// function prototypes
//------------------------------------------------------------------------------
char* terminal_itoa ( t_int number );
void terminal_parse ( t_terminal* object, t_symbol* selector, t_int items, t_atom* list );
void terminal_bang ( t_terminal* object );
void* terminal_new ( void );
void terminal_setup ( void );
//------------------------------------------------------------------------------
// terminal_itoa - converts integers to ascii strings
//------------------------------------------------------------------------------
char* terminal_itoa( t_int number )
{
t_int i = 0;
t_int j = 0;
t_int sign = number;
char character;
static char string[ STRING_MAX ];
// if number is negative
if( sign < 0 )
{
// make the number positive
number = -number;
}
// generate digits in reverse order
for( number = number ; number > 0 ; number /= 10 )
{
// calculate and store ascii values
string[ i ] = number % 10 + '0';
++i;
}
// if number is negative
if( sign < 0 )
{
// add the minus sign
string[ i++ ] = '-';
}
// null terminate the string
string[ i ] = '\0';
// reverse the string
for( i = 0, j = strlen( string ) - 1 ; i < j ; ++i, --j )
{
character = string[ i ];
string[ i ] = string[ j ];
string[ j ] = character;
}
// hand the string to the calling function
return string;
}
//------------------------------------------------------------------------------
// terminal_bang - causes status list output
//------------------------------------------------------------------------------
void terminal_bang( t_terminal* object )
{
// location of null terminator in each output string
t_int null_terminator;
// an os FILE pointer for the pipe
FILE* terminal_pipe;
// string to hold what comes out of the pipe
char output[ STRING_MAX ];
// open a "read" pipe and send it the object's command
terminal_pipe = popen( ( char* )object->terminal_command, "r" );
// move through the output to its end
while( fgets( output, STRING_MAX, terminal_pipe ) != NULL )
{
// find the null terminator location
null_terminator = strchr( output, '\n' ) - output;
// remove the null terminator
output[ null_terminator ] = 0;
// send the output out the object's outlet
outlet_anything( object->outlet, gensym( output ), 0, NULL );
}
// close the pipe
pclose( terminal_pipe );
}
//------------------------------------------------------------------------------
// terminal_parse - parses list input
//------------------------------------------------------------------------------
void terminal_parse( t_terminal* object, t_symbol* selector, t_int items, t_atom* list )
{
// index to keep track of position in input list
t_int item_index = 0;
// clear out the last command
memset( object->terminal_command, 0, 1024 * sizeof( char ) );
// copy the first word into the command string
strcpy( ( char* )object->terminal_command, selector->s_name );
// iterate through the input mesage list
for( item_index = 0 ; item_index < items ; ++item_index )
{
// if the list item is a symbol
if( list[ item_index ].a_type == A_SYMBOL )
{
// first add a space then copy the item into the command string
strcat( ( char* )object->terminal_command, " " );
strcat( ( char* )object->terminal_command, list[ item_index ].a_w.w_symbol->s_name );
}
// if the list item is a float
else if( list[ item_index ].a_type == A_FLOAT )
{
// first add a space then copy the item into the command string
strcat( ( char* )object->terminal_command, " " );
strcat( ( char* )object->terminal_command, terminal_itoa( list[ item_index ].a_w.w_float ) );
}
}
// call bang to trigger output
terminal_bang( object );
}
//------------------------------------------------------------------------------
// terminal_new - initialize the object upon instantiation ( aka "constructor" )
//------------------------------------------------------------------------------
void* terminal_new( void )
{
// declare a pointer to this class
t_terminal* object;
// generate a new object and save its pointer in "object"
object = ( t_terminal* )pd_new( terminal_class );
// create an outlet for anything
object->outlet = outlet_new( &object->object, gensym( "anything" ) );
// return the pointer to this class
return ( void* )object;
}
//------------------------------------------------------------------------------
// terminal setup - defines this object and its properties to Pd
//------------------------------------------------------------------------------
void terminal_setup( void )
{
// create a new class and assign its pointer to terminal_class
terminal_class = class_new( gensym( "terminal" ), ( t_newmethod )terminal_new, 0, sizeof( t_terminal ), 0, 0 );
// add message handler, responding to any message
class_addmethod( terminal_class, ( t_method )terminal_parse, gensym( "anything" ), A_GIMME, 0 );
// add bang handler
class_addbang( terminal_class, ( t_method )terminal_bang );
}
//------------------------------------------------------------------------------
// EOF
//------------------------------------------------------------------------------
// Pd Spectral Toolkit
//
// terminal.c
//
// Accepts a command line shell instruction and outputs the result
//
// Created by Cooper Baker on 3/29/12.
// Updated for 64 Bit Support in September 2019.
// Copyright (C) 2019 Cooper Baker. All Rights Reserved.
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// m_pd.h - main header for Pd
//------------------------------------------------------------------------------
#include "m_pd.h"
#include "stdio.h"
#include "string.h"
// utility header for Pd Spectral Toolkit project
#include "utility.h"
#define STRING_MAX 65535
//------------------------------------------------------------------------------
// terminal_class - pointer to this object's definition
//------------------------------------------------------------------------------
t_class* terminal_class;
//------------------------------------------------------------------------------
// terminal - data structure holding this object's data
//------------------------------------------------------------------------------
typedef struct terminal
{
// this object - must always be first variable in struct
t_object object;
// pointer to the outlet
t_outlet* outlet;
// character string to hold a terminal command
char* terminal_command[ 1024 ];
} t_terminal;
//------------------------------------------------------------------------------
// function prototypes
//------------------------------------------------------------------------------
char* terminal_itoa ( t_int number );
void terminal_parse ( t_terminal* object, t_symbol* selector, t_int items, t_atom* list );
void terminal_bang ( t_terminal* object );
void* terminal_new ( void );
void terminal_setup ( void );
//------------------------------------------------------------------------------
// terminal_itoa - converts integers to ascii strings
//------------------------------------------------------------------------------
char* terminal_itoa( t_int number )
{
t_int i = 0;
t_int j = 0;
t_int sign = number;
char character;
static char string[ STRING_MAX ];
// if number is negative
if( sign < 0 )
{
// make the number positive
number = -number;
}
// generate digits in reverse order
for( number = number ; number > 0 ; number /= 10 )
{
// calculate and store ascii values
string[ i ] = number % 10 + '0';
++i;
}
// if number is negative
if( sign < 0 )
{
// add the minus sign
string[ i++ ] = '-';
}
// null terminate the string
string[ i ] = '\0';
// reverse the string
for( i = 0, j = strlen( string ) - 1 ; i < j ; ++i, --j )
{
character = string[ i ];
string[ i ] = string[ j ];
string[ j ] = character;
}
// hand the string to the calling function
return string;
}
//------------------------------------------------------------------------------
// terminal_bang - causes status list output
//------------------------------------------------------------------------------
void terminal_bang( t_terminal* object )
{
// location of null terminator in each output string
t_int null_terminator;
// an os FILE pointer for the pipe
FILE* terminal_pipe;
// string to hold what comes out of the pipe
char output[ STRING_MAX ];
// open a "read" pipe and send it the object's command
terminal_pipe = popen( ( char* )object->terminal_command, "r" );
// move through the output to its end
while( fgets( output, STRING_MAX, terminal_pipe ) != NULL )
{
// find the null terminator location
null_terminator = strchr( output, '\n' ) - output;
// remove the null terminator
output[ null_terminator ] = 0;
// send the output out the object's outlet
outlet_anything( object->outlet, gensym( output ), 0, NULL );
}
// close the pipe
pclose( terminal_pipe );
}
//------------------------------------------------------------------------------
// terminal_parse - parses list input
//------------------------------------------------------------------------------
void terminal_parse( t_terminal* object, t_symbol* selector, t_int items, t_atom* list )
{
// index to keep track of position in input list
t_int item_index = 0;
// clear out the last command
memset( object->terminal_command, 0, 1024 * sizeof( char ) );
// copy the first word into the command string
strcpy( ( char* )object->terminal_command, selector->s_name );
// iterate through the input mesage list
for( item_index = 0 ; item_index < items ; ++item_index )
{
// if the list item is a symbol
if( list[ item_index ].a_type == A_SYMBOL )
{
// first add a space then copy the item into the command string
strcat( ( char* )object->terminal_command, " " );
strcat( ( char* )object->terminal_command, list[ item_index ].a_w.w_symbol->s_name );
}
// if the list item is a float
else if( list[ item_index ].a_type == A_FLOAT )
{
// first add a space then copy the item into the command string
strcat( ( char* )object->terminal_command, " " );
strcat( ( char* )object->terminal_command, terminal_itoa( list[ item_index ].a_w.w_float ) );
}
}
// call bang to trigger output
terminal_bang( object );
}
//------------------------------------------------------------------------------
// terminal_new - initialize the object upon instantiation ( aka "constructor" )
//------------------------------------------------------------------------------
void* terminal_new( void )
{
// declare a pointer to this class
t_terminal* object;
// generate a new object and save its pointer in "object"
object = ( t_terminal* )pd_new( terminal_class );
// create an outlet for anything
object->outlet = outlet_new( &object->object, gensym( "anything" ) );
// return the pointer to this class
return ( void* )object;
}
//------------------------------------------------------------------------------
// terminal setup - defines this object and its properties to Pd
//------------------------------------------------------------------------------
void terminal_setup( void )
{
// create a new class and assign its pointer to terminal_class
terminal_class = class_new( gensym( "terminal" ), ( t_newmethod )terminal_new, 0, sizeof( t_terminal ), 0, 0 );
// add message handler, responding to any message
class_addmethod( terminal_class, ( t_method )terminal_parse, gensym( "anything" ), A_GIMME, 0 );
// add bang handler
class_addbang( terminal_class, ( t_method )terminal_bang );
}
//------------------------------------------------------------------------------
// EOF
//------------------------------------------------------------------------------