]> git.sesse.net Git - vlc/blob - modules/demux/mkv/demux.cpp
Remove unused parameter
[vlc] / modules / demux / mkv / demux.cpp
1
2 /*****************************************************************************
3  * mkv.cpp : matroska demuxer
4  *****************************************************************************
5  * Copyright (C) 2003-2004 the VideoLAN team
6  * $Id$
7  *
8  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
9  *          Steve Lhomme <steve.lhomme@free.fr>
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
24  *****************************************************************************/
25
26 #include "demux.hpp"
27
28 #include "Ebml_parser.hpp"
29
30 demux_sys_t::~demux_sys_t()
31 {
32     StopUiThread();
33     size_t i;
34     for ( i=0; i<streams.size(); i++ )
35         delete streams[i];
36     for ( i=0; i<opened_segments.size(); i++ )
37         delete opened_segments[i];
38     for ( i=0; i<used_segments.size(); i++ )
39         delete used_segments[i];
40     for ( i=0; i<stored_attachments.size(); i++ )
41         delete stored_attachments[i];
42     if( meta ) vlc_meta_Delete( meta );
43
44     while( titles.size() )
45     { vlc_input_title_Delete( titles.back() ); titles.pop_back();}
46
47     vlc_mutex_destroy( &lock_demuxer );
48 }
49
50
51 matroska_stream_c *demux_sys_t::AnalyseAllSegmentsFound( demux_t *p_demux, EbmlStream *p_estream, bool b_initial )
52 {
53     int i_upper_lvl = 0;
54     size_t i;
55     EbmlElement *p_l0, *p_l1, *p_l2;
56     bool b_keep_stream = false, b_keep_segment;
57
58     // verify the EBML Header
59     p_l0 = p_estream->FindNextID(EbmlHead::ClassInfos, 0xFFFFFFFFL);
60     if (p_l0 == NULL)
61     {
62         msg_Err( p_demux, "No EBML header found" );
63         return NULL;
64     }
65
66     // verify we can read this Segment, we only support Matroska version 1 for now
67     p_l0->Read(*p_estream, EbmlHead::ClassInfos.Context, i_upper_lvl, p_l0, true);
68
69     EDocType doc_type = GetChild<EDocType>(*static_cast<EbmlHead*>(p_l0));
70     if (std::string(doc_type) != "matroska")
71     {
72         msg_Err( p_demux, "Not a Matroska file : DocType = %s ", std::string(doc_type).c_str());
73         return NULL;
74     }
75
76     EDocTypeReadVersion doc_read_version = GetChild<EDocTypeReadVersion>(*static_cast<EbmlHead*>(p_l0));
77     if (uint64(doc_read_version) > 2)
78     {
79         msg_Err( p_demux, "This matroska file is needs version %"PRId64" and this VLC only supports version 1 & 2", uint64(doc_read_version));
80         return NULL;
81     }
82
83     delete p_l0;
84
85
86     // find all segments in this file
87     p_l0 = p_estream->FindNextID(KaxSegment::ClassInfos, 0xFFFFFFFFFLL);
88     if (p_l0 == NULL)
89     {
90         return NULL;
91     }
92
93     matroska_stream_c *p_stream1 = new matroska_stream_c( *this );
94
95     while (p_l0 != 0)
96     {
97         if (EbmlId(*p_l0) == KaxSegment::ClassInfos.GlobalId)
98         {
99             EbmlParser  *ep;
100             matroska_segment_c *p_segment1 = new matroska_segment_c( *this, *p_estream );
101             b_keep_segment = b_initial;
102
103             ep = new EbmlParser(p_estream, p_l0, &demuxer );
104             p_segment1->ep = ep;
105             p_segment1->segment = (KaxSegment*)p_l0;
106
107             while ((p_l1 = ep->Get()))
108             {
109                 if (MKV_IS_ID(p_l1, KaxInfo))
110                 {
111                     // find the families of this segment
112                     KaxInfo *p_info = static_cast<KaxInfo*>(p_l1);
113
114                     p_info->Read(*p_estream, KaxInfo::ClassInfos.Context, i_upper_lvl, p_l2, true);
115                     for( i = 0; i < p_info->ListSize(); i++ )
116                     {
117                         EbmlElement *l = (*p_info)[i];
118
119                         if( MKV_IS_ID( l, KaxSegmentUID ) )
120                         {
121                             KaxSegmentUID *p_uid = static_cast<KaxSegmentUID*>(l);
122                             b_keep_segment = (FindSegment( *p_uid ) == NULL);
123                             if ( !b_keep_segment )
124                                 break; // this segment is already known
125                             opened_segments.push_back( p_segment1 );
126                             delete p_segment1->p_segment_uid;
127                             p_segment1->p_segment_uid = new KaxSegmentUID(*p_uid);
128                         }
129                         else if( MKV_IS_ID( l, KaxPrevUID ) )
130                         {
131                             p_segment1->p_prev_segment_uid = new KaxPrevUID( *static_cast<KaxPrevUID*>(l) );
132                         }
133                         else if( MKV_IS_ID( l, KaxNextUID ) )
134                         {
135                             p_segment1->p_next_segment_uid = new KaxNextUID( *static_cast<KaxNextUID*>(l) );
136                         }
137                         else if( MKV_IS_ID( l, KaxSegmentFamily ) )
138                         {
139                             KaxSegmentFamily *p_fam = new KaxSegmentFamily( *static_cast<KaxSegmentFamily*>(l) );
140                             p_segment1->families.push_back( p_fam );
141                         }
142                     }
143                     break;
144                 }
145             }
146             if ( b_keep_segment )
147             {
148                 b_keep_stream = true;
149                 p_stream1->segments.push_back( p_segment1 );
150             }
151             else
152             {
153                 p_segment1->segment = NULL;
154                 delete p_segment1;
155             }
156         }
157         if (p_l0->IsFiniteSize() )
158         {
159             p_l0->SkipData(*p_estream, KaxMatroska_Context);
160             p_l0 = p_estream->FindNextID(KaxSegment::ClassInfos, 0xFFFFFFFFL);
161         }
162         else
163             p_l0 = p_l0->SkipData(*p_estream, KaxSegment_Context);
164     }
165
166     if ( !b_keep_stream )
167     {
168         delete p_stream1;
169         p_stream1 = NULL;
170     }
171
172     return p_stream1;
173 }
174
175 void demux_sys_t::StartUiThread()
176 {
177     if ( !b_ui_hooked )
178     {
179         msg_Dbg( &demuxer, "Starting the UI Hook" );
180         b_ui_hooked = true;
181         /* FIXME hack hack hack hack FIXME */
182         /* Get p_input and create variable */
183         p_input = (input_thread_t *) vlc_object_find( &demuxer, VLC_OBJECT_INPUT, FIND_PARENT );
184         var_Create( p_input, "x-start", VLC_VAR_INTEGER );
185         var_Create( p_input, "y-start", VLC_VAR_INTEGER );
186         var_Create( p_input, "x-end", VLC_VAR_INTEGER );
187         var_Create( p_input, "y-end", VLC_VAR_INTEGER );
188         var_Create( p_input, "color", VLC_VAR_ADDRESS );
189         var_Create( p_input, "menu-palette", VLC_VAR_ADDRESS );
190         var_Create( p_input, "highlight", VLC_VAR_BOOL );
191         var_Create( p_input, "highlight-mutex", VLC_VAR_MUTEX );
192
193         /* Now create our event thread catcher */
194         p_ev = (event_thread_t *) vlc_object_create( &demuxer, sizeof( event_thread_t ) );
195         p_ev->p_demux = &demuxer;
196         p_ev->b_die = false;
197         vlc_mutex_init( &p_ev->lock );
198         vlc_thread_create( p_ev, "mkv event thread handler", EventThread,
199                         VLC_THREAD_PRIORITY_LOW );
200     }
201 }
202
203 void demux_sys_t::StopUiThread()
204 {
205     if ( b_ui_hooked )
206     {
207         vlc_object_kill( p_ev );
208         vlc_thread_join( p_ev );
209         vlc_object_release( p_ev );
210
211         p_ev = NULL;
212
213         var_Destroy( p_input, "highlight-mutex" );
214         var_Destroy( p_input, "highlight" );
215         var_Destroy( p_input, "x-start" );
216         var_Destroy( p_input, "x-end" );
217         var_Destroy( p_input, "y-start" );
218         var_Destroy( p_input, "y-end" );
219         var_Destroy( p_input, "color" );
220         var_Destroy( p_input, "menu-palette" );
221
222         vlc_object_release( p_input );
223
224         msg_Dbg( &demuxer, "Stopping the UI Hook" );
225     }
226     b_ui_hooked = false;
227 }
228
229 int demux_sys_t::EventMouse( vlc_object_t *p_this, char const *psz_var,
230                        vlc_value_t oldval, vlc_value_t newval, void *p_data )
231 {
232     event_thread_t *p_ev = (event_thread_t *) p_data;
233     vlc_mutex_lock( &p_ev->lock );
234     if( psz_var[6] == 'c' )
235     {
236         p_ev->b_clicked = true;
237         msg_Dbg( p_this, "Event Mouse: clicked");
238     }
239     else if( psz_var[6] == 'm' )
240         p_ev->b_moved = true;
241     vlc_mutex_unlock( &p_ev->lock );
242
243     return VLC_SUCCESS;
244 }
245
246 int demux_sys_t::EventKey( vlc_object_t *p_this, char const *,
247                            vlc_value_t, vlc_value_t newval, void *p_data )
248 {
249     event_thread_t *p_ev = (event_thread_t *) p_data;
250     vlc_mutex_lock( &p_ev->lock );
251     p_ev->i_key_action = newval.i_int;
252     vlc_mutex_unlock( &p_ev->lock );
253     msg_Dbg( p_this, "Event Key");
254
255     return VLC_SUCCESS;
256 }
257
258 void * demux_sys_t::EventThread( vlc_object_t *p_this )
259 {
260     event_thread_t *p_ev = (event_thread_t*)p_this;
261     demux_sys_t    *p_sys = p_ev->p_demux->p_sys;
262     vlc_object_t   *p_vout = NULL;
263     int canc = vlc_savecancel ();
264
265     p_ev->b_moved   = false;
266     p_ev->b_clicked = false;
267     p_ev->i_key_action = 0;
268
269     /* catch all key event */
270     var_AddCallback( p_ev->p_libvlc, "key-action", EventKey, p_ev );
271
272     /* main loop */
273     while( vlc_object_alive (p_ev) )
274     {
275         if ( !p_sys->b_pci_packet_set )
276         {
277             /* Wait 100ms */
278             msleep( 100000 );
279             continue;
280         }
281
282         bool b_activated = false;
283
284         /* KEY part */
285         if( p_ev->i_key_action )
286         {
287             int i;
288
289             msg_Dbg( p_ev->p_demux, "Handle Key Event");
290
291             vlc_mutex_lock( &p_ev->lock );
292
293             pci_t *pci = (pci_t *) &p_sys->pci_packet;
294
295             uint16 i_curr_button = p_sys->dvd_interpretor.GetSPRM( 0x88 );
296
297             switch( p_ev->i_key_action )
298             {
299             case ACTIONID_NAV_LEFT:
300                 if ( i_curr_button > 0 && i_curr_button <= pci->hli.hl_gi.btn_ns )
301                 {
302                     btni_t *p_button_ptr = &(pci->hli.btnit[i_curr_button-1]);
303                     if ( p_button_ptr->left > 0 && p_button_ptr->left <= pci->hli.hl_gi.btn_ns )
304                     {
305                         i_curr_button = p_button_ptr->left;
306                         p_sys->dvd_interpretor.SetSPRM( 0x88, i_curr_button );
307                         btni_t button_ptr = pci->hli.btnit[i_curr_button-1];
308                         if ( button_ptr.auto_action_mode )
309                         {
310                             vlc_mutex_unlock( &p_ev->lock );
311                             vlc_mutex_lock( &p_sys->lock_demuxer );
312
313                             // process the button action
314                             p_sys->dvd_interpretor.Interpret( button_ptr.cmd.bytes, 8 );
315
316                             vlc_mutex_unlock( &p_sys->lock_demuxer );
317                             vlc_mutex_lock( &p_ev->lock );
318                         }
319                     }
320                 }
321                 break;
322             case ACTIONID_NAV_RIGHT:
323                 if ( i_curr_button > 0 && i_curr_button <= pci->hli.hl_gi.btn_ns )
324                 {
325                     btni_t *p_button_ptr = &(pci->hli.btnit[i_curr_button-1]);
326                     if ( p_button_ptr->right > 0 && p_button_ptr->right <= pci->hli.hl_gi.btn_ns )
327                     {
328                         i_curr_button = p_button_ptr->right;
329                         p_sys->dvd_interpretor.SetSPRM( 0x88, i_curr_button );
330                         btni_t button_ptr = pci->hli.btnit[i_curr_button-1];
331                         if ( button_ptr.auto_action_mode )
332                         {
333                             vlc_mutex_unlock( &p_ev->lock );
334                             vlc_mutex_lock( &p_sys->lock_demuxer );
335
336                             // process the button action
337                             p_sys->dvd_interpretor.Interpret( button_ptr.cmd.bytes, 8 );
338
339                             vlc_mutex_unlock( &p_sys->lock_demuxer );
340                             vlc_mutex_lock( &p_ev->lock );
341                         }
342                     }
343                 }
344                 break;
345             case ACTIONID_NAV_UP:
346                 if ( i_curr_button > 0 && i_curr_button <= pci->hli.hl_gi.btn_ns )
347                 {
348                     btni_t *p_button_ptr = &(pci->hli.btnit[i_curr_button-1]);
349                     if ( p_button_ptr->up > 0 && p_button_ptr->up <= pci->hli.hl_gi.btn_ns )
350                     {
351                         i_curr_button = p_button_ptr->up;
352                         p_sys->dvd_interpretor.SetSPRM( 0x88, i_curr_button );
353                         btni_t button_ptr = pci->hli.btnit[i_curr_button-1];
354                         if ( button_ptr.auto_action_mode )
355                         {
356                             vlc_mutex_unlock( &p_ev->lock );
357                             vlc_mutex_lock( &p_sys->lock_demuxer );
358
359                             // process the button action
360                             p_sys->dvd_interpretor.Interpret( button_ptr.cmd.bytes, 8 );
361
362                             vlc_mutex_unlock( &p_sys->lock_demuxer );
363                             vlc_mutex_lock( &p_ev->lock );
364                         }
365                     }
366                 }
367                 break;
368             case ACTIONID_NAV_DOWN:
369                 if ( i_curr_button > 0 && i_curr_button <= pci->hli.hl_gi.btn_ns )
370                 {
371                     btni_t *p_button_ptr = &(pci->hli.btnit[i_curr_button-1]);
372                     if ( p_button_ptr->down > 0 && p_button_ptr->down <= pci->hli.hl_gi.btn_ns )
373                     {
374                         i_curr_button = p_button_ptr->down;
375                         p_sys->dvd_interpretor.SetSPRM( 0x88, i_curr_button );
376                         btni_t button_ptr = pci->hli.btnit[i_curr_button-1];
377                         if ( button_ptr.auto_action_mode )
378                         {
379                             vlc_mutex_unlock( &p_ev->lock );
380                             vlc_mutex_lock( &p_sys->lock_demuxer );
381
382                             // process the button action
383                             p_sys->dvd_interpretor.Interpret( button_ptr.cmd.bytes, 8 );
384
385                             vlc_mutex_unlock( &p_sys->lock_demuxer );
386                             vlc_mutex_lock( &p_ev->lock );
387                         }
388                     }
389                 }
390                 break;
391             case ACTIONID_NAV_ACTIVATE:
392                 b_activated = true;
393  
394                 if ( i_curr_button > 0 && i_curr_button <= pci->hli.hl_gi.btn_ns )
395                 {
396                     btni_t button_ptr = pci->hli.btnit[i_curr_button-1];
397
398                     vlc_mutex_unlock( &p_ev->lock );
399                     vlc_mutex_lock( &p_sys->lock_demuxer );
400
401                     // process the button action
402                     p_sys->dvd_interpretor.Interpret( button_ptr.cmd.bytes, 8 );
403
404                     vlc_mutex_unlock( &p_sys->lock_demuxer );
405                     vlc_mutex_lock( &p_ev->lock );
406                 }
407                 break;
408             default:
409                 break;
410             }
411             p_ev->i_key_action = 0;
412             vlc_mutex_unlock( &p_ev->lock );
413         }
414
415         /* MOUSE part */
416         if( p_vout && ( p_ev->b_moved || p_ev->b_clicked ) )
417         {
418             vlc_value_t valx, valy;
419
420             vlc_mutex_lock( &p_ev->lock );
421             pci_t *pci = (pci_t *) &p_sys->pci_packet;
422             var_Get( p_vout, "mouse-x", &valx );
423             var_Get( p_vout, "mouse-y", &valy );
424
425             if( p_ev->b_clicked )
426             {
427                 int32_t button;
428                 int32_t best,dist,d;
429                 int32_t mx,my,dx,dy;
430
431                 msg_Dbg( p_ev->p_demux, "Handle Mouse Event: Mouse clicked x(%d)*y(%d)", (unsigned)valx.i_int, (unsigned)valy.i_int);
432
433                 b_activated = true;
434                 // get current button
435                 best = 0;
436                 dist = 0x08000000; /* >> than  (720*720)+(567*567); */
437                 for(button = 1; button <= pci->hli.hl_gi.btn_ns; button++)
438                 {
439                     btni_t *button_ptr = &(pci->hli.btnit[button-1]);
440
441                     if(((unsigned)valx.i_int >= button_ptr->x_start)
442                      && ((unsigned)valx.i_int <= button_ptr->x_end)
443                      && ((unsigned)valy.i_int >= button_ptr->y_start)
444                      && ((unsigned)valy.i_int <= button_ptr->y_end))
445                     {
446                         mx = (button_ptr->x_start + button_ptr->x_end)/2;
447                         my = (button_ptr->y_start + button_ptr->y_end)/2;
448                         dx = mx - valx.i_int;
449                         dy = my - valy.i_int;
450                         d = (dx*dx) + (dy*dy);
451                         /* If the mouse is within the button and the mouse is closer
452                         * to the center of this button then it is the best choice. */
453                         if(d < dist) {
454                             dist = d;
455                             best = button;
456                         }
457                     }
458                 }
459
460                 if ( best != 0)
461                 {
462                     btni_t button_ptr = pci->hli.btnit[best-1];
463                     uint16 i_curr_button = p_sys->dvd_interpretor.GetSPRM( 0x88 );
464
465                     msg_Dbg( &p_sys->demuxer, "Clicked button %d", best );
466                     vlc_mutex_unlock( &p_ev->lock );
467                     vlc_mutex_lock( &p_sys->lock_demuxer );
468
469                     // process the button action
470                     p_sys->dvd_interpretor.SetSPRM( 0x88, best );
471                     p_sys->dvd_interpretor.Interpret( button_ptr.cmd.bytes, 8 );
472
473                     msg_Dbg( &p_sys->demuxer, "Processed button %d", best );
474
475                     // select new button
476                     if ( best != i_curr_button )
477                     {
478                         vlc_value_t val;
479
480                         if( var_Get( p_sys->p_input, "highlight-mutex", &val ) == VLC_SUCCESS )
481                         {
482                             vlc_mutex_t *p_mutex = (vlc_mutex_t *) val.p_address;
483                             uint32_t i_palette;
484
485                             if(button_ptr.btn_coln != 0) {
486                                 i_palette = pci->hli.btn_colit.btn_coli[button_ptr.btn_coln-1][1];
487                             } else {
488                                 i_palette = 0;
489                             }
490
491                             for( int i = 0; i < 4; i++ )
492                             {
493                                 uint32_t i_yuv = 0xFF;//p_sys->clut[(hl.palette>>(16+i*4))&0x0f];
494                                 uint8_t i_alpha = (i_palette>>(i*4))&0x0f;
495                                 i_alpha = i_alpha == 0xf ? 0xff : i_alpha << 4;
496
497                                 p_sys->palette[i][0] = (i_yuv >> 16) & 0xff;
498                                 p_sys->palette[i][1] = (i_yuv >> 0) & 0xff;
499                                 p_sys->palette[i][2] = (i_yuv >> 8) & 0xff;
500                                 p_sys->palette[i][3] = i_alpha;
501                             }
502
503                             vlc_mutex_lock( p_mutex );
504                             val.i_int = button_ptr.x_start; var_Set( p_sys->p_input, "x-start", val );
505                             val.i_int = button_ptr.x_end;   var_Set( p_sys->p_input, "x-end",   val );
506                             val.i_int = button_ptr.y_start; var_Set( p_sys->p_input, "y-start", val );
507                             val.i_int = button_ptr.y_end;   var_Set( p_sys->p_input, "y-end",   val );
508
509                             val.p_address = (void *)p_sys->palette;
510                             var_Set( p_sys->p_input, "menu-palette", val );
511
512                             val.b_bool = true; var_Set( p_sys->p_input, "highlight", val );
513                             vlc_mutex_unlock( p_mutex );
514                         }
515                     }
516                     vlc_mutex_unlock( &p_sys->lock_demuxer );
517                     vlc_mutex_lock( &p_ev->lock );
518                 }
519             }
520             else if( p_ev->b_moved )
521             {
522 //                dvdnav_mouse_select( NULL, pci, valx.i_int, valy.i_int );
523             }
524
525             p_ev->b_moved = false;
526             p_ev->b_clicked = false;
527             vlc_mutex_unlock( &p_ev->lock );
528         }
529
530         /* VOUT part */
531         if( p_vout && !vlc_object_alive (p_vout) )
532         {
533             var_DelCallback( p_vout, "mouse-moved", EventMouse, p_ev );
534             var_DelCallback( p_vout, "mouse-clicked", EventMouse, p_ev );
535             vlc_object_release( p_vout );
536             p_vout = NULL;
537         }
538
539         else if( p_vout == NULL )
540         {
541             p_vout = (vlc_object_t*) vlc_object_find( p_sys->p_input, VLC_OBJECT_VOUT,
542                                       FIND_CHILD );
543             if( p_vout)
544             {
545                 var_AddCallback( p_vout, "mouse-moved", EventMouse, p_ev );
546                 var_AddCallback( p_vout, "mouse-clicked", EventMouse, p_ev );
547             }
548         }
549
550         /* Wait a bit, 10ms */
551         msleep( 10000 );
552     }
553
554     /* Release callback */
555     if( p_vout )
556     {
557         var_DelCallback( p_vout, "mouse-moved", EventMouse, p_ev );
558         var_DelCallback( p_vout, "mouse-clicked", EventMouse, p_ev );
559         vlc_object_release( p_vout );
560     }
561     var_DelCallback( p_ev->p_libvlc, "key-action", EventKey, p_ev );
562
563     vlc_mutex_destroy( &p_ev->lock );
564
565     vlc_restorecancel (canc);
566     return VLC_SUCCESS;
567 }
568
569 void demux_sys_t::PreloadFamily( const matroska_segment_c & of_segment )
570 {
571     for (size_t i=0; i<opened_segments.size(); i++)
572     {
573         opened_segments[i]->PreloadFamily( of_segment );
574     }
575 }
576
577 // preload all the linked segments for all preloaded segments
578 void demux_sys_t::PreloadLinked( matroska_segment_c *p_segment )
579 {
580     size_t i_preloaded, i, j;
581     virtual_segment_c *p_seg;
582
583     p_current_segment = VirtualFromSegments( p_segment );
584  
585     used_segments.push_back( p_current_segment );
586
587     // create all the other virtual segments of the family
588     do {
589         i_preloaded = 0;
590         for ( i=0; i< opened_segments.size(); i++ )
591         {
592             if ( opened_segments[i]->b_preloaded && !IsUsedSegment( *opened_segments[i] ) )
593             {
594                 p_seg = VirtualFromSegments( opened_segments[i] );
595                 used_segments.push_back( p_seg );
596                 i_preloaded++;
597             }
598         }
599     } while ( i_preloaded ); // worst case: will stop when all segments are found as family related
600
601     // publish all editions of all usable segment
602     for ( i=0; i< used_segments.size(); i++ )
603     {
604         p_seg = used_segments[i];
605         if ( p_seg->p_editions != NULL )
606         {
607             input_title_t *p_title = vlc_input_title_New();
608             p_seg->i_sys_title = i;
609             int i_chapters;
610
611             // TODO use a name for each edition, let the TITLE deal with a codec name
612             for ( j=0; j<p_seg->p_editions->size(); j++ )
613             {
614                 if ( p_title->psz_name == NULL )
615                 {
616                     const char* psz_tmp = (*p_seg->p_editions)[j]->GetMainName().c_str();
617                     if( *psz_tmp != '\0' )
618                         p_title->psz_name = strdup( psz_tmp );
619                 }
620
621                 chapter_edition_c *p_edition = (*p_seg->p_editions)[j];
622
623                 i_chapters = 0;
624                 p_edition->PublishChapters( *p_title, i_chapters, 0 );
625             }
626
627             // create a name if there is none
628             if ( p_title->psz_name == NULL )
629             {
630                 if( asprintf(&(p_title->psz_name), "%s %d", N_("Segment"), (int)i) == -1 )
631                     p_title->psz_name = NULL;
632             }
633
634             titles.push_back( p_title );
635         }
636     }
637
638     // TODO decide which segment should be first used (VMG for DVD)
639 }
640
641 bool demux_sys_t::IsUsedSegment( matroska_segment_c &segment ) const
642 {
643     for ( size_t i=0; i< used_segments.size(); i++ )
644     {
645         if ( used_segments[i]->FindUID( *segment.p_segment_uid ) )
646             return true;
647     }
648     return false;
649 }
650
651 virtual_segment_c *demux_sys_t::VirtualFromSegments( matroska_segment_c *p_segment ) const
652 {
653     size_t i_preloaded, i;
654
655     virtual_segment_c *p_result = new virtual_segment_c( p_segment );
656
657     // fill our current virtual segment with all hard linked segments
658     do {
659         i_preloaded = 0;
660         for ( i=0; i< opened_segments.size(); i++ )
661         {
662             i_preloaded += p_result->AddSegment( opened_segments[i] );
663         }
664     } while ( i_preloaded ); // worst case: will stop when all segments are found as linked
665
666     p_result->Sort( );
667
668     p_result->PreloadLinked( );
669
670     p_result->PrepareChapters( );
671
672     return p_result;
673 }
674
675 bool demux_sys_t::PreparePlayback( virtual_segment_c *p_new_segment )
676 {
677     if ( p_new_segment != NULL && p_new_segment != p_current_segment )
678     {
679         if ( p_current_segment != NULL && p_current_segment->Segment() != NULL )
680             p_current_segment->Segment()->UnSelect();
681
682         p_current_segment = p_new_segment;
683         i_current_title = p_new_segment->i_sys_title;
684     }
685     if( !p_current_segment->Segment()->b_cues )
686         msg_Warn( &p_current_segment->Segment()->sys.demuxer, "no cues/empty cues found->seek won't be precise" );
687
688     f_duration = p_current_segment->Duration();
689
690     /* add information */
691     p_current_segment->Segment()->InformationCreate( );
692     p_current_segment->Segment()->Select( 0 );
693
694     return true;
695 }
696
697 void demux_sys_t::JumpTo( virtual_segment_c & vsegment, chapter_item_c * p_chapter )
698 {
699     // if the segment is not part of the current segment, select the new one
700     if ( &vsegment != p_current_segment )
701     {
702         PreparePlayback( &vsegment );
703     }
704
705     if ( p_chapter != NULL )
706     {
707         if ( !p_chapter->Enter( true ) )
708         {
709             // jump to the location in the found segment
710             vsegment.Seek( demuxer, p_chapter->i_user_start_time, -1, p_chapter, -1 );
711         }
712     }
713  
714 }
715
716 matroska_segment_c *demux_sys_t::FindSegment( const EbmlBinary & uid ) const
717 {
718     for (size_t i=0; i<opened_segments.size(); i++)
719     {
720         if ( *opened_segments[i]->p_segment_uid == uid )
721             return opened_segments[i];
722     }
723     return NULL;
724 }
725
726 chapter_item_c *demux_sys_t::BrowseCodecPrivate( unsigned int codec_id,
727                                         bool (*match)(const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size ),
728                                         const void *p_cookie,
729                                         size_t i_cookie_size,
730                                         virtual_segment_c * &p_segment_found )
731 {
732     chapter_item_c *p_result = NULL;
733     for (size_t i=0; i<used_segments.size(); i++)
734     {
735         p_result = used_segments[i]->BrowseCodecPrivate( codec_id, match, p_cookie, i_cookie_size );
736         if ( p_result != NULL )
737         {
738             p_segment_found = used_segments[i];
739             break;
740         }
741     }
742     return p_result;
743 }
744
745 chapter_item_c *demux_sys_t::FindChapter( int64_t i_find_uid, virtual_segment_c * & p_segment_found )
746 {
747     chapter_item_c *p_result = NULL;
748     for (size_t i=0; i<used_segments.size(); i++)
749     {
750         p_result = used_segments[i]->FindChapter( i_find_uid );
751         if ( p_result != NULL )
752         {
753             p_segment_found = used_segments[i];
754             break;
755         }
756     }
757     return p_result;
758 }
759
760 void demux_sys_t::SwapButtons()
761 {
762 #ifndef WORDS_BIGENDIAN
763     uint8_t button, i, j;
764
765     for( button = 1; button <= pci_packet.hli.hl_gi.btn_ns; button++) {
766         btni_t *button_ptr = &(pci_packet.hli.btnit[button-1]);
767         binary *p_data = (binary*) button_ptr;
768
769         uint16 i_x_start = ((p_data[0] & 0x3F) << 4 ) + ( p_data[1] >> 4 );
770         uint16 i_x_end   = ((p_data[1] & 0x03) << 8 ) + p_data[2];
771         uint16 i_y_start = ((p_data[3] & 0x3F) << 4 ) + ( p_data[4] >> 4 );
772         uint16 i_y_end   = ((p_data[4] & 0x03) << 8 ) + p_data[5];
773         button_ptr->x_start = i_x_start;
774         button_ptr->x_end   = i_x_end;
775         button_ptr->y_start = i_y_start;
776         button_ptr->y_end   = i_y_end;
777
778     }
779     for ( i = 0; i<3; i++ )
780     {
781         for ( j = 0; j<2; j++ )
782         {
783             pci_packet.hli.btn_colit.btn_coli[i][j] = U32_AT( &pci_packet.hli.btn_colit.btn_coli[i][j] );
784         }
785     }
786 #endif
787 }