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.
 
 
 
 
 
 

89 lines
2.7 KiB

// Copyright (C) 2003-2024 VLC authors and VideoLAN
// SPDX-License-Identifier: LGPL-2.1-or-later
//
// chapter_command_script.cpp : Matroska Script Codec for Matroska Chapter Codecs
// Authors: Laurent Aimar <fenrir@via.ecp.fr>
// Steve Lhomme <steve.lhomme@free.fr>
#include "chapter_command_script.hpp"
#include "virtual_segment.hpp"
namespace mkv {
#define M_MS_MAX_DEPTH 8
//Matroska Script
const std::string matroska_script_interpretor_c::CMD_MS_GOTO_AND_PLAY = "GotoAndPlay";
// see http://www.matroska.org/technical/specs/chapters/index.html#mscript
// for a description of existing commands
bool matroska_script_interpretor_c::Interpret( MatroskaChapterProcessTime time, const binary * p_command, size_t i_size )
{
static thread_local int n_call = 0;
if( n_call > M_MS_MAX_DEPTH )
return false;
n_call++;
bool b_result = false;
std::string sz_command( reinterpret_cast<const char*> (p_command), i_size );
vlc_debug( l, "command : %s", sz_command.c_str() );
if ( sz_command.compare( 0, CMD_MS_GOTO_AND_PLAY.size(), CMD_MS_GOTO_AND_PLAY ) == 0 )
{
size_t i,j;
// find the (
for ( i=CMD_MS_GOTO_AND_PLAY.size(); i<sz_command.size(); i++)
{
if ( sz_command[i] == ' ' )
continue;
if ( sz_command[i] == '(' )
{
i++;
break;
}
return false; // extra characters between command and ( is not supported
}
// find the )
for ( j=i; j<sz_command.size(); j++)
{
if ( sz_command[j] == ')' )
{
i--;
break;
}
}
if(i+1 < j-i-1)
{
std::string st = sz_command.substr( i+1, j-i-1 );
chapter_uid i_chapter_uid = std::stoull( st );
virtual_segment_c *p_vsegment;
virtual_chapter_c *p_vchapter = vm.FindVChapter( i_chapter_uid, p_vsegment );
if ( p_vchapter == NULL )
vlc_debug( l, "Chapter %" PRId64 " not found", i_chapter_uid);
else
{
auto current_chapter = vm.GetCurrentVSegment()->CurrentChapter();
if ( p_vchapter == current_chapter) {
if ( time == MATROSKA_CHAPPROCESSTIME_BEFORE )
// the enter command is enter itself, avoid infinite loop
return false;
vm.JumpTo( *p_vsegment, *p_vchapter );
}
else if ( !p_vchapter->EnterAndLeave( current_chapter, false ) )
vm.JumpTo( *p_vsegment, *p_vchapter );
b_result = true;
}
}
}
n_call--;
return b_result;
}
} // namespace