demux.cpp 26.6 KB
Newer Older
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
/*****************************************************************************
 * mkv.cpp : matroska demuxer
 *****************************************************************************
 * Copyright (C) 2003-2004 the VideoLAN team
 * $Id$
 *
 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
 *          Steve Lhomme <steve.lhomme@free.fr>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

26
#include "demux.hpp"
27

28
#include "Ebml_parser.hpp"
29

30
event_thread_t::event_thread_t(demux_t *p_demux) : p_demux(p_demux)
31
{
32
33
34
    vlc_mutex_init( &lock );
    vlc_cond_init( &wait );
    is_running = false;
35
}
36
event_thread_t::~event_thread_t()
37
{
38
39
40
41
    ResetPci();
    vlc_cond_destroy( &wait );
    vlc_mutex_destroy( &lock );
}
42

43
44
45
void event_thread_t::SetPci(const pci_t *data)
{
    vlc_mutex_locker l(&lock);
46

47
    pci_packet = *data;
48

49
50
51
52
#ifndef WORDS_BIGENDIAN
    for( uint8_t button = 1; button <= pci_packet.hli.hl_gi.btn_ns; button++) {
        btni_t *button_ptr = &(pci_packet.hli.btnit[button-1]);
        binary *p_data = (binary*) button_ptr;
53

54
55
56
57
58
59
60
61
        uint16 i_x_start = ((p_data[0] & 0x3F) << 4 ) + ( p_data[1] >> 4 );
        uint16 i_x_end   = ((p_data[1] & 0x03) << 8 ) + p_data[2];
        uint16 i_y_start = ((p_data[3] & 0x3F) << 4 ) + ( p_data[4] >> 4 );
        uint16 i_y_end   = ((p_data[4] & 0x03) << 8 ) + p_data[5];
        button_ptr->x_start = i_x_start;
        button_ptr->x_end   = i_x_end;
        button_ptr->y_start = i_y_start;
        button_ptr->y_end   = i_y_end;
62

63
    }
64
65
66
67
68
    for ( uint8_t i = 0; i<3; i++ )
        for ( uint8_t j = 0; j<2; j++ )
            pci_packet.hli.btn_colit.btn_coli[i][j] = U32_AT( &pci_packet.hli.btn_colit.btn_coli[i][j] );
#endif
    if( !is_running )
69
    {
70
71
        b_abort = false;
        is_running = !vlc_clone( &thread, EventThread, this, VLC_THREAD_PRIORITY_LOW );
72
73
    }
}
74
void event_thread_t::ResetPci()
75
{
76
77
    if( !is_running )
        return;
78

79
80
81
82
    vlc_mutex_lock( &lock );
    b_abort = true;
    vlc_cond_signal( &wait );
    vlc_mutex_unlock( &lock );
83

84
85
    vlc_join( thread, NULL );
    is_running = false;
86
}
87
88
int event_thread_t::EventMouse( vlc_object_t *p_this, char const *psz_var,
                                vlc_value_t oldval, vlc_value_t newval, void *p_data )
89
{
90
    VLC_UNUSED( oldval ); VLC_UNUSED( newval );
91
92
93
94
95
96
97
98
99
    event_thread_t *p_ev = (event_thread_t *) p_data;
    vlc_mutex_lock( &p_ev->lock );
    if( psz_var[6] == 'c' )
    {
        p_ev->b_clicked = true;
        msg_Dbg( p_this, "Event Mouse: clicked");
    }
    else if( psz_var[6] == 'm' )
        p_ev->b_moved = true;
100
    vlc_cond_signal( &p_ev->wait );
101
    vlc_mutex_unlock( &p_ev->lock );
102

103
104
    return VLC_SUCCESS;
}
105

106
107
int event_thread_t::EventKey( vlc_object_t *p_this, char const *,
                              vlc_value_t, vlc_value_t newval, void *p_data )
108
109
110
111
{
    event_thread_t *p_ev = (event_thread_t *) p_data;
    vlc_mutex_lock( &p_ev->lock );
    p_ev->i_key_action = newval.i_int;
112
    vlc_cond_signal( &p_ev->wait );
113
114
    vlc_mutex_unlock( &p_ev->lock );
    msg_Dbg( p_this, "Event Key");
115

116
117
    return VLC_SUCCESS;
}
118

119
120
121
int event_thread_t::EventInput( vlc_object_t *p_this, char const *,
                                vlc_value_t, vlc_value_t newval, void *p_data )
{
122
    VLC_UNUSED( p_this );
123
124
125
126
127
128
129
130
131
132
133
134
135
    event_thread_t *p_ev = (event_thread_t *) p_data;
    vlc_mutex_lock( &p_ev->lock );
    if( newval.i_int == INPUT_EVENT_VOUT )
    {
        p_ev->b_vout |= true;
        vlc_cond_signal( &p_ev->wait );
    }
    vlc_mutex_unlock( &p_ev->lock );

    return VLC_SUCCESS;
}

void event_thread_t::EventThread()
136
{
137
    demux_sys_t    *p_sys = p_demux->p_sys;
138
139
    vlc_object_t   *p_vout = NULL;
    int canc = vlc_savecancel ();
140

141
142
143
144
    b_moved      = false;
    b_clicked    = false;
    i_key_action = 0;
    b_vout       = true;
145

146
    /* catch all key event */
147
148
149
    var_AddCallback( p_demux->p_libvlc, "key-action", EventKey, this );
    /* catch input event */
    var_AddCallback( p_sys->p_input, "intf-event", EventInput, this );
150

151
    /* main loop */
152
    for( ;; )
153
    {
154
155
156
157
158
        vlc_mutex_lock( &lock );
        while( !b_abort && !i_key_action && !b_moved && !b_clicked && !b_vout)
            vlc_cond_wait( &wait, &lock );

        if( b_abort )
159
        {
160
161
            vlc_mutex_unlock( &lock );
            break;
162
        }
163

164
        /* KEY part */
165
        if( i_key_action )
166
        {
167
            msg_Dbg( p_demux, "Handle Key Event");
168

169
            pci_t *pci = &pci_packet;
170

171
            uint16 i_curr_button = p_sys->dvd_interpretor.GetSPRM( 0x88 );
172

173
            switch( i_key_action )
174
175
176
177
178
179
180
181
182
183
184
185
            {
            case ACTIONID_NAV_LEFT:
                if ( i_curr_button > 0 && i_curr_button <= pci->hli.hl_gi.btn_ns )
                {
                    btni_t *p_button_ptr = &(pci->hli.btnit[i_curr_button-1]);
                    if ( p_button_ptr->left > 0 && p_button_ptr->left <= pci->hli.hl_gi.btn_ns )
                    {
                        i_curr_button = p_button_ptr->left;
                        p_sys->dvd_interpretor.SetSPRM( 0x88, i_curr_button );
                        btni_t button_ptr = pci->hli.btnit[i_curr_button-1];
                        if ( button_ptr.auto_action_mode )
                        {
186
                            vlc_mutex_unlock( &lock );
187
                            vlc_mutex_lock( &p_sys->lock_demuxer );
188

189
190
                            // process the button action
                            p_sys->dvd_interpretor.Interpret( button_ptr.cmd.bytes, 8 );
191

192
                            vlc_mutex_unlock( &p_sys->lock_demuxer );
193
                            vlc_mutex_lock( &lock );
194
195
                        }
                    }
196
                }
197
198
199
200
201
202
203
204
205
206
207
208
                break;
            case ACTIONID_NAV_RIGHT:
                if ( i_curr_button > 0 && i_curr_button <= pci->hli.hl_gi.btn_ns )
                {
                    btni_t *p_button_ptr = &(pci->hli.btnit[i_curr_button-1]);
                    if ( p_button_ptr->right > 0 && p_button_ptr->right <= pci->hli.hl_gi.btn_ns )
                    {
                        i_curr_button = p_button_ptr->right;
                        p_sys->dvd_interpretor.SetSPRM( 0x88, i_curr_button );
                        btni_t button_ptr = pci->hli.btnit[i_curr_button-1];
                        if ( button_ptr.auto_action_mode )
                        {
209
                            vlc_mutex_unlock( &lock );
210
                            vlc_mutex_lock( &p_sys->lock_demuxer );
211

212
213
                            // process the button action
                            p_sys->dvd_interpretor.Interpret( button_ptr.cmd.bytes, 8 );
214

215
                            vlc_mutex_unlock( &p_sys->lock_demuxer );
216
                            vlc_mutex_lock( &lock );
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
                        }
                    }
                }
                break;
            case ACTIONID_NAV_UP:
                if ( i_curr_button > 0 && i_curr_button <= pci->hli.hl_gi.btn_ns )
                {
                    btni_t *p_button_ptr = &(pci->hli.btnit[i_curr_button-1]);
                    if ( p_button_ptr->up > 0 && p_button_ptr->up <= pci->hli.hl_gi.btn_ns )
                    {
                        i_curr_button = p_button_ptr->up;
                        p_sys->dvd_interpretor.SetSPRM( 0x88, i_curr_button );
                        btni_t button_ptr = pci->hli.btnit[i_curr_button-1];
                        if ( button_ptr.auto_action_mode )
                        {
232
                            vlc_mutex_unlock( &lock );
233
                            vlc_mutex_lock( &p_sys->lock_demuxer );
234

235
236
                            // process the button action
                            p_sys->dvd_interpretor.Interpret( button_ptr.cmd.bytes, 8 );
237

238
                            vlc_mutex_unlock( &p_sys->lock_demuxer );
239
                            vlc_mutex_lock( &lock );
240
241
242
243
244
245
                        }
                    }
                }
                break;
            case ACTIONID_NAV_DOWN:
                if ( i_curr_button > 0 && i_curr_button <= pci->hli.hl_gi.btn_ns )
246
                {
247
248
249
250
251
252
253
254
                    btni_t *p_button_ptr = &(pci->hli.btnit[i_curr_button-1]);
                    if ( p_button_ptr->down > 0 && p_button_ptr->down <= pci->hli.hl_gi.btn_ns )
                    {
                        i_curr_button = p_button_ptr->down;
                        p_sys->dvd_interpretor.SetSPRM( 0x88, i_curr_button );
                        btni_t button_ptr = pci->hli.btnit[i_curr_button-1];
                        if ( button_ptr.auto_action_mode )
                        {
255
                            vlc_mutex_unlock( &lock );
256
                            vlc_mutex_lock( &p_sys->lock_demuxer );
257

258
259
260
261
                            // process the button action
                            p_sys->dvd_interpretor.Interpret( button_ptr.cmd.bytes, 8 );

                            vlc_mutex_unlock( &p_sys->lock_demuxer );
262
                            vlc_mutex_lock( &lock );
263
264
                        }
                    }
265
                }
266
267
268
269
270
                break;
            case ACTIONID_NAV_ACTIVATE:
                if ( i_curr_button > 0 && i_curr_button <= pci->hli.hl_gi.btn_ns )
                {
                    btni_t button_ptr = pci->hli.btnit[i_curr_button-1];
271

272
                    vlc_mutex_unlock( &lock );
273
                    vlc_mutex_lock( &p_sys->lock_demuxer );
274

275
276
                    // process the button action
                    p_sys->dvd_interpretor.Interpret( button_ptr.cmd.bytes, 8 );
277

278
                    vlc_mutex_unlock( &p_sys->lock_demuxer );
279
                    vlc_mutex_lock( &lock );
280
281
282
283
                }
                break;
            default:
                break;
284
            }
285
            i_key_action = 0;
286
287
        }

288
        /* MOUSE part */
289
        if( p_vout && ( b_moved || b_clicked ) )
290
        {
291
            int x, y;
292

293
            var_GetCoords( p_vout, "mouse-moved", &x, &y );
294
            pci_t *pci = &pci_packet;
295

296
            if( b_clicked )
297
            {
298
299
300
                int32_t button;
                int32_t best,dist,d;
                int32_t mx,my,dx,dy;
301

302
                msg_Dbg( p_demux, "Handle Mouse Event: Mouse clicked x(%d)*y(%d)", x, y);
303

304
305
306
307
308
309
                // get current button
                best = 0;
                dist = 0x08000000; /* >> than  (720*720)+(567*567); */
                for(button = 1; button <= pci->hli.hl_gi.btn_ns; button++)
                {
                    btni_t *button_ptr = &(pci->hli.btnit[button-1]);
310

311
312
313
314
                    if(((unsigned)x >= button_ptr->x_start)
                     && ((unsigned)x <= button_ptr->x_end)
                     && ((unsigned)y >= button_ptr->y_start)
                     && ((unsigned)y <= button_ptr->y_end))
315
                    {
316
317
                        mx = (button_ptr->x_start + button_ptr->x_end)/2;
                        my = (button_ptr->y_start + button_ptr->y_end)/2;
318
319
                        dx = mx - x;
                        dy = my - y;
320
321
322
323
324
325
                        d = (dx*dx) + (dy*dy);
                        /* If the mouse is within the button and the mouse is closer
                        * to the center of this button then it is the best choice. */
                        if(d < dist) {
                            dist = d;
                            best = button;
326
327
                        }
                    }
328
329
330
331
332
333
334
335
                }

                if ( best != 0)
                {
                    btni_t button_ptr = pci->hli.btnit[best-1];
                    uint16 i_curr_button = p_sys->dvd_interpretor.GetSPRM( 0x88 );

                    msg_Dbg( &p_sys->demuxer, "Clicked button %d", best );
336
                    vlc_mutex_unlock( &lock );
337
338
339
340
341
                    vlc_mutex_lock( &p_sys->lock_demuxer );

                    // process the button action
                    p_sys->dvd_interpretor.SetSPRM( 0x88, best );
                    p_sys->dvd_interpretor.Interpret( button_ptr.cmd.bytes, 8 );
342

343
                    msg_Dbg( &p_sys->demuxer, "Processed button %d", best );
344

345
346
                    // select new button
                    if ( best != i_curr_button )
347
                    {
348
                        uint32_t i_palette;
349

350
351
352
353
354
355
356
                        if(button_ptr.btn_coln != 0) {
                            i_palette = pci->hli.btn_colit.btn_coli[button_ptr.btn_coln-1][1];
                        } else {
                            i_palette = 0;
                        }

                        for( int i = 0; i < 4; i++ )
357
                        {
358
359
360
361
362
363
364
365
                            uint32_t i_yuv = 0xFF;//p_sys->clut[(hl.palette>>(16+i*4))&0x0f];
                            uint8_t i_alpha = (i_palette>>(i*4))&0x0f;
                            i_alpha = i_alpha == 0xf ? 0xff : i_alpha << 4;

                            p_sys->palette[i][0] = (i_yuv >> 16) & 0xff;
                            p_sys->palette[i][1] = (i_yuv >> 0) & 0xff;
                            p_sys->palette[i][2] = (i_yuv >> 8) & 0xff;
                            p_sys->palette[i][3] = i_alpha;
366
                        }
367
368
369
370
371
372
373
374
375
376
377
378
379
380

                        vlc_global_lock( VLC_HIGHLIGHT_MUTEX );
                        var_SetInteger( p_sys->p_input, "x-start",
                                        button_ptr.x_start );
                        var_SetInteger( p_sys->p_input, "x-end",
                                        button_ptr.x_end );
                        var_SetInteger( p_sys->p_input, "y-start",
                                        button_ptr.y_start );
                        var_SetInteger( p_sys->p_input, "y-end",
                                        button_ptr.y_end );
                        var_SetAddress( p_sys->p_input, "menu-palette",
                                        p_sys->palette );
                        var_SetBool( p_sys->p_input, "highlight", true );
                        vlc_global_unlock( VLC_HIGHLIGHT_MUTEX );
381
                    }
382
                    vlc_mutex_unlock( &p_sys->lock_demuxer );
383
                    vlc_mutex_lock( &lock );
384
385
                }
            }
386
            else if( b_moved )
387
            {
388
//                dvdnav_mouse_select( NULL, pci, x, y );
389
390
            }

391
392
            b_moved = false;
            b_clicked = false;
393
        }
394

395
396
397
398
        b_vout = false;
        vlc_mutex_unlock( &lock );

        /* Always check vout */
399
        if( p_vout && !vlc_object_alive (p_vout) )
400
        {
401
402
            var_DelCallback( p_vout, "mouse-moved", EventMouse, this );
            var_DelCallback( p_vout, "mouse-clicked", EventMouse, this );
403
404
            vlc_object_release( p_vout );
            p_vout = NULL;
405
        }
406
407

        else if( p_vout == NULL )
408
        {
409
            p_vout = (vlc_object_t*) input_GetVout(p_sys->p_input);
410
            if( p_vout)
411
            {
412
413
                var_AddCallback( p_vout, "mouse-moved", EventMouse, this );
                var_AddCallback( p_vout, "mouse-clicked", EventMouse, this );
414
415
            }
        }
416
    }
417

418
419
420
    /* Release callback */
    if( p_vout )
    {
421
422
        var_DelCallback( p_vout, "mouse-moved", EventMouse, this );
        var_DelCallback( p_vout, "mouse-clicked", EventMouse, this );
423
        vlc_object_release( p_vout );
424
    }
425
426
    var_DelCallback( p_sys->p_input, "intf-event", EventInput, this );
    var_DelCallback( p_demux->p_libvlc, "key-action", EventKey, this );
427

428
    vlc_restorecancel (canc);
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
void *event_thread_t::EventThread(void *data)
{
    static_cast<event_thread_t*>(data)->EventThread();
    return NULL;
}


demux_sys_t::~demux_sys_t()
{
    CleanUi();
    size_t i;
    for ( i=0; i<streams.size(); i++ )
        delete streams[i];
    for ( i=0; i<opened_segments.size(); i++ )
        delete opened_segments[i];
    for ( i=0; i<used_segments.size(); i++ )
        delete used_segments[i];
    for ( i=0; i<stored_attachments.size(); i++ )
        delete stored_attachments[i];
    if( meta ) vlc_meta_Delete( meta );

    while( titles.size() )
    { vlc_input_title_Delete( titles.back() ); titles.pop_back();}

    vlc_mutex_destroy( &lock_demuxer );
}


matroska_stream_c *demux_sys_t::AnalyseAllSegmentsFound( demux_t *p_demux, EbmlStream *p_estream, bool b_initial )
{
    int i_upper_lvl = 0;
    EbmlElement *p_l0, *p_l1, *p_l2;
    bool b_keep_stream = false, b_keep_segment;

    // verify the EBML Header
    p_l0 = p_estream->FindNextID(EBML_INFO(EbmlHead), 0xFFFFFFFFL);
    if (p_l0 == NULL)
    {
        msg_Err( p_demux, "No EBML header found" );
        return NULL;
    }

    // verify we can read this Segment, we only support Matroska version 1 for now
    p_l0->Read(*p_estream, EBML_CLASS_CONTEXT(EbmlHead), i_upper_lvl, p_l0, true);

    EDocType doc_type = GetChild<EDocType>(*static_cast<EbmlHead*>(p_l0));
    if (std::string(doc_type) != "matroska" && std::string(doc_type) != "webm" )
    {
        msg_Err( p_demux, "Not a Matroska file : DocType = %s ", std::string(doc_type).c_str());
        return NULL;
    }

    EDocTypeReadVersion doc_read_version = GetChild<EDocTypeReadVersion>(*static_cast<EbmlHead*>(p_l0));
    if (uint64(doc_read_version) > 2)
    {
        msg_Err( p_demux, "matroska file needs version %"PRId64" but only versions 1 & 2 supported", uint64(doc_read_version));
        return NULL;
    }

    delete p_l0;


    // find all segments in this file
    p_l0 = p_estream->FindNextID(EBML_INFO(KaxSegment), 0xFFFFFFFFFLL);
    if (p_l0 == NULL)
    {
        return NULL;
    }

500
    matroska_stream_c *p_stream1 = new matroska_stream_c();
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

    while (p_l0 != 0)
    {
        if ( MKV_IS_ID( p_l0, KaxSegment) )
        {
            EbmlParser  *ep;
            matroska_segment_c *p_segment1 = new matroska_segment_c( *this, *p_estream );
            b_keep_segment = b_initial;

            ep = new EbmlParser(p_estream, p_l0, &demuxer );
            p_segment1->ep = ep;
            p_segment1->segment = (KaxSegment*)p_l0;

            while ((p_l1 = ep->Get()))
            {
                if (MKV_IS_ID(p_l1, KaxInfo))
                {
                    // find the families of this segment
                    KaxInfo *p_info = static_cast<KaxInfo*>(p_l1);

                    p_info->Read(*p_estream, EBML_CLASS_CONTEXT(KaxInfo), i_upper_lvl, p_l2, true);
                    for( size_t i = 0; i < p_info->ListSize(); i++ )
                    {
                        EbmlElement *l = (*p_info)[i];

                        if( MKV_IS_ID( l, KaxSegmentUID ) )
                        {
                            KaxSegmentUID *p_uid = static_cast<KaxSegmentUID*>(l);
                            b_keep_segment = (FindSegment( *p_uid ) == NULL);
                            if ( !b_keep_segment )
                                break; // this segment is already known
                            delete p_segment1->p_segment_uid;
                            p_segment1->p_segment_uid = new KaxSegmentUID(*p_uid);
                        }
                        else if( MKV_IS_ID( l, KaxPrevUID ) )
                        {
                            p_segment1->p_prev_segment_uid = new KaxPrevUID( *static_cast<KaxPrevUID*>(l) );
                        }
                        else if( MKV_IS_ID( l, KaxNextUID ) )
                        {
                            p_segment1->p_next_segment_uid = new KaxNextUID( *static_cast<KaxNextUID*>(l) );
                        }
                        else if( MKV_IS_ID( l, KaxSegmentFamily ) )
                        {
                            KaxSegmentFamily *p_fam = new KaxSegmentFamily( *static_cast<KaxSegmentFamily*>(l) );
                            p_segment1->families.push_back( p_fam );
                        }
                    }
Denis Charmet's avatar
Denis Charmet committed
549
550
                    if( b_keep_segment || !p_segment1->p_segment_uid )
                        opened_segments.push_back( p_segment1 );
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
                    break;
                }
            }
            if ( b_keep_segment )
            {
                b_keep_stream = true;
                p_stream1->segments.push_back( p_segment1 );
            }
            else
            {
                p_segment1->segment = NULL;
                delete p_segment1;
            }
        }
        if (p_l0->IsFiniteSize() )
        {
            p_l0->SkipData(*p_estream, KaxMatroska_Context);
            p_l0 = p_estream->FindNextID(EBML_INFO(KaxSegment), 0xFFFFFFFFL);
        }
        else
        {
            p_l0 = NULL;
        }
    }

    if ( !b_keep_stream )
    {
        delete p_stream1;
        p_stream1 = NULL;
    }

    return p_stream1;
}

void demux_sys_t::InitUi()
{
    msg_Dbg( &demuxer, "Starting the UI Hook" );

    /* FIXME hack hack hack hack FIXME */
    /* Get p_input and create variable */
    p_input = demux_GetParentInput( &demuxer );
592
593
594
595
596
597
598
599
600
601
    if( p_input )
    {
        var_Create( p_input, "x-start", VLC_VAR_INTEGER );
        var_Create( p_input, "y-start", VLC_VAR_INTEGER );
        var_Create( p_input, "x-end", VLC_VAR_INTEGER );
        var_Create( p_input, "y-end", VLC_VAR_INTEGER );
        var_Create( p_input, "color", VLC_VAR_ADDRESS );
        var_Create( p_input, "menu-palette", VLC_VAR_ADDRESS );
        var_Create( p_input, "highlight", VLC_VAR_BOOL );
    }
602
603
604
605
606
607
608
609
610
611

    /* Now create our event thread catcher */
    p_ev = new event_thread_t(&demuxer);
}

void demux_sys_t::CleanUi()
{
    delete p_ev;
    p_ev = NULL;

612
613
614
615
616
617
618
619
620
621
622
623
    if( p_input )
    {
        var_Destroy( p_input, "highlight" );
        var_Destroy( p_input, "x-start" );
        var_Destroy( p_input, "x-end" );
        var_Destroy( p_input, "y-start" );
        var_Destroy( p_input, "y-end" );
        var_Destroy( p_input, "color" );
        var_Destroy( p_input, "menu-palette" );

        vlc_object_release( p_input );
    }
624
625

    msg_Dbg( &demuxer, "Stopping the UI Hook" );
626
627
}

628
void demux_sys_t::PreloadFamily( const matroska_segment_c & of_segment )
629
{
630
631
632
633
    for (size_t i=0; i<opened_segments.size(); i++)
    {
        opened_segments[i]->PreloadFamily( of_segment );
    }
634
635
}

636
// preload all the linked segments for all preloaded segments
Denis Charmet's avatar
Denis Charmet committed
637
void demux_sys_t::PreloadLinked()
638
{
Denis Charmet's avatar
Denis Charmet committed
639
    size_t i, j;
640
641
    virtual_segment_c *p_seg;

Denis Charmet's avatar
Denis Charmet committed
642
    p_current_segment = VirtualFromSegments( &opened_segments );
643

644
    used_segments.push_back( p_current_segment );
645

646
647
648
649
    // publish all editions of all usable segment
    for ( i=0; i< used_segments.size(); i++ )
    {
        p_seg = used_segments[i];
650
        if ( p_seg->Editions() != NULL )
651
652
653
654
        {
            input_title_t *p_title = vlc_input_title_New();
            p_seg->i_sys_title = i;
            int i_chapters;
655

656
            // TODO use a name for each edition, let the TITLE deal with a codec name
657
            for ( j=0; j<p_seg->Editions()->size(); j++ )
658
659
660
            {
                if ( p_title->psz_name == NULL )
                {
661
                    const char* psz_tmp = (*p_seg->Editions())[j]->GetMainName().c_str();
662
663
                    if( *psz_tmp != '\0' )
                        p_title->psz_name = strdup( psz_tmp );
664
                }
665

666
                i_chapters = 0;
Denis Charmet's avatar
Denis Charmet committed
667
                ( *p_seg->Editions() )[j]->PublishChapters( *p_title, i_chapters, 0 );
668
            }
669

670
671
672
            // create a name if there is none
            if ( p_title->psz_name == NULL )
            {
673
674
                if( asprintf(&(p_title->psz_name), "%s %d", N_("Segment"), (int)i) == -1 )
                    p_title->psz_name = NULL;
675
            }
676

677
678
679
            titles.push_back( p_title );
        }
    }
680

681
    // TODO decide which segment should be first used (VMG for DVD)
682
683
}

Denis Charmet's avatar
Denis Charmet committed
684
virtual_segment_c *demux_sys_t::VirtualFromSegments( std::vector<matroska_segment_c*> *p_segments ) const
685
{
Denis Charmet's avatar
Denis Charmet committed
686
    virtual_segment_c *p_result = new virtual_segment_c( p_segments );
687
    return p_result;
688
689
}

690
bool demux_sys_t::PreparePlayback( virtual_segment_c *p_new_segment )
691
{
692
693
    if ( p_new_segment != NULL && p_new_segment != p_current_segment )
    {
694
695
        if ( p_current_segment != NULL && p_current_segment->CurrentSegment() != NULL )
            p_current_segment->CurrentSegment()->UnSelect();
696
697
698
699

        p_current_segment = p_new_segment;
        i_current_title = p_new_segment->i_sys_title;
    }
700
701
    if( !p_current_segment->CurrentSegment() )
        return false;
702
703
    if( !p_current_segment->CurrentSegment()->b_cues )
        msg_Warn( &p_current_segment->CurrentSegment()->sys.demuxer, "no cues/empty cues found->seek won't be precise" );
704
705

    f_duration = p_current_segment->Duration();
706

707
    /* add information */
708
709
    p_current_segment->CurrentSegment()->InformationCreate( );
    p_current_segment->CurrentSegment()->Select( 0 );
710

711
    return true;
712
713
}

Denis Charmet's avatar
Denis Charmet committed
714
void demux_sys_t::JumpTo( virtual_segment_c & vsegment, virtual_chapter_c * p_chapter )
715
{
716
717
718
719
720
721
    // if the segment is not part of the current segment, select the new one
    if ( &vsegment != p_current_segment )
    {
        PreparePlayback( &vsegment );
    }

Denis Charmet's avatar
Denis Charmet committed
722
    if ( p_chapter )
723
    {
Denis Charmet's avatar
Denis Charmet committed
724
        if ( !p_chapter->p_chapter || !p_chapter->p_chapter->Enter( true ) )
725
        {
726
            // jump to the location in the found segment
Denis Charmet's avatar
Denis Charmet committed
727
            vsegment.Seek( demuxer, p_chapter->i_virtual_start_time, -1, p_chapter, -1 );
728
729
        }
    }
730

731
732
}

733
matroska_segment_c *demux_sys_t::FindSegment( const EbmlBinary & uid ) const
734
{
735
    for (size_t i=0; i<opened_segments.size(); i++)
736
    {
737
738
        if ( *opened_segments[i]->p_segment_uid == uid )
            return opened_segments[i];
739
    }
740
    return NULL;
741
742
}

Denis Charmet's avatar
Denis Charmet committed
743
virtual_chapter_c *demux_sys_t::BrowseCodecPrivate( unsigned int codec_id,
744
745
746
747
                                        bool (*match)(const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size ),
                                        const void *p_cookie,
                                        size_t i_cookie_size,
                                        virtual_segment_c * &p_segment_found )
748
{
Denis Charmet's avatar
Denis Charmet committed
749
    virtual_chapter_c *p_result = NULL;
750
    for (size_t i=0; i<used_segments.size(); i++)
751
    {
752
753
        p_result = used_segments[i]->BrowseCodecPrivate( codec_id, match, p_cookie, i_cookie_size );
        if ( p_result != NULL )
754
        {
755
756
            p_segment_found = used_segments[i];
            break;
757
        }
758
759
760
    }
    return p_result;
}
761

Denis Charmet's avatar
Denis Charmet committed
762
virtual_chapter_c *demux_sys_t::FindChapter( int64_t i_find_uid, virtual_segment_c * & p_segment_found )
763
{
Denis Charmet's avatar
Denis Charmet committed
764
    virtual_chapter_c *p_result = NULL;
765
766
767
768
    for (size_t i=0; i<used_segments.size(); i++)
    {
        p_result = used_segments[i]->FindChapter( i_find_uid );
        if ( p_result != NULL )
769
        {
770
771
            p_segment_found = used_segments[i];
            break;
772
773
        }
    }
774
    return p_result;
775
776
}