demux.cpp
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:28k
源码类别:

midi

开发平台:

Unix_Linux

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