1\documentclass{article} 2\usepackage[T1]{fontenc} 3\usepackage{ae} 4 5%\usepackage{html} 6%\bodytext{link="#662a00" vlink="#666655" bgcolor="#ffffff"} 7 8\title{Ecasound Control Interface Guide} 9\author{Kai Vehmanen, Brad Bowman, Tony Leake, Jan Weil, Mario Lang} 10\date{03062006} 11\begin{document} 12 13\maketitle 14\tableofcontents 15\clearpage 16 17% ---------------------------------------------------------------------- 18% ---------------------------------------------------------------------- 19\section{Introduction} 20The idea behind the Ecasound Control Interface (ECI) is to take a subset of 21functionality provided by libecasound, provide a simple API for it, and 22port it to various languages. At the moment, implementations of the 23ECI API are available for C, C++, elisp, Python and Ruby. These all 24come by default with the Ecasound package. Additional implementations, 25for example for Perl and PHP, are distributed independently. 26 27ECI is heavily based on Ecasound's interactive mode (EIAM), and the 28services it provides. See \texttt{ecasound-iam(1) manual page} for 29a detailed EIAM documentation. 30 31% ---------------------------------------------------------------------- 32% ---------------------------------------------------------------------- 33\section{Document history} 34\begin{itemize} 35\item 04.06.2006 - Added more information to the ``Tips for debugging'' section. 36\item 21.03.2005 - Updated the ``Tips for debugging'' section. 37\item 25.09.2004 - Updated the ``Return values'' section based on feedback 38 from Adam Linson. 39\item 02.05.2004 - ``Emacs'' section added (written by Mario Lang). 40\item 28.11.2003 - ``Ruby'' section added (written by Jan Weil). 41 Updated the introduction. 42\item 26.11.2003 - Fix filename for the alternative Python API (eci.py). 43\item 18.11.2003 - Typo fixes. Updated documentation to reflect the new 44 naming convention (ecasound refers to the binary, 45 Ecasound refers to the whole package). 46\item 26.10.2002 - Changed the C++ linking example. 47\item 24.10.2002 - Added ``Notes Concerning Standalone ECI Implementations'' 48 section. Added compilation examples. 49\item 06.10.2002 - Added ``Application development'' section. 50\item 05.10.2002 - Changed the libecasoundc link path. 51\item 29.09.2002 - ``PHP'' section added (written by Tony Leake). 52\item 25.04.2002 - Changed headers path from ``<ecasoundc/file.h>'' to 53 ``<file.h>'' and added library version number to 54 link instructions. 55\item 21.10.2001 - Added this history section. Minor changes to 56 ECI examples. 57\end{itemize} 58 59% ---------------------------------------------------------------------- 60% ---------------------------------------------------------------------- 61\section{General} 62ECI doesn't provide any routines that directly manipulate audio or 63Ecasound objects. What it does provide is an easy and generic way 64to issue EIAM (Ecasound Inter-Active Mode) commands, access the 65command return-values and perform error handling. 66 67This approach has two benefits. First, it is possible to keep the API 68small, and thus make it easier to port ECI to new languages. Secondly, 69it's possible to keep ECI relatively stable. Ecasound itself is a large, 70developing library. New features are added all the time, and from time 71to time, older parts of the library will get rewritten to better suit 72new uses. Now for application developers wanting to take advantage of 73libecasound, these constant changes are very annoying, especially if 74your specific app doesn't need the latest new features. In these 75cases, ECI is the best platform for application development. 76 77 78% ---------------------------------------------------------------------- 79\subsection{What's it good for?} 80 81Specific tasks ECI is aimed at: 82 83\begin{itemize} 84\item 1. automating (scripting in its traditional sense) 85\item 2. frontends (generic / specialized) 86\item 3. sound services to other apps 87\end{itemize} 88 89 90% ---------------------------------------------------------------------- 91\subsection{Services and behaviour} 92 93Here is a list of services provided by all ECI implementations: 94 95\subsubsection{Actions} 96\begin{description} 97\item[command(string)] 98Issue an EIAM command. 99 100\item[command\_float\_arg(string, float)] 101Issue an EIAM command. This function can be used instead of 102\emph{command(string)}, if the command in question requires exactly one 103numerical parameter. This way it's possible to avoid the extra 104string -> float conversion, which would lead to lost precision. 105\end{description} 106 107\subsubsection{Return values} 108Each EIAM command has exactly one return value type. After a command 109has been issued, only one last\_type() functions returns a non-empty 110value. For example, last\_float() only returns a valid value if 111\emph{last\_type() == 'f'} holds true. Not all EIAM commands return 112a value (return type is void). 113 114\begin{description} 115\item[last\_string()] 116Returns the last string return value. 117 118\item[last\_string\_list()] 119Returns the last collection of strings (one or more strings). 120 121\item[last\_float()] 122Returns the last floating-point return value. Note! last\_float() 123doesn't refer to the C/C++ type 'float'. In most implementations, 124floats are 64bit values (doubles in C/C++). 125 126\item[last\_integer()] 127Returns the last integer return value. This function is also 128used to return boolean values, where non-zero means 'true' 129and zero 'false'. 130 131\item[last\_long\_integer()] 132Returns the last long integer return value. Long integers are 133used to pass values like 'length\_in\_samples' and 'length\_in\_bytes'. 134It's implementation specific whether there's any real difference 135between integers and long integers. 136\end{description} 137 138\subsubsection{Errors} 139\begin{description} 140\item[error()] 141Returns true (!= 0) if error has occured during the execution 142of last EIAM command. Otherwise returns false (= 0). 143 144\item[last\_error()] 145Returns a string describing the last error. If the last EIAM command 146was executed successfully, last\_error() returns an empty string. 147 148\end{description} 149 150\subsubsection{Other} 151\begin{description} 152\item[initialize()] 153Reserve resources. 154 155\item[cleanup()] 156Free all reserved resources. 157\end{description} 158 159 160 161% ---------------------------------------------------------------------- 162\subsection{Porting to new environments} 163Porting ECI to new languages should be easy. All there is to do is 164to implement the services listed in the previous section to the target 165language. In most cases it's to easiest to use the C++ or C ECI 166as the underlying implementation to build upon. 167 168 169 170% ---------------------------------------------------------------------- 171% ---------------------------------------------------------------------- 172\section{Implementations} 173 174 175% ---------------------------------------------------------------------- 176\subsection{General} 177 178\subsubsection{Overview} 179This section contains overview of how ECI is implemented in the 180discussed language (eg. as a single class, set of classes, set of 181routines, etc). 182 183\subsubsection{Usage} 184A quick tutorial to get you started. 185 186\subsubsection{Example} 187Implementation of the following: 188\begin{enumerate} 189\item Setup ECI to read audio from file, apply a 100Hz lowpass filter, and 190 send it to the soundcard (/dev/dsp). 191\item Every second, check the current position. If the stream has 192 been running for over 15 seconds, exit immediately. Also, 193 every second, increase the lowpass filter's cutoff frequency 194 by 500Hz. 195\item Stop the stream (if not already finished) and disconnect the 196 chainsetup. Print chain operator status info. 197\end{enumerate} 198 199 200% ---------------------------------------------------------------------- 201\subsection{Notes Concerning Standalone ECI Implementations} 202 203The C implementation of ECI is not directly linked against the main 204Ecasound libraries. Instead, the ecasound executable is launched 205on the background and command pipes are used to communicate with it. 206 207The launched ecasound executable can be selected by using the 208\emph{ECASOUND} environment variable. If it is not defined, 209the C ECI implementation will try to launch ``ecasound'' (ie. 210has to be somewhere in PATH). 211 212In addition to the C implementation, this also affects all 213ECI implementations that are based on the C version. Currently 214this includes at least the Perl, PHP and Python ECI modules. 215 216% ---------------------------------------------------------------------- 217\subsection{C++} 218\subsubsection{Overview} 219C++ implementation is based around the ECA\_CONTROL\_INTERFACE class. 220STL vector is used for representing collections of objects 221(last\_string\_list()). 222 223\subsubsection{Usage} 224\begin{enumerate} 225\item \#include <eca-control-interface.h> 226\item create an instance of the ECA\_CONTROL\_INTERFACE class 227 and use its member functions 228\item link you app agains libecasoundc (-lecasoundc) 229\item compilation example: \emph{c++ -o ecidoc\_example ecidoc\_example.cpp `libecasoundc-config --cflags --libs`} 230\end{enumerate} 231 232\subsubsection{Example} 233\begin{verbatim} 234 235#include <iostream> 236#include <unistd.h> 237#include <eca-control-interface.h> 238 239int main(int argc, char *argv[]) 240{ 241 double cutoff_inc = 500.0; 242 243 ECA_CONTROL_INTERFACE e; 244 e.command("cs-add play_chainsetup"); 245 e.command("c-add 1st_chain"); 246 e.command("ai-add some_file.wav"); 247 e.command("ao-add /dev/dsp"); 248 e.command("cop-add -efl:100"); 249 e.command("cop-select 1"); 250 e.command("copp-select 1"); 251 e.command("cs-connect"); 252 e.command("start"); 253 while(1) { 254 sleep(1); 255 e.command("engine-status"); 256 if (e.last_string() != "running") break; 257 e.command("get-position"); 258 double curpos = e.last_float(); 259 if (curpos > 15.0) break; 260 e.command("copp-get"); 261 double next_cutoff = cutoff_inc + e.last_float(); 262 e.command_float_arg("copp-set", next_cutoff); 263 } 264 265 e.command("stop"); 266 e.command("cs-disconnect"); 267 e.command("cop-status"); 268 cerr << "Chain operator status: " << e.last_string() << endl; 269 270 return(0); 271} 272 273\end{verbatim} 274 275% ---------------------------------------------------------------------- 276\subsection{C} 277\subsubsection{Overview} 278All C ECI functions are prefixed with "eci\_". When returning string 279values, a const pointer to a null-terminated char array (const char*) 280is returned. It's important to keep in mind that these are "borrowed" 281references. If you need to later use the data, you must copy 282it to application's own buffers. 283 284Returning a list of strings is implemented using two functions: 285\emph{eci\_last\_string\_list\_count()} returns the number of strings 286available, and \emph{eci\_last\_string\_list\_item(int n)} returns a 287pointer (const char*) to the string at index \emph{n}. 288 289\emph{Note!} As of Ecasound 2.0.1, the C ECI implementation also 290 provides reentrant access to the ECI API. These 291 alternative routines are marked with '\_r' postfix. 292 293\subsubsection{Usage} 294 295\begin{enumerate} 296\item \#include <ecasoundc.h> 297\item use the eci\_* routines 298\item link your app against libecasoundc (-lecasoundc) 299\item compilation example: \emph{gcc -o ecidoc\_example ecidoc\_example.c `libecasoundc-config --cflags --libs`} 300\end{enumerate} 301 302\subsubsection{Example} 303\begin{verbatim} 304 305#include <stdio.h> 306#include <unistd.h> 307#include <ecasoundc.h> 308 309int main(int argc, char *argv[]) 310{ 311 double cutoff_inc = 500.0; 312 313 eci_init(); 314 eci_command("cs-add play_chainsetup"); 315 eci_command("c-add 1st_chain"); 316 eci_command("ai-add some_file.wav"); 317 eci_command("ao-add /dev/dsp"); 318 eci_command("cop-add -efl:100"); 319 eci_command("cop-select 1"); 320 eci_command("copp-select 1"); 321 eci_command("cs-connect"); 322 eci_command("start"); 323 324 while(1) { 325 double curpos, next_cutoff; 326 327 sleep(1); 328 eci_command("engine-status"); 329 if (strcmp(eci_last_string(), "running") != 0) break; 330 eci_command("get-position"); 331 curpos = eci_last_float(); 332 if (curpos > 15.0) break; 333 eci_command("copp-get"); 334 next_cutoff = cutoff_inc + eci_last_float(); 335 eci_command_float_arg("copp-set", next_cutoff); 336 } 337 338 eci_command("stop"); 339 eci_command("cs-disconnect"); 340 eci_command("cop-status"); 341 printf("Chain operator status: %s", eci_last_string()); 342 eci_cleanup(); 343 344 return(0); 345} 346 347\end{verbatim} 348 349% ---------------------------------------------------------------------- 350\subsection{Emacs} 351\subsubsection{Overview} 352The Ecasound package comes with an 'Ecasound' library for Emacs included. 353ecasound.el is a implementation of the ECI API for Emacs, as well 354as an interactive interface to Ecasound sessions implemented 355on top of that. Simply use "M-x ecasound RET" to fire up an 356interactive Ecasound session. 357 358All Emacs Lisp ECI functions are prefixed with ``eci\-''. 359'ecasound.el' is implemented in a high level manner which means 360that you won't find most of the commands known from libecasoundc like 361last\_string, last\_float, etc. 362Instead of that every call to function "eci-command", which accepts all 363the well known IAM commands, returns ecasound's response in an appropriate type 364automatically. 365If an error occurs, e. g. there's a typo in a command or a file is not found, 366the function returns ``nil''. In all other cases, either an automatically 367converted Lisp value is returned, or ``t'' in the case where there was no 368particular value returned. 369 370Additionally, most of the available IAM commands have their own Emacs Lisp 371function including documentation and possibly a parameter list. All these 372functions are interactive, so you can use them in ecasound-iam-mode simply 373by invoking them via M-x or by pressing an assigned key combination. 374Emacs will prompt you for the required parameters, providing completion 375wherever possible. 376 377As a convention, "eci-command" and its variants do take a buffer or process 378as an optional last argument. If this is ``nil'', the current 379buffer is assumed to be the ecasound session refered to by this call. 380This makes it possible to use several ECI sessions concurrently, dispatching 381on the buffer or process in use. 382 383\subsubsection{Usage} 384\begin{enumerate} 385\item make ecasound.el available in your ``load-path'' 386\item (require 'ecasound) 387\item create a buffer with an associated Ecasound session (``eci-init'') 388\item use ``eci\-'' functions with the new buffer 389\end{enumerate} 390 391\subsubsection{Example} 392\begin{verbatim} 393(require 'ecasound) 394 395(defun example (file &optional cutoff-increment session) 396 (unless cutoff-increment (setq cutoff-increment 500.0)) 397 (with-current-buffer (or session (eci-init)) 398 (eci-cs-add "play_chainsetup") 399 (eci-c-add "1st_chain") 400 (eci-ai-add file) 401 (eci-ao-add "/dev/dsp") 402 (eci-cop-add "-efl:100") 403 (eci-cop-select 1) 404 (eci-copp-select 1) 405 (eci-cs-connect) 406 (eci-start) 407 (sit-for 1) 408 (while (and (string= (eci-engine-status) "running") 409 (<= (eci-get-position) 15)) 410 (eci-copp-set (+ cutoff-increment (eci-copp-get))) 411 (sit-for 1)) 412 (eci-command "stop") 413 (when (eci-cs-disconnect) 414 (destructuring-bind 415 ((cop n1 (copp n2 val))) 416 (cdr (assoc "1st_chain" (eci-cop-status))) 417 (message "%s %s is now %f" cop copp val))))) 418\end{verbatim} 419 420NOTE: function ``eci-cop-status'' is actually a very high level function 421which already converts the returned information to a nested list 422structure. 423 424For more complex examples of the Emacs Lisp ECI implementation, see function 425``eci-example'', ``ecasound-normalize'' and ``ecasound-signalview'' in 426ecasound.el. 427 428% ---------------------------------------------------------------------- 429\subsection{Python} 430\subsubsection{Overview} 431Python implementation is based around the ECA\_CONTROL\_INTERFACE class. 432Lists are used for representing collections of objects. 433 434Note! Eric S. Tiedemann has written an alternative Python interface 435 to ECI. You'll find this interface included in the main 436 Ecasound packege, in ``pyecasound/eci.py''. To use this instead 437 of the standard interface, just 'import eci' and you're set! :) 438 439\subsubsection{Usage} 440 441\begin{enumerate} 442\item import pyeca 443\item create an instance of the ECA\_CONTROL\_INTERFACE class 444 and use its member functions 445\item python 'yourapp.py' and that's it :) 446\end{enumerate} 447 448\subsubsection{Example} 449\begin{verbatim} 450 451#!/usr/local/bin/python 452import time 453from pyeca import * 454e = ECA_CONTROL_INTERFACE() 455e.command("cs-add play_chainsetup") 456e.command("c-add 1st_chain") 457e.command("ai-add some_file.wav") 458e.command("ao-add /dev/dsp") 459e.command("cop-add -efl:100") 460e.command("cop-select 1") 461e.command("copp-select 1") 462e.command("cs-connect") 463e.command("start") 464cutoff_inc = 500.0 465while 1: 466 time.sleep(1) 467 e.command("engine-status") 468 if e.last_string() != "running": break 469 e.command("get-position") 470 curpos = e.last_float() 471 if curpos > 15: break 472 e.command("copp-get") 473 next_cutoff = cutoff_inc + e.last_float() 474 e.command_float_arg("copp-set", next_cutoff) 475e.command("stop") 476e.command("cs-disconnect") 477e.command("cop-status") 478print "Chain operator status: ", e.last_string() 479 480\end{verbatim} 481 482% ---------------------------------------------------------------------- 483\subsection{Perl} 484\subsubsection{Overview} 485Audio::Ecasound provides perl bindings to the Ecasound 486control interface of the Ecasound program. You can use 487perl to automate or interact with Ecasound so you don't 488have to turn you back on the adoring masses packed into 489Wembly Stadium. 490 491Audio::Ecasound was written by Brad Bowman. At the moment this module 492is not distributed with Ecasound. To get the latest version, check the 493following \texttt{CPAN link}. 494 495\subsubsection{Usage} 496See the below example. For more info, here's another 497\texttt{CPAN link}. 498 499\subsubsection{Example} 500use Audio::Ecasound qw(:simple); 501 502\begin{verbatim} 503 504eci("cs-add play_chainsetup"); 505eci("c-add 1st_chain"); 506eci("ai-add some_file.wav"); 507eci("ao-add /dev/dsp"); 508# multiple \n separated commands 509eci("cop-add -efl:100 510 # with comments 511 cop-select 1 512 copp-select 1 513 cs-connect"); 514eci("start"); 515my $cutoff_inc = 500.0; 516while (1) { 517 sleep(1); 518 last if eci("engine-status") ne "running"; 519 my $curpos = eci("get-position"); 520 last if $curpos > 15; 521 my $next_cutoff = $cutoff_inc + eci("copp-get"); 522 # Optional float argument 523 eci("copp-set", $next_cutoff); 524} 525eci("stop"); 526eci("cs-disconnect"); 527print "Chain operator status: ", eci("cop-status"); 528 529\end{verbatim} 530 531% ---------------------------------------------------------------------- 532\subsection{PHP} 533\subsubsection{Overview} 534This PHP extension provides bindings to the Ecasound 535control interface. It is useful both for scripting Ecasound 536and for writing graphical audio applications with PHP Gtk. 537 538The PHP Ecasound extension was written by Tony Leake. At the moment this module 539is not distributed with Ecasound. The latest version and example scripts, are 540available from \texttt{http://www.webwise-data.co.uk/php\_audio/php\_audio\_extension.html}. 541 542\subsubsection{Usage} 543\begin{enumerate} 544\item Obtain and build the Ecasound PHP extension 545\item Initialise Ecasound, eci\_int(); 546\item Issue EAM commands eg, eci\_command("cs-add my\_chain\_setup"); 547\item Free resources, eci\_cleanup(); 548\end{enumerate} 549 550\subsubsection{Example} 551\begin{verbatim} 552 553Implementation of the following: 554 5551. Setup ECI to read audio from file, apply a 100Hz lowpass filter, 556and send it to the soundcard (/dev/dsp). 5572. Every second, check the current position. If the stream has been 558running for over 15 seconds, exit immediately. Also, every second, 559increase the lowpass filter's cutoff frequency by 500Hz. 5603. Stop the stream (if not already finished) and disconnect the chainsetup. 561Print chain operator status info 562 563<?php 564 565$cutoff_inc = 500.0; 566$curpos=0; 567$next_cutoff=0; 568 569eci_init(); 570eci_command("cs-add play_chainsetup"); 571eci_command("c-add 1st_chain"); 572eci_command("ai-add /tmp/somefile.wav"); 573eci_command("ao-add /dev/dsp"); 574eci_command("cop-add -efl:10"); 575eci_command("cop-select 1"); 576eci_command("copp-select 1"); 577eci_command("cs-connect"); 578eci_command("start"); 579 580while(1) { 581 582 sleep(1); 583 584 eci_command("engine-status"); 585 if (eci_last_string() !="running"){ 586 break; 587 } 588 589 eci_command("get-position"); 590 $curpos = eci_last_float(); 591 if ($curpos > 15.0){ 592 break; 593 } 594 595 eci_command("copp-get"); 596 $next_cutoff = $cutoff_inc + eci_last_float(); 597 eci_command_float_arg("copp-set",$next_cutoff); 598} 599 600eci_command("stop"); 601eci_command("cs-disconnect"); 602eci_command("cop-status"); 603 604printf("Chain operator status: %s", eci_last_string()); 605 606eci_cleanup(); 607?> 608\end{verbatim} 609 610% ---------------------------------------------------------------------- 611\subsection{Ruby} 612\subsubsection{Overview} 613The Ecasound package comes with an 'Ecasound' module for Ruby included. 614If ruby is detected during the installation process it is installed 615automatically (assuming you are installing ecasound from source code). 616The module contains the class definition of a native ecasound control interface 617called "ControlInterface". 618 619'Ecasound::ControlInterface' is implemented in a high level manner which means 620that you won't find most of the commands known from libecasoundc like 621last\_string, last\_float, etc. 622Instead of that every call to the instance method "command", which accepts all 623the well known IAM commands, returns ecasound's response in an appropriate type 624automatically. 625If an error occurs, e. g. there's a typo in a command or a file is not found, 626an exception of type EcasoundError is raised. 627 628\subsubsection{Usage} 629\begin{enumerate} 630\item require 'ecasound' 631\item create an instance of Ecasound::ControlInterface 632\item use it's command method to send IAM commands to ecasound 633\item catch an EcasoundError if necessary 634\end{enumerate} 635 636\subsubsection{Example} 637\begin{verbatim} 638#!/usr/bin/env ruby 639require "ecasound" 640 641SOME_FILE = "path/to/file.wav" 642 643e = Ecasound::ControlInterface.new() 644e.command("cs-add play_chainsetup") 645e.command("c-add 1st_chain") 646e.command("ai-add #{SOME_FILE}") 647e.command("ao-add /dev/dsp") 648e.command("cop-add -efl:100") 649e.command("cop-select 1") 650e.command("copp-select 1") 651e.command("cs-connect") 652e.command("start") 653 654cutoff_inc = 500.0 655 656loop do 657 sleep(1) 658 break if e.command("engine-status") != "running" 659 break if e.command("get-position") > 15 660 e.command("copp-set #{cutoff_inc + e.command('copp-get')}") 661end 662 663e.command("stop") 664e.command("cs-disconnect") 665 666$stdout << "Chain operator status: " + e.command("cop-status") + "\n" 667\end{verbatim} 668 669% ---------------------------------------------------------------------- 670% ---------------------------------------------------------------------- 671\section{Application development} 672 673% ---------------------------------------------------------------------- 674\subsection{Tips for debugging} 675 676Here's a few tips what to do if the ECI app you have developed 677is not working correctly. 678 679\begin{enumerate} 680\item Check your Ecasound installation. Try to run the ``ecasound'' 681 console user-interface and verify that the basic functionality 682 is working (ie. something like ``ecasound -i foo.wav -o 683 /dev/dsp''. 684 685\item If developing in C or C++, check that your application 686 is correcly linked: ``ldd /path/to/myapp''. All the libraries 687 should be properly found. 688 689\item Check error conditions. You should remember to check 690 for errors in your ECI apps using the eci\_error() and 691 eci\_last\_error() functions. Especially when intializing 692 ECI for the first time and after important commands 693 like ``cs-connect'', you should always check for errors. 694 695\item Use the ECASOUND\_LOGFILE environment variable to write all 696 engine output to a separate logfile. See ecasound(1) manpage 697 for details on how to use this mechanism. Requires Ecasound 698 version 2.4.5 or newer. 699 700\item Utilize the ``int-log-history'' ECI command added to 701 version 2.4.0 of Ecasound. Recent messages from the 702 engine can help to track down the problem. Before use, you 703 need to first set the history length to a non-zero value with 704 ``int-set-log-history-length''. 705 706\item Launch Ecasound in interactive mode (``ecasound -c''), 707 and issue the commands your ECI application is using, 708 manually one-by-one and see what happens. If something 709 goes wrong, increase Ecasound's debug level (for instance 710 ``-ddd'') and re-run the test. 711 712\end{enumerate} 713 714\end{document} 715