Writing Extensions to Snack in C/C++

Snack can be extended with new commands that operate on its sound objects. It is also possible to add new sound file formats and filter types. You can even define new kinds of object commands which link to a Snack sound and track changes to it. This is accomplished using the Snack C-library.

An example extension can be found in the ext directory of the Snack source distribution together with information on how to build and use them on both Unix and Windows.

Source code showing how a speech recognizer can track a Snack sound object can be found here.

Below is a minimal example of a command that extends Snack. The code and related files can be found in the ext directory of the Snack distribution.


Example C-code for a Snack extension

#include "snack.h"

int
Square(ClientData cdata, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
{
  Sound *sound;
  int i;

  /* Get the sound structure for this sound. */

  sound = Snack_GetSound(interp, Tcl_GetStringFromObj(objv[0], NULL));

  for (i = 0; i < Snack_GetLength(sound); i++) {
    if ((i/10)%2) {
      Snack_SetSample(sound, 0, i, 10000);
    } else {
      Snack_SetSample(sound, 0, i, -10000);
    }
  }

  return TCL_OK;
}

/*
  Initialize the square package and create a new sound command 'square'.
  The syntax is: sndName square
 */

EXPORT(int, Square_Init)(Tcl_Interp *interp)
{
#ifdef USE_TCL_STUBS
  if (Tcl_InitStubs(interp, "8", 0) == NULL) {
    return TCL_ERROR;
  }
#endif

#ifdef USE_TK_STUBS
    if (Tk_InitStubs(interp, "8", 0) == NULL) {
      return TCL_ERROR;
    }
#endif

#ifdef USE_SNACK_STUBS
  if (Snack_InitStubs(interp, "2", 0) == NULL) {
    return TCL_ERROR;
  }
#endif

  if (Tcl_PkgProvide(interp, "square", "1.0") != TCL_OK) {
    return TCL_ERROR;
  }

  Snack_AddSubCmd(SNACK_SOUND_CMD, "square", (Snack_CmdProc *) Square, NULL);

  return TCL_OK;
}
 


Example script using the extension

The following Tcl script demonstrates how to use the new 'square' command.

#/usr/local/bin/wish

# 'info sharedlibext' returns .dll on Windows and .so on most Unix systems

load libsquare[info sharedlibext]

sound s

s length 10000
s square

pack [button .b -text Play -command {s play}]


Building the extension

The example archive contains a Makefile and configure-script usable on all Unix platforms.

Here is a step by step guide for Windows users using MS Visual C++ 6.0.

  1. Create an empty Win32 Dynamic-Link Library project. (File/New...) Name it 'Square' and click Ok and then Finish.
  2. Add the file square.c to the project (Project/Add to project/Files...)
  3. Specify the locations of the Snack and Tcl include files. (Project/Settings..., C/C++ tab, Category: Preprocessor, Additional include directories.) With a default installation, this would be C:\Program Files\Tcl\include\,C:\Program Files\Snack2.0\include\
  4. Specify the stubs definitions (Project/Settings... C/C++ tab, Category: General, Preprocessor definitions.) USE_SNACK_STUBS, USE_TCL_STUBS, USE_TK_STUBS
  5. Specify the Snack and Tcl link libraries (Link tab, Category: Input, Object/library modules) tclstub83.lib tkstub83.lib snackstub20.lib and their locations (Additional library path). With a default installation, this would be C:\Program Files\Tcl\lib\,C:\Program Files\Snack2.0\lib\.
  6. Specify the output file name of the dll to be libsquare.dll. (Category: General, Output file name)
  7. Build the extension.
  8. Try the extension using the script above. You will have to edit the script and specify the full path to the dll in the load command.

Snack home