00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifdef HAVE_CONFIG_H
00022 #include <config.h>
00023 #endif
00024
00025
00026 #include <iostream>
00027 #include <fstream>
00028 #include <sstream>
00029 #include <string>
00030 #include <list>
00031 #include <map>
00032
00033 using std::cerr;
00034 using std::endl;
00035 using std::ends;
00036 using std::ofstream;
00037 using std::ostringstream;
00038 using std::list;
00039 using std::map;
00040
00041
00042 #include <libxml/xmlmemory.h>
00043 #include <libxml/parser.h>
00044 #include <libxml/tree.h>
00045 #include <pthread.h>
00046 #include <unistd.h>
00047 #include <sys/stat.h>
00048 #include <sys/types.h>
00049 #include <dirent.h>
00050
00051
00052 #include "playlist.h"
00053 #include "error.h"
00054 #include "filehandler.h"
00055 #include "frame.h"
00056 #include "stringutils.h"
00057
00058 const xmlChar* SMIL20_NAMESPACE_HREF = reinterpret_cast< const xmlChar* >( "http://www.w3.org/2001/SMIL20/Language" );
00059 const string KINO_AUTOSAVE_DIR = string( getenv("HOME") ) + string( "/.kino-history" );
00060
00065 class KinoFileMap : public FileMap
00066 {
00067 private:
00068 map < string, FileHandler* > filemap;
00069
00070 public:
00071 virtual ~KinoFileMap()
00072 {}
00073
00074 map<string, FileHandler*> &GetMap()
00075 {
00076 return filemap;
00077 }
00078
00079 void Clear( )
00080 {
00081 map<string, FileHandler*>::iterator n;
00082 for ( n = filemap.begin(); n != filemap.end(); ++n )
00083 delete ( *n ).second;
00084 filemap.erase( filemap.begin(), filemap.end() );
00085 }
00086
00087 void GetUnusedFxFiles( PlayList &list, vector< string > &unused )
00088 {
00089 unused.erase( unused.begin(), unused.end() );
00090 map<string, FileHandler*>::iterator n;
00091 for ( n = filemap.begin(); n != filemap.end(); ++n )
00092 {
00093 if ( n->first.find( ".kinofx.dv" ) != string::npos && !list.IsFileUsed( n->first ) )
00094 {
00095 unused.push_back( n->first );
00096 }
00097 }
00098 }
00099 };
00100
00104 FileMap *GetFileMap( )
00105 {
00106 static FileMap * thismap = new KinoFileMap( );
00107 return thismap;
00108 }
00109
00121 string directory_utils::join_file_to_directory( const string directory, const string &file )
00122 {
00123 vector <string> items;
00124
00125
00126 if ( file[ 0 ] != '/' && directory[ 0 ] != '/' )
00127 {
00128 char path[ PATH_MAX ];
00129 getcwd( path, PATH_MAX );
00130 StringUtils::split( path, "/", items );
00131 }
00132
00133
00134 if ( file[ 0 ] != '/' )
00135 StringUtils::split( directory, "/", items );
00136
00137
00138 StringUtils::split( file, "/", items );
00139
00140
00141 for ( vector< string >::iterator item = items.begin( ); item != items.end( ); )
00142 {
00143 if ( *item == ".." )
00144 {
00145 if ( item == items.begin( ) )
00146 {
00147 items.erase( item );
00148 item = items.begin();
00149 }
00150 else
00151 {
00152 items.erase( -- item + 1 );
00153 items.erase( -- item + 1 );
00154 item ++;
00155 }
00156 }
00157 else
00158 {
00159 item ++;
00160 }
00161 }
00162
00163 return "/" + StringUtils::join( items, "/" );
00164 }
00165
00173 string directory_utils::get_directory_from_file( const string &file )
00174 {
00175 return join_file_to_directory( "", file + "/.." );
00176 }
00177
00190 string directory_utils::get_absolute_path_to_file( const string &directory, const string &file )
00191 {
00192 return join_file_to_directory( directory, file );
00193 }
00194
00201 string directory_utils::get_relative_path_to_file( const string &directory, const string &file )
00202 {
00203 string output = "";
00204 string absolute = join_file_to_directory( directory, file );
00205 vector < string > directory_items;
00206 vector < string > absolute_items;
00207 StringUtils::split( absolute, "/", absolute_items );
00208 StringUtils::split( directory, "/", directory_items );
00209
00210 vector < string >::iterator directory_item;
00211 vector < string >::iterator absolute_item;
00212
00213
00214 for ( directory_item = directory_items.begin(), absolute_item = absolute_items.begin();
00215 directory_item != directory_items.end() && absolute_item != absolute_items.end() && *directory_item == *absolute_item; )
00216 {
00217 directory_items.erase( directory_item );
00218 absolute_items.erase( absolute_item );
00219 directory_item = directory_items.begin();
00220 absolute_item = absolute_items.begin();
00221 }
00222
00223
00224 for ( directory_item = directory_items.begin(); directory_item != directory_items.end() ; directory_item ++ )
00225 output += "../";
00226
00227
00228 output += StringUtils::join( absolute_items, "/" );
00229 return output;
00230 }
00231
00235 string directory_utils::expand_directory( const string directory )
00236 {
00237 string output;
00238 vector <string> items;
00239 StringUtils::split( directory, "/", items );
00240 vector< string >::iterator item = items.begin( );
00241
00242 if ( item != items.end( ) && *item == "~" )
00243 {
00244 output = getenv( "HOME" );
00245 item ++;
00246 }
00247
00248 for ( ; item != items.end( ); item ++ )
00249 output += "/" + *item;
00250
00251 return output;
00252 }
00253
00254 typedef bool ( *callback ) ( xmlNodePtr node, void *p, bool *freed );
00255
00256 typedef struct
00257 {
00258 int absFrame;
00259 int absBegin;
00260 int absEnd;
00261 int clipFrame;
00262 int clipBegin;
00263 int clipEnd;
00264 int clipNumber;
00265 int clipLength;
00266 char fileName[ 1024 ];
00267 xmlNodePtr sequence;
00268 xmlNodePtr video;
00269 }
00270 MovieInfo;
00271
00293 static bool findFile( xmlNodePtr node, void *p, bool *freed )
00294 {
00295 MovieInfo * data = ( MovieInfo* ) p;
00296
00297 if ( xmlStrcmp( node->name, ( const xmlChar* ) "seq" ) == 0 )
00298 {
00299 data->sequence = node;
00300 data->clipNumber++;
00301 }
00302
00303
00304
00305 else if ( xmlStrcmp( node->name, ( const xmlChar* ) "video" ) == 0 )
00306 {
00307
00308 data->video = node;
00309
00310
00311
00312 xmlChar *src = xmlGetProp( node, ( const xmlChar* ) "src" );
00313 xmlChar *clipBegin = xmlGetProp( node, ( const xmlChar* ) "clipBegin" );
00314 xmlChar *clipEnd = xmlGetProp( node, ( const xmlChar* ) "clipEnd" );
00315
00316 if ( ( src != NULL ) && ( clipBegin != NULL ) && ( clipEnd != NULL ) )
00317 {
00318
00319 data->clipBegin = atoi( ( const char* ) clipBegin );
00320 data->clipEnd = atoi( ( const char* ) clipEnd );
00321
00322 data->absBegin += data->clipLength;
00323 data->clipLength = data->clipEnd - data->clipBegin + 1;
00324 data->absEnd = data->absBegin + data->clipLength - 1;
00325
00326
00327
00328
00329
00330
00331 if ( data->absFrame <= data->absEnd )
00332 {
00333 strcpy( data->fileName, ( char * ) src );
00334 data->clipFrame = data->absFrame - data->absBegin + data->clipBegin;
00335
00336
00337 xmlFree( src );
00338 xmlFree( clipEnd );
00339 xmlFree( clipBegin );
00340
00341
00342
00343 return true;
00344 }
00345 }
00346
00347 if ( src )
00348 xmlFree( src );
00349 if ( clipEnd )
00350 xmlFree( clipEnd );
00351 if ( clipBegin )
00352 xmlFree( clipBegin );
00353
00354 }
00355 return false;
00356 }
00357
00358
00365 static bool fillMap( xmlNodePtr node, void *p, bool *freed )
00366 {
00367 if ( xmlStrcmp( node->name, ( const xmlChar* ) "video" ) == 0 )
00368 {
00369
00370
00371
00372 xmlChar * src = xmlGetProp( node, ( const xmlChar* ) "src" );
00373 xmlChar *clipBegin = xmlGetProp( node, ( const xmlChar* ) "clipBegin" );
00374 xmlChar *clipEnd = xmlGetProp( node, ( const xmlChar* ) "clipEnd" );
00375
00376 if ( ( src != NULL ) && ( clipBegin != NULL ) && ( clipEnd != NULL ) )
00377 {
00378
00379
00380 string & directory = *( string * ) p;
00381 string index = directory_utils::get_absolute_path_to_file( directory, ( char * ) src );
00382
00383
00384 xmlSetProp( node, ( const xmlChar* ) "src", ( xmlChar * ) index.c_str() );
00385
00386
00387 if ( GetFileMap() ->GetMap().find( index ) == GetFileMap() ->GetMap().end() )
00388 {
00389
00390 FileHandler * mediaFile;
00391
00392 if ( strncasecmp( strrchr( ( char* ) src, '.' ), ".avi", 4 ) == 0 )
00393 mediaFile = new AVIHandler();
00394 else if ( strncasecmp( strrchr( ( char* ) src, '.' ), ".dv", 3 ) == 0 ||
00395 strncasecmp( strrchr( ( char* ) src, '.' ), ".dif", 4 ) == 0 )
00396 mediaFile = new RawHandler();
00397 #ifdef HAVE_LIBQUICKTIME
00398
00399 else if ( strncasecmp( strrchr( ( char* ) src, '.' ), ".mov", 4 ) == 0 )
00400 mediaFile = new QtHandler();
00401 #endif
00402
00403 else
00404 {
00405 xmlFree( src );
00406 xmlFree( clipEnd );
00407 xmlFree( clipBegin );
00408 return false;
00409 }
00410
00411 if ( mediaFile->Open( index.c_str() ) )
00412 {
00413 GetFileMap() ->GetMap() [ index ] = mediaFile;
00414 }
00415 else
00416 {
00417 cerr << "Unable to open " << ( char * ) src
00418 << " - removing from list" << endl;
00419 xmlUnlinkNode( node );
00420 xmlFreeNode( node );
00421 *freed = true;
00422 }
00423 }
00424 }
00425
00426 xmlFree( src );
00427 xmlFree( clipEnd );
00428 xmlFree( clipBegin );
00429 }
00430 return false;
00431 }
00432
00433
00443 static bool findSceneStart( xmlNodePtr node, void *p, bool *freed )
00444 {
00445 int fileCount = 0;
00446 MovieInfo *data = ( MovieInfo* ) p;
00447 int begin = data->absBegin;
00448
00449
00450
00451 if ( xmlStrcmp( node->name, ( const xmlChar* ) "seq" ) == 0 )
00452 {
00453
00454 data->sequence = node;
00455
00456 node = node->children;
00457 while ( node != NULL )
00458 {
00459 if ( xmlStrcmp( node->name, ( const xmlChar* ) "video" ) == 0 )
00460 {
00461
00462 data->video = node;
00463
00464 xmlChar *src = xmlGetProp( node, ( const xmlChar* ) "src" );
00465 xmlChar *clipBegin = xmlGetProp( node, ( const xmlChar* ) "clipBegin" );
00466 xmlChar *clipEnd = xmlGetProp( node, ( const xmlChar* ) "clipEnd" );
00467
00468 if ( ( src != NULL ) && ( clipBegin != NULL ) && ( clipEnd != NULL ) )
00469 {
00470
00471 data->clipBegin = atoi( ( const char* ) clipBegin );
00472 data->clipEnd = atoi( ( const char* ) clipEnd );
00473
00474
00475
00476 if ( fileCount == 0 )
00477 {
00478 data->clipFrame = data->clipBegin;
00479 strcpy( data->fileName, ( char * ) src );
00480 }
00481
00482
00483
00484
00485
00486 if ( data->absFrame <= begin + data->clipEnd - data->clipBegin )
00487 {
00488 xmlFree( clipBegin );
00489 xmlFree( clipEnd );
00490 xmlFree( src );
00491 return true;
00492 }
00493 else
00494 {
00495 begin += ( data->clipEnd - data->clipBegin + 1 );
00496 }
00497 fileCount++;
00498 }
00499 if ( src )
00500 xmlFree( src );
00501 if ( clipEnd )
00502 xmlFree( clipEnd );
00503 if ( clipBegin )
00504 xmlFree( clipBegin );
00505 }
00506 node = node->next;
00507 }
00508 }
00509 data->absBegin = begin;
00510 data->clipFrame = 0;
00511 strcpy( data->fileName, "" );
00512 return false;
00513 }
00514
00515
00516 static bool findSceneEnd( xmlNodePtr node, void *p, bool *freed )
00517 {
00518 bool found = false;
00519 xmlChar *src = NULL;
00520 MovieInfo *data = ( MovieInfo* ) p;
00521
00522
00523
00524 if ( xmlStrcmp( node->name, ( const xmlChar* ) "seq" ) == 0 )
00525 {
00526
00527 data->sequence = node;
00528
00529 node = node->children;
00530 while ( node != NULL )
00531 {
00532 if ( xmlStrcmp( node->name, ( const xmlChar* ) "video" ) == 0 )
00533 {
00534
00535 data->video = node;
00536
00537 if ( src )
00538 xmlFree( src );
00539
00540 src = xmlGetProp( node, ( const xmlChar* ) "src" );
00541 xmlChar *clipBegin = xmlGetProp( node, ( const xmlChar* ) "clipBegin" );
00542 xmlChar *clipEnd = xmlGetProp( node, ( const xmlChar* ) "clipEnd" );
00543
00544 if ( ( src != NULL ) && ( clipBegin != NULL ) && ( clipEnd != NULL ) )
00545 {
00546
00547 data->clipBegin = atoi( ( const char* ) clipBegin );
00548 data->clipEnd = atoi( ( const char* ) clipEnd );
00549 data->clipFrame = data->clipEnd;
00550
00551 if ( data->absFrame <= data->absBegin + data->clipEnd - data->clipBegin )
00552 found = true;
00553 data->absBegin += ( data->clipEnd - data->clipBegin + 1 );
00554 }
00555
00556 if ( clipEnd )
00557 xmlFree( clipEnd );
00558 if ( clipBegin )
00559 xmlFree( clipBegin );
00560 }
00561 node = node->next;
00562 }
00563
00564 if ( found )
00565 {
00566 strcpy( data->fileName, ( char * ) src );
00567 xmlFree( src );
00568 data->absEnd = data->absBegin - 1;
00569 return true;
00570 }
00571
00572 if ( src )
00573 xmlFree( src );
00574 }
00575 data->clipFrame = 0;
00576 strcpy( data->fileName, "" );
00577 return false;
00578 }
00579
00594 static bool countFrames( xmlNodePtr node, void *p, bool *freed )
00595 {
00596 if ( xmlStrcmp( node->name, ( const xmlChar* ) "video" ) == 0 )
00597 {
00598
00599 xmlChar * src = xmlGetProp( node, ( const xmlChar* ) "src" );
00600 xmlChar *clipBegin = xmlGetProp( node, ( const xmlChar* ) "clipBegin" );
00601 xmlChar *clipEnd = xmlGetProp( node, ( const xmlChar* ) "clipEnd" );
00602
00603 if ( ( src != NULL ) && ( clipBegin != NULL ) && ( clipEnd != NULL ) )
00604 * ( ( int* ) p ) += atoi( ( const char* ) clipEnd ) - atoi( ( const char* ) clipBegin ) + 1;
00605
00606 if ( clipEnd )
00607 xmlFree( clipEnd );
00608 if ( clipBegin )
00609 xmlFree( clipBegin );
00610 if ( src )
00611 xmlFree( src );
00612 }
00613 return false;
00614 }
00615
00617 typedef struct
00618 {
00619 string file;
00620 string clipBegin;
00621 string clipEnd;
00622 }
00623 EliInfo;
00624
00625 typedef list<EliInfo> EliInfos;
00626 typedef EliInfos::iterator EliInfosIterator;
00627
00640 static bool convertEli( xmlNodePtr node, void *p, bool *freed )
00641 {
00642 if ( xmlStrcmp( node->name, ( const xmlChar* ) "video" ) == 0 )
00643 {
00644
00645 xmlChar * src = xmlGetProp( node, ( const xmlChar* ) "src" );
00646 xmlChar *clipBegin = xmlGetProp( node, ( const xmlChar* ) "clipBegin" );
00647 xmlChar *clipEnd = xmlGetProp( node, ( const xmlChar* ) "clipEnd" );
00648
00649 if ( ( src != NULL ) && ( clipBegin != NULL ) && ( clipEnd != NULL ) )
00650 {
00651
00652
00653
00654
00655 EliInfos * Eli = ( EliInfos * ) p;
00656 EliInfo tmp;
00657 tmp.file = ( const char* ) src;
00658 tmp.clipBegin = ( const char* ) clipBegin;
00659 tmp.clipEnd = ( const char* ) clipEnd;
00660 Eli->push_back( tmp );
00661 }
00662
00663 if ( clipEnd )
00664 xmlFree( clipEnd );
00665 if ( clipBegin )
00666 xmlFree( clipBegin );
00667 if ( src )
00668 xmlFree( src );
00669 }
00670 return false;
00671 }
00672
00673 class SrtContext
00674 {
00675 public:
00676 ofstream file;
00677 unsigned counter;
00678 xmlChar* title;
00679 xmlChar* abstract;
00680 xmlChar* src;
00681 unsigned begin;
00682 unsigned duration;
00683
00684 SrtContext( const char* filename ) :
00685 file(filename), counter(0), title(NULL), abstract(NULL), src(NULL),
00686 begin(0), duration(0)
00687 {
00688 }
00689
00690 ~SrtContext()
00691 {
00692 printEntry();
00693 file.close();
00694 }
00695
00696 void printEntry(void)
00697 {
00698 if ( title || abstract )
00699 {
00700 Frame *frame = GetFramePool( )->GetFrame( );
00701 FileHandler *mediaFile = GetFileMap()->GetMap() [ string( ( const char* ) src ) ];
00702 SMIL::MediaClippingTime time;
00703
00704 mediaFile->GetFrame( *frame, 0 );
00705 time.setFramerate( frame->GetFrameRate() );
00706 GetFramePool( )->DoneWithFrame( frame );
00707 string beginString = time.parseFramesToString( begin, SMIL::Time::TIME_FORMAT_CLOCK );
00708 string durationString = time.parseFramesToString( duration - begin, SMIL::Time::TIME_FORMAT_CLOCK );
00709 begin = 0;
00710
00711 file << ++counter << endl;
00712 file << StringUtils::replaceAll( beginString, ".", "," );
00713 file << " --> " << StringUtils::replaceAll( durationString, ".", "," ) << endl;
00714 if ( title )
00715 file << title << endl;
00716 if ( abstract )
00717 file << abstract << endl;
00718 file << endl;
00719 }
00720 if ( src )
00721 {
00722 xmlFree( src );
00723 src = NULL;
00724 }
00725 if ( title )
00726 {
00727 xmlFree( title );
00728 title = NULL;
00729 }
00730 if ( abstract )
00731 {
00732 xmlFree( abstract );
00733 abstract = NULL;
00734 }
00735 }
00736 };
00737
00738 static bool convertSrt( xmlNodePtr node, void *data, bool *freed )
00739 {
00740 SrtContext* srt = static_cast< SrtContext* >( data );
00741
00742 if ( xmlStrcmp( node->name, ( const xmlChar* ) "seq" ) == 0 )
00743 {
00744 srt->printEntry();
00745 srt->title = xmlGetProp( node, ( const xmlChar * ) "title" );
00746 srt->abstract = xmlGetProp( node, ( const xmlChar * ) "abstract" );
00747 }
00748 else if ( xmlStrcmp( node->name, ( const xmlChar* ) "video" ) == 0 )
00749 {
00750 xmlChar* clipBegin = xmlGetProp( node, ( const xmlChar* ) "clipBegin" );
00751 xmlChar* clipEnd = xmlGetProp( node, ( const xmlChar* ) "clipEnd" );
00752
00753 srt->src = xmlGetProp( node, ( const xmlChar* ) "src" );
00754 if ( !srt->begin && ( srt->title || srt->abstract ) )
00755 srt->begin = srt->duration;
00756 srt->duration += atoi( ( const char* ) clipEnd ) - atoi( ( const char* ) clipBegin ) + 1;
00757
00758 xmlFree( clipBegin );
00759 xmlFree( clipEnd );
00760 }
00761
00762 return false;
00763 }
00764
00765 static bool convertFramesToSmilTime( xmlNodePtr node, void *data, bool *freed )
00766 {
00767 if ( xmlStrcmp( node->name, ( const xmlChar* ) "video" ) == 0 )
00768 {
00769 Frame *frame = GetFramePool( )->GetFrame( );
00770 xmlChar *src = xmlGetProp( node, ( const xmlChar* ) "src" );
00771 string index( ( char* ) src );
00772 xmlFree( src );
00773 FileHandler *mediaFile = GetFileMap()->GetMap() [ index ];
00774 mediaFile->GetFrame( *frame, 0 );
00775 SMIL::MediaClippingTime time;
00776 time.setFramerate( frame->GetFrameRate() );
00777 GetFramePool( )->DoneWithFrame( frame );
00778
00779 xmlChar *prop = xmlGetProp( node, ( const xmlChar* ) "clipBegin" );
00780 if ( prop )
00781 {
00782 std::string newValue = time.parseFramesToString( atoi( ( const char* ) prop ), SMIL::Time::TIME_FORMAT_CLOCK );
00783 xmlFree( prop );
00784 xmlSetProp( node, ( const xmlChar* ) "clipBegin", ( const xmlChar* ) newValue.c_str() );
00785 }
00786 prop = xmlGetProp( node, ( const xmlChar* ) "clipEnd" );
00787 if ( prop )
00788 {
00789 std::string newValue = time.parseFramesToString( atoi( ( const char* ) prop ), SMIL::Time::TIME_FORMAT_CLOCK );
00790 xmlFree( prop );
00791 xmlSetProp( node, ( const xmlChar* ) "clipEnd", ( const xmlChar* ) newValue.c_str() );
00792 }
00793 }
00794 return false;
00795 }
00796
00797 static bool convertSmilTimeToFrames( xmlNodePtr node, void *data, bool *freed )
00798 {
00799 if ( xmlStrcmp( node->name, ( const xmlChar* ) "video" ) == 0 )
00800 {
00801 Frame *frame = GetFramePool( )->GetFrame( );
00802 xmlChar *src = xmlGetProp( node, ( const xmlChar* ) "src" );
00803 string index( ( char* ) src );
00804 xmlFree( src );
00805 FileHandler *mediaFile = GetFileMap()->GetMap() [ index ];
00806 mediaFile->GetFrame( *frame, 0 );
00807 SMIL::MediaClippingTime time;
00808 time.setFramerate( frame->GetFrameRate() );
00809 GetFramePool( )->DoneWithFrame( frame );
00810
00811 xmlChar *prop = xmlGetProp( node, ( const xmlChar* ) "clipBegin" );
00812 if ( prop )
00813 {
00814 time.parseValue( ( const char* ) prop );
00815 xmlFree( prop );
00816 std::string newValue = time.toString( SMIL::Time::TIME_FORMAT_FRAMES );
00817 xmlSetProp( node, ( const xmlChar* ) "clipBegin", ( const xmlChar* ) newValue.c_str() );
00818 }
00819 prop = xmlGetProp( node, ( const xmlChar* ) "clipEnd" );
00820 if ( prop )
00821 {
00822 time.parseValue( ( const char* ) prop );
00823 xmlFree( prop );
00824 std::string newValue = time.toString( SMIL::Time::TIME_FORMAT_FRAMES );
00825 xmlSetProp( node, ( const xmlChar* ) "clipEnd", ( const xmlChar* ) newValue.c_str() );
00826 }
00827 }
00828 return false;
00829 }
00830
00831 static bool clone( xmlNodePtr node, void *data, bool *freed )
00832 {
00833 xmlNodePtr* parent = (xmlNodePtr*) data;
00834
00835 xmlNodePtr child = xmlNewNode( NULL, node->name );
00836 xmlAddChild( *parent, child );
00837 for ( xmlAttr* attr = node->properties; attr; attr = attr->next )
00838 xmlNewProp( child, attr->name, xmlGetProp( attr->parent, attr->name) );
00839 if ( node->children )
00840 *parent = child;
00841 else if ( node == node->parent->last )
00842 *parent = (*parent)->parent;
00843
00844 return false;
00845 }
00846
00861 static bool parse( xmlNodePtr node, callback func, void *p )
00862 {
00863 bool done = false;
00864
00865 while ( node != NULL && done == false )
00866 {
00867 bool freed = false;
00868 xmlNodePtr next = node->next;
00869 done = ( *func ) ( node, p, &freed );
00870 if ( !done && !freed && node->children )
00871 done = parse( node->children, func, p );
00872 node = next;
00873 }
00874 return done;
00875 }
00876
00877
00880 PlayList::PlayList() : dirty( false ), doc_name( "" ), count( 0 )
00881 {
00882 xmlNsPtr ns;
00883 xmlNodePtr root;
00884
00885
00886
00887 doc = xmlNewDoc( ( const xmlChar* ) "1.0" );
00888 root = xmlNewNode( NULL, ( const xmlChar* ) "smil" );
00889 ns = xmlNewNs( root, SMIL20_NAMESPACE_HREF, ( const xmlChar* ) NULL );
00890 xmlDocSetRootElement( doc, root );
00891 xmlAddChild( root, xmlNewNode( NULL, ( const xmlChar* ) "body" ) );
00892 }
00893
00894
00897 PlayList::PlayList( const PlayList& playList )
00898 {
00899 xmlNsPtr ns;
00900 xmlNodePtr root;
00901
00902 doc = xmlNewDoc( ( const xmlChar* ) "1.0" );
00903 root = xmlNewNode( NULL, ( const xmlChar* ) "smil" );
00904 ns = xmlNewNs( root, ( const xmlChar* ) SMIL20_NAMESPACE_HREF, ( const xmlChar* ) NULL );
00905 xmlDocSetRootElement( doc, root );
00906 parse( playList.GetBody(), clone, &root );
00907 dirty = playList.dirty;
00908 doc_name = playList.GetDocName( );
00909 RefreshCount( );
00910 }
00911
00912
00915 PlayList& PlayList::operator=( const PlayList& playList )
00916 {
00917
00918
00919 if ( doc != playList.doc )
00920 {
00921 xmlNsPtr ns;
00922 xmlNodePtr root;
00923
00924 xmlFreeDoc( doc );
00925 doc = xmlNewDoc( ( const xmlChar* ) "1.0" );
00926 root = xmlNewNode( NULL, ( const xmlChar* ) "smil" );
00927 ns = xmlNewNs( root, ( const xmlChar* ) SMIL20_NAMESPACE_HREF, ( const xmlChar* ) NULL );
00928 xmlDocSetRootElement( doc, root );
00929 parse( playList.GetBody(), clone, &root );
00930 dirty = playList.dirty;
00931 doc_name = playList.GetDocName( );
00932 RefreshCount( );
00933 }
00934 return *this;
00935 }
00936
00937
00941 PlayList::~PlayList()
00942 {
00943
00944 if ( doc != NULL )
00945 {
00946 xmlFreeDoc( doc );
00947 doc = NULL;
00948 }
00949 }
00950
00955 xmlNodePtr PlayList::GetBody( ) const
00956 {
00957 return xmlDocGetRootElement( doc )->children;
00958 }
00959
00960
00961 void PlayList::RefreshCount( )
00962 {
00963 count = 0;
00964 if ( doc != NULL )
00965 parse( GetBody(), countFrames, &count );
00966 }
00967
00972 int PlayList::GetNumFrames() const
00973 {
00974 return count;
00975 }
00976
00977
00978 char* PlayList::GetFileNameOfFrame( int frameNum ) const
00979 {
00980
00981 MovieInfo data;
00982
00983 memset( &data, 0, sizeof( MovieInfo ) );
00984 data.absBegin = 0;
00985 data.absEnd = 0;
00986 data.absFrame = frameNum;
00987
00988 parse( GetBody(), findFile, &data );
00989 return strdup( data.fileName );
00990 }
00991
00992
01002 bool PlayList::GetFrame( int frameNum, Frame &frame )
01003 {
01004 MovieInfo data;
01005
01006
01007
01008 memset( &data, 0, sizeof( MovieInfo ) );
01009 data.absBegin = 0;
01010 data.absEnd = 0;
01011 data.absFrame = frameNum;
01012
01013 parse( GetBody(), findFile, &data );
01014
01015 if ( strcmp( data.fileName, "" ) )
01016 {
01017
01018
01019 string index( ( char * ) data.fileName );
01020 FileHandler *mediaFile = GetFileMap() ->GetMap() [ index ];
01021 if ( data.clipFrame >= mediaFile->GetTotalFrames() )
01022 data.clipFrame = mediaFile->GetTotalFrames() - 1;
01023 return ( mediaFile->GetFrame( frame, data.clipFrame ) >= 0 );
01024 }
01025
01026 return false;
01027 }
01028
01029
01036 bool PlayList::GetMediaObject( int frameNum, FileHandler **media )
01037 {
01038 MovieInfo data;
01039
01040 memset( &data, 0, sizeof( MovieInfo ) );
01041 data.absBegin = 0;
01042 data.absEnd = 0;
01043 data.absFrame = frameNum;
01044
01045 parse( GetBody(), findFile, &data );
01046
01047 if ( strcmp( data.fileName, "" ) )
01048 {
01049
01050 string index( ( char * ) data.fileName );
01051 *media = GetFileMap() ->GetMap() [ index ];
01052 return true;
01053 }
01054
01055 return false;
01056 }
01057
01058
01059 int PlayList::GetClipBegin( int frameNum ) const
01060 {
01061 MovieInfo data;
01062
01063 memset( &data, 0, sizeof( MovieInfo ) );
01064 data.absBegin = 0;
01065 data.absEnd = 0;
01066 data.absFrame = frameNum;
01067
01068 if ( parse( GetBody(), findSceneStart, &data ) )
01069 return data.clipBegin;
01070 else
01071 return 0;
01072 }
01073
01074
01075 int PlayList::GetClipEnd( int frameNum ) const
01076 {
01077 MovieInfo data;
01078
01079 memset( &data, 0, sizeof( MovieInfo ) );
01080 data.absBegin = 0;
01081 data.absEnd = 0;
01082 data.absFrame = frameNum;
01083
01084 if ( parse( GetBody(), findSceneEnd, &data ) )
01085 return data.clipEnd;
01086 else
01087 return 0;
01088 }
01089
01090
01091 bool PlayList::SetClipBegin( int frameNum, const char* value )
01092 {
01093 MovieInfo data;
01094
01095 memset( &data, 0, sizeof( MovieInfo ) );
01096 data.absBegin = 0;
01097 data.absEnd = 0;
01098 data.absFrame = frameNum;
01099
01100 if ( parse( GetBody(), findSceneStart, &data ) )
01101 {
01102 xmlSetProp( data.video, ( const xmlChar * ) "clipBegin", ( const xmlChar * ) value );
01103 RefreshCount( );
01104 return true;
01105 }
01106 else
01107 return false;
01108 }
01109
01110
01111 bool PlayList::SetClipEnd( int frameNum, const char* value )
01112 {
01113 MovieInfo data;
01114
01115 memset( &data, 0, sizeof( MovieInfo ) );
01116 data.absBegin = 0;
01117 data.absEnd = 0;
01118 data.absFrame = frameNum;
01119
01120 if ( parse( GetBody(), findSceneEnd, &data ) )
01121 {
01122 xmlSetProp( data.video, ( const xmlChar * ) "clipEnd", ( const xmlChar * ) value );
01123 RefreshCount( );
01124 return true;
01125 }
01126 else
01127 return false;
01128 }
01129
01130
01131 int PlayList::FindStartOfScene( int frameNum ) const
01132 {
01133 MovieInfo data;
01134
01135
01136
01137 memset( &data, 0, sizeof( MovieInfo ) );
01138 data.absBegin = 0;
01139 data.absEnd = 0;
01140 data.absFrame = frameNum;
01141
01142 parse( GetBody(), findSceneStart, &data );
01143
01144 if ( strcmp( data.fileName, "" ) )
01145 return data.absBegin;
01146 else
01147 return 0;
01148 }
01149
01150
01151 int PlayList::FindEndOfScene( int frameNum ) const
01152 {
01153 MovieInfo data;
01154
01155
01156
01157 data.absBegin = 0;
01158 data.absEnd = 0;
01159 data.absFrame = frameNum;
01160
01161 parse( GetBody(), findSceneEnd, &data );
01162
01163 if ( strcmp( data.fileName, "" ) )
01164 return data.absEnd;
01165 else
01166 return 999999;
01167 }
01168
01169
01170 void PlayList::AutoSplit( int start, int end )
01171 {
01172 MovieInfo firstFile;
01173 MovieInfo lastFile;
01174 Frame *frame = GetFramePool( ) ->GetFrame( );
01175 struct tm recDate;
01176 time_t startTime;
01177 time_t endTime;
01178
01179
01180
01181
01182 memset( &firstFile, 0, sizeof( MovieInfo ) );
01183 firstFile.absBegin = 0;
01184 firstFile.absEnd = 0;
01185 firstFile.absFrame = start;
01186
01187 parse( GetBody(), findFile, &firstFile );
01188 string index1( ( char* ) firstFile.fileName );
01189 FileHandler *mediaFile1 = GetFileMap() ->GetMap() [ index1 ];
01190 mediaFile1->GetFrame( *frame, firstFile.clipFrame );
01191 frame->GetRecordingDate( recDate );
01192 startTime = mktime( &recDate );
01193
01194 memset( &lastFile, 0, sizeof( MovieInfo ) );
01195 lastFile.absBegin = 0;
01196 lastFile.absEnd = 0;
01197 lastFile.absFrame = end;
01198
01199 parse( GetBody(), findFile, &lastFile );
01200
01201 string index2( ( char* ) lastFile.fileName );
01202 FileHandler *mediaFile2 = GetFileMap() ->GetMap() [ index2 ];
01203 mediaFile2->GetFrame( *frame, lastFile.clipFrame );
01204 frame->GetRecordingDate( recDate );
01205 endTime = mktime( &recDate );
01206
01207 int fps = frame->IsPAL() ? 25 : 30;
01208
01209 GetFramePool( ) ->DoneWithFrame( frame );
01210
01211
01212 if ( startTime < 0 || endTime < 0 )
01213 return ;
01214
01215 AutoSplit ( start, startTime, end, endTime, fps );
01216 }
01217
01218
01219 void PlayList::AutoSplit( int start, time_t startTime, int end, time_t endTime, int fps )
01220 {
01221 time_t diffTime = static_cast<time_t>( difftime( endTime, startTime ) );
01222 if ( ( ( diffTime * fps ) - ( end - start ) ) > fps || diffTime < 0.0 )
01223 {
01224 if ( ( end - start ) > 1 )
01225 {
01226 time_t mid = start + ( end - start ) / 2;
01227 time_t midTime;
01228
01229 {
01230 MovieInfo midFile;
01231 struct tm recDate;
01232 Frame *frame = GetFramePool( ) ->GetFrame( );
01233
01234 memset( &midFile, 0, sizeof( MovieInfo ) );
01235 midFile.absFrame = mid;
01236
01237 parse( GetBody(), findFile, &midFile );
01238
01239 string index( ( char* ) midFile.fileName );
01240 FileHandler *mediaFile = GetFileMap() ->GetMap() [ index ];
01241 mediaFile->GetFrame( *frame, midFile.clipFrame );
01242 frame->GetRecordingDate( recDate );
01243 midTime = mktime( &recDate );
01244
01245 GetFramePool( ) ->DoneWithFrame( frame );
01246 }
01247
01248
01249 if ( midTime < 0 )
01250 return ;
01251
01252 AutoSplit ( start, startTime, mid, midTime, fps );
01253 AutoSplit ( mid, midTime, end, endTime, fps );
01254 }
01255 else
01256 {
01257 SplitSceneBefore( end );
01258 }
01259 }
01260 }
01261
01262
01263 bool PlayList::SplitSceneBefore( int frameNum )
01264 {
01265 MovieInfo data;
01266
01267
01268
01269 if ( GetNumFrames() == 0 )
01270 return false;
01271
01272 memset( &data, 0, sizeof( MovieInfo ) );
01273 data.absBegin = 0;
01274 data.absEnd = 0;
01275 data.absFrame = frameNum;
01276 parse( GetBody(), findSceneStart, &data );
01277 int begin = data.absBegin;
01278
01279 memset( &data, 0, sizeof( MovieInfo ) );
01280 data.absBegin = 0;
01281 data.absEnd = 0;
01282 data.absFrame = frameNum;
01283 parse( GetBody(), findSceneEnd, &data );
01284 int end = data.absEnd;
01285
01286 if ( strcmp( data.fileName, "" ) && begin != frameNum )
01287 {
01288
01289 dirty = true;
01290
01291
01292 xmlNode *firstSequence = data.sequence;
01293 PlayList playlist;
01294 GetPlayList( frameNum, end, playlist );
01295
01296
01297 xmlAddNextSibling( firstSequence, playlist.GetBody()->children );
01298
01299
01300 Delete( frameNum, end );
01301
01302 return true;
01303 }
01304 else
01305 {
01306 return false;
01307 }
01308 }
01309
01310 bool PlayList::JoinScenesAt( int frameNum )
01311 {
01312 MovieInfo scene1;
01313 MovieInfo scene2;
01314 MovieInfo scene2end;
01315
01316 if ( GetNumFrames() == 0 )
01317 return false;
01318
01319
01320
01321 memset( &scene1, 0, sizeof( MovieInfo ) );
01322 scene1.absBegin = 0;
01323 scene1.absEnd = 0;
01324 scene1.absFrame = frameNum;
01325 parse( GetBody(), findSceneStart, &scene1 );
01326
01327 memset( &scene2, 0, sizeof( MovieInfo ) );
01328 scene2.absBegin = 0;
01329 scene2.absEnd = 0;
01330 scene2.absFrame = frameNum;
01331 parse( GetBody(), findSceneEnd, &scene2 );
01332 int end = scene2.absEnd + 1;
01333
01334 memset( &scene2end, 0, sizeof( MovieInfo ) );
01335 scene2end.absBegin = 0;
01336 scene2end.absEnd = 0;
01337 scene2end.absFrame = end;
01338 parse( GetBody(), findSceneEnd, &scene2end );
01339
01340 if ( scene1.sequence != scene2end.sequence )
01341 {
01342
01343 dirty = true;
01344
01345
01346
01347
01348
01349 xmlNode *lastchild = xmlGetLastChild( scene1.sequence );
01350 xmlNodePtr next = NULL;
01351 for ( xmlNodePtr ptr = scene2end.sequence->children; ptr != NULL; ptr = next )
01352 {
01353 next = ptr->next;
01354 lastchild = xmlAddNextSibling( lastchild, ptr );
01355 ptr = next;
01356 }
01357
01358 for ( xmlAttr* attr = scene2end.sequence->properties; attr; attr = attr->next )
01359 {
01360 const char *valueB = ( const char* ) xmlGetProp( attr->parent, ( const xmlChar * ) attr->name );
01361
01362 if ( valueB && strcmp( valueB, "" ) )
01363 {
01364
01365 const char *valueA = ( const char* ) xmlGetProp( scene1.sequence, ( const xmlChar * ) attr->name );
01366 if ( valueA && strcmp( valueA, "" ) )
01367 {
01368 xmlChar* value = new xmlChar[ strlen(valueA) + strlen(valueB) + 1 ];
01369 strcpy( (char*) value, (const char*) valueA );
01370 strcat( (char*) value, " " );
01371 strcat( (char*) value, (const char*) valueB );
01372 xmlSetProp( scene1.sequence, attr->name, ( const xmlChar * ) value );
01373 delete[] value;
01374 }
01375 else
01376 {
01377 xmlSetProp( scene1.sequence, attr->name, ( const xmlChar * ) valueB );
01378 }
01379 }
01380 }
01381 xmlUnlinkNode( scene2end.sequence );
01382 xmlFreeNode( scene2end.sequence );
01383 RefreshCount( );
01384
01385 return true;
01386 }
01387 else
01388 {
01389 return false;
01390 }
01391 }
01392
01393
01405 bool PlayList::GetPlayList( int first, int last, PlayList &playlist ) const
01406 {
01407 MovieInfo firstFile, lastFile;
01408 bool copyFlag = false;
01409
01410 if ( GetNumFrames() == 0 )
01411 return false;
01412
01413 playlist.dirty = false;
01414
01415
01416
01417 memset( &firstFile, 0, sizeof( MovieInfo ) );
01418 firstFile.absBegin = 0;
01419 firstFile.absEnd = 0;
01420 firstFile.absFrame = first;
01421
01422 parse( GetBody(), findFile, &firstFile );
01423
01424 memset( &lastFile, 0, sizeof( MovieInfo ) );
01425 lastFile.absBegin = 0;
01426 lastFile.absEnd = 0;
01427 lastFile.absFrame = last;
01428
01429 parse( GetBody(), findFile, &lastFile );
01430
01431 if ( strcmp( firstFile.fileName, "" ) && strcmp( lastFile.fileName, "" ) )
01432 {
01433
01434 xmlNodePtr srcNode = GetBody();
01435 xmlNodePtr dstNode = playlist.GetBody();
01436 xmlNodePtr nextSeq = NULL;
01437
01438 for ( xmlNodePtr srcSeq = srcNode->children; srcSeq != NULL; srcSeq = nextSeq )
01439 {
01440 nextSeq = srcSeq->next;
01441 if ( xmlStrcmp( srcSeq->name, ( const xmlChar* ) "seq" ) == 0 )
01442 {
01443 xmlNodePtr seq = xmlNewNode( NULL, ( const xmlChar* ) "seq" );
01444 xmlAddChild( dstNode, seq );
01445 xmlNodePtr nextVideo = NULL;
01446
01447 for ( xmlNodePtr srcVideo = srcSeq->children; srcVideo != NULL; srcVideo = nextVideo )
01448 {
01449 nextVideo = srcVideo->next;
01450 if ( xmlStrcmp( srcVideo->name, ( const xmlChar* ) "video" ) == 0 )
01451 {
01452
01453
01454
01455 if ( copyFlag && srcVideo != firstFile.video && srcVideo != lastFile.video )
01456 {
01457 xmlNodePtr video = xmlNewNode( NULL, ( const xmlChar* ) "video" );
01458 xmlAddChild( seq, video );
01459 for ( xmlAttr* attr = srcVideo->properties; attr; attr = attr->next )
01460 xmlNewProp( video, attr->name, xmlGetProp( attr->parent, attr->name) );
01461 }
01462
01463
01464
01465 else if ( srcVideo == firstFile.video && srcVideo != lastFile.video )
01466 {
01467
01468 ostringstream sb1, sb2;
01469
01470 xmlNodePtr video = xmlNewNode( NULL, ( const xmlChar* ) "video" );
01471 xmlNewProp( video, ( const xmlChar* ) "src", ( const xmlChar* ) firstFile.fileName );
01472 sb1 << firstFile.clipFrame << ends;
01473 xmlNewProp( video, ( const xmlChar* ) "clipBegin", ( const xmlChar* ) sb1.str().c_str() );
01474 sb2 << firstFile.clipEnd << ends;
01475 xmlNewProp( video, ( const xmlChar* ) "clipEnd", ( const xmlChar* ) sb2.str().c_str() );
01476 xmlAddChild( seq, video );
01477 copyFlag = true;
01478 }
01479
01480
01481
01482 else if ( srcVideo != firstFile.video && srcVideo == lastFile.video )
01483 {
01484
01485 ostringstream sb1, sb2;
01486
01487 xmlNodePtr video = xmlNewNode( NULL, ( const xmlChar* ) "video" );
01488 xmlNewProp( video, ( const xmlChar* ) "src", ( const xmlChar* ) lastFile.fileName );
01489 sb1 << lastFile.clipBegin << ends;
01490 xmlNewProp( video, ( const xmlChar* ) "clipBegin", ( const xmlChar* ) sb1.str().c_str() );
01491 sb2 << lastFile.clipFrame << ends;
01492 xmlNewProp( video, ( const xmlChar* ) "clipEnd", ( const xmlChar* ) sb2.str().c_str() );
01493 xmlAddChild( seq, video );
01494 copyFlag = false;
01495 }
01496
01497
01498
01499 else if ( srcVideo == firstFile.video && srcVideo == lastFile.video )
01500 {
01501
01502 ostringstream sb1, sb2;
01503
01504 xmlNodePtr video = xmlNewNode( NULL, ( const xmlChar* ) "video" );
01505 xmlNewProp( video, ( const xmlChar* ) "src", ( const xmlChar* ) firstFile.fileName );
01506 sb1 << firstFile.clipFrame << ends;
01507 xmlNewProp( video, ( const xmlChar* ) "clipBegin", ( const xmlChar* ) sb1.str().c_str() );
01508 sb2 << lastFile.clipFrame << ends;
01509 xmlNewProp( video, ( const xmlChar* ) "clipEnd", ( const xmlChar* ) sb2.str().c_str() );
01510 xmlAddChild( seq, video );
01511 }
01512 }
01513 }
01514
01515
01516
01517 if ( seq->children == NULL )
01518 {
01519 xmlUnlinkNode( seq );
01520 xmlFreeNode( seq );
01521 }
01522 else
01523
01524 {
01525 for ( xmlAttr* attr = srcSeq->properties; attr; attr = attr->next )
01526 xmlNewProp( seq, attr->name, xmlGetProp( attr->parent, attr->name) );
01527 }
01528 }
01529 }
01530
01531 string path = directory_utils::get_directory_from_file( GetDocName() );
01532 parse( playlist.GetBody(), fillMap, &path );
01533 }
01534 playlist.RefreshCount( );
01535 return true;
01536 }
01537
01538
01550 bool PlayList::InsertPlayList( PlayList &playlist, int before )
01551 {
01552
01553
01554 if ( playlist.GetNumFrames() == 0 )
01555 return false;
01556
01557
01558 string path = directory_utils::get_directory_from_file( GetDocName() );
01559 parse( playlist.GetBody(), fillMap, &path );
01560
01561 MovieInfo file;
01562
01563 memset( &file, 0, sizeof( MovieInfo ) );
01564 file.absBegin = 0;
01565 file.absEnd = 0;
01566 file.absFrame = before;
01567 file.sequence = NULL;
01568 file.video = NULL;
01569
01570
01571 parse( GetBody(), findFile, &file );
01572
01573 xmlNodePtr node = playlist.GetBody();
01574 bool first = true;
01575 xmlNodePtr next = NULL;
01576 xmlNodePtr sequence = file.sequence;
01577
01578 if ( GetNumFrames() > 0 )
01579 {
01580 dirty = true;
01581 }
01582 else
01583 {
01584 dirty = playlist.dirty;
01585
01586 if ( doc_name == "" )
01587 doc_name = playlist.GetDocName( );
01588
01589 }
01590
01591 for ( xmlNodePtr ptr = node->children; ptr != NULL; ptr = next )
01592 {
01593
01594
01595
01596
01597
01598
01599 next = ptr->next;
01600
01601
01602
01603
01604 if ( first && sequence == NULL )
01605 {
01606
01607 xmlNodePtr tmp = xmlNewNode( NULL, ( const xmlChar* ) "seq" );
01608 xmlAddChild( GetBody(), tmp );
01609 sequence = xmlAddNextSibling( tmp, ptr );
01610 xmlUnlinkNode( tmp );
01611 xmlFreeNode( tmp );
01612 }
01613 else if ( first && before == file.absBegin && before != ( file.absEnd + 1 ) )
01614 {
01615
01616 sequence = xmlAddPrevSibling( sequence, ptr );
01617 }
01618 else if ( first && before != ( file.absEnd + 1 ) )
01619 {
01620
01621
01622
01623
01624
01625
01626 SplitSceneBefore( before );
01627
01628
01629 memset( &file, 0, sizeof( MovieInfo ) );
01630 file.absBegin = 0;
01631 file.absFrame = before;
01632 file.sequence = NULL;
01633 file.video = NULL;
01634
01635 parse( GetBody(), findFile, &file );
01636
01637
01638
01639
01640
01641
01642 sequence = xmlAddPrevSibling( file.sequence, ptr );
01643 }
01644 else
01645 {
01646
01647 sequence = xmlAddNextSibling( sequence, ptr );
01648 }
01649
01650
01651 first = false;
01652 }
01653
01654 RefreshCount( );
01655 return true;
01656 }
01657
01658
01659 bool PlayList::Delete( int first, int last )
01660 {
01661 int absClipBegin;
01662 int clipBegin;
01663 int clipEnd;
01664 static int firstCall = 0;
01665
01666
01667
01668
01669
01670 if ( GetNumFrames() == 0 )
01671 return false;
01672
01673 if ( firstCall == 0 )
01674 {
01675 firstCall = 1;
01676 SplitSceneBefore( first );
01677 firstCall = 0;
01678 }
01679
01680 xmlNodePtr srcNode = GetBody();
01681 absClipBegin = 0;
01682 xmlNodePtr nextSequence = NULL;
01683 for ( xmlNodePtr srcSeq = srcNode->children; srcSeq != NULL; srcSeq = nextSequence )
01684 {
01685
01686 dirty = true;
01687
01688
01689 nextSequence = srcSeq->next;
01690
01691 if ( xmlStrcmp( srcSeq->name, ( const xmlChar* ) "seq" ) == 0 )
01692 {
01693 xmlNodePtr nextVideo = NULL;
01694
01695 for ( xmlNodePtr srcVideo = srcSeq->children; srcVideo != NULL; srcVideo = nextVideo )
01696 {
01697
01698
01699 nextVideo = srcVideo->next;
01700
01701 if ( xmlStrcmp( srcVideo->name, ( const xmlChar* ) "video" ) == 0 )
01702 {
01703
01704 ostringstream sb1, sb2;
01705 xmlChar *s;
01706
01707 sb1 << ( s = xmlGetProp( srcVideo, ( const xmlChar* ) "clipBegin" ) ) << ends;
01708 clipBegin = atoi( sb1.str().c_str() );
01709 if ( s )
01710 xmlFree( s );
01711 s = xmlGetProp( srcVideo, ( const xmlChar* ) "clipEnd" );
01712 clipEnd = atoi( ( char * ) s );
01713 sb2 << ( s = xmlGetProp( srcVideo, ( const xmlChar* ) "clipEnd" ) ) << ends;
01714 clipEnd = atoi( sb2.str().c_str() );
01715 if ( s )
01716 xmlFree( s );
01717
01718
01719
01720 if ( first <= absClipBegin && last >= absClipBegin + clipEnd - clipBegin )
01721 {
01722 xmlUnlinkNode( srcVideo );
01723 xmlFreeNode( srcVideo );
01724
01725 }
01726
01727
01728
01729
01730 else if ( first <= absClipBegin && last >= absClipBegin && last <= absClipBegin + clipEnd - clipBegin )
01731 {
01732
01733 ostringstream sb;
01734
01735 sb << last - absClipBegin + clipBegin + 1 << ends;
01736 xmlSetProp( srcVideo, ( const xmlChar* ) "clipBegin", ( const xmlChar* ) sb.str().c_str() );
01737
01738 }
01739
01740
01741
01742
01743 else if ( first > absClipBegin && first <= absClipBegin + clipEnd - clipBegin && last >= absClipBegin + clipEnd - clipBegin )
01744 {
01745
01746 ostringstream sb;
01747
01748 sb << first - absClipBegin + clipBegin - 1 << ends;
01749 xmlSetProp( srcVideo, ( const xmlChar* ) "clipEnd", ( const xmlChar* ) sb.str().c_str() );
01750
01751 }
01752
01753
01754
01755
01756
01757 else if ( first > absClipBegin && last < absClipBegin + clipEnd - clipBegin )
01758 {
01759
01760 ostringstream sb1, sb2;
01761 xmlChar *s;
01762
01763 xmlNodePtr video = xmlNewNode( NULL, ( const xmlChar* ) "video" );
01764 xmlNewProp( video, ( const xmlChar* ) "src", ( s = xmlGetProp( srcVideo, ( const xmlChar* ) "src" ) ) );
01765 if ( s )
01766 xmlFree( s );
01767 sb1 << last - absClipBegin + clipBegin + 1 << ends;
01768 xmlNewProp( video, ( const xmlChar* ) "clipBegin", ( const xmlChar* ) sb1.str().c_str() );
01769 xmlNewProp( video, ( const xmlChar* ) "clipEnd", ( s = xmlGetProp( srcVideo, ( const xmlChar* ) "clipEnd" ) ) );
01770 if ( s )
01771 xmlFree( s );
01772 xmlAddNextSibling( srcVideo, video );
01773 sb2 << first - absClipBegin + clipBegin - 1 << ends;
01774 xmlSetProp( srcVideo, ( const xmlChar* ) "clipEnd", ( const xmlChar* ) sb2.str().c_str() );
01775
01776 }
01777
01778 absClipBegin += clipEnd - clipBegin + 1;
01779 }
01780 }
01781
01782
01783
01784 if ( srcSeq->children == NULL )
01785 {
01786 xmlUnlinkNode( srcSeq );
01787 xmlFreeNode( srcSeq );
01788 }
01789 }
01790 }
01791
01792 RefreshCount( );
01793
01794 return true;
01795 }
01796
01797
01798 bool PlayList::LoadMediaObject( char *filename )
01799 {
01800
01801
01802 xmlNodePtr seq;
01803 xmlNodePtr node;
01804 ostringstream sb;
01805 FileHandler *mediaFile = NULL;
01806 int existingFrames;
01807 int framesInFile;
01808
01809 dirty = true;
01810
01811
01812 string index = directory_utils::get_abs