/src/vlc/modules/demux/mkv/chapter_command_script.cpp
Line | Count | Source |
1 | | // Copyright (C) 2003-2024 VLC authors and VideoLAN |
2 | | // SPDX-License-Identifier: LGPL-2.1-or-later |
3 | | // |
4 | | // chapter_command_script.cpp : Matroska Script Codec for Matroska Chapter Codecs |
5 | | // Authors: Laurent Aimar <fenrir@via.ecp.fr> |
6 | | // Steve Lhomme <steve.lhomme@free.fr> |
7 | | |
8 | | |
9 | | #include "chapter_command_script.hpp" |
10 | | #include "virtual_segment.hpp" |
11 | | |
12 | | namespace mkv { |
13 | | |
14 | 159 | #define M_MS_MAX_DEPTH 8 |
15 | | //Matroska Script |
16 | | const std::string matroska_script_interpretor_c::CMD_MS_GOTO_AND_PLAY = "GotoAndPlay"; |
17 | | |
18 | | // see http://www.matroska.org/technical/specs/chapters/index.html#mscript |
19 | | // for a description of existing commands |
20 | | bool matroska_script_interpretor_c::Interpret( MatroskaChapterProcessTime time, const binary * p_command, size_t i_size ) |
21 | 159 | { |
22 | 159 | static thread_local int n_call = 0; |
23 | 159 | if( n_call > M_MS_MAX_DEPTH ) |
24 | 0 | return false; |
25 | 159 | n_call++; |
26 | | |
27 | 159 | bool b_result = false; |
28 | | |
29 | 159 | std::string sz_command( reinterpret_cast<const char*> (p_command), i_size ); |
30 | | |
31 | 159 | vlc_debug( l, "command : %s", sz_command.c_str() ); |
32 | | |
33 | 159 | if ( sz_command.compare( 0, CMD_MS_GOTO_AND_PLAY.size(), CMD_MS_GOTO_AND_PLAY ) == 0 ) |
34 | 16 | { |
35 | 16 | size_t i,j; |
36 | | |
37 | | // find the ( |
38 | 20 | for ( i=CMD_MS_GOTO_AND_PLAY.size(); i<sz_command.size(); i++) |
39 | 20 | { |
40 | 20 | if ( sz_command[i] == ' ' ) |
41 | 4 | continue; |
42 | 16 | if ( sz_command[i] == '(' ) |
43 | 14 | { |
44 | 14 | i++; |
45 | 14 | break; |
46 | 14 | } |
47 | 2 | return false; // extra characters between command and ( is not supported |
48 | 16 | } |
49 | | // find the ) |
50 | 178 | for ( j=i; j<sz_command.size(); j++) |
51 | 171 | { |
52 | 171 | if ( sz_command[j] == ')' ) |
53 | 7 | { |
54 | 7 | i--; |
55 | 7 | break; |
56 | 7 | } |
57 | 171 | } |
58 | | |
59 | 14 | if(i+1 < j-i-1) |
60 | 6 | { |
61 | 6 | std::string st = sz_command.substr( i+1, j-i-1 ); |
62 | 6 | chapter_uid i_chapter_uid = std::stoull( st ); |
63 | | |
64 | 6 | virtual_segment_c *p_vsegment; |
65 | 6 | virtual_chapter_c *p_vchapter = vm.FindVChapter( i_chapter_uid, p_vsegment ); |
66 | | |
67 | 6 | if ( p_vchapter == NULL ) |
68 | 6 | vlc_debug( l, "Chapter %" PRId64 " not found", i_chapter_uid); |
69 | 0 | else |
70 | 0 | { |
71 | 0 | auto current_chapter = vm.GetCurrentVSegment()->CurrentChapter(); |
72 | 0 | if ( p_vchapter == current_chapter) { |
73 | 0 | if ( time == MATROSKA_CHAPPROCESSTIME_BEFORE ) |
74 | | // the enter command is enter itself, avoid infinite loop |
75 | 0 | return false; |
76 | 0 | vm.JumpTo( *p_vsegment, *p_vchapter ); |
77 | 0 | } |
78 | 0 | else if ( !p_vchapter->EnterAndLeave( current_chapter, false ) ) |
79 | 0 | vm.JumpTo( *p_vsegment, *p_vchapter ); |
80 | 0 | b_result = true; |
81 | 0 | } |
82 | 6 | } |
83 | 14 | } |
84 | | |
85 | 157 | n_call--; |
86 | 157 | return b_result; |
87 | 159 | } |
88 | | |
89 | | } // namespace |