xine code overview Walking the source tree The src/ directory in xine-lib contains several modules, this should give you a quick overview on where to find what sources. Directories marked with "(imported)" contain code that is copied from an external project into xine-lib. Everything below such a directory is up to this project. When modifying code there, be sure to send the patches on. If some xine specific adaptation of the code is absolutely necessary, a patch containing the changes should be stored in Mercurial to not lose the changes the next time we sync with the external project. audio_out Audio output plugins. These provide a thin abstraction layer around different types of audio output architectures or platforms. Basically an audio output plugin provides functions to query and setup the audio hardware and output audio data (e.g. PCM samples). demuxers Demuxer plugins that handle various system layer file formats like avi, asf or mpeg. The ideal demuxer know nothing about where the data comes from and who decodes it. It should basically just unpack it into chunks the rest of the engine can eat. dxr3 Code to support the DXR3 / hollywood+ hardware mpeg decoder. input Input plugins encapsulate the origin of the data. Data sources like ordinary files, DVDs, CDA or streaming media are handled here. dvb Some headers for Digital Video Broadcast. libdvdnav (imported) The libdvdnav library for DVD navigation is used by xine's DVD input plugin. libreal, librtsp Support for RealMedia streaming as used by the RTSP input plugin. vcd The enhanced VCD input plugin which also handles VCD navigation. libcdio, libvcd (imported) Libraries used by the enhanced VCD plugin. liba52 (imported) A52 (aka AC3, aka Dolby Digital) audio decoder library and xine plugin. We maintain some small integration improving differences between the original liba52 and our copy in the file diff_against_release.patch. libdts (imported) AC5 (aka DTS) audio decoder library and xine plugin, which is capable of software decoding as well as digital passthrough. libfaad (imported) The Free AAC Decoder library and xine plugin. libffmpeg A xine decoder plugin using various audio and video decoders from the ffmpeg decoder pack libavcodec. Their MPEG encoder is also for the DXR3. To optimize the integration of libavcodec and the xine engine, we maintain some differences between the original ffmpeg and our copy in the file diff_to_ffmpeg_cvs.txt. libavcodec (imported) The libavcodec decoder pack as used by xine's ffmpeg plugin. libflac A xine demuxer and decoder plugin for the Free Lossless Audio Codec library, which has to be installed separately. liblpcm Audio decoder plugin that "decodes" raw PCM data; most notably endianess-conversions are done here. libmad (imported) Mpeg audio decoder plugin (i.e. mp2 and mp3 decoding). ISO/IEC compliant decoder using fixed point math. libmpeg2 (imported) Most important MPEG video decoder plugin, provides fast and high-precision MPEG-1/2 video decoding. Although this is an imported library, we have heavily modified our internal copy to blend it as seamlessly as possible into the xine engine in order to get the maximum MPEG decoding performance. libmpeg2new James started an effort to bring a recent and unmodified version of libmpeg2 into xine to one day replace our current internal modified libmpeg2 with one closer to the original. But since the full feature catalog has not yet been achieved with the new one, it is still disabled. include, libmpeg2 (imported) The code of the imported new libmpeg2. libreal A thin wrapper around Real's binary codecs from the Linux RealPlayer to use them as a xine plugin. libspeex A xine decoder plugin for the speex library, which has to be installed separately. libspucc Closed caption subtitle decoder plugin. libspudec DVD SPU subtitle decoder plugin. libsputext Plain text subtitle decoder plugins. libtheora A xine decoder plugin for the theora library, which has to be installed separately. libvorbis A xine decoder plugin for the ogg/vorbis library, which has to be installed separately. libw32dll Video and audio decoder plugins that exploit some wine code to use win32 (media player and Quicktime) codecs in xine. Works on x86 platforms only. DirectShow, dmo, qtx, wine (imported) Stripped down version of wine to support Video for Windows DLLs and additional code to use DirectShow, DMO and QuickTime DLLs. libxineadec xine's decoder pack of additional audio decoders. gsm610 (imported) The gsm610 audio decoder library as used by the related xine plugin. nosefart (imported) The nosefart audio decoder library as used by the related xine plugin. libxinevdec xine's decoder pack of additional video decoders. post Video and audio post effect plugins live here. Post plugins modify streams of video frames or audio buffers as they leave the decoder to provide conversion or effects. audio Some audio effects as xine audio filter posts. deinterlace (imported) The tvtime deinterlacer as a xine video filter post. goom (imported) The goom audio visualizer as a xine visualizer post. mosaico Some post plugins merging multiple frames into one. For example picture in picture can be done with this. planar Some simple 2D video effects as xine video filter posts. visualizations Audio visualization post plugins. video_out 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. libdha (imported) A library for direct hardware access to the graphics card as used by the vidix video out plugin. vidix (imported) The vidix system for high performance video output as used by the vidix video out plugin. xine-engine The heart of xine – its engine. Contains code to load and handle all the plugins, the configuration repository as well as the generic decoding loops and code for synchronized output. A lot of helper functions for plugins to use live here as well. What's in the individual files should be guessable by the files' names. This document is not going to explain the source, because it simply changes too often. A look at the architectural drawing in the internals section should give you a pretty good idea, what to expect in this directory. Basically, everything in this picture that is not called "plugin" lives here. xine-utils Collection of utility functions and platform abstractions. Also contains a simple XML parser for frontend playlist handling. Object oriented programming in C 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. Classes are structs containing function pointers and public member data. Example:    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(void); To derive from such a class, private member variables can be added:    typedef struct {     my_stack_t stack; /* public part */         /* private part follows here */     int values[MAX_STACK_SIZE];     int stack_size;    } intstack_t; 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:    static void push (my_stack_t *this_gen, int i) {     intstack_t *this = (intstack_t *)this_gen;     this->values[MAX_STACK_SIZE - ++this->stack_size] = i;    } The part added to the derived class is private, because when defining the new structure directly in the .c file, where it will be used, outside modules have no way of seeing the definition of the derived class. A public derivation is possible by defining the above structure in a .h file for others to include. Something similar to a protected, package or friend visibility is also possible:    struct my_stack_s {     void (*push)(my_stack_t *this, int i);     void (*add)(my_stack_t *this);     int (*pop)(my_stack_t *this);        #ifdef STACK_INTERNAL     void (*flush)(my_stack_t *this);    #endif    }; All modules, who need to access the internal part have to add    #define STACK_INTERNAL before including the header with the definition. It is clear that only those friend modules can derive from this class. Finally the contructor malloc()s the data struct (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:    my_stack_t *new_my_stack(void) {     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;         /* return public part */     return &this->stack;    } Why not using C++? After all these considerations about object oriented C, you might ask, why we do not use C++ after all? The easy answer would be: xine wants to be as fast as possible and C++ is simply too slow. But this is only the easy answer and it is not entirely true any more. Thoughtfully applied, you can write very fast C++ code with today's compilers, but these compilers might not be available on all platforms in the necessary quality. Even with a sophisticated compiler, C++ is much harder to optimize than plain C and thus C compiles much faster. Another big problem is that the C++ ABI is not as well-defined as the C ABI. With C, you can easily mix libraries and applications built by different compilers. With C++, this is unlikely to work. But the final argument is that xine does not really need C++. xine's inheritance hierarchy is very flat, mostly one level only and does not need things like multiple or virtual inheritance. Most of the external projects that are used by xine are plain C as well and using more than one language complicates the build system. As we saw above, we can emulate object orientation reduced to our real needs in plain C. Coding style and guidelines 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 even more appreciated if they do. Comment your interfaces directly in the header files. No doxygen comments, ordinary C comments will do. Use C-style comments (/* */), not C++-style (//). When in doubt, use lower case. BTW: This thing is called xine, never Xine. 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). Avoid macros unless they are really useful. Avoid gotos. use something like    printf("module: ..."[,…]); for console output. All console output goes to stdout and must be prefixed by the module name which generates the output (see example above). Refer to emac's C-mode for all questions of proper indentiation. That first of all means: indent with two spaces. The xine logging system xine offers a wide range of possibilities to display strings. This section should describe when to use which way and how to do it right. xine_log Output which is done thru this function will be displayed for the end user by the frontend. If xine->verbosity is not 0 the messages will also be displayed on the console. Ideally these strings are translated. This function is for information which the user should read always.    xine_log(xine_t *xine, int buf, const char *format, ...); buf is either XINE_LOG_MSG for general messages or XINE_LOG_PLUGIN for messages about plugins. xprintf This macro uses the xine->verbosity value to decide if the string should be printed to the console. Possible values are XINE_VERBOSITY_NONE, XINE_VERBOSITY_LOG or XINE_VERBOSITY_DEBUG. By default nothing is printed. When you use xine-ui you can enable this output with the --verbose=[1,2] options. This function should be used for information which the user should only read up on request.    xprintf(xine_t *xine, int verbosity, const char *format, ...); lprintf/llprintf These macros are for debugging purpose only. Under normal circumstances it is disabled. And can only be enabled by changing a define statement and a recompilation. It has to be enabled for these files that are of interest. It should only be used for information which is intended for developers.    lprintf(const char *format, ...);    llprintf(bool, const char *format, ...); bool is a flag which enables or disables this logging. lprintf can be enabled by defining LOG at the top of the source file. llprintf can be used for more than one categorie per file by using diffent lables:    #define LOG_LOAD 1    #define LOG_SAVE 0        llprintf(LOG_LOAD, "loading was successful\n");    llprintf(LOG_SAVE, "could not save to file %s\n", filename); In this case only the first messages is printed. To enable/disable change the defines. LOG_MODULE should be used to set the modulename for xprintf/lprintf/llprintf. Each output line will start with "modulename: ".    #define LOG_MODULE "modulename" LOG_VERBOSE can be defined to enable the logging of functionname and linenumbers. Then the output will be: "modulename: (function_name:42) message". _x_assert/_x_abort These are not purely logging functions, but despite their original C library versions, they always output debugging text, which is why usage of these functions is preferred. _x_assert() checks a condition and prints a note, when the condition is false. In addition, a debug build and only a debug build will terminate the application, when the condition is false. Release versions will only print the note, but try to continue. _x_abort() always terminates the application after printing a note. How to contribute 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 instructed otherwise 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). We prefer to receive patches in a format which is immediately committable. This normally means that we want your name and email address (we're not keen on pseudonyms), a subject line which provides a convenient summary of your changes, and body text which provides a longer description (if needed). There are a few ways to submit your patches: hg diff is probably the easiest. You'll need a subject line and body text as described above. If you're copying or renaming files, or a file should be marked as executable, then use hg diff --git; this will include the necessary information (if copying or renaming, you need to have used hg copy or hg rename for this to work). If you're attaching the patch (recommended), then including the metadata in the patch file is recommended, e.g. From: Fred Patcher <patcher@example.com> Subject: Properly toggle the randomiser switch The randomiser switch was sometimes not being toggled, leading to random behaviour. diff --git a/foo/control.c b/foo/control.c ... diff -u is also acceptable, but we prefer that you do so from the top-level directory within the source code (prefix the files' path names with ./) or from the directory containing the source code directory. Basically, use hg diff if you can. hg email is preferred. You'll need to commit your changes locally for this to work, but this is the easiest way of sending a set of patches for inclusion and review; it'll send the mail directly. hg export can also be used with specific changeset identifiers. Again, you'll need to commit your changes locally for this to work. Patches should normally be included as attachments. Some mail clients and webmail services are known to mangle whitespace or wrap lines, either of which is enough to render a patch potentially useless.