demux: mkv: ProcessNavAction: negate if to prevent nesting
[vlc.git] / modules / demux / mkv / events.cpp
blobc8c68fefeb39cbea00b8f81cd64c98a91af30eb2
1 /*****************************************************************************
2 * events.cpp : matroska demuxer
3 *****************************************************************************
4 * Copyright (C) 2003-2004 VLC authors and VideoLAN
5 * $Id$
7 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8 * Steve Lhomme <steve.lhomme@free.fr>
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU Lesser General Public License as published by
12 * the Free Software Foundation; either version 2.1 of the License, or
13 * (at your option) any later version.
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 Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with this program; if not, write to the Free Software Foundation,
22 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 *****************************************************************************/
25 #include "mkv.hpp"
26 #include "demux.hpp"
27 #include "events.hpp"
29 #include <vlc_actions.h>
30 #include <vlc_threads.h>
32 #include <algorithm>
34 namespace mkv {
36 event_thread_t::event_thread_t(demux_t *p_demux) : p_demux(p_demux)
38 vlc_mutex_init( &lock );
39 vlc_cond_init( &wait );
40 is_running = false;
41 memset(&pci_packet, 0, sizeof(pci_packet));
43 event_thread_t::~event_thread_t()
45 ResetPci();
46 vlc_cond_destroy( &wait );
47 vlc_mutex_destroy( &lock );
50 void event_thread_t::SetPci(const pci_t *data)
52 vlc_mutex_locker l(&lock);
54 pci_packet = *data;
56 #ifndef WORDS_BIGENDIAN
57 for( uint8_t button = 1; button <= pci_packet.hli.hl_gi.btn_ns; button++) {
58 btni_t *button_ptr = &(pci_packet.hli.btnit[button-1]);
59 binary *p_data = (binary*) button_ptr;
61 uint16 i_x_start = ((p_data[0] & 0x3F) << 4 ) + ( p_data[1] >> 4 );
62 uint16 i_x_end = ((p_data[1] & 0x03) << 8 ) + p_data[2];
63 uint16 i_y_start = ((p_data[3] & 0x3F) << 4 ) + ( p_data[4] >> 4 );
64 uint16 i_y_end = ((p_data[4] & 0x03) << 8 ) + p_data[5];
65 button_ptr->x_start = i_x_start;
66 button_ptr->x_end = i_x_end;
67 button_ptr->y_start = i_y_start;
68 button_ptr->y_end = i_y_end;
71 for ( uint8_t i = 0; i<3; i++ )
72 for ( uint8_t j = 0; j<2; j++ )
73 pci_packet.hli.btn_colit.btn_coli[i][j] = U32_AT( &pci_packet.hli.btn_colit.btn_coli[i][j] );
74 #endif
75 if( !is_running )
77 b_abort = false;
78 is_running = !vlc_clone( &thread, EventThread, this, VLC_THREAD_PRIORITY_LOW );
81 void event_thread_t::ResetPci()
83 if( !is_running )
84 return;
86 vlc_mutex_lock( &lock );
87 b_abort = true;
88 vlc_cond_signal( &wait );
89 vlc_mutex_unlock( &lock );
91 vlc_join( thread, NULL );
92 is_running = false;
95 void event_thread_t::EventMouse( vlc_mouse_t const* new_state, void* userdata )
97 ESInfo* info = static_cast<ESInfo*>( userdata );
98 vlc_mutex_locker lock_guard( &info->owner.lock );
100 if( !new_state )
101 return vlc_mouse_Init( &info->mouse_state );
103 info->owner.pending_events.push_back(
104 EventInfo( info, info->mouse_state, *new_state ) );
106 vlc_cond_signal( &info->owner.wait );
107 info->mouse_state = *new_state;
110 int event_thread_t::EventKey( vlc_object_t *p_this, char const *,
111 vlc_value_t, vlc_value_t newval, void *p_data )
113 event_thread_t* owner = static_cast<event_thread_t*>( p_data );
114 vlc_mutex_locker lock_guard( &owner->lock );
116 owner->pending_events.push_back(
117 EventInfo( static_cast<vlc_action_id_t>( newval.i_int ) ) );
119 vlc_cond_signal( &owner->wait );
120 msg_Dbg( p_this, "Event Key");
122 return VLC_SUCCESS;
125 void event_thread_t::EventThread()
127 int canc = vlc_savecancel ();
129 /* catch all key event */
130 var_AddCallback( p_demux->obj.libvlc, "key-action", EventKey, this );
132 for( vlc_mutex_locker guard( &lock );; )
134 while( !b_abort && pending_events.empty() )
135 vlc_cond_wait( &wait, &lock );
137 if( b_abort )
138 break;
140 while( !pending_events.empty() )
142 EventInfo const& ev = pending_events.front();
144 switch( ev.type )
146 case EventInfo::ESMouseEvent:
147 HandleMouseEvent( ev );
148 break;
150 case EventInfo::ActionEvent:
151 HandleKeyEvent( ev );
152 break;
155 pending_events.pop_front();
159 var_DelCallback( p_demux->obj.libvlc, "key-action", EventKey, this );
160 vlc_restorecancel (canc);
163 void *event_thread_t::EventThread(void *data)
165 static_cast<event_thread_t*>(data)->EventThread();
166 return NULL;
169 void event_thread_t::ProcessNavAction( uint16 button, pci_t* pci )
171 demux_sys_t* p_sys = (demux_sys_t*)p_demux->p_sys;
173 if( button <= 0 || button > pci->hli.hl_gi.btn_ns )
174 return;
176 p_sys->dvd_interpretor.SetSPRM( 0x88, button );
177 btni_t button_ptr = pci->hli.btnit[button-1];
178 if ( button_ptr.auto_action_mode )
180 vlc_mutex_unlock( &lock );
181 vlc_mutex_lock( &p_sys->lock_demuxer );
183 // process the button action
184 p_sys->dvd_interpretor.Interpret( button_ptr.cmd.bytes, 8 );
186 vlc_mutex_unlock( &p_sys->lock_demuxer );
187 vlc_mutex_lock( &lock );
191 void event_thread_t::HandleKeyEvent( EventInfo const& ev )
193 msg_Dbg( p_demux, "Handle Key Event");
195 demux_sys_t* p_sys = (demux_sys_t*)p_demux->p_sys;
196 pci_t *pci = &pci_packet;
198 uint16 i_curr_button = p_sys->dvd_interpretor.GetSPRM( 0x88 );
200 if( i_curr_button <= 0 || i_curr_button > pci->hli.hl_gi.btn_ns )
201 return;
203 btni_t button_ptr = pci->hli.btnit[i_curr_button-1];
205 switch( ev.action.id )
207 case ACTIONID_NAV_LEFT: return ProcessNavAction( button_ptr.left, pci );
208 case ACTIONID_NAV_RIGHT: return ProcessNavAction( button_ptr.right, pci );
209 case ACTIONID_NAV_UP: return ProcessNavAction( button_ptr.up, pci );
210 case ACTIONID_NAV_DOWN: return ProcessNavAction( button_ptr.down, pci );
211 case ACTIONID_NAV_ACTIVATE:
213 vlc_mutex_unlock( &lock );
214 vlc_mutex_lock( &p_sys->lock_demuxer );
216 // process the button action
217 p_sys->dvd_interpretor.Interpret( button_ptr.cmd.bytes, 8 );
219 vlc_mutex_unlock( &p_sys->lock_demuxer );
220 vlc_mutex_lock( &lock );
222 break;
223 default:
224 break;
228 void event_thread_t::HandleMouseEvent( EventInfo const& event )
230 demux_sys_t* p_sys = (demux_sys_t*)p_demux->p_sys;
231 int x = event.mouse.state_new.i_x;
232 int y = event.mouse.state_new.i_y;
234 pci_t *pci = &pci_packet;
236 if( vlc_mouse_HasPressed( &event.mouse.state_old, &event.mouse.state_new,
237 MOUSE_BUTTON_LEFT ) )
239 int32_t button;
240 int32_t best,dist,d;
241 int32_t mx,my,dx,dy;
243 msg_Dbg( p_demux, "Handle Mouse Event: Mouse clicked x(%d)*y(%d)", x, y);
245 // get current button
246 best = 0;
247 dist = 0x08000000; /* >> than (720*720)+(567*567); */
248 for(button = 1; button <= pci->hli.hl_gi.btn_ns; button++)
250 btni_t *button_ptr = &(pci->hli.btnit[button-1]);
252 if(((unsigned)x >= button_ptr->x_start)
253 && ((unsigned)x <= button_ptr->x_end)
254 && ((unsigned)y >= button_ptr->y_start)
255 && ((unsigned)y <= button_ptr->y_end))
257 mx = (button_ptr->x_start + button_ptr->x_end)/2;
258 my = (button_ptr->y_start + button_ptr->y_end)/2;
259 dx = mx - x;
260 dy = my - y;
261 d = (dx*dx) + (dy*dy);
262 /* If the mouse is within the button and the mouse is closer
263 * to the center of this button then it is the best choice. */
264 if(d < dist) {
265 dist = d;
266 best = button;
271 if ( best != 0)
273 btni_t button_ptr = pci->hli.btnit[best-1];
274 uint16 i_curr_button = p_sys->dvd_interpretor.GetSPRM( 0x88 );
276 msg_Dbg( &p_sys->demuxer, "Clicked button %d", best );
277 vlc_mutex_unlock( &lock );
278 vlc_mutex_lock( &p_sys->lock_demuxer );
280 // process the button action
281 p_sys->dvd_interpretor.SetSPRM( 0x88, best );
282 p_sys->dvd_interpretor.Interpret( button_ptr.cmd.bytes, 8 );
284 msg_Dbg( &p_sys->demuxer, "Processed button %d", best );
286 // select new button
287 if ( best != i_curr_button )
289 // TODO: make sure we do not overflow in the conversion
290 vlc_spu_highlight_t spu_hl = vlc_spu_highlight_t();
292 spu_hl.x_start = (int)button_ptr.x_start;
293 spu_hl.y_start = (int)button_ptr.y_start;
295 spu_hl.x_end = (int)button_ptr.x_end;
296 spu_hl.y_end = (int)button_ptr.y_end;
298 uint32_t i_palette;
300 if(button_ptr.btn_coln != 0) {
301 i_palette = pci->hli.btn_colit.btn_coli[button_ptr.btn_coln-1][1];
302 } else {
303 i_palette = 0;
306 for( int i = 0; i < 4; i++ )
308 uint32_t i_yuv = 0xFF;//p_sys->clut[(hl.palette>>(16+i*4))&0x0f];
309 uint8_t i_alpha = (i_palette>>(i*4))&0x0f;
310 i_alpha = i_alpha == 0xf ? 0xff : i_alpha << 4;
312 spu_hl.palette.palette[i][0] = (i_yuv >> 16) & 0xff;
313 spu_hl.palette.palette[i][1] = (i_yuv >> 0) & 0xff;
314 spu_hl.palette.palette[i][2] = (i_yuv >> 8) & 0xff;
315 spu_hl.palette.palette[i][3] = i_alpha;
318 /* TODO: only control relevant SPU_ES given who fired the event */
319 for( es_list_t::iterator it = es_list.begin(); it != es_list.end(); ++it )
321 if( it->category != SPU_ES )
322 continue;
324 es_out_Control( p_demux->out, ES_OUT_SPU_SET_HIGHLIGHT, it->es, &spu_hl );
327 vlc_mutex_unlock( &p_sys->lock_demuxer );
328 vlc_mutex_lock( &lock );
331 else if( vlc_mouse_HasMoved( &event.mouse.state_old, &event.mouse.state_new ) )
333 // dvdnav_mouse_select( NULL, pci, x, y );
337 void event_thread_t::AddES( es_out_id_t* es, int category )
339 vlc_mutex_locker lock_guard( &lock );
341 es_list.push_front( ESInfo( es, category, *this ) );
342 es_list_t::iterator info = es_list.begin();
344 if( category == VIDEO_ES )
346 if( es_out_Control( p_demux->out, ES_OUT_VOUT_SET_MOUSE_EVENT,
347 es, EventMouse, static_cast<void*>( &*info ) ) )
349 msg_Warn( p_demux, "Unable to subscribe to mouse events" );
350 es_list.erase( info );
351 return;
356 void event_thread_t::DelES( es_out_id_t* es )
358 vlc_mutex_locker lock_guard( &lock );
359 es_list.erase( std::find( es_list.begin(), es_list.end(), es ) );
362 } // namespace