You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

274 lines
7.3 KiB

/*****************************************************************************
* events.cpp : matroska demuxer
*****************************************************************************
* Copyright (C) 2003-2004 VLC authors and VideoLAN
*
* 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 Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser 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.
*****************************************************************************/
#include "mkv.hpp"
#include "demux.hpp"
#include "events.hpp"
#include "chapter_command_dvd.hpp"
#include <vlc_threads.h>
#include <algorithm>
namespace mkv {
event_thread_t::event_thread_t(demux_t *p_demux) : p_demux(p_demux)
{
vlc_mutex_init( &lock );
vlc_cond_init( &wait );
is_running = false;
}
event_thread_t::~event_thread_t()
{
AbortThread();
}
void event_thread_t::SendData( mkv_track_t &track, block_t * p_block )
{
if ( track.codec == "B_VOBBTN")
{
if( p_block->i_size > 0)
{
QueueEvent( EventInfo{ p_block } );
return; // the block will be released later
}
}
block_Release( p_block );
}
void event_thread_t::EnsureThreadLocked()
{
if (is_running || b_abort)
return;
is_running = !vlc_clone( &thread, EventThread, this );
}
void event_thread_t::AbortThread()
{
if( !is_running )
return;
{
vlc_mutex_locker lock_guard(&lock);
b_abort = true;
vlc_cond_signal( &wait );
}
vlc_join( thread, NULL );
is_running = false;
}
int event_thread_t::SendEventNav( demux_query_e nav_query )
{
NavivationKey key;
switch( nav_query )
{
case DEMUX_NAV_LEFT: key = NavivationKey::LEFT; break;
case DEMUX_NAV_RIGHT: key = NavivationKey::RIGHT; break;
case DEMUX_NAV_UP: key = NavivationKey::UP; break;
case DEMUX_NAV_DOWN: key = NavivationKey::DOWN; break;
case DEMUX_NAV_ACTIVATE: key = NavivationKey::OK; break;
case DEMUX_NAV_MENU: key = NavivationKey::MENU; break;
case DEMUX_NAV_POPUP: key = NavivationKey::POPUP; break;
default:
assert(false); // invalid navigation query received
return VLC_ENOTSUP;
}
if( !is_running )
return VLC_EGENERIC;
if ( !HandleKeyEvent( key ) )
return VLC_EGENERIC;
return VLC_SUCCESS;
}
void event_thread_t::EventMouse( vlc_mouse_t const* new_state, void* userdata )
{
ESInfo* info = static_cast<ESInfo*>( userdata );
if( !new_state )
return vlc_mouse_Init( &info->mouse_state );
info->owner.QueueEvent( EventInfo{ info->mouse_state, *new_state } );
info->mouse_state = *new_state;
}
void event_thread_t::EventThread()
{
vlc_thread_set_name("vlc-mkv-events");
int canc = vlc_savecancel ();
for( vlc_mutex_locker guard( &lock );; )
{
while( !b_abort && pending_events.empty() )
vlc_cond_wait( &wait, &lock );
if( b_abort )
break;
while( !pending_events.empty() )
{
const EventInfo ev = pending_events.front();
pending_events.pop_front();
if(es_list.empty())
break;
vlc_mutex_unlock( &lock );
switch( ev.type )
{
case EventInfo::ESMouseEvent:
HandleMouseEvent( ev );
break;
case EventInfo::ButtonDataEvent:
HandleButtonData( ev );
break;
}
vlc_mutex_lock( &lock );
}
}
vlc_restorecancel (canc);
}
void *event_thread_t::EventThread(void *data)
{
static_cast<event_thread_t*>(data)->EventThread();
return NULL;
}
bool event_thread_t::HandleKeyEvent( NavivationKey key )
{
demux_sys_t* p_sys = (demux_sys_t*)p_demux->p_sys;
vlc_mutex_locker demux_lock ( &p_sys->lock_demuxer );
auto interpretor = p_sys->GetDVDInterpretor();
if (!interpretor)
return false;
// process the button action
return interpretor->HandleKeyEvent( key );
}
void event_thread_t::HandleMouseEvent( EventInfo const& event )
{
int x = event.mouse.state_new.i_x;
int y = event.mouse.state_new.i_y;
if( vlc_mouse_HasPressed( &event.mouse.state_old, &event.mouse.state_new,
MOUSE_BUTTON_LEFT ) )
{
HandleMousePressed( (unsigned)x, (unsigned)y );
}
else if( vlc_mouse_HasMoved( &event.mouse.state_old, &event.mouse.state_new ) )
{
// dvdnav_mouse_select( NULL, pci, x, y );
}
}
void event_thread_t::HandleButtonData( EventInfo const& event )
{
HandleButtonData( event.button_data.get() );
}
void event_thread_t::HandleButtonData( block_t *p_block )
{
demux_sys_t* p_sys = (demux_sys_t*)p_demux->p_sys;
vlc_mutex_locker demux_lock ( &p_sys->lock_demuxer );
auto interpretor = p_sys->GetDVDInterpretor();
if (!interpretor)
return;
interpretor->SetPci( &p_block->p_buffer[1], p_block->i_size - 1 );
}
void event_thread_t::HandleMousePressed( unsigned x, unsigned y )
{
demux_sys_t* p_sys = (demux_sys_t*)p_demux->p_sys;
msg_Dbg( p_demux, "Handle Mouse Event: Mouse clicked x(%d)*y(%d)", x, y);
vlc_mutex_locker demux_lock ( &p_sys->lock_demuxer );
auto interpretor = p_sys->GetDVDInterpretor();
if (!interpretor)
return;
interpretor->HandleMousePressed( x, y );
}
void event_thread_t::SetHighlight( vlc_spu_highlight_t & spu_hl )
{
/* TODO: only control relevant SPU_ES given who fired the event */
for( auto it : es_list )
{
if( it.track.fmt.i_cat != SPU_ES )
continue;
es_out_Control( p_demux->out, ES_OUT_SPU_SET_HIGHLIGHT, it.track.p_es, &spu_hl );
}
}
bool event_thread_t::AddTrack( mkv_track_t & track )
{
es_out_id_t* es = track.p_es;
int category = track.fmt.i_cat;
vlc_mutex_locker lock_guard( &lock );
es_list.push_front( ESInfo( track, *this ) );
es_list_t::iterator info = es_list.begin();
if( category == VIDEO_ES )
{
if( es_out_Control( p_demux->out, ES_OUT_VOUT_SET_MOUSE_EVENT,
es, static_cast<vlc_mouse_event>(EventMouse),
static_cast<void*>( &*info ) ) )
{
msg_Warn( p_demux, "Unable to subscribe to mouse events" );
es_list.erase( info );
return false;
}
}
return true;
}
void event_thread_t::DelTrack( mkv_track_t &track )
{
vlc_mutex_locker lock_guard( &lock );
es_list_t::iterator info = std::find( es_list.begin(), es_list.end(), track );
if( info != es_list.end() )
es_list.erase( info );
}
} // namespace