]> git.sesse.net Git - vlc/blobdiff - modules/demux/mkv/demux.cpp
MKV: Virtual segment rewrite
[vlc] / modules / demux / mkv / demux.cpp
index c5f47a6a49847136e6e8644b49b8a8245c176392..ac399d4f6e2f6e4d82d6d8e478fe35d0f548118d 100644 (file)
 
 #include "Ebml_parser.hpp"
 
-demux_sys_t::~demux_sys_t()
+event_thread_t::event_thread_t(demux_t *p_demux) : p_demux(p_demux)
 {
-    StopUiThread();
-    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 );
+    vlc_mutex_init( &lock );
+    vlc_cond_init( &wait );
+    is_running = false;
 }
-
-
-matroska_stream_c *demux_sys_t::AnalyseAllSegmentsFound( demux_t *p_demux, EbmlStream *p_estream, bool b_initial )
+event_thread_t::~event_thread_t()
 {
-    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(EbmlHead::ClassInfos, 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, EbmlHead::ClassInfos.Context, 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, "This matroska file is needs version %"PRId64" and this VLC only supports version 1 & 2", uint64(doc_read_version));
-        return NULL;
-    }
-
-    delete p_l0;
-
-
-    // find all segments in this file
-    p_l0 = p_estream->FindNextID(KaxSegment::ClassInfos, 0xFFFFFFFFFLL);
-    if (p_l0 == NULL)
-    {
-        return NULL;
-    }
-
-    matroska_stream_c *p_stream1 = new matroska_stream_c( *this );
-
-    while (p_l0 != 0)
-    {
-        if (EbmlId(*p_l0) == KaxSegment::ClassInfos.GlobalId)
-        {
-            EbmlParser  *ep;
-            matroska_segment_c *p_segment1 = new matroska_segment_c( *this, *p_estream );
-            b_keep_segment = b_initial;
+    ResetPci();
+    vlc_cond_destroy( &wait );
+    vlc_mutex_destroy( &lock );
+}
 
-            ep = new EbmlParser(p_estream, p_l0, &demuxer );
-            p_segment1->ep = ep;
-            p_segment1->segment = (KaxSegment*)p_l0;
+void event_thread_t::SetPci(const pci_t *data)
+{
+    vlc_mutex_locker l(&lock);
 
-            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);
+    pci_packet = *data;
 
-                    p_info->Read(*p_estream, KaxInfo::ClassInfos.Context, i_upper_lvl, p_l2, true);
-                    for( size_t i = 0; i < p_info->ListSize(); i++ )
-                    {
-                        EbmlElement *l = (*p_info)[i];
+#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;
 
-                        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
-                            opened_segments.push_back( p_segment1 );
-                            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 );
-                        }
-                    }
-                    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(KaxSegment::ClassInfos, 0xFFFFFFFFL);
-        }
-        else
-        {
-            p_l0 = NULL;
-        }
-    }
+        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;
 
-    if ( !b_keep_stream )
-    {
-        delete p_stream1;
-        p_stream1 = NULL;
     }
-
-    return p_stream1;
-}
-
-void demux_sys_t::StartUiThread()
-{
-    if ( !b_ui_hooked )
+    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 )
     {
-        msg_Dbg( &demuxer, "Starting the UI Hook" );
-        b_ui_hooked = true;
-        /* FIXME hack hack hack hack FIXME */
-        /* Get p_input and create variable */
-        p_input = (input_thread_t *) vlc_object_find( &demuxer, VLC_OBJECT_INPUT, FIND_PARENT );
-        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 );
-        var_Create( p_input, "highlight-mutex", VLC_VAR_MUTEX );
-
-        /* Now create our event thread catcher */
-        p_ev = (event_thread_t *) vlc_object_create( &demuxer, sizeof( event_thread_t ) );
-        p_ev->p_demux = &demuxer;
-        p_ev->b_die = false;
-        vlc_mutex_init( &p_ev->lock );
-        vlc_thread_create( p_ev, "mkv event thread handler", EventThread,
-                        VLC_THREAD_PRIORITY_LOW );
+        b_abort = false;
+        is_running = !vlc_clone( &thread, EventThread, this, VLC_THREAD_PRIORITY_LOW );
     }
 }
-
-void demux_sys_t::StopUiThread()
+void event_thread_t::ResetPci()
 {
-    if ( b_ui_hooked )
-    {
-        vlc_object_kill( p_ev );
-        vlc_thread_join( p_ev );
-        vlc_object_release( p_ev );
+    if( !is_running )
+        return;
 
-        p_ev = NULL;
+    vlc_mutex_lock( &lock );
+    b_abort = true;
+    vlc_cond_signal( &wait );
+    vlc_mutex_unlock( &lock );
 
-        var_Destroy( p_input, "highlight-mutex" );
-        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 );
-
-        msg_Dbg( &demuxer, "Stopping the UI Hook" );
-    }
-    b_ui_hooked = false;
+    vlc_join( thread, NULL );
+    is_running = false;
 }
-
-int demux_sys_t::EventMouse( vlc_object_t *p_this, char const *psz_var,
-                       vlc_value_t oldval, vlc_value_t newval, void *p_data )
+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 )
 {
+    VLC_UNUSED( oldval ); VLC_UNUSED( newval );
     event_thread_t *p_ev = (event_thread_t *) p_data;
     vlc_mutex_lock( &p_ev->lock );
     if( psz_var[6] == 'c' )
@@ -239,61 +97,80 @@ int demux_sys_t::EventMouse( vlc_object_t *p_this, char const *psz_var,
     }
     else if( psz_var[6] == 'm' )
         p_ev->b_moved = true;
+    vlc_cond_signal( &p_ev->wait );
     vlc_mutex_unlock( &p_ev->lock );
 
     return VLC_SUCCESS;
 }
 
-int demux_sys_t::EventKey( vlc_object_t *p_this, char const *,
-                           vlc_value_t, vlc_value_t newval, void *p_data )
+int event_thread_t::EventKey( vlc_object_t *p_this, char const *,
+                              vlc_value_t, vlc_value_t newval, void *p_data )
 {
     event_thread_t *p_ev = (event_thread_t *) p_data;
     vlc_mutex_lock( &p_ev->lock );
     p_ev->i_key_action = newval.i_int;
+    vlc_cond_signal( &p_ev->wait );
     vlc_mutex_unlock( &p_ev->lock );
     msg_Dbg( p_this, "Event Key");
 
     return VLC_SUCCESS;
 }
 
-void * demux_sys_t::EventThread( vlc_object_t *p_this )
+int event_thread_t::EventInput( vlc_object_t *p_this, char const *,
+                                vlc_value_t, vlc_value_t newval, void *p_data )
+{
+    VLC_UNUSED( p_this );
+    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()
 {
-    event_thread_t *p_ev = (event_thread_t*)p_this;
-    demux_sys_t    *p_sys = p_ev->p_demux->p_sys;
+    demux_sys_t    *p_sys = p_demux->p_sys;
     vlc_object_t   *p_vout = NULL;
     int canc = vlc_savecancel ();
 
-    p_ev->b_moved   = false;
-    p_ev->b_clicked = false;
-    p_ev->i_key_action = 0;
+    b_moved      = false;
+    b_clicked    = false;
+    i_key_action = 0;
+    b_vout       = true;
 
     /* catch all key event */
-    var_AddCallback( p_ev->p_libvlc, "key-action", EventKey, p_ev );
+    var_AddCallback( p_demux->p_libvlc, "key-action", EventKey, this );
+    /* catch input event */
+    var_AddCallback( p_sys->p_input, "intf-event", EventInput, this );
 
     /* main loop */
-    while( vlc_object_alive (p_ev) )
+    for( ;; )
     {
-        if ( !p_sys->b_pci_packet_set )
+        vlc_mutex_lock( &lock );
+        while( !b_abort && !i_key_action && !b_moved && !b_clicked && !b_vout)
+            vlc_cond_wait( &wait, &lock );
+
+        if( b_abort )
         {
-            /* Wait 100ms */
-            msleep( 100000 );
-            continue;
+            vlc_mutex_unlock( &lock );
+            break;
         }
 
-        bool b_activated = false;
-
         /* KEY part */
-        if( p_ev->i_key_action )
+        if( i_key_action )
         {
-            msg_Dbg( p_ev->p_demux, "Handle Key Event");
+            msg_Dbg( p_demux, "Handle Key Event");
 
-            vlc_mutex_lock( &p_ev->lock );
-
-            pci_t *pci = (pci_t *) &p_sys->pci_packet;
+            pci_t *pci = &pci_packet;
 
             uint16 i_curr_button = p_sys->dvd_interpretor.GetSPRM( 0x88 );
 
-            switch( p_ev->i_key_action )
+            switch( i_key_action )
             {
             case ACTIONID_NAV_LEFT:
                 if ( i_curr_button > 0 && i_curr_button <= pci->hli.hl_gi.btn_ns )
@@ -306,14 +183,14 @@ void * demux_sys_t::EventThread( vlc_object_t *p_this )
                         btni_t button_ptr = pci->hli.btnit[i_curr_button-1];
                         if ( button_ptr.auto_action_mode )
                         {
-                            vlc_mutex_unlock( &p_ev->lock );
+                            vlc_mutex_unlock( &lock );
                             vlc_mutex_lock( &p_sys->lock_demuxer );
 
                             // process the button action
                             p_sys->dvd_interpretor.Interpret( button_ptr.cmd.bytes, 8 );
 
                             vlc_mutex_unlock( &p_sys->lock_demuxer );
-                            vlc_mutex_lock( &p_ev->lock );
+                            vlc_mutex_lock( &lock );
                         }
                     }
                 }
@@ -329,14 +206,14 @@ void * demux_sys_t::EventThread( vlc_object_t *p_this )
                         btni_t button_ptr = pci->hli.btnit[i_curr_button-1];
                         if ( button_ptr.auto_action_mode )
                         {
-                            vlc_mutex_unlock( &p_ev->lock );
+                            vlc_mutex_unlock( &lock );
                             vlc_mutex_lock( &p_sys->lock_demuxer );
 
                             // process the button action
                             p_sys->dvd_interpretor.Interpret( button_ptr.cmd.bytes, 8 );
 
                             vlc_mutex_unlock( &p_sys->lock_demuxer );
-                            vlc_mutex_lock( &p_ev->lock );
+                            vlc_mutex_lock( &lock );
                         }
                     }
                 }
@@ -352,14 +229,14 @@ void * demux_sys_t::EventThread( vlc_object_t *p_this )
                         btni_t button_ptr = pci->hli.btnit[i_curr_button-1];
                         if ( button_ptr.auto_action_mode )
                         {
-                            vlc_mutex_unlock( &p_ev->lock );
+                            vlc_mutex_unlock( &lock );
                             vlc_mutex_lock( &p_sys->lock_demuxer );
 
                             // process the button action
                             p_sys->dvd_interpretor.Interpret( button_ptr.cmd.bytes, 8 );
 
                             vlc_mutex_unlock( &p_sys->lock_demuxer );
-                            vlc_mutex_lock( &p_ev->lock );
+                            vlc_mutex_lock( &lock );
                         }
                     }
                 }
@@ -375,60 +252,55 @@ void * demux_sys_t::EventThread( vlc_object_t *p_this )
                         btni_t button_ptr = pci->hli.btnit[i_curr_button-1];
                         if ( button_ptr.auto_action_mode )
                         {
-                            vlc_mutex_unlock( &p_ev->lock );
+                            vlc_mutex_unlock( &lock );
                             vlc_mutex_lock( &p_sys->lock_demuxer );
 
                             // process the button action
                             p_sys->dvd_interpretor.Interpret( button_ptr.cmd.bytes, 8 );
 
                             vlc_mutex_unlock( &p_sys->lock_demuxer );
-                            vlc_mutex_lock( &p_ev->lock );
+                            vlc_mutex_lock( &lock );
                         }
                     }
                 }
                 break;
             case ACTIONID_NAV_ACTIVATE:
-                b_activated = true;
                 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];
 
-                    vlc_mutex_unlock( &p_ev->lock );
+                    vlc_mutex_unlock( &lock );
                     vlc_mutex_lock( &p_sys->lock_demuxer );
 
                     // process the button action
                     p_sys->dvd_interpretor.Interpret( button_ptr.cmd.bytes, 8 );
 
                     vlc_mutex_unlock( &p_sys->lock_demuxer );
-                    vlc_mutex_lock( &p_ev->lock );
+                    vlc_mutex_lock( &lock );
                 }
                 break;
             default:
                 break;
             }
-            p_ev->i_key_action = 0;
-            vlc_mutex_unlock( &p_ev->lock );
+            i_key_action = 0;
         }
 
         /* MOUSE part */
-        if( p_vout && ( p_ev->b_moved || p_ev->b_clicked ) )
+        if( p_vout && ( b_moved || b_clicked ) )
         {
             int x, y;
 
             var_GetCoords( p_vout, "mouse-moved", &x, &y );
-            vlc_mutex_lock( &p_ev->lock );
-            pci_t *pci = (pci_t *) &p_sys->pci_packet;
+            pci_t *pci = &pci_packet;
 
-            if( p_ev->b_clicked )
+            if( b_clicked )
             {
                 int32_t button;
                 int32_t best,dist,d;
                 int32_t mx,my,dx,dy;
 
-                msg_Dbg( p_ev->p_demux, "Handle Mouse Event: Mouse clicked x(%d)*y(%d)", x, y);
+                msg_Dbg( p_demux, "Handle Mouse Event: Mouse clicked x(%d)*y(%d)", x, y);
 
-                b_activated = true;
                 // get current button
                 best = 0;
                 dist = 0x08000000; /* >> than  (720*720)+(567*567); */
@@ -461,7 +333,7 @@ void * demux_sys_t::EventThread( vlc_object_t *p_this )
                     uint16 i_curr_button = p_sys->dvd_interpretor.GetSPRM( 0x88 );
 
                     msg_Dbg( &p_sys->demuxer, "Clicked button %d", best );
-                    vlc_mutex_unlock( &p_ev->lock );
+                    vlc_mutex_unlock( &lock );
                     vlc_mutex_lock( &p_sys->lock_demuxer );
 
                     // process the button action
@@ -473,95 +345,284 @@ void * demux_sys_t::EventThread( vlc_object_t *p_this )
                     // select new button
                     if ( best != i_curr_button )
                     {
-                        vlc_value_t val;
+                        uint32_t i_palette;
 
-                        if( var_Get( p_sys->p_input, "highlight-mutex", &val ) == VLC_SUCCESS )
+                        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++ )
                         {
-                            vlc_mutex_t *p_mutex = (vlc_mutex_t *) val.p_address;
-                            uint32_t i_palette;
-
-                            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++ )
-                            {
-                                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;
-                            }
-
-                            vlc_mutex_lock( p_mutex );
-                            val.i_int = button_ptr.x_start; var_Set( p_sys->p_input, "x-start", val );
-                            val.i_int = button_ptr.x_end;   var_Set( p_sys->p_input, "x-end",   val );
-                            val.i_int = button_ptr.y_start; var_Set( p_sys->p_input, "y-start", val );
-                            val.i_int = button_ptr.y_end;   var_Set( p_sys->p_input, "y-end",   val );
-
-                            val.p_address = (void *)p_sys->palette;
-                            var_Set( p_sys->p_input, "menu-palette", val );
-
-                            val.b_bool = true; var_Set( p_sys->p_input, "highlight", val );
-                            vlc_mutex_unlock( p_mutex );
+                            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;
                         }
+
+                        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 );
                     }
                     vlc_mutex_unlock( &p_sys->lock_demuxer );
-                    vlc_mutex_lock( &p_ev->lock );
+                    vlc_mutex_lock( &lock );
                 }
             }
-            else if( p_ev->b_moved )
+            else if( b_moved )
             {
 //                dvdnav_mouse_select( NULL, pci, x, y );
             }
 
-            p_ev->b_moved = false;
-            p_ev->b_clicked = false;
-            vlc_mutex_unlock( &p_ev->lock );
+            b_moved = false;
+            b_clicked = false;
         }
 
-        /* VOUT part */
+        b_vout = false;
+        vlc_mutex_unlock( &lock );
+
+        /* Always check vout */
         if( p_vout && !vlc_object_alive (p_vout) )
         {
-            var_DelCallback( p_vout, "mouse-moved", EventMouse, p_ev );
-            var_DelCallback( p_vout, "mouse-clicked", EventMouse, p_ev );
+            var_DelCallback( p_vout, "mouse-moved", EventMouse, this );
+            var_DelCallback( p_vout, "mouse-clicked", EventMouse, this );
             vlc_object_release( p_vout );
             p_vout = NULL;
         }
 
         else if( p_vout == NULL )
         {
-            p_vout = (vlc_object_t*) vlc_object_find( p_sys->p_input, VLC_OBJECT_VOUT,
-                                      FIND_CHILD );
+            p_vout = (vlc_object_t*) input_GetVout(p_sys->p_input);
             if( p_vout)
             {
-                var_AddCallback( p_vout, "mouse-moved", EventMouse, p_ev );
-                var_AddCallback( p_vout, "mouse-clicked", EventMouse, p_ev );
+                var_AddCallback( p_vout, "mouse-moved", EventMouse, this );
+                var_AddCallback( p_vout, "mouse-clicked", EventMouse, this );
             }
         }
-
-        /* Wait a bit, 10ms */
-        msleep( 10000 );
     }
 
     /* Release callback */
     if( p_vout )
     {
-        var_DelCallback( p_vout, "mouse-moved", EventMouse, p_ev );
-        var_DelCallback( p_vout, "mouse-clicked", EventMouse, p_ev );
+        var_DelCallback( p_vout, "mouse-moved", EventMouse, this );
+        var_DelCallback( p_vout, "mouse-clicked", EventMouse, this );
         vlc_object_release( p_vout );
     }
-    var_DelCallback( p_ev->p_libvlc, "key-action", EventKey, p_ev );
-
-    vlc_mutex_destroy( &p_ev->lock );
+    var_DelCallback( p_sys->p_input, "intf-event", EventInput, this );
+    var_DelCallback( p_demux->p_libvlc, "key-action", EventKey, this );
 
     vlc_restorecancel (canc);
-    return VLC_SUCCESS;
+}
+
+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;
+    }
+
+    matroska_stream_c *p_stream1 = new matroska_stream_c();
+
+    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 );
+                        }
+                    }
+                    if( b_keep_segment || !p_segment1->p_segment_uid )
+                        opened_segments.push_back( p_segment1 );
+                    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 );
+    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 );
+    }
+
+    /* Now create our event thread catcher */
+    p_ev = new event_thread_t(&demuxer);
+}
+
+void demux_sys_t::CleanUi()
+{
+    delete p_ev;
+    p_ev = NULL;
+
+    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 );
+    }
+
+    msg_Dbg( &demuxer, "Stopping the UI Hook" );
 }
 
 void demux_sys_t::PreloadFamily( const matroska_segment_c & of_segment )
@@ -573,53 +634,37 @@ void demux_sys_t::PreloadFamily( const matroska_segment_c & of_segment )
 }
 
 // preload all the linked segments for all preloaded segments
-void demux_sys_t::PreloadLinked( matroska_segment_c *p_segment )
+void demux_sys_t::PreloadLinked()
 {
-    size_t i_preloaded, i, j;
+    size_t i, j;
     virtual_segment_c *p_seg;
 
-    p_current_segment = VirtualFromSegments( p_segment );
-    used_segments.push_back( p_current_segment );
+    p_current_segment = VirtualFromSegments( &opened_segments );
 
-    // create all the other virtual segments of the family
-    do {
-        i_preloaded = 0;
-        for ( i=0; i< opened_segments.size(); i++ )
-        {
-            if ( opened_segments[i]->b_preloaded && !IsUsedSegment( *opened_segments[i] ) )
-            {
-                p_seg = VirtualFromSegments( opened_segments[i] );
-                used_segments.push_back( p_seg );
-                i_preloaded++;
-            }
-        }
-    } while ( i_preloaded ); // worst case: will stop when all segments are found as family related
+    used_segments.push_back( p_current_segment );
 
     // publish all editions of all usable segment
     for ( i=0; i< used_segments.size(); i++ )
     {
         p_seg = used_segments[i];
-        if ( p_seg->p_editions != NULL )
+        if ( p_seg->Editions() != NULL )
         {
             input_title_t *p_title = vlc_input_title_New();
             p_seg->i_sys_title = i;
             int i_chapters;
 
             // TODO use a name for each edition, let the TITLE deal with a codec name
-            for ( j=0; j<p_seg->p_editions->size(); j++ )
+            for ( j=0; j<p_seg->Editions()->size(); j++ )
             {
                 if ( p_title->psz_name == NULL )
                 {
-                    const char* psz_tmp = (*p_seg->p_editions)[j]->GetMainName().c_str();
+                    const char* psz_tmp = (*p_seg->Editions())[j]->GetMainName().c_str();
                     if( *psz_tmp != '\0' )
                         p_title->psz_name = strdup( psz_tmp );
                 }
 
-                chapter_edition_c *p_edition = (*p_seg->p_editions)[j];
-
                 i_chapters = 0;
-                p_edition->PublishChapters( *p_title, i_chapters, 0 );
+                ( *p_seg->Editions() )[j]->PublishChapters( *p_title, i_chapters, 0 );
             }
 
             // create a name if there is none
@@ -636,37 +681,9 @@ void demux_sys_t::PreloadLinked( matroska_segment_c *p_segment )
     // TODO decide which segment should be first used (VMG for DVD)
 }
 
-bool demux_sys_t::IsUsedSegment( matroska_segment_c &segment ) const
+virtual_segment_c *demux_sys_t::VirtualFromSegments( std::vector<matroska_segment_c*> *p_segments ) const
 {
-    for ( size_t i=0; i< used_segments.size(); i++ )
-    {
-        if ( used_segments[i]->FindUID( *segment.p_segment_uid ) )
-            return true;
-    }
-    return false;
-}
-
-virtual_segment_c *demux_sys_t::VirtualFromSegments( matroska_segment_c *p_segment ) const
-{
-    size_t i_preloaded, i;
-
-    virtual_segment_c *p_result = new virtual_segment_c( p_segment );
-
-    // fill our current virtual segment with all hard linked segments
-    do {
-        i_preloaded = 0;
-        for ( i=0; i< opened_segments.size(); i++ )
-        {
-            i_preloaded += p_result->AddSegment( opened_segments[i] );
-        }
-    } while ( i_preloaded ); // worst case: will stop when all segments are found as linked
-
-    p_result->Sort( );
-
-    p_result->PreloadLinked( );
-
-    p_result->PrepareChapters( );
-
+    virtual_segment_c *p_result = new virtual_segment_c( p_segments );
     return p_result;
 }
 
@@ -674,25 +691,25 @@ bool demux_sys_t::PreparePlayback( virtual_segment_c *p_new_segment )
 {
     if ( p_new_segment != NULL && p_new_segment != p_current_segment )
     {
-        if ( p_current_segment != NULL && p_current_segment->Segment() != NULL )
-            p_current_segment->Segment()->UnSelect();
+        if ( p_current_segment != NULL && p_current_segment->CurrentSegment() != NULL )
+            p_current_segment->CurrentSegment()->UnSelect();
 
         p_current_segment = p_new_segment;
         i_current_title = p_new_segment->i_sys_title;
     }
-    if( !p_current_segment->Segment()->b_cues )
-        msg_Warn( &p_current_segment->Segment()->sys.demuxer, "no cues/empty cues found->seek won't be precise" );
+    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" );
 
     f_duration = p_current_segment->Duration();
 
     /* add information */
-    p_current_segment->Segment()->InformationCreate( );
-    p_current_segment->Segment()->Select( 0 );
+    p_current_segment->CurrentSegment()->InformationCreate( );
+    p_current_segment->CurrentSegment()->Select( 0 );
 
     return true;
 }
 
-void demux_sys_t::JumpTo( virtual_segment_c & vsegment, chapter_item_c * p_chapter )
+void demux_sys_t::JumpTo( virtual_segment_c & vsegment, virtual_chapter_c * p_chapter )
 {
     // if the segment is not part of the current segment, select the new one
     if ( &vsegment != p_current_segment )
@@ -700,15 +717,15 @@ void demux_sys_t::JumpTo( virtual_segment_c & vsegment, chapter_item_c * p_chapt
         PreparePlayback( &vsegment );
     }
 
-    if ( p_chapter != NULL )
+    if ( p_chapter )
     {
-        if ( !p_chapter->Enter( true ) )
+        if ( !p_chapter->p_chapter || !p_chapter->p_chapter->Enter( true ) )
         {
             // jump to the location in the found segment
-            vsegment.Seek( demuxer, p_chapter->i_user_start_time, -1, p_chapter, -1 );
+            vsegment.Seek( demuxer, p_chapter->i_virtual_start_time, -1, p_chapter, -1 );
         }
     }
+
 }
 
 matroska_segment_c *demux_sys_t::FindSegment( const EbmlBinary & uid ) const
@@ -721,13 +738,13 @@ matroska_segment_c *demux_sys_t::FindSegment( const EbmlBinary & uid ) const
     return NULL;
 }
 
-chapter_item_c *demux_sys_t::BrowseCodecPrivate( unsigned int codec_id,
+virtual_chapter_c *demux_sys_t::BrowseCodecPrivate( unsigned int codec_id,
                                         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 )
 {
-    chapter_item_c *p_result = NULL;
+    virtual_chapter_c *p_result = NULL;
     for (size_t i=0; i<used_segments.size(); i++)
     {
         p_result = used_segments[i]->BrowseCodecPrivate( codec_id, match, p_cookie, i_cookie_size );
@@ -740,9 +757,9 @@ chapter_item_c *demux_sys_t::BrowseCodecPrivate( unsigned int codec_id,
     return p_result;
 }
 
-chapter_item_c *demux_sys_t::FindChapter( int64_t i_find_uid, virtual_segment_c * & p_segment_found )
+virtual_chapter_c *demux_sys_t::FindChapter( int64_t i_find_uid, virtual_segment_c * & p_segment_found )
 {
-    chapter_item_c *p_result = NULL;
+    virtual_chapter_c *p_result = NULL;
     for (size_t i=0; i<used_segments.size(); i++)
     {
         p_result = used_segments[i]->FindChapter( i_find_uid );
@@ -755,31 +772,3 @@ chapter_item_c *demux_sys_t::FindChapter( int64_t i_find_uid, virtual_segment_c
     return p_result;
 }
 
-void demux_sys_t::SwapButtons()
-{
-#ifndef WORDS_BIGENDIAN
-    uint8_t button, i, j;
-
-    for( 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;
-
-        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;
-
-    }
-    for ( i = 0; i<3; i++ )
-    {
-        for ( 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
-}