+ sdl - SDL dependent services
+ resample - libresample dependent services
+ gtk2 - pango and pixbuf dependent services
+ + xine - xine-derived services
+ bluefish - Bluefish dependent services (*)
+ mainconcept - mainconcept dependent services (*)
+ inigo - A media playing test application
1. The server will interact with public interfaces from the framework only;
2. The modules must expose public framework interfaces only;
3. All modules are dynamically loaded at runtime.
-
Westley to File westley:
MainConcept DV to /dev/dv1394 mcdv:/dev/dv1394 rescale=nearest buffer=25
libdv to /dev/dv1394 libdv:/dev/dv1394 rescale=nearest buffer=25
-BlueFish444 PAL bluefish
-BlueFish444 NTSC bluefish:NTSC
+BlueFish444 PAL bluefish:1
+BlueFish444 NTSC bluefish:1 standard=NTSC
+------------------+------------------------------------+------------------+
|samples |The samples of the audio | |
+------------------+------------------------------------+------------------+
- |aspect_ratio |The aspect ratio of the image |double |
+ |aspect_ratio |The sample aspect ratio of the image|double |
+------------------+------------------------------------+------------------+
|test_image |Used to indicate no image available |0 or 1 |
+------------------+------------------------------------+------------------+
void mlt_playlist_close( mlt_playlist this );
mlt_tractor:
-
-
The directory heirarchy is defined as follows:
+ + demo - A selection of samples to show off capabilities.
+ docs - Location of all documentation
+ src - All project source is provided here
+ framework - The mlt media framework
+ sdl - SDL dependent services
+ resample - libresample dependent services
+ gtk2 - pango and pixbuf dependent services
+ + fezzik - A giant (meta) service to load and normalise media
+ + westley Nice and clever XML services
+ + vorbis Ogg Vorbis dependent services
+ + xine - Xine-derived sources
+ bluefish - Bluefish dependent services (*)
+ mainconcept - mainconcept dependent services (*)
+ inigo - A media playing test application
+ valerie - Client API to access the server
+ miracle - The server implementation
- + humperdink - The evil demo
- + albino - The simple but nice demo
+ + albino - A simple console (protocol level) example
+ + humperdink - A terminal-based example client
+ tests - Reserved for regression and unit tests
Additional subdirectories may be nested below those shown and should be
This allows migration of source between external and internal modules.
The configuration and Makefile template requirements will require
attention though.
-
-
pango producer interprets the filename as pango text. This is a
shortcut to embed titles in inigo commands. For westley, it is
recommended that you embed the title text in the property value.
- If you need to embed Pango markup in a westley XML file, then
- enclose the value inside "<![CDATA[ ... ]]>".
Pango has builtin scaling. It will rescale the originally rendered
title to whatever the consumer requests. Therefore, it will lose
Mutable Properties
- string markup - a UTF-8 string containing Pango markup see:
+ string markup - a string containing Pango markup see:
http://developer.gnome.org/doc/API/2.0/pango/PangoMarkupFormat.html
- requires xml-like encoding special chars from:
<, >, & -to- <, >, &
markup chars un-encoded)
string font - the default typeface to use when not using markup.
default "Sans 48". FreeType2 renders at 72 dpi.
+ string encoding - the text encoding type of the input if not UTF-8.
+ - see 'iconv --list' for a list of possible inputs.
Read Only Properties
load all pictures with matching extension from a directory.
- If filename contains the string "<svg", then pixbuf tries
to load the filename as inline SVG XML, which is convenient
- for inigo commands. For westley XML, set the resource
- property value with inline XML embedded using a CDATA node
- ("<![CDATA[ ... ]]>").
+ for inigo commands.
Details
Constructor Argument
- string video_standard - "PAL" (default) or "NTSC"
+ card - a numeric card id starting at 1, default is 1.
Initialisation Properties
- int video_standard - 0 = PAL, 1 = NTSC
+ string standard - "PAL" (default) or "NTSC"
+ - default is based upon MLT_NORMALISATION
+ environment variable, which defaults to PAL.
+ int frames - the number of DMA video frames. default is 4.
+ minimum is 2. maximum on my system is 11.
+ int buffer - the number of frames to buffer within MLT, minimum 1,
+ default 25.
+ string rescale - a rescale method, see the Filters/rescale.
Read Only Properties
Does not work with any service that uses pipes!
- If mlt crashes, you must reload the BlueDriver kernel module
- due to unreleased DMA buffers.
+ If mlt crashes, you might need to reload the BlueDriver kernel
+ module due to unreleased DMA buffers.
- Needs an argument or property for multi-card address.
+ Only supports 2 channel audio at the moment.
libdv
placed between all producers and the consumer).
TODO: transition example
+
+
+Flexibility:
+
+ The information presented above is considered the MLT Westley "normal"
+ form. This is the output generated by the westley consumer, for example,
+ when used with inigo. It is the output generated when you use the
+ "Westley to File" consumer in the demo script, which beginners will find
+ most useful for learning to use westley XML. This section describes
+ alternative forms the westley producer accepts.
+
+ First of all, the normal form is more of a linear format with producers
+ and playlists defined prior to their usage in a multitrack. Westley
+ also accepts a hierarchical format with producers as children of tracks
+ or playlist entries and with playlists as children of tracks:
+
+ <westley>
+ <tractor>
+ <multitrack>
+ <track>
+ <playlist>
+ <entry>
+ <producer>
+ <property name="resource">clip1.dv</property>
+ </producer>
+ </entry>
+ </playlist>
+ </track>
+ </multitrack>
+ </tractor>
+ </westley>
+
+ Obviously, this example is meant to demonstrate hierarchy and not effective
+ use of playlist or multitrack!
+
+ Secondly, as part of error handling, westley is forgiving if you fail to
+ supply <tractor>, <track>, and <entry> where one can be understood. This
+ affords an abbreviated syntax that is less verbose and perhaps less
+ intimidating for a human to read and understand. One can simplify the
+ above example as:
+
+ <westley>
+ <multitrack>
+ <playlist>
+ <producer>
+ <property name="resource">clip1.dv</property>
+ </producer>
+ </playlist>
+ </multitrack>
+ </westley>
+
+ Yes, filters and transitions can be added to the above example after the
+ closing multitrack tag (</multitrack>) because it is still enclosed within
+ the westley body tags.
+
+ If you specify in and out on a producer and it has been enclosed within
+ an <entry> or <playlist>, then the edit points apply to the playlist
+ entry and not to the producer itself. This facilitates re-use of media:
+
+ <playlist>
+ <producer id="clip1" in="25" out="78">
+ <property name="resource">clip1.dv</property>
+ </producer>
+ <entry producer="clip1" in="119" out="347"/>
+ </playlist>
+
+ In the above example, the producer attribute of the entry element is
+ a reference to the preceding producer. All references must follow the
+ definition. The edit points supplied on the producer above will not affect
+ the entry that references it below because westley knows the clip is a
+ playlist entry and optimises this situation. The advantage is that one
+ does not need to determine every clip to be included ahead of time
+ and specify them outside the context of the mutlitrack timeline.
+
+ This form of authoring will be easier for many to visualise as a non-linear
+ editor's timeline. Here is a more complex example:
+
+ <westley>
+ <multitrack>
+ <playlist>
+ <producer id="foo" in="100" out="149">
+ <property name="resource">clip2.mpeg</property>
+ </producer>
+ <blank length="25"/>
+ <entry producer="foo" in="10" out="59"/>
+ </playlist>
+ <playlist>
+ <blank length="25"/>
+ <producer id="bar" in="100" out="199">
+ <property name="resource">clip3.mpeg</property>
+ </producer>
+ <entry out="99" producer="bar"/>
+ </playlist>
+ </multitrack>
+ <filter mlt_service="greyscale" track="0"/>
+ <transition mlt_service="luma" in="25" out="49" a_track="0" b_track="1"/>
+ <transition mlt_service="luma" in="75" out="99" a_track="0" b_track="1">
+ <property name="reverse" value="1"/>
+ </transition>
+ </westley>
+
+ Did you notice something different in the last example? Properties can be
+ expressed using XML attributes on the element as well. However, only
+ non-service-specific properties are supported in this way. For example,
+ "mlt_service" is available to any producer, filter, or transition. However,
+ "resource" is actually service-specific. Notice the syntax of the last
+ property, on the last transition. Westley accepts property values using
+ the "value" attribute as well as using element text.
+
+ We have seen a few different ways of expressing property values. There are
+ a couple more for properties that can accept XML data. For example, the
+ GDK pixbuf producer with librsvg can handle embedded SVG, and the Pango
+ producer can handle embedded Pango markup. You can enclose the embedded XML
+ using a CDATA section:
+
+ <property name="resource"><![CDATA[ <svg>...</svg> ]]></property>
+
+ Please ensure the opening CDATA tag immediately follows the opening
+ property tag and that the section closing tag immediately precedes the
+ closing property tag.
+
+ However, westley can also accept inline embedded XML:
+
+ <property name="resource">
+ <svg>
+ </svg>
+ </property>
+
+ Currently, there is no namespace handling so a conflict will occur only on
+ any embedded XML that contains an element named "property" because
+ westley collects embedded XML until it reaches a closing property tag.
+
+ TODO: xml entities
+
+
+Technique:
+
+ If one finds the above hierarchical, abbreviated format intuitive,
+ start with a simple template and fill and extend as needed:
+ <westley>
+ <multitrack>
+ <playlist>
+ </playlist>
+ ...add a playlist for each track...
+ </multitrack>
+ ...add filters and transitions...
+ </westley>
+
+ By using a playlist for each track, it is easier to iteratively add new
+ clips and blank regions as you develop the project. You will not have to
+ use <track> or later add <playlist> when necessary.
+
+ A more advanced template that allows sequencing multitracks is:
+ <playlist>
+ <entry>
+ <multitrack>
+ <playlist>
+ </playlist>
+ ...add a playlist for each track...
+ </multitrack>
+ ...add filters and transitions...
+ </entry>
+
+ <entry>
+ <multitrack>
+ <playlist>
+ </playlist>
+ ...add a playlist for each track...
+ </multitrack>
+ ...add filters and transitions...
+ </entry>
+ </playlist>
+
+ If you want to have a silent, black background for audio and video fades,
+ then make the last track simply <producer mlt_service="colour"/>. Then,
+ use composite and volume key-framable properties.
+ TODO: to be continued
+
+ TODO: considerations with mixing multiple audio layers
if ( argc > 2 && !strcmp( argv[ 1 ], "-s" ) )
{
- printf( "DV1394D Client Instance\n" );
+ printf( "Miracle Client Instance\n" );
parser = valerie_parser_init_remote( argv[ 2 ], 5250 );
response = valerie_parser_connect( parser );
index = 3;
}
else
{
- printf( "DV1394D Standalone Instance\n" );
+ printf( "Miracle Standalone Instance\n" );
parser = miracle_parser_init_local( );
response = valerie_parser_connect( parser );
}
}
else
{
- fprintf( stderr, "Unable to connect to a dv1394 instance.\n" );
+ fprintf( stderr, "Unable to connect to a Miracle instance.\n" );
}
printf( "\n" );
char command[ 10240 ];
int terminated = 0;
- printf( "DV1394D Shell\n" );
+ printf( "Miracle Shell\n" );
printf( "Enter an empty command to exit.\n\n" );
while ( !terminated )
{
free( demo );
}
-
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <pango/pangoft2.h>
#include <freetype/freetype.h>
+#include <iconv.h>
struct producer_pango_s
{
static GdkPixbuf *pango_get_pixbuf( const char *markup, const char *text, const char *font,
rgba_color fg, rgba_color bg, int pad, int align );
+/** Return nonzero if the two strings are equal, ignoring case, up to
+ the first n characters.
+*/
+int strncaseeq(const char *s1, const char *s2, size_t n)
+{
+ for ( ; n > 0; n--)
+ {
+ if (tolower(*s1++) != tolower(*s2++))
+ return 0;
+ }
+ return 1;
+}
+
/** Parse the alignment property.
*/
mlt_properties_set_int( properties, "pad", 0 );
mlt_properties_set( properties, "text", "" );
mlt_properties_set( properties, "font", "Sans 48" );
+ mlt_properties_set( properties, "encoding", "UTF-8" );
if ( filename == NULL )
{
return result;
}
+/** Convert a string property to UTF-8
+*/
+static int iconv_utf8( mlt_properties properties, char *prop_name, const char* encoding )
+{
+ char *text = mlt_properties_get( properties, prop_name );
+ int result = -1;
+
+ iconv_t cd = iconv_open( "UTF-8", encoding );
+ if ( cd != ( iconv_t )-1 )
+ {
+ char *inbuf_p = strdup( text );
+ size_t inbuf_n = strlen( text );
+ size_t outbuf_n = inbuf_n * 6;
+ char *outbuf = mlt_pool_alloc( outbuf_n );
+ char *outbuf_p = outbuf;
+
+ if ( iconv( cd, &inbuf_p, &inbuf_n, &outbuf_p, &outbuf_n ) != -1 )
+ {
+ outbuf[ outbuf_n ] = 0;
+ mlt_properties_set( properties, prop_name, outbuf );
+ result = 0;
+ }
+ mlt_pool_release( outbuf );
+ iconv_close( cd );
+ }
+ return result;
+}
+
static void refresh_image( mlt_frame frame, int width, int height )
{
// Pixbuf
char *markup = mlt_properties_get( producer_props, "markup" );
char *text = mlt_properties_get( producer_props, "text" );
char *font = mlt_properties_get( producer_props, "font" );
-
+ char *encoding = mlt_properties_get( producer_props, "encoding" );
+
// See if any properties changed
int property_changed = ( align != this->align );
property_changed = property_changed || ( this->fgcolor == NULL || ( fg && strcmp( fg, this->fgcolor ) ) );
this->image = NULL;
this->alpha = NULL;
+ // Convert from specified encoding to UTF-8
+ if ( encoding != NULL && !strncaseeq( encoding, "utf-8", 5 ) && !strncaseeq( encoding, "utf8", 4 ) )
+ {
+ if ( markup != NULL && iconv_utf8( producer_props, "markup", encoding ) != -1 )
+ {
+ markup = mlt_properties_get( producer_props, "markup" );
+ set_string( &this->markup, markup, NULL );
+ }
+ if ( text != NULL && iconv_utf8( producer_props, "text", encoding ) != -1 )
+ {
+ text = mlt_properties_get( producer_props, "text" );
+ set_string( &this->text, text, NULL );
+ }
+ }
+
// Render the title
pixbuf = pango_get_pixbuf( markup, text, font, fgcolor, bgcolor, pad, align );
if ( strcmp( name, "entry" ) == 0 )
mlt_properties_set( mlt_service_properties( service ), "resource", "<entry>" );
+ else
+ mlt_properties_set( mlt_service_properties( service ), "resource", "<track>" );
for ( ; atts != NULL && *atts != NULL; atts += 2 )
{
if ( mlt_properties_get_data( context->producer_map, (char*) atts[1], NULL ) != NULL )
// Push the referenced producer onto the stack
context_push_service( context, MLT_SERVICE( mlt_properties_get_data( context->producer_map, (char*) atts[1], NULL ) ) );
+ else
+ // Remove the dummy service to cause end element failure
+ context_pop_service( context );
}
}
}
// Get the dummy track service from the stack
mlt_service track = context_pop_service( context );
- if ( track == NULL )
+ if ( track == NULL || strcmp( mlt_properties_get( mlt_service_properties( track ), "resource" ), "<track>" ) )
{
context_push_service( context, producer );
return;
// Get the dummy entry service from the stack
mlt_service entry = context_pop_service( context );
- if ( entry == NULL )
+ if ( entry == NULL || strcmp( mlt_properties_get( mlt_service_properties( entry ), "resource" ), "<entry>" ) )
{
context_push_service( context, producer );
return;