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
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
|
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V4.1//EN" [
<!ENTITY intro SYSTEM "intro.sgml">
]>
<book>
<bookinfo>
<title>The xine hacker's guide</title>
<titleabbrev>hackersguide</titleabbrev>
<authorgroup>
<author><firstname>Günter</firstname><surname>Bartsch</surname></author>
<author><firstname>Heiko</firstname><surname>Schäfer</surname></author>
<author><firstname>Richard</firstname><surname>Wareham</surname></author>
</authorgroup>
<copyright>
<year>2001-2002</year>
<holder>the xine project team</holder>
</copyright>
<abstract>
<para>
This document should help xine hackers to find their way through
xine's architecture and source code. It's a pretty free-form document
containing a loose collection of articles describing various aspects
of xine's internals.
</para>
</abstract>
</bookinfo>
<chapter id="intro">
<title>Introduction</title>
&intro;
</chapter>
<chapter id="overview"><title>Overview</title>
<sect1>
<title>Source modules</title>
<para>The source directory in xine-lib contains several
modules, this should give you a quick overview on where
to find what sources:
</para>
<sect2>
<title>xine-engine</title>
<para>The heart of xine - it's engine. Contains code to
load and handle all the plugins, as well as the generic decoding
and synchroniation/output code.
</para>
</sect2>
<sect2>
<title>audio_out</title>
<para>
Audio output plugins, these provide a thin abstraction layer
over different types of audio output architectures/platforms.
Basically an audio output plugin provides functions to query/setup
the audio hardware and output audio data (e.g. PCM samples).
</para>
</sect2>
<sect2>
<title>demuxers</title>
<para>
Demuxer plugins that handle various system layer file formats
like avi, asf or mpeg.
</para>
</sect2>
<sect2>
<title>dxr3</title>
<para>
Code specific to the dxr3 / hollywood+ hardware mpeg decoder.
</para>
</sect2>
<sect2>
<title>liba52</title>
<para>
Dolby digital audio decoder plugin.
</para>
</sect2>
<sect2>
<title>libdivx4</title>
<para>
Video decoder plugin using libdivx4linux if it is installed.
</para>
</sect2>
<sect2>
<title>libdts</title>
<para>
Audio decoder plugin that does nothing but passing through
DTS (AC5) data to the audio output plugin. This is only usefull
when using an external hardware DTS decoder.
</para>
</sect2>
<sect2>
<title>libffmpeg</title>
<para>
Various Audio/Video decoder plugins based on ffmpeg; most
importantly this contains a free mpeg-4 video decoder.
</para>
</sect2>
<sect2>
<title>liblpcm</title>
<para>
Audio decoder plugin that "decodes" raw PCM data; most notably
endianess-conversions are done here.
</para>
</sect2>
<sect2>
<title>libmad</title>
<para>
Mpeg audio decoder plugin (i.e. mp3 decoding). Quite slow and
due to be replaced by ffmpeg's mp3 decoder.
</para>
</sect2>
<sect2>
<title>libmpeg2</title>
<para>
Most important mpeg video decoder plugin, provides fast and
high-precision mpeg-1/2 video decoding.
</para>
</sect2>
<sect2>
<title>libspucc, libspudec, libsputext</title>
<para>
Various subtitle (spu: subpicture, dvd slang) decoder plugins.
</para>
</sect2>
<sect2>
<title>libvorbis</title>
<para>
Vorbis audio decoder plugin.
</para>
</sect2>
<sect2>
<title>libw32dll</title>
<para>
Video/Audio decoder plugins that exploit some wine code
to use win32 (media player) codecs in xine. Works on x86 platforms
only.
</para>
</sect2>
<sect2>
<title>video_out</title>
<para>
Contains various video output driver plugins. Video output drivers
are thin abstraction layers over various video output platforms
(e.g. X11, directfb, directX,...). Video output driver plugins
provide functions like frame allocation and drawing and handle
stuff like hardware acceleration, scaling and colorspace conversion
if necessary. They do not handle a/v sync since this is done
in the xine-engine already.
</para>
</sect2>
<sect2>
<title>xine-utils</title>
<para>
collection of utility functions and platform abstractions.
</para>
</sect2>
<sect2>
<title>libac3, libmpg123, libvfill</title>
<para>
deprecated.
</para>
</sect2>
</sect1>
<sect1>
<title>Architecture and data flow</title>
<mediaobject>
<imageobject>
<imagedata fileref="architecture.png" format="PNG">
</imageobject>
<imageobject>
<imagedata fileref="architecture.eps" format="EPS">
</imageobject>
<caption>
<para> xine architecture </para>
</caption>
</mediaobject>
<para>
Media streams usually consist of audio- and video-packages multiplexed
into one bitstream in the so-called system-layer (e.g. AVI, Quicktime or Mpeg).
A demuxer plugin is used to parse the system layer and extract audio- and video-
packages. The demuxer uses an input-plugin to read the data and stores it
in pre-allocated buffers from the global buffer pool.
The buffers are then added to the audio- or video- fifo.
</para>
<para>
From the other end of these fifos audio-/video-decoder threads
remove the buffers and hand them over to the current audio- or video-
decoder plugin for decompression. These plugins then send the decoded
data to the audio-/video- output layers. The buffer holding the encoded
data is no longer needed and thus released to the global buffer pool.
</para>
</sect1>
<sect1>
<title>Object oriented programming in c</title>
<para>
xine uses a lot of design principles normally found in
object oriented designs. As xine is written in c, a few
basic principles shall be explained here on how xine
is object oriented anyway.
</para>
<para>
classes are structs containing (ideally only) function pointers in xine.
Example:
<programlisting>
typedef struct my_stack_s my_class_t;
struct my_stack_s {
/* method "push" with one parameter and no return value*/
void (*push) (my_stack_t *this, int i);
/* method "add" with no parameters and no return value */
void (*add) (my_stack_t *this);
/* method "pop" with no parameters (except "this") and a return value */
int (*pop) (my_stack_t *this);
} ;
/* constructor */
my_class_t *new_my_stack (...);
</programlisting>
to implement such a "class", frequently "private" member variables
can be added:
<programlisting>
typedef struct {
my_stack_t stack; /* public part */
/* private part follows here */
int values[MAX_STACK_SIZE];
int stack_size;
} intstack_t;
</programlisting>
each method is implemented as a static method (static to prevent
namespace pollution). The "this" pointer needs to be cast to the
private pointer type to gain access to the private member variables.
Implementation of the "push" method follows:
<programlisting>
static void push (my_stack_t *this_gen, int i) {
intstack_t *this = (intstack_t *) this_gen;
}
</programlisting>
Finally the contructor mallocs() the data structs (private variant)
and fills in function pointers and default values. Usually the
constructor is the only public (i.e. non-static) function in the module:
<programlisting>
my_stack_t *new_my_stack (...) {
intstack_t *this;
/* alloc memory */
this = malloc (sizeof (intstack_t));
/* fill in methods */
this->push = push;
this->add = add;
this->pop = pop;
/* init data fields */
this->stack_size = 0;
/* cast & return */
return (my_stack_t *) this;
}
</programlisting>
</para>
</sect1>
<sect1>
<title>Library interfaces</title>
<para></para>
</sect1>
</chapter>
<chapter id="internals"><title>xine internals</title>
<sect1>
<title>What is this metronom thingy ?</title>
<para>
Metronom serves two purposes:
<itemizedlist>
<listitem>
<para>
generate vpts (virtual presentation time stamps) from pts (presentation time stamps)
for a/v output and synchronization
</para>
</listitem>
<listitem>
<para>
provide a master clock (system clock reference, scr), possibly provided
by external scr plugins (this can be used if some hardware decoder or network
server dictates the time)
</para>
</listitem>
</itemizedlist>
</para>
<para>
pts/vpts values are given in 1/90000 sec units. pts values in mpeg streams
may wrap, can be missing on some frames or (for broken streams) may "dance" around
the correct values. Metronom therefore has some heuristics built-in to generate
clean vpts values which can then be used in the output layers to schedule audio/video
output.
</para>
<para>
The heuristics used in metronom have always been a field of research.
</para>
</sect1>
<sect1>
<title>The xine engine from the inside</title>
<para></para>
</sect1>
<sect1>
<title>Plugin architecture</title>
<para>
xine plugins are built as shared libraries that export at least one
public function named <function>init_type_plugin</function>, where
<function>type</function> reflects the function of the plugin (video,
audio, etc). This function returns a pointer to freshly allocated (typically
via <function>malloc()</function>) structure containing mainly
function pointers; these are the "methods" of the plugin.
If you think this is pretty much an object-oriented aproach,
then you're right.
</para>
<para>
All plugins are installed in a special xine plugins directory
which can be found using the <command>xine-config --plugindir</command>
command.
</para>
<para>
You'll find exact definitions of public functions and plugin structs
in the appropriate header files for each plugin type
(e.g. <filename>demux/demux.h</filename>, <filename>input/input_plugin.h</filename>,
<filename>xine-engine/video_out.h</filename>, etc) within the xine source-code.
</para>
<para>
Many plugins will need some additional "private" data fields.
These should be simply added at the end of the plugin structure.
For example a demuxer plugin called "foo" with two private
fields "xine" and "count" may have a plugin structure declared in
the following way:
<programlisting>
typedef struct {
/* public fields "inherited" from demux.h */
demux_plugin_t demux_plugin;
xine_t *xine;
int count;
} demux_foo_t;
</programlisting>
</para>
<para>
The plugin would then access public fields via the
<varname>demux_plugin</varname> field and private fields directly.
</para>
</sect1>
</chapter>
<chapter id="input"><title>Extending xine's input</title>
<sect1>
<title>Adding support for a new file format (writing a demuxer)</title>
<para>
Use an existing demuxer plugin, e.g. demux_mpeg_block
as an example.
</para>
<para>
Demuxers need to start/stop their own thread for performance reasons
(input plugins may block and if the demuxer runs in a seperate
thread other xine modules can work during blocking time).
</para>
<para>
You need to implement all the functions given in demux.h:
<programlisting>
struct demux_plugin_s
{
/*
* plugin interface version, lower versions _may_ be supported
*/
int interface_version;
/*
* ask demuxer to open the given stream (input-plugin)
* using the content-detection method specified in "stage"
*
* return values:
* DEMUX_CAN_HANDLE on success
* DEMUX_CANNOT_HANDLE on failure
*/
int (*open) (demux_plugin_t *this, input_plugin_t *ip,
int stage);
/*
* start demux thread
*
* for seekable streams, a start position can be specified
*
* start_pos : position in input source
* start_time : position measured in seconds from stream start
*
* if both parameters are !=0 start_pos will be used
* for non-seekable streams both values will be ignored
*/
void (*start) (demux_plugin_t *this, fifo_buffer_t *video_fifo,
fifo_buffer_t *audio_fifo,
off_t start_pos, int start_time);
/*
* stop & kill demux thread, free resources associated with current
* input stream
*/
void (*stop) (demux_plugin_t *this) ;
/*
* close demuxer, free all resources
*/
void (*close) (demux_plugin_t *this) ;
/*
* returns DEMUX_OK or DEMUX_FINISHED
*/
int (*get_status) (demux_plugin_t *this) ;
/*
* return human readable identifier for this plugin
*/
char* (*get_identifier) (void);
/*
* return MIME types supported for this plugin
*/
char* (*get_mimetypes) (void);
/*
* estimate stream length in seconds
* may return 0 for non-seekable streams
*/
int (*get_stream_length) (demux_plugin_t *this);
} ;
</programlisting>
</para>
<para>
Demuxer plugins export only one function:
<programlisting>
demux_plugin_t *init_demux_plugin (int iface_version, xine_t *xine);
</programlisting>
this is called on startup when the demuxer plugin is loaded.
The funtion should malloc() a demux_plugin_t* pointer,
fill in the function pointers and return the demux_plugin_t * pointer.
</para>
</sect1>
<sect1>
<title>Adding support for a new audio/video format
(writing a decoder)</title>
<para></para>
</sect1>
<sect1>
<title>Adding support for a new media type,
e.g. disc format, network transport method
(writing an input plugin)</title>
<para></para>
</sect1>
</chapter>
<chapter id="output"><title>Extending xine's output</title>
<sect1>
<title>Adding support for a new type of video output
(e.g. framebuffer device)</title>
<para>
In order to allow for device-dependant acceleration features, xine
calls upon the video output plugin for more than just displaying
images. The tasks performed by the video plugins are:
</para>
<para>
<itemizedlist>
<listitem>
<para>Allocation of a <type>vo_frame_s</type> structure and its
subsequent destruction.
</para>
</listitem>
<listitem>
<para>Allocation of memory for use by one frame (this is to allow
for the ability of some video output plugins to map frames directly
into video-card memory hence removing the need for the frame to
be copied across the PCI/AGP bus at display time).
</para>
</listitem>
<listitem>
<para>Most importantly, the ability to render/copy a given
frame to the output device.
</para>
</listitem>
<listitem>
<para>(Optional) The copying of the frame from a file dependant
colour-space and depth into the frame structure. This is to allow for
on-the fly
colour-space conversion and scalaing if required (e.g. the XShm
ouput plugin uses this mechanism).
</listitem>
</itemizedlist>
</para>
<para>
Although these extra responsibilities add great complexity to your
plugin it should be noted that they allow plugins to take full advantage
of any special hardware-acceleration without sacrificing flexibility.
</para>
<para>
All video plugins take the form of a shared library which exports at least
the functions <function>init_video_out_plugin()</function> and
<function>get_video_out_plugin_info()</function> which
returns a pointer to a <type>vo_info_s</type>. This structure has the
following declaration:
</para>
<programlisting>
struct vo_info_s {
int interface_version; /* plugin interface version */
char *id; /* id of this plugin */
char *description; /* human-readable description of this plugin */
int visual_type; /* visual type supported by this plugin */
int priority; /* priority of this plugin for auto-probing */
};</programlisting>
<para>
At the time of writing, the current interface version was `3' but
you may wish to look at an existing plugin's source-code to check.
</para>
<para>
The <varname>visual_type</varname> field is used by the Xine UI to
determine if it is supported by the UI (e.g. X11 output plugins require
the GUI to be running under the X Windowing system) and also to
determine the information passed to the
<function>init_video_out_plugin()</function> function.
The library must also export this function and it has the following
declaration:
</para>
<programlisting>
vo_driver_t *init_video_out_plugin (config_values_t *config, void *visual_gen)</programlisting>
<para>
The arguments to the function are as follows
</para>
<itemizedlist>
<listitem>
<para><varname>config</varname> -- A pointer to an object which
allows you to register, change and access configuration information.
See elsewhere in this document for more information.</para>
</listitem>
<listitem>
<para><varname>visual_gen</varname> -- A pointer to a visual-dependant
structure/variable. For example, if you had previously claimed your
plugin was of the VISUAL_TYPE_X11 type, this would be a pointer
to the <type>Display</type> variable associated with the
X-server xine is running under. See plugin source-code for other
VISUAL_TYPE_... constants and associated structures. Note that this
field is provided by the UI and so if you wish to add another visual
type you will either need to extend an existing UI or write a new
one.</para>
</listitem>
</itemizedlist>
<para>
The function creates and returns a pointer to a <type>vo_driver_s</type>
structure which contains the following function pointers:
</para>
<programlisting>
struct vo_driver_s {
uint32_t (*get_capabilities) (vo_driver_t *this); /* for constants see above */
/*
* allocate an vo_frame_t struct,
* the driver must supply the copy, field and dispose functions
*/
vo_frame_t* (*alloc_frame) (vo_driver_t *this);
/*
* check if the given image fullfills the format specified
* (re-)allocate memory if necessary
*/
void (*update_frame_format) (vo_driver_t *this, vo_frame_t *img,
uint32_t width, uint32_t height,
int ratio_code, int format, int flags);
/* display a given frame */
void (*display_frame) (vo_driver_t *this, vo_frame_t *vo_img);
/* overlay functions */
void (*overlay_blend) (vo_driver_t *this, vo_frame_t *vo_img, vo_overlay_t *overlay);
/*
* these can be used by the gui directly:
*/
int (*get_property) (vo_driver_t *this, int property);
int (*set_property) (vo_driver_t *this,
int property, int value);
void (*get_property_min_max) (vo_driver_t *this,
int property, int *min, int *max);
/*
* general purpose communication channel between gui and driver
*
* this should be used to propagate events, display data, window sizes
* etc. to the driver
*/
int (*gui_data_exchange) (vo_driver_t *this, int data_type,
void *data);
void (*exit) (vo_driver_t *this);
vo_info_t* (*get_info) ();
};</programlisting>
<para>
The <varname>get_info</varname> field is simply a pointer to the
<function>get_video_out_plugin_info()</function> function described
above.
</para>
<para>
The <varname>get_capbilities</varname> field points to a function
which returns a bit-wise ORed combination of the following constants
which reflects the video output plugin's capabilities.
</para>
<programlisting>
#define VO_CAP_COPIES_IMAGE 0x00000001 /* driver will copy image rather than providing */
/* a buffer for xine to write the image into */
#define VO_CAP_RGB 0x00000002 /* driver can handle 24bit rgb pictures */
#define VO_CAP_YV12 0x00000004 /* driver can handle YUV 4:2:0 pictures */
#define VO_CAP_YUY2 0x00000008 /* driver can handle YUY2 pictures */
#define VO_CAP_HUE 0x00000010 /* driver can set HUE value */
#define VO_CAP_SATURATION 0x00000020 /* driver can set SATURATION value */
#define VO_CAP_BRIGHTNESS 0x00000040 /* driver can set BRIGHTNESS value */
#define VO_CAP_CONTRAST 0x00000080 /* driver can set CONTRAST value */
#define VO_CAP_COLORKEY 0x00000100 /* driver can set COLORKEY value */
#define VO_CAP_AUTOPAINT_COLORKEY 0x00000200 /* driver can set AUTOPAINT_COLORKEY value */</programlisting>
<para>
A plugin should use the VO_CAP_COPIES_IMAGE flag if it wishes to provide a
copy function to perform on-the-fly colour-space conversion and
scaling.
</para>
<para>
The <varname>get_property</varname>, <varname>set_proprty</varname> and
<varname>get_property_min_max</varname> fields point to functions which
handle the getting, setting of properties and define their bounds.
Valid property IDs can be found in the <filename>video_out.h</filename>
header file.
</para>
<para>
The <varname>gui_data_exchange</varname> field points to a function which can
accept various forms of data from the UI (e.g. the mouse has moved or the
window has been hidden). Look at existing plugins for examples of data
exchanges from various UIs.
</para>
<para>
The <varname>alloc_frame</varname> field points to a function which returns
a pointer to a <type>vo_frame_s</type> structure which is defined as:
</para>
<programlisting>
/* public part, video drivers may add private fields */
struct vo_frame_s {
struct vo_frame_s *next;
uint32_t PTS;
uint32_t pts_corrector; /* Repeat first field tricks */
uint32_t SCR;
int bad_frame; /* e.g. frame skipped or based on skipped frame */
int drawn;
uint8_t *base[3];
/* additional information to be able to duplicate frames: */
int width, height;
int ratio, format;
int duration;
int aspect_ratio;
int frame_rate_code;
int progressive_sequence;
int top_field_first;
int repeat_first_field;
int progressive_frame;
int picture_coding_type;
int bitrate;
int display_locked, decoder_locked, driver_locked;
pthread_mutex_t mutex; /* so the various locks will be serialized */
vo_instance_t *instance;
/*
* member functions
*/
/* this frame is no longer used by decoder */
void (*free) (vo_frame_t *vo_img);
/* tell video driver to copy/convert a slice of this frame */
void (*copy) (vo_frame_t *vo_img, uint8_t **src);
/* tell video driver that the decoder starts a new field */
void (*field) (vo_frame_t *vo_img, int which_field);
/* append this frame to the display queue,
returns number of frames to skip if decoder is late */
int (*draw) (vo_frame_t *vo_img);
/* this frame is no longer used by the video driver */
void (*displayed) (vo_frame_t *vo_img);
/* free memory/resources for this frame */
void (*dispose) (vo_frame_t *vo_img);
}</programlisting>
<para>
Typically the video plugin will add private fields to the end of this structure
which are used for internal purposes by the plugin.
</para>
<para>
The function pointers within the frame structure provides a mechanism for the
driver to retain full control of how the frames are managed and rendered to. If
the VO_CAP_COPIES_IMAGE flag was set in the plugins capabilities then the
copy field is required and will be called sequentially for each 16-pixel high
strip in the image. The plugin may then decide, based on the frame's format, how
this is copied into the frame.
</para>
<para>
Returning to the <type>vo_driver_s</type> structure, the
<function>update_frame_format</function> field points to a function which will
be called each time the colour-depth/space or size of a frame changes. Typically
this function would allocate sufficient memory for the frame, assign the pointers
to the individual planes of the frame to the <varname>base</varname> field of the
frame and perform and driver-specific changes.
</para>
<para>
The <varname>display_frame</varname> field points to a function to render a
given frame to the output device.
</para>
<para>
The <varname>overlay_blend</varname> field points to a function which accepts
an association between a frame and overlay which will result in the latter
being overlayed on the former.
</para>
</sect1>
<sect1>
<title>Adding support for a new type of audio output</title>
<para></para>
</sect1>
</chapter>
<chapter id="xine-library"><title>Using xine as a library</title>
<sect1>
<title>Writing a new frontend to xine</title>
<para></para>
</sect1>
</chapter>
<chapter id="misc"><title>misc</title>
<sect1>
<title>Coding style and guidelines</title>
<para>
This section contains some guidelines for writing xine-code.
These are really just guidelines, no strict rules.
Contributions will not be rejected if they do not meet these
rules but they will be appreciated if they do.
<itemizedlist>
<listitem>
<para>
when in doubt, use lower case. BTW: This thing is called xine, never Xine.
</para>
</listitem>
<listitem>
<para>
comment your interfaces in the header files.
</para>
</listitem>
<listitem>
<para>
use expressive variable and function identifiers on all public interfaces.
use underscores to seperate words in identifiers, not uppercase
letters (my_function_name is ok, myFunctionName is not ok).
</para>
</listitem>
<listitem>
<para>
avoid macros if possible. avoid gotos.
</para>
</listitem>
<listitem>
<para>
use
<programlisting>
#ifdef LOG
printf ("module: ..."[,...]);
#endif
</programlisting>
for debug output. All debug output must be prefixed by the module
name which generates the output (see example above).
</para>
</listitem>
<listitem>
<para>
refer to emac's c-mode for all questions of proper indentiation.
</para>
</listitem>
<listitem>
<para>
use c-style comments (/* */), not c++-style (//)
</para>
</listitem>
</itemizedlist>
</para>
</sect1>
<sect1>
<title>How to contribute</title>
<para>
Make sure you send your patches in unified diff format to
the xine-devel mailing list (you'll have to subscribe first,
otherwise you're not allowed to post). Please do not send
patches to individual developers unless otherwise instructed
because your patch is more likely to get lost in an overfull
INBOX in that case. Please be patient, it may take 1-2 weeks
before you hear any comments on your work (developers may be
working on other parts of the code or are simply busy at
the moment).
</para>
</sect1>
</chapter>
</book>
|