1 /*****************************************************************************
2 * events.cpp : matroska demuxer
3 *****************************************************************************
4 * Copyright (C) 2003-2004 VLC authors and VideoLAN
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 *****************************************************************************/
29 #include <vlc_actions.h>
30 #include <vlc_threads.h>
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
);
41 memset(&pci_packet
, 0, sizeof(pci_packet
));
43 event_thread_t::~event_thread_t()
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
);
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
] );
78 is_running
= !vlc_clone( &thread
, EventThread
, this, VLC_THREAD_PRIORITY_LOW
);
81 void event_thread_t::ResetPci()
86 vlc_mutex_lock( &lock
);
88 vlc_cond_signal( &wait
);
89 vlc_mutex_unlock( &lock
);
91 vlc_join( thread
, NULL
);
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
);
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");
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
);
140 while( !pending_events
.empty() )
142 EventInfo
const& ev
= pending_events
.front();
146 case EventInfo::ESMouseEvent
:
147 HandleMouseEvent( ev
);
150 case EventInfo::ActionEvent
:
151 HandleKeyEvent( ev
);
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();
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
)
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
)
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
);
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
) )
243 msg_Dbg( p_demux
, "Handle Mouse Event: Mouse clicked x(%d)*y(%d)", x
, y
);
245 // get current button
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;
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. */
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
);
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
;
300 if(button_ptr
.btn_coln
!= 0) {
301 i_palette
= pci
->hli
.btn_colit
.btn_coli
[button_ptr
.btn_coln
-1][1];
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
)
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
);
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
) );