Coverage Report

Created: 2025-08-29 06:30

/src/vlc/modules/demux/mkv/events.cpp
Line
Count
Source (jump to first uncovered line)
1
/*****************************************************************************
2
 * events.cpp : matroska demuxer
3
 *****************************************************************************
4
 * Copyright (C) 2003-2004 VLC authors and VideoLAN
5
 *
6
 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
7
 *          Steve Lhomme <steve.lhomme@free.fr>
8
 *
9
 * This program is free software; you can redistribute it and/or modify it
10
 * under the terms of the GNU Lesser General Public License as published by
11
 * the Free Software Foundation; either version 2.1 of the License, or
12
 * (at your option) any later version.
13
 *
14
 * This program is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
 * GNU Lesser General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU Lesser General Public License
20
 * along with this program; if not, write to the Free Software Foundation,
21
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22
 *****************************************************************************/
23
24
#include "mkv.hpp"
25
#include "demux.hpp"
26
#include "events.hpp"
27
#include "chapter_command_dvd.hpp"
28
29
#include <vlc_threads.h>
30
31
#include <algorithm>
32
33
namespace mkv {
34
35
0
event_thread_t::event_thread_t(demux_t *p_demux) : p_demux(p_demux)
36
0
{
37
0
    vlc_mutex_init( &lock );
38
0
    vlc_cond_init( &wait );
39
0
    is_running = false;
40
0
}
41
event_thread_t::~event_thread_t()
42
0
{
43
0
    AbortThread();
44
0
}
45
46
void event_thread_t::SendData( mkv_track_t &track, block_t * p_block )
47
0
{
48
0
    if ( track.codec == "B_VOBBTN")
49
0
    {
50
0
        if( p_block->i_size > 0)
51
0
        {
52
0
            QueueEvent( EventInfo{ p_block } );
53
0
            return; // the block will be released later
54
0
        }
55
0
    }
56
57
0
    block_Release( p_block );
58
0
}
59
60
void event_thread_t::EnsureThreadLocked()
61
0
{
62
0
    if (is_running || b_abort)
63
0
        return;
64
65
0
    is_running = !vlc_clone( &thread, EventThread, this );
66
0
}
67
68
void event_thread_t::AbortThread()
69
0
{
70
0
    if( !is_running )
71
0
        return;
72
73
0
    {
74
0
        vlc_mutex_locker lock_guard(&lock);
75
0
        b_abort = true;
76
0
        vlc_cond_signal( &wait );
77
0
    }
78
79
0
    vlc_join( thread, NULL );
80
0
    is_running = false;
81
0
}
82
83
int event_thread_t::SendEventNav( demux_query_e nav_query )
84
0
{
85
0
    NavivationKey key;
86
0
    switch( nav_query )
87
0
    {
88
0
    case DEMUX_NAV_LEFT:     key = NavivationKey::LEFT;  break;
89
0
    case DEMUX_NAV_RIGHT:    key = NavivationKey::RIGHT; break;
90
0
    case DEMUX_NAV_UP:       key = NavivationKey::UP;    break;
91
0
    case DEMUX_NAV_DOWN:     key = NavivationKey::DOWN;  break;
92
0
    case DEMUX_NAV_ACTIVATE: key = NavivationKey::OK;    break;
93
0
    case DEMUX_NAV_MENU:     key = NavivationKey::MENU;  break;
94
0
    case DEMUX_NAV_POPUP:    key = NavivationKey::POPUP; break;
95
0
    default:
96
0
        assert(false); // invalid navigation query received
97
0
        return VLC_ENOTSUP;
98
0
    }
99
100
0
    if( !is_running )
101
0
        return VLC_EGENERIC;
102
103
0
    if ( !HandleKeyEvent( key ) )
104
0
        return VLC_EGENERIC;
105
106
0
    return VLC_SUCCESS;
107
0
}
108
109
void event_thread_t::EventMouse( vlc_mouse_t const* new_state, void* userdata )
110
0
{
111
0
    ESInfo* info = static_cast<ESInfo*>( userdata );
112
113
0
    if( !new_state )
114
0
        return vlc_mouse_Init( &info->mouse_state );
115
116
0
    info->owner.QueueEvent( EventInfo{ info->mouse_state, *new_state } );
117
0
    info->mouse_state = *new_state;
118
0
}
119
120
void event_thread_t::EventThread()
121
0
{
122
0
    vlc_thread_set_name("vlc-mkv-events");
123
124
0
    int canc = vlc_savecancel ();
125
126
0
    for( vlc_mutex_locker guard( &lock );; )
127
0
    {
128
0
        while( !b_abort && pending_events.empty() )
129
0
            vlc_cond_wait( &wait, &lock );
130
131
0
        if( b_abort )
132
0
            break;
133
134
0
        while( !pending_events.empty() )
135
0
        {
136
0
            const EventInfo ev = pending_events.front();
137
0
            pending_events.pop_front();
138
139
0
            if(es_list.empty())
140
0
                break;
141
142
0
            vlc_mutex_unlock( &lock );
143
0
            switch( ev.type )
144
0
            {
145
0
                case EventInfo::ESMouseEvent:
146
0
                    HandleMouseEvent( ev );
147
0
                    break;
148
149
0
                case EventInfo::ButtonDataEvent:
150
0
                    HandleButtonData( ev );
151
0
                    break;
152
0
            }
153
0
            vlc_mutex_lock( &lock );
154
0
        }
155
0
    }
156
157
0
    vlc_restorecancel (canc);
158
0
}
159
160
void *event_thread_t::EventThread(void *data)
161
0
{
162
0
    static_cast<event_thread_t*>(data)->EventThread();
163
0
    return NULL;
164
0
}
165
166
bool event_thread_t::HandleKeyEvent( NavivationKey key )
167
0
{
168
0
    demux_sys_t* p_sys = (demux_sys_t*)p_demux->p_sys;
169
170
0
    vlc_mutex_locker demux_lock ( &p_sys->lock_demuxer );
171
172
0
    auto interpretor = p_sys->GetDVDInterpretor();
173
0
    if (!interpretor)
174
0
        return false;
175
176
    // process the button action
177
0
    return interpretor->HandleKeyEvent( key );
178
0
}
179
180
void event_thread_t::HandleMouseEvent( EventInfo const& event )
181
0
{
182
0
    int x = event.mouse.state_new.i_x;
183
0
    int y = event.mouse.state_new.i_y;
184
185
0
    if( vlc_mouse_HasPressed( &event.mouse.state_old, &event.mouse.state_new,
186
0
                              MOUSE_BUTTON_LEFT ) )
187
0
    {
188
0
        HandleMousePressed( (unsigned)x, (unsigned)y );
189
0
    }
190
0
    else if( vlc_mouse_HasMoved( &event.mouse.state_old, &event.mouse.state_new ) )
191
0
    {
192
//                dvdnav_mouse_select( NULL, pci, x, y );
193
0
    }
194
0
}
195
196
void event_thread_t::HandleButtonData( EventInfo const& event )
197
0
{
198
0
    HandleButtonData( event.button_data.get() );
199
0
}
200
201
void event_thread_t::HandleButtonData( block_t *p_block )
202
0
{
203
0
    demux_sys_t* p_sys = (demux_sys_t*)p_demux->p_sys;
204
205
0
    vlc_mutex_locker demux_lock ( &p_sys->lock_demuxer );
206
207
0
    auto interpretor = p_sys->GetDVDInterpretor();
208
0
    if (!interpretor)
209
0
        return;
210
211
0
    interpretor->SetPci( &p_block->p_buffer[1], p_block->i_size - 1 );
212
0
}
213
214
void event_thread_t::HandleMousePressed( unsigned x, unsigned y )
215
0
{
216
0
    demux_sys_t* p_sys = (demux_sys_t*)p_demux->p_sys;
217
218
0
    msg_Dbg( p_demux, "Handle Mouse Event: Mouse clicked x(%d)*y(%d)", x, y);
219
220
0
    vlc_mutex_locker demux_lock ( &p_sys->lock_demuxer );
221
222
0
    auto interpretor = p_sys->GetDVDInterpretor();
223
0
    if (!interpretor)
224
0
        return;
225
226
0
    interpretor->HandleMousePressed( x, y );
227
0
}
228
229
void event_thread_t::SetHighlight( vlc_spu_highlight_t & spu_hl )
230
0
{
231
    /* TODO: only control relevant SPU_ES given who fired the event */
232
0
    for( auto it : es_list )
233
0
    {
234
0
        if( it.track.fmt.i_cat != SPU_ES )
235
0
            continue;
236
237
0
        es_out_Control( p_demux->out, ES_OUT_SPU_SET_HIGHLIGHT, it.track.p_es, &spu_hl );
238
0
    }
239
0
}
240
241
bool event_thread_t::AddTrack( mkv_track_t & track )
242
0
{
243
0
    es_out_id_t* es = track.p_es;
244
0
    int category = track.fmt.i_cat;
245
246
0
    vlc_mutex_locker lock_guard( &lock );
247
248
0
    es_list.push_front( ESInfo( track, *this ) );
249
0
    es_list_t::iterator info = es_list.begin();
250
251
0
    if( category == VIDEO_ES )
252
0
    {
253
0
        if( es_out_Control( p_demux->out, ES_OUT_VOUT_SET_MOUSE_EVENT,
254
0
                            es, static_cast<vlc_mouse_event>(EventMouse),
255
0
                            static_cast<void*>( &*info ) ) )
256
0
        {
257
0
            msg_Warn( p_demux, "Unable to subscribe to mouse events" );
258
0
            es_list.erase( info );
259
0
            return false;
260
0
        }
261
0
    }
262
0
    return true;
263
0
}
264
265
void event_thread_t::DelTrack( mkv_track_t &track )
266
0
{
267
0
    vlc_mutex_locker lock_guard( &lock );
268
0
    es_list_t::iterator info = std::find( es_list.begin(), es_list.end(), track );
269
0
    if( info != es_list.end() )
270
0
        es_list.erase( info );
271
0
}
272
273
} // namespace
274