1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819
|
Sweep Plugin Writer's Guide
---------------------------
Documents Sweep Plugin API Version 1.0.0
Last modified Oct 22 2000
Copyright (C) 2000 Conrad Parker <conrad@vergenet.net>
1. Introduction
===============
Sweep plugins are able to modify all aspects of a sample file, including
the audio data, the sampling format used, and which regions of the sample
are currently selected. Sweep provides some convenience functions to make
plugin writing easy.
If you intend to write plugins which only modify audio data, you are
encouraged to use the Linux Audio Developer's Simple Plugin API
(LADSPA) [1] instead of writing a native Sweep plugin.
Other types of plugins include those which simply modify the selection
data, and those which provide conversions between different data formats.
Plugins do not need to provide their own graphical user interface
code. This API provides an abstraction by which plugins specify
numeric and string parameters. Sweep creates and presents to the user
a graphical dialog window for setting these parameters.
This document explains the programming interface for writing native Sweep
plugins and how to set up a build environment for your plugin code.
2. Getting started
==================
A sweep plugin is a shared library which contains one or more
procedures. These procedures can modify any of the data associated
with a particular sound wave. Procedures take as input a set of
parameters. They must specify the types of these parameters, and can
optionally provide some constraints (such as an acceptable numeric
range, or a list of values to choose from) and hints (such as to
interpret a number logarithmically). The constraints are interpreted
by Sweep as hard limits, ie. it will not pass values to the plugin
which fall outside of the constraints. Both constraints and hints are
used to construct a useful dialog box to the user for setting
parameters.
Procedures can optionally supply a function to suggest appropriate
values for the parameters as needed, provide Help and Copyright
information, and of course must supply a function to perform the
desired operation.
It is a requirement that all operations which modify a sound wave or
its associated data also provide a means for undoing and redoing
themselves. Sweep provides some standard mechanisms for efficiently
undoing and redoing some common types of operation.
This section describes the data structures used by Sweep and its
plugins, the mechanisms provided for performing common operations, and
information on building the resulting plugin libraries.
2.1 Sample code
---------------
You will most likely find it useful to examine the existing plugins in
the Sweep source archive. These are in the plugins/ directory. In
particular, the "example" plugin contains many of the features discussed
in this document.
2.2 Files to include
--------------------
<sweep/sweep.h>
Includes all required sweep header files.
Sweep plugins have access to all functions and datatypes defined in
GLib [2]. <glib.h> is automatically included in <sweep/sweep_types.h>,
so there is no need to explicitly include it once <sweep/sweep.h> has
been included. In particular the GList data structure is used
extensively by this API.
2.3 Internationalisation
------------------------
<sweep/sweep_i18n.h>
Sweep includes support for translatable strings via GNU gettext [3]. It
uses the same macros that the Gnome project defines to mark out strings
which can be translated.
When writing a plugin, you will provide some text strings describing the
plugin's procedures, the names of parameters used, and short descriptions
of the paramters meanings. In order to enable translators to provide
complete translations of Sweep and its plugins in other languages, you
must specifically mark strings which should be translated.
The usual way to do this is to place the macro _(...) around any strings
used within the code. However, when the string appears outside of a
function, you must use the macro N_(...) instead. N(...) marks a string
for later translation; _(...) marks a string for immediate translation,
and can only be used where a function call is permitted.
For more detailed information on the use of these macros, see the
relevent section in "GTK+/Gnome Application Development" [4].
If you would like to add a translation for Sweep into a new language,
all you need to do is provide translations for the text strings used in
Sweep. Please see the documentation for GNU gettext [3] for more
information on how to create the required file.
2.4 Basic types
---------------
<sweep/sweep_types.h>
Sweep provides some basic types which are useful for audio
handling. It is important to use these types where appropriate, as
this allows the sourcecode to be reconfigured for different
environments.
Individual sample values of audio data are represented by the types
sw_audio_t and sw_audio_intermediate_t. These are floating point
values ranging between SW_AUDIO_T_MIN and SW_AUDIO_T_MAX. For most
data storage and moving operations you should use sw_audio_t, and
where more precision is required (eg. when mixing sounds together) use
sw_audio_intermediate_t.
Blocks of audio data are stored in consecutive frames, where a frame
is a collection of the data values corresponding to the same instant
of time in each channel. That is, multichannel audio data is
interleaved, for example stereo data is stored:
(LR)(LR)(LR)(LR)...(LR)
where L and R are sample values of type sw_audio_t, and (LR) is a
single frame of data.
Frame counts are given as sw_framecount_t. Please use this type
wherever a count or offset in terms of frames is required.
Time is represented by sw_time_t. Time is defined in a floating point
format in units of seconds.
2.5 Complex types
-----------------
<sweep/sweep_types.h>
struct _sw_sample {
sw_sounddata * sounddata;
...
};
<sweep/sweep_sample.h>
struct _sw_sounddata {
sw_format * format;
sw_framecount_t nr_frames; /* nr frames */
gpointer data;
GList * sels; /* selection: list of sw_sels */
...
};
<sweep/sweep_sounddata.h>
struct _sw_format {
gint channels; /* nr channels per frame */
gint rate; /* sampling rate (Hz) */
};
The selection component of a sounddata object is a GList of sw_sel
objects. An sw_sel describes a region in a selection. Units are frame
offsets from start of sample.
struct _sw_sel {
sw_framecount_t sel_start;
sw_framecount_t sel_end;
};
2.6 Types for parameters
------------------------
<sweep/sweep_types.h>
The parameters to pass to functions can be any of a few simple types
as defined in <sweep/sweep_types.h>: SWEEP_TYPE_BOOL, SWEEP_TYPE_INT,
SWEEP_TYPE_FLOAT, SWEEP_TYPE_STRING.
A parameter object is a union which can take any of these values. A
parameter set is defined as a pointer to a sequence of parameters.
/*
* Instances of Parameter Sets
*/
typedef union _sw_param sw_param;
typedef sw_param * sw_param_set;
union _sw_param {
sw_bool b;
sw_int i;
sw_float f;
sw_string s;
};
2.7 Parameter Specifications
----------------------------
<sweep/sweep_types.h>
Information about a parameter accepted by a procedure is stored in a
parameter specification object, as defined in <sweep/sweep_types.h>
/*
* sw_param_spec: specification for a parameter.
*/
struct _sw_param_spec {
/* A short name for this parameter */
gchar * name;
/* A longer description of the parameter's purpose and usage */
gchar * desc;
/* The type of the parameter */
sw_param_type type;
/* Constraints */
sw_constraint_type constraint_type;
sw_constraint constraint;
/* Hints */
sw_hints hints;
};
Please remember to mark the name and description fields for
translation.
2.7.1 Constraints
-----------------
<sweep/sweep_types.h>
There are two ways of defining constraints on parameter values
accepted by the procedure; additionally, you can specify that the
values for a parameter are completely unconstrained.
SW_PARAM_CONSTRAINED_NOT
SW_PARAM_CONSTRAINED_LIST indicates that the parameter is constrained
to values given in a param list. NB: the length of this list is given
by the value of the first parameter, interpreted as an integer.
ie. this length = constraint->param_list[0].i
SW_PARAM_CONSTRAINED_RANGE indicates that the parameter is constrained
to a given range.
/*
* sw_param_range: a range of acceptable parameter values.
*
* NB: this is a hard limit. Values <lower and values >upper
* need not be expected by plugins.
*
* The first parameter is a mask consisting of a bitwise or of between
* zero and three of SW_RANGE_LOWER_BOUND_VALID,
* SW_RANGE_UPPER_BOUND_VALID, and SW_RANGE_STEP_VALID.
*
* The three following parameters are interpreted as the type of the
* parameter they constrain. The 'step' parameter is never valid for
* string parameters.
*/
struct _sw_param_range {
int valid_mask;
sw_param lower;
sw_param upper;
sw_param step;
};
2.7.2 Hints
-----------
<sweep/sweep_types.h>
A few hints exist which Sweep can use to provide different graphical
input methods as appropriate.
SW_PARAM_HINT_LOGARITHMIC indicates that the parameter should be
interpreted as logarithmic.
SW_PARAM_HINT_TIME indicates that the parameter should be interpreted
as a time
SW_PARAM_HINT_FILENAME indicates that the parameter should be
interpreted as a valid filename on the user's system.
2.8 Procedures
--------------
<sweep/sweep_types.h>
A procedure object ties together all the aspects of a particular
operation, including some textual data, the specifications for
parameters, and functions to suggest useful parameters and to do the
work required.
When the user initiates a procedure, the following occurs:
1. A new, empty, parameter set is created large enough to hold
the parameters required for this proc
2. The parameter set is passed to the suggest() function (if
that is defined) along with the sample and custom data. This allows
the suggest() function to provide some useful values based on the
characteristics of the sample. The suggest() function modifies the
values in the parameter set and returns.
3. A graphical dialog is created to allow the user to edit the
parameter values. It is initialised with the values given by the
suggests() function.
4. The user changes the parameter values as they wish, and upon
pressing "OK" the apply() function is called with these adjusted
parameter values.
The sw_procedure object has the following structure:
typedef struct _sw_procedure sw_procedure;
struct _sw_procedure {
gchar * name;
gchar * description;
gchar * author;
gchar * copyright;
gchar * url;
gchar * identifier;
/* Key bindings */
guint accel_key;
GdkModifierType accel_mods;
gint nr_params;
sw_param_spec * param_specs;
/* suggest sets suggested values for the members of pset,
* possibly using the sample.
*
* If nr_params is 0 then this function will not be called.
* If this function is NULL then default values (zero,FALSE,"")
* will be used.
*/
void (*suggest) (sw_sample * sample, sw_param_set pset,
gpointer custom_data);
/* This is the function that actually does the work!
*
* apply applies the parameter set pset to a sample
*
* If nr_params is 0 then this function will be passed a NULL pset.
*/
sw_op_instance * (*apply) (sw_sample * sample,
sw_param_set pset, gpointer custom_data);
/* custom data to pass to the suggest and apply functions */
gpointer custom_data;
};
The name field should be a short descriptive name, as appropriate for
labelling the menu item to invoke this procedure from Sweep. The
description should be some somewhat longer ASCII text describing what
this procedure does. Please remember to mark the name and description
fields for translation.
The author field should be a comma separated list of names of authors
of this procedure, each optionally providing an email address in angle
brackets. The copyright field should be a string such as "Copyright
(C) 2000 Joe Blow". The url field can optionally give the URL of a web
page describing the procedure in more detail.
The identifier field should be a string which will uniquely identify
this plugin. You may choose to put identifying information here such
as your name, domain, a suggested categorisation for the procedure, or
the name of your favourite vegetable or fish.
The accel_key and accel_mods fields list keybindings to initiate this
procedure. The values of their types are defined in <gdk/gdkkeysyms.h>.
The nr_params field gives the number of parameters this procedure
takes. You must point the param_specs field to an array of nr_params
sw_param_spec objects as defined in section 2.7.
Procedures must provide a suggest() and an apply() function. These
functions take the same arguments (sample, parameter set, custom
data). The first argument is the sample which is being edited. The
second is the parameter set object to use, and the third is some
custom data provided by the proc.
The suggest() function is used to set some meaningful parameter
values. The apply() function does the actual work of the procedure.
A useful means of handling suggest() is to remember the parameter
values set by the last invocation of this procedure. This can simply
be done by keeping these values in static global variables within the
plugin file.
The (sw_op_instance *) returned by the apply() function is described
in section 3.1. However in the usual case of writing a selection
modifier or audio filter, you do not need to understand the internals
of an sw_op_instance.
You may provide some custom_data to pass to the suggest() and apply()
functions if required. This is often useful if many procedures share
the same suggest() and apply() functions, as custom_data can then
provide further information to these functions as to how they should
actually operate. See the ladspameta plugin for an example of this use
of custom_data.
2.9 Writing a selection modifier
--------------------------------
A selection modifier is an operation which only affects the sels
member of a sample's sounddata. The undo and redo methods which are
registered for a selection modifier do not attempt to retain any
information about any other portion of the sample -- they are
optimised to only retain information about changes in the selection.
To create a selection modifier, you must provide a function of the
form SweepModify, as defined in <sweep/sweep_types.h>:
typedef void (*SweepModify) (sw_sample * sample, sw_param_set pset,
gpointer custom_data);
This function is expected to modify only the selection data, ie.
sample->sounddata->sels. Note that this data may also be accessed by
the playback thread, so it is protected by a mutex. You must surround
any modifications to the sels member of a sounddata object with
calls to sounddata_lock_selection() and sounddata_unlock_selection(),
as defined in <sweep/sweep_selection.h>.
To perform the selection modification, call the following function
(also defined in <sweep/sweep_selection.h>):
sw_op_instance *
perform_selection_op (sw_sample * s, char * desc, SweepModify func,
sw_param_set pset, gpointer custom_data);
The first argument is the sample to modify, the second is some
short descriptive text for the operation, 'func' is the SweepModify
function, and pset and custom_data are those provided by the proc.
see eg. plugins/byenergy/byenergy.c for an example of a Selection
plugin.
2.10 Writing an audio filter
---------------------------
<sweep/sweep_filter.h>
Two convenience routines exist for creating plugins which only modify
audio data. Note that where possible it is preferable to use the
LADSPA API instead for developing such plugins. See Appendix B for
more information about building LADSPA plugins for use with Sweep.
Filter plugins must only modify the audio data corresponding to
selected regions of a sample. The functions provided to perform filter
operations remember only information in the selected regions for the
purposes of undoing and redoing. Thus any modifications done outside the
selected regions will be lost after an undo.
As the selection information consists of a linked list of selected
regions (see section 2.3) it is necessary for a filter plugin to
somehow iterate over the selection and operate only on these regions.
The SweepFilterRegion mechanism handles this iteration for you,
whereas the SweepFilter mechanism allows for more general filters for
which you must provide the iteration over the selection regions.
2.10.1 SweepFilterRegion
-----------------------
To make use of the SweepFilterRegion mechanism define a function of
type SweepFilterRegion, which has the following prototype:
typedef void (*SweepFilterRegion) (gpointer data, sw_format * format,
sw_framecount_t nr_frames,
sw_param_set pset, gpointer custom_data);
A SweepFilterRegion function takes a pointer 'data' to a block of
audio data, an (sw_format *) describing the format of the data, and a
count of the number of frames to process from that point onwards. It
also accepts a parameter set and some custom data.
To perform a FilterRegion operation, use the following function:
sw_op_instance *
perform_filter_region_op (sw_sample * sample, char * desc,
SweepFilterRegion func, sw_param_set pset,
gpointer custom_data);
see eg. plugins/reverse/reverse.c for an example of a FilterRegion
The LADSPA meta-plugin is implemented as a FilterRegion.
2.10.2 SweepFilter
-----------------
If the processing involved cannot be done independently for each
selection region, it is necessary to use a SweepFilter function. Note
that the plugin must then perform the iteration over the selection
regions itself. These functions have the following prototype:
typedef sw_sounddata * (*SweepFilter) (sw_sounddata * sounddata,
sw_param_set pset,
gpointer custom_data);
To perform a Filter operation, use the following function:
sw_op_instance *
perform_filter_op (sw_sample * sample, char * desc, SweepFilter func,
sw_param_set pset, gpointer custom_data);
For example, the Normalise plugin (plugins/normalise/normalise.c) is
implemened as a Filter. This is necessary because it must first find
the greatest data value in any of the selected regions, and then in
a second pass amplify each region by an amount calculated.
2.11 Creating Plugin Shared Libraries
-------------------------------------
<sweep/sweep_types.h>
The usual way to make a proc available for use with Sweep is to build
it into a shared library file. When building a shared library to
contain one or more procs you must define a structure of type
sw_plugin with the name "plugin". This is the only name that should be
exposed in the library's symbol table; declare all other functions and
global variables as static. If multiple procedures share common code
or data then place them in the same plugin library. A plugin must not rely
on any other particular plugin being loaded.
typedef struct _sw_plugin sw_plugin;
struct _sw_plugin {
/* plugin_init () returns a list of procs */
GList * (*plugin_init) (void);
/* plugin_cleanup() frees the plugin's private data structures */
void (*plugin_cleanup) (void);
};
An sw_plugin structure contains two members, a plugin_init function
that takes no arguments and returns a list of procs, and a void
plugin_cleanup function.
The initialisation is performed through a function call and can
instantiate an indeterminate number of procs. This allows the creation
of plugins which may not necessarily know when built how many procs
they will create; for example, the LADSPA meta plugin dynamically
creates a proc corresponding to every LADSPA function it can find in
all the LADSPA plugins it can find.
In the usual case where the procs are known at build time (ie. they
consist of functions within the plugin library) the plugin_init
function can simply construct a GList out of these known procs, each
of which can be statically defined. This list is constructed using
g_list_append(); see <glib.h> for more information on using GLists.
2.12 Building plugins within the sweep source tree
-------------------------------------------------
Have a look at plugins/example/
Makefile.am:
## Process this file with automake to produce Makefile.in
INCLUDES = -I$(top_srcdir)/include
libdir = $(PACKAGE_PLUGIN_DIR)
lib_LTLIBRARIES = \
libexample.la
libexample_la_SOURCES = example.c
libexample_la_LDFLAGS = -version-info 1:0:0
The version info (1:0:0 in the example above) should consist of
the numbers SWEEP_PLUGIN_API_MAJOR, SWEEP_PLUGIN_API_MINOR and
SWEEP_PLUGIN_API_REVISION listed in <sweep/sweep_version.h>, colon
separated. Copy the numbers in manually, do not attempt to generate
them from the values defined. These numbers should only be changed
when your plugin code changes to use features only available in
newer versions of the plugin API.
Note that the plugin API is maintained independently of the
application version. See section 3.2 for more information on API
versioning.
3. Advanced topics
==================
This section explains in depth some topics which are not usually required
by plugin writers. This includes the creation of new types of operation
and undo/redo mechanisms and a detailed discussion of the versioning system
employed.
3.1 Sweep "Operations", Handling Undo and Redo
----------------------------------------------
Sweep maintains a stack of recent operations for each sample, which
are used to allow undoing and redoing of all operations. If you write
a new operation method that modifies a sample's 'sounddata' (ie. the
sampling rate, length, selections or audio data) then you must
implement Undo and Redo methods for it. However if you are using one
of the convenience mechanisms covered in Sections 2.7 and 2.8 then
these things are already taken care of by the perform_* functions.
The datatypes used are defined in <sweep/sweep_types.h> as follows:
typedef void (*SweepFunction) (gpointer data);
typedef void (*SweepCallback) (sw_sample * sample, gpointer data);
typedef struct _sw_operation sw_operation;
typedef struct _sw_op_instance sw_op_instance;
struct _sw_operation {
SweepCallback undo;
SweepFunction purge_undo;
SweepCallback redo;
SweepFunction purge_redo;
};
struct _sw_op_instance {
char * description;
sw_operation * op;
gpointer undo_data;
gpointer redo_data;
};
Once an operation has been successfully performed, it needs to
register itself with Sweep's undo handler. This involves:
1. Finding or constructing an sw_operation structure. These are
often statically defined.
2. Creating an sw_op_instance structure. This contains a
description of the operation performed, a pointer to the sw_operation,
and pointers to data for use in undoing and redoing the operation
performed.
3. Calling register_operation() to add the sw_op_instance to
the sample's stack of operations.
The apply() method of a proc usually does these things, does its actual
work, registers the operation then returns the sw_op_instance created.
An operation given by (sw_op_instance * inst) is undone by calling
inst->op->undo (sample, inst->undo_data);
and redone by calling
inst->op->redo (sample, inst->redo_data);
When an operation instance can be discarded (eg. if only a finite number
of recent operations are remembered), the undo_data and redo_data
members are purged by calling
inst->op->purge_undo (inst->undo_data);
inst->op->purge_redo (inst->redo_data);
Thus, if any memory was allocated to create undo_data or redo_data it
should be freed in the purge functions.
Some stock undo and redo methods exist for handling operations which
need to paste new data over the selected region, or which need to splice
data into the sample. These are outlined in <sweep/sweep_undo.h>. For
examples of their use, see "src/edit.c" in the Sweep application source.
3.2 Versioning
--------------
<sweep/sweep_version.h>
Sweep's plugin API is strictly versioned. Note that the plugin API's
versions are maintained completely independently of the application
version. You can find out the application and plugin API versions of
your installed copy of Sweep by issuing the command "sweep --version".
Versioning of the plugin API tracks the interface provided by
Sweep. This is done because the application is actively linking itself
against the plugin libraries, and must look for plugins which
implement versions it understands.
Versions are given in the form Major.Minor.Revision (M.m.R). The API
version implemented by a particular release of Sweep is defined in
<sweep/sweep_version.h> by the values SWEEP_PLUGIN_API_MAJOR,
SWEEP_PLUGIN_API_MINOR and SWEEP_PLUGIN_API_REVISION.
Note: in the following description, a "public data structure" is one
defined in any of the headers included by <sweep/sweep.h>, and a
"public function" is any function declared in any of the headers
included by <sweep/sweep.h>. An "interface" is anything that is either
a public data structure or a public function.
The version information is only ever updated upon a release of
Sweep. Interfaces defined in the code available through CVS between
releases are subject to change.
The version information V = M.m.R is updated to V' as follows:
1. If any interfaces have been removed or modified by a
release (ie. backwards compatability has been broken) then the Major
number is incremented and Minor and Revision are set to 0. (V' = M+1.0.0)
2. Otherwise, if any interfaces have been added since the last
release the Minor number is incremented and Revision is set to 0.
(V' = M.m+1.0)
3. Otherwise, if the application code has changed at all since
the last release the Revision is incremented. (V' = M.m.R+1)
A plugin library 'plugin' must be built with a name of the form
libplugin.so.M.m.R
where M, m, and R correspond to the Major, Minor and Revision provided
by the particular version of sweep you are developing against, or an
earlier Minor and Revision which are known to work. The current behaviour
of sweep is to attempt to load all plugins with a Major number it
understands, and fail silently if the plugin makes use of interfaces
added in subsequent Minor API versions. Thus it is not absolutely necessary
to find the earliest API version which will work with your plugin.
Additionally, symlinks should be created for the plugin as follows:
libplugin.so -> libplugin.so.M
libplugin.so.M -> libplugin.so.M.m
libplugin.so.M.m -> libplugin.so.M.m.R
These symlinks are created automatically when using libtool to build
plugin libraries by including the line
libplugin_la_LDFLAGS = -version-info M:m:R
in the Makefile.am within the plugin's build directory (if using automake,
or the flag "-version-info M:m:R" needs to be otherwise passed to libtool).
Note that this flag contains colons, not dots.
Appendix A. Keeping in touch with Sweep development
===================================================
The Sweep homepage contains links to many relevent resources.
http://sweep.sourceforge.net/
The Sweep project page on Sourceforge holds the infrastructure for such
things as CVS access and bug reporting. It is available at
http://sourceforge.net/projects/sweep/
If you have any questions or comments about Sweep please send them to
the sweep-devel mailing list <sweep-devel@lists.sourceforge.net>.
If in doubt, contact the main author: Conrad Parker <conrad@vergenet.net>
Appendix B. Building LADSPA plugins for use with Sweep
======================================================
If you intend to create a plugin which only modifies audio data (such
as an effects plugin), it is recommended that you use the LADSPA API
[1] if possible. This ensures that the plugin you create is usable by
a wide variety of free audio programs, rather than only being usable
by Sweep.
If writing a LADSPA plugin please write a mono filter unless there is
some kind of algorithmic interaction between the channels such as
panning. Sweep, and most other LADSPA hosts, use multiple instances or
invocations of the LADSPA plugins as required so that any number of
channels can be catered for with a mono plugin.
In fact Sweep will quite happily use a stereo LADSPA filter on a mono
sample (it will generate an empty second channel and ignore its
output) but it is inefficient to rely on this behaviour.
To clarify: LADSPA defines a standardised interface for audio plugins.
When creating LADSPA plugins, do not reference any data structures
used internally by Sweep. You do not provide any undo or redo methods;
Sweep will construct these as required when performing an operation
from a LADSPA plugin.
Acknowledgements
================
This API was constructed after careful studying of plugin APIs from
many other free software projects, including SANE, the Gimp, LADSPA,
and xmms.
References
==========
[1] Linux Audio Developer's Simple Plugin API
http://www.ladspa.org/
[2] GLib Reference Manual
http://developer.gnome.org/doc/API/glib/index.html
[3] GNU gettext
http://www.gnu.org/software/gettext/
[4] GTK+/Gnome Application Development, Section 5.2 "Internationalization"
Havoc Pennington, New Riders Publishing 1999
http://developer.gnome.org/doc/GGAD/sec-i18n.html
|