[Scummvm-git-logs] scummvm master -> 0e47c5ef24e0ee688d2ebb13910e6e282f32f7e7
sev-
noreply at scummvm.org
Wed Mar 29 21:49:57 UTC 2023
This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
0e47c5ef24 DIRECTOR: Update MCI parser
Commit: 0e47c5ef24e0ee688d2ebb13910e6e282f32f7e7
https://github.com/scummvm/scummvm/commit/0e47c5ef24e0ee688d2ebb13910e6e282f32f7e7
Author: Evangelos Lamprou (vagoslabrou at gmail.com)
Date: 2023-03-29T23:49:51+02:00
Commit Message:
DIRECTOR: Update MCI parser
- Updated the old MCI parser to work based on the specification described
in https://patentimages.storage.googleapis.com/ad/06/7a/48766ca9df6fbc/US6397263.pdf
- Replaced the old code to showcase how each MCI command can now be
handled through the parsed_cmd object.
Microsoft MCI documentation: https://learn.microsoft.com/en-us/windows/win32/multimedia/mci
Parser code used as reference: https://github.com/wine-mirror/wine/blob/master/dlls/winmm/mci.c
Changed paths:
A engines/director/lingo/lingo-mci.cpp
engines/director/lingo/lingo-funcs.cpp
engines/director/module.mk
diff --git a/engines/director/lingo/lingo-funcs.cpp b/engines/director/lingo/lingo-funcs.cpp
index cc6f2671ca6..e0add1a92f0 100644
--- a/engines/director/lingo/lingo-funcs.cpp
+++ b/engines/director/lingo/lingo-funcs.cpp
@@ -42,145 +42,6 @@
namespace Director {
-enum MCITokenType {
- kMCITokenNone,
-
- kMCITokenOpen,
- kMCITokenWait,
- kMCITokenPlay,
-
- kMCITokenType,
- kMCITokenAlias,
- kMCITokenBuffer,
- kMCITokenFrom,
- kMCITokenTo,
- kMCITokenRepeat
-};
-
-struct MCIToken {
- MCITokenType command; // Command this flag belongs to
- MCITokenType flag;
- const char *token;
- int pos; // Position of parameter to store. 0 is always filename. Negative parameters mean boolean
-} MCITokens[] = {
- { kMCITokenNone, kMCITokenOpen, "open", 0 },
- { kMCITokenOpen, kMCITokenType, "type", 1 },
- { kMCITokenOpen, kMCITokenAlias, "alias", 2 },
- { kMCITokenOpen, kMCITokenBuffer, "buffer", 3 },
-
- { kMCITokenNone, kMCITokenPlay, "play", 0 },
- { kMCITokenPlay, kMCITokenFrom, "from", 1 },
- { kMCITokenPlay, kMCITokenTo, "to", 2 },
- { kMCITokenPlay, kMCITokenRepeat, "repeat", -3 }, // This is boolean parameter
-
- { kMCITokenNone, kMCITokenWait, "wait", 0 },
-
- { kMCITokenNone, kMCITokenNone, nullptr, 0 }
-};
-
-void Lingo::func_mci(const Common::String &name) {
- Common::String params[5];
- MCITokenType command = kMCITokenNone;
-
- Common::String s = name;
- s.trim();
- s.toLowercase();
-
- MCITokenType state = kMCITokenNone;
- Common::String token;
- const char *ptr = s.c_str();
- int respos = -1;
-
- while (*ptr) {
- while (*ptr && *ptr == ' ')
- ptr++;
-
- token.clear();
-
- while (*ptr && *ptr != ' ')
- token += *ptr++;
-
- switch (state) {
- case kMCITokenNone:
- {
- MCIToken *f = MCITokens;
-
- while (f->token) {
- if (command == f->command && token == f->token)
- break;
-
- f++;
- }
-
- if (command == kMCITokenNone) { // We caught command
- command = f->flag; // Switching to processing this command parameters
- } else if (f->flag == kMCITokenNone) { // Unmatched token, storing as filename
- if (!params[0].empty())
- warning("Duplicate filename in MCI command: %s -> %s", params[0].c_str(), token.c_str());
- params[0] = token;
- } else { // This is normal parameter, storing next token to designated position
- if (f->pos > 0) { // This is normal parameter
- state = f->flag;
- respos = f->pos;
- } else { // This is boolean
- params[-f->pos] = "true";
- state = kMCITokenNone;
- }
- }
- break;
- }
- default:
- params[respos] = token;
- state = kMCITokenNone;
- break;
- }
- }
-
- switch (command) {
- case kMCITokenOpen:
- {
- warning("MCI open file: %s, type: %s, alias: %s buffer: %s", params[0].c_str(), params[1].c_str(), params[2].c_str(), params[3].c_str());
-
- Common::File *file = new Common::File();
-
- if (!file->open(params[0])) {
- warning("Failed to open %s", params[0].c_str());
- delete file;
- return;
- }
-
- if (params[1] == "waveaudio") {
- Audio::AudioStream *sound = Audio::makeWAVStream(file, DisposeAfterUse::YES);
- _audioAliases[params[2]] = sound;
- } else {
- warning("Unhandled audio type %s", params[2].c_str());
- }
- }
- break;
- case kMCITokenPlay:
- {
- warning("MCI play file: %s, from: %s, to: %s, repeat: %s", params[0].c_str(), params[1].c_str(), params[2].c_str(), params[3].c_str());
-
- if (!_audioAliases.contains(params[0])) {
- warning("Unknown alias %s", params[0].c_str());
- return;
- }
-
- uint32 from = strtol(params[1].c_str(), nullptr, 10);
- uint32 to = strtol(params[2].c_str(), nullptr, 10);
-
- _vm->getCurrentWindow()->getSoundManager()->playMCI(*_audioAliases[params[0]], from, to);
- }
- break;
- default:
- warning("Unhandled MCI command: %s", s.c_str());
- }
-}
-
-void Lingo::func_mciwait(const Common::String &name) {
- warning("STUB: MCI wait file: %s", name.c_str());
-}
-
void Lingo::func_goto(Datum &frame, Datum &movie, bool calledfromgo) {
_vm->_playbackPaused = false;
diff --git a/engines/director/lingo/lingo-mci.cpp b/engines/director/lingo/lingo-mci.cpp
new file mode 100644
index 00000000000..42b53814938
--- /dev/null
+++ b/engines/director/lingo/lingo-mci.cpp
@@ -0,0 +1,463 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+/*
+ * The MCI documentation is: https://learn.microsoft.com/en-us/windows/win32/multimedia/mci
+ * Based on sources from Wine: https://github.com/wine-mirror/wine/blob/master/dlls/winmm/mci.c
+ * Table structure and algorithms also described in: https://patentimages.storage.googleapis.com/ad/06/7a/48766ca9df6fbc/US6397263.pdf
+ */
+
+#include "audio/audiostream.h"
+#include "audio/decoders/wave.h"
+
+#include "director/score.h"
+#include "director/sound.h"
+#include "director/window.h"
+
+namespace Director {
+
+enum MCITokenType {
+ MCI_PLAY,
+ MCI_OPEN,
+ MCI_CLOSE,
+ MCI_STATUS,
+ MCI_RECORD,
+ MCI_SEEK,
+ MCI_STOP,
+ MCI_PAUSE,
+ MCI_GETDEVCAPS,
+ MCI_SYSINFO,
+ MCI_BREAK,
+ MCI_SOUND,
+ MCI_SAVE,
+ MCI_LOAD,
+ MCI_RESUME,
+ MCI_SET,
+ MCI_INFO,
+};
+
+
+enum MCIDataType {
+ MCI_COMMAND_HEAD,
+ MCI_END_COMMAND,
+ MCI_END_COMMAND_LIST,
+ MCI_CONSTANT,
+ MCI_END_CONSTANT,
+ MCI_RETURN,
+
+ MCI_FLAG,
+ MCI_INTEGER,
+ MCI_STRING,
+ MCI_RECT,
+ MCI_DWORD_PTR,
+};
+
+typedef struct MCITokenData {
+ MCIDataType type;
+ Common::String string;
+ int integer = 0;
+} MCITokenData;
+
+typedef struct MCICommand {
+ MCITokenType id;
+ uint flags = 0;
+ Common::String device; /* MCI device name */
+ Common::HashMap<Common::String, MCITokenData> parameters;
+} MCICommand;
+
+enum MCIError {
+ MCIERR_NO_ERROR,
+ MCIERR_UNRECOGNISED_COMMAND,
+ MCIERR_STRING_PARSE,
+};
+
+struct CmdTableRow {
+ const char *keystr;
+ int flag;
+ int num;
+ MCIDataType data_type;
+};
+
+static CmdTableRow table[] = {
+ {"open" ,MCI_OPEN ,0 ,MCI_COMMAND_HEAD },
+ {"" ,MCI_INTEGER ,0 ,MCI_RETURN } ,
+ {"notify" ,0x00000001L ,-1 ,MCI_FLAG } ,
+ {"wait" ,0x00000002L ,-1 ,MCI_FLAG } ,
+ {"type" ,0x00002000L ,-1 ,MCI_STRING } ,
+ {"element" ,0x00000200L ,-1 ,MCI_STRING } ,
+ {"alias" ,0x00000400L ,-1 ,MCI_STRING } ,
+ {"shareable" ,0x00000100L ,-1 ,MCI_FLAG } ,
+ {"" ,0x00000000L ,-1 ,MCI_END_COMMAND } ,
+
+ {"close" ,MCI_CLOSE ,0 ,MCI_COMMAND_HEAD },
+ {"notify" ,0x00000001L ,-1 ,MCI_FLAG } ,
+ {"wait" ,0x00000002L ,-1 ,MCI_FLAG } ,
+ {"" ,0x00000000L ,-1 ,MCI_END_COMMAND } ,
+
+ {"play" ,MCI_PLAY ,0 ,MCI_COMMAND_HEAD },
+ {"notify" ,0x00000001L ,-1 ,MCI_FLAG } ,
+ {"wait" ,0x00000002L ,-1 ,MCI_FLAG } ,
+ {"from" ,0x00000004L ,-1 ,MCI_INTEGER } ,
+ {"to" ,0x00000008L ,-1 ,MCI_INTEGER } ,
+ {"" ,0x00000000L ,-1 ,MCI_END_COMMAND } ,
+
+ {"status" ,MCI_STATUS ,0 ,MCI_COMMAND_HEAD },
+ {"" ,MCI_DWORD_PTR ,0 ,MCI_RETURN } ,
+ {"notify" ,0x00000001L ,-1 ,MCI_FLAG } ,
+ {"wait" ,0x00000002L ,-1 ,MCI_FLAG } ,
+ {"" ,0x00000100L ,-1 ,MCI_CONSTANT } ,
+ {"position" ,0x00000002L ,-1 ,MCI_INTEGER } ,
+ {"length" ,0x00000001L ,-1 ,MCI_INTEGER } ,
+ {"number of tracks",-1 ,0x00000003L,MCI_INTEGER } ,
+ {"ready" ,0x00000007L ,-1 ,MCI_INTEGER } ,
+ {"mode" ,0x00000004L ,-1 ,MCI_INTEGER } ,
+ {"time format" ,-1 ,0x00000006L,MCI_INTEGER } ,
+ {"current track" ,-1 ,0x00000008L,MCI_INTEGER } ,
+ {"" ,0x00000000L ,-1 ,MCI_END_CONSTANT },
+ { "track" ,0x00000010L ,-1 ,MCI_INTEGER } ,
+ { "start" ,0x00000200L ,-1 ,MCI_FLAG } ,
+ { "" ,0x00000000L ,-1 ,MCI_END_COMMAND } ,
+
+ { "record" ,MCI_RECORD ,0 ,MCI_COMMAND_HEAD },
+ { "notify" ,0x00000001L ,-1 ,MCI_FLAG } ,
+ { "wait" ,0x00000002L ,-1 ,MCI_FLAG } ,
+ { "from" ,0x00000004L ,-1 ,MCI_INTEGER } ,
+ { "to" ,0x00000008L ,-1 ,MCI_INTEGER } ,
+ { "insert" ,0x00000100L ,-1 ,MCI_FLAG } ,
+ { "overwrite" ,0x00000200L ,-1 ,MCI_FLAG } ,
+ { "" ,0x00000000L ,-1 ,MCI_END_COMMAND } ,
+
+ { "seek" ,MCI_SEEK ,0 ,MCI_COMMAND_HEAD },
+ { "notify" ,0x00000001L ,-1 ,MCI_FLAG } ,
+ { "wait" ,0x00000002L ,-1 ,MCI_FLAG } ,
+ { "to start" ,0x00000100L ,-1 ,MCI_FLAG } ,
+ { "to end" ,0x00000200L ,-1 ,MCI_FLAG } ,
+ { "to" ,0x00000008L ,-1 ,MCI_INTEGER } ,
+ { "" ,0x00000000L ,-1 ,MCI_END_COMMAND } ,
+
+ { "stop" ,MCI_STOP ,0 ,MCI_COMMAND_HEAD },
+ { "notify" ,0x00000001L ,-1 ,MCI_FLAG } ,
+ { "wait" ,0x00000002L ,-1 ,MCI_FLAG } ,
+ { "" ,0x00000000L ,-1 ,MCI_END_COMMAND } ,
+
+ { "pause" ,MCI_PAUSE ,0 ,MCI_COMMAND_HEAD },
+ { "notify" ,0x00000001L ,-1 ,MCI_FLAG } ,
+ { "wait" ,0x00000002L ,-1 ,MCI_FLAG } ,
+ { "" ,0x00000000L ,-1 ,MCI_END_COMMAND } ,
+
+ { "capability" ,MCI_GETDEVCAPS,0 ,MCI_COMMAND_HEAD },
+ { "" ,MCI_INTEGER ,0 ,MCI_RETURN } ,
+ { "notify" ,0x00000001L ,-1 ,MCI_FLAG } ,
+ { "wait" ,0x00000002L ,-1 ,MCI_FLAG } ,
+ { "" ,0x00000100L ,-1 ,MCI_CONSTANT } ,
+ { "can record" ,0x00000001L ,-1 ,MCI_INTEGER } ,
+ { "has audio" ,0x00000002L ,-1 ,MCI_INTEGER } ,
+ { "has video" ,0x00000003L ,-1 ,MCI_INTEGER } ,
+ { "uses files" ,0x00000005L ,-1 ,MCI_INTEGER } ,
+ { "compound device",0x00000006L ,-1 ,MCI_INTEGER } ,
+ { "device type" ,0x00000004L ,-1 ,MCI_INTEGER } ,
+ { "can eject" ,0x00000007L ,-1 ,MCI_INTEGER } ,
+ { "can play" ,0x00000008L ,-1 ,MCI_INTEGER } ,
+ { "can save" ,0x00000009L ,-1 ,MCI_INTEGER } ,
+ { "" ,0x00000000L ,-1 ,MCI_END_CONSTANT },
+ { "" ,0x00000000L ,-1 ,MCI_END_COMMAND } ,
+
+ { "info" ,MCI_INFO ,0 ,MCI_COMMAND_HEAD },
+ { "" ,MCI_STRING ,0 ,MCI_RETURN } ,
+ { "notify" ,0x00000001L ,-1 ,MCI_FLAG } ,
+ { "wait" ,0x00000002L ,-1 ,MCI_FLAG } ,
+ { "product" ,0x00000100L ,-1 ,MCI_FLAG } ,
+ { "" ,0x00000000L ,-1 ,MCI_END_COMMAND } ,
+
+ { "set" ,MCI_SET ,0 ,MCI_COMMAND_HEAD },
+ { "notify" ,0x00000001L ,-1 ,MCI_FLAG } ,
+ { "wait" ,0x00000002L ,-1 ,MCI_FLAG } ,
+ { "time format" ,0x00000400L ,-1 ,MCI_CONSTANT } ,
+ { "milliseconds" ,0x00000000L ,-1 ,MCI_INTEGER } ,
+ { "ms" ,0x00000000L ,-1 ,MCI_INTEGER } ,
+ { "" ,0x00000000L ,-1 ,MCI_END_CONSTANT },
+ { "door open" ,0x00000100L ,-1 ,MCI_FLAG } ,
+ { "door closed" ,0x00000200L ,-1 ,MCI_FLAG } ,
+ { "audio" ,0x00000800L ,-1 ,MCI_CONSTANT } ,
+ { "all" ,0x00000000L ,-1 ,MCI_INTEGER } ,
+ { "left" ,0x00000001L ,-1 ,MCI_INTEGER } ,
+ { "right" ,0x00000002L ,-1 ,MCI_INTEGER } ,
+ { "" ,0x00000000L ,-1 ,MCI_END_CONSTANT },
+ { "video" ,0x00001000L ,-1 ,MCI_FLAG } ,
+ { "on" ,0x00002000L ,-1 ,MCI_FLAG } ,
+ { "off" ,0x00004000L ,-1 ,MCI_FLAG } ,
+ { "" ,0x00000000L ,-1 ,MCI_END_COMMAND } ,
+
+ { "sysinfo" ,MCI_SYSINFO ,0 ,MCI_COMMAND_HEAD },
+ { "" ,MCI_STRING ,0 ,MCI_RETURN } ,
+ { "notify" ,0x00000001L ,-1 ,MCI_FLAG } ,
+ { "wait" ,0x00000002L ,-1 ,MCI_FLAG } ,
+ { "quantity" ,0x00000100L ,-1 ,MCI_FLAG } ,
+ { "open" ,0x00000200L ,-1 ,MCI_FLAG } ,
+ { "installname" ,0x00000800L ,-1 ,MCI_FLAG } ,
+ { "name" ,0x00000400L ,-1 ,MCI_INTEGER } ,
+ { "" ,0x00000000L ,-1 ,MCI_END_COMMAND } ,
+
+ { "break" ,MCI_BREAK ,0 ,MCI_COMMAND_HEAD },
+ { "notify" ,0x00000001L ,-1 ,MCI_FLAG } ,
+ { "wait" ,0x00000002L ,-1 ,MCI_FLAG } ,
+ { "on" ,0x00000100L ,-1 ,MCI_INTEGER } ,
+ { "off" ,0x00000400L ,-1 ,MCI_FLAG } ,
+ { "" ,0x00000000L ,-1 ,MCI_END_COMMAND } ,
+
+ { "sound" ,MCI_SOUND ,0 ,MCI_COMMAND_HEAD },
+ { "notify" ,0x00000001L ,-1 ,MCI_FLAG } ,
+ { "wait" ,0x00000002L ,-1 ,MCI_FLAG } ,
+ { "" ,0x00000000L ,-1 ,MCI_END_COMMAND } ,
+
+ { "save" ,MCI_SAVE ,0 ,MCI_COMMAND_HEAD },
+ { "notify" ,0x00000001L ,-1 ,MCI_FLAG } ,
+ { "wait" ,0x00000002L ,-1 ,MCI_FLAG } ,
+ { "" ,0x00000100L ,-1 ,MCI_STRING } ,
+ { "" ,0x00000000L ,-1 ,MCI_END_COMMAND } ,
+
+ { "load" ,MCI_LOAD ,0 ,MCI_COMMAND_HEAD },
+ { "notify" ,0x00000001L ,-1 ,MCI_FLAG } ,
+ { "wait" ,0x00000002L ,-1 ,MCI_FLAG } ,
+ { "" ,0x00000100L ,-1 ,MCI_STRING } ,
+ { "" ,0x00000000L ,-1 ,MCI_END_COMMAND } ,
+
+ { "resume" ,MCI_RESUME ,0 ,MCI_COMMAND_HEAD },
+ { "notify" ,0x00000001L ,-1 ,MCI_FLAG } ,
+ { "wait" ,0x00000002L ,-1 ,MCI_FLAG } ,
+ { "" ,0x00000000L ,-1 ,MCI_END_COMMAND } ,
+ };
+
+static MCIError getString(const Common::String &name, uint &idx, Common::String &str) {
+ uint i_end;
+ if (name[idx] == '"' || name[idx] == '\'') { /* Quoted string */
+ char quote = name[idx];
+ i_end = name.findFirstOf(quote, idx + 1);
+ if (i_end == Common::String::npos) {
+ return MCIERR_STRING_PARSE; /* Unterminated string */
+ }
+ str = name.substr(idx + 1, i_end - idx - 1);
+ idx = i_end + 2;
+ } else { /* No quotes, so just find the next space */
+ i_end = name.findFirstOf(' ', idx);
+ if (i_end == Common::String::npos) {
+ i_end = name.size();
+ }
+
+ str = name.substr(idx, i_end - idx);
+ idx = i_end + 1;
+ }
+ debugC(5, kDebugLingoExec, "get_string(): Got string \"%s\"", str.c_str());
+ return MCIERR_NO_ERROR;
+}
+
+static void createTokenList(Common::StringArray &tokenList, const Common::String &name) {
+ uint idx = 0;
+
+ while (idx < name.size()) {
+ Common::String str;
+ MCIError err = getString(name, idx, str);
+ if (err != MCIERR_NO_ERROR) {
+ break;
+ }
+ tokenList.push_back(str);
+ }
+}
+
+static MCIError parseMCICommand(const Common::String &name, MCICommand &parsedCmd) {
+ Common::StringArray token_list;
+ createTokenList(token_list, name);
+
+ uint i_token = 0;
+ int i_table = 0;
+ int tableStart = -1, tableEnd = -1;
+
+ Common::String &verb = token_list[0];
+
+ /* Find the table section corresponding to the command's verb. */
+ for (auto& cmd : table) {
+ if ((tableStart < 0) && (cmd.data_type == MCI_COMMAND_HEAD) && (cmd.keystr == verb)) {
+ tableStart = i_table;
+ } else if ((tableStart >= 0) && (cmd.data_type == MCI_END_COMMAND)) {
+ tableEnd = i_table;
+ break;
+ }
+ i_table++;
+ }
+
+ debugC(5, kDebugLingoExec, "parseMCICommand(): tableStart: %d, tableEnd: %d", tableStart, tableEnd);
+ assert(tableStart >= 0 && tableEnd > 0);
+
+ auto cmd = table[tableStart];
+ parsedCmd.id = (MCITokenType)cmd.flag;
+ parsedCmd.flags = cmd.num;
+
+ /* The MCI device will ALWAYS be the second token. */
+ parsedCmd.device = token_list[1];
+
+ /* Parse the rest of the arguments */
+ i_token = 2;
+
+ while (i_token < token_list.size()) {
+
+ bool found = false;
+ bool inConst = false;
+ int flag, cflag;
+ CmdTableRow *cmdtable, *c_cmdtable;
+ auto& token = token_list[i_token];
+
+ for (i_table = tableStart; i_table < tableEnd; i_table++) {
+
+ MCIDataType cmd_type = table[i_table].data_type;
+ flag = table[i_table].flag;
+ cmdtable = &table[i_table];
+
+ switch (cmd_type) {
+ case MCI_CONSTANT:
+ c_cmdtable = cmdtable;
+ inConst = true;
+ cflag = flag;
+ break;
+ case MCI_END_CONSTANT:
+ c_cmdtable = nullptr;
+ inConst = false;
+ cflag = 0;
+ break;
+ default: break;
+ }
+
+ if (token != table[i_table].keystr)
+ continue;
+
+ found = true;
+
+ switch (cmd_type) {
+ case MCI_COMMAND_HEAD:
+ case MCI_RETURN:
+ case MCI_END_COMMAND:
+ case MCI_END_COMMAND_LIST:
+ case MCI_CONSTANT:
+ case MCI_END_CONSTANT:
+ break;
+ case MCI_FLAG:
+ parsedCmd.flags |= flag;
+ i_token++;
+ break;
+ case MCI_INTEGER: {
+ if (inConst) { /* Handle the case where we've hit a MCI_INTEGER which is inside a MCI_CONSTANT block. */
+ MCITokenData token_data;
+ if (parsedCmd.parameters.tryGetVal(c_cmdtable->keystr, token_data)) {
+ token_data.integer |= flag;
+ } else {
+ token_data.type = MCI_CONSTANT;
+ token_data.integer |= flag;
+ parsedCmd.parameters[c_cmdtable->keystr] = token_data;
+ }
+ parsedCmd.flags |= cflag;
+ inConst = false;
+ } else {
+ parsedCmd.flags |= flag;
+
+ MCITokenData token_data;
+ token_data.type = MCI_INTEGER;
+ token_data.integer = atoi(token_list[++i_token].c_str());
+ parsedCmd.parameters[token] = token_data;
+ }
+ i_token++;
+ break;
+ }
+ case MCI_STRING: {
+ parsedCmd.flags |= flag;
+
+ MCITokenData token_data;
+ token_data.type = MCI_STRING;
+ token_data.string = token_list[++i_token];
+ parsedCmd.parameters[token] = token_data;
+ i_token++;
+ break;
+ }
+ default:
+ warning("parseMCICommand(): Unhandled command type.");
+ return MCIERR_UNRECOGNISED_COMMAND;
+ }
+ }
+
+ if (!found) {
+ warning("parseMCICommand(): Parameter %s not found in table", token_list[i_token].c_str());
+ return MCIERR_UNRECOGNISED_COMMAND;
+ }
+ }
+
+ return MCIERR_NO_ERROR;
+}
+
+void Lingo::func_mci(const Common::String &name) {
+
+ MCICommand parsedCmd;
+ parseMCICommand(name, parsedCmd);
+
+ switch (parsedCmd.id) {
+ case MCI_OPEN: {
+ Common::File *file = new Common::File();
+
+ if (!file->open(parsedCmd.device)) {
+ warning("func_mci(): Failed to open %s", parsedCmd.device.c_str());
+ delete file;
+ return;
+ }
+
+ parsedCmd.parameters["type"].string.toLowercase(); /* In the case the open command type has something like WaveAudio instead of waveaudio */
+
+ if (parsedCmd.parameters["type"].string == "waveaudio") {
+ Audio::AudioStream *sound = Audio::makeWAVStream(file, DisposeAfterUse::YES);
+ if (parsedCmd.parameters.contains("alias")) {
+ _audioAliases[parsedCmd.parameters["alias"].string] = sound;
+ }
+ } else {
+ warning("func_mci(): Unhandled audio type %s", parsedCmd.parameters["type"].string.c_str());
+ }
+ }
+ break;
+ case MCI_PLAY: {
+ warning("func_mci(): MCI play file: %s, from: %d, to: %d", parsedCmd.device.c_str(), parsedCmd.parameters["from"].integer, parsedCmd.parameters["to"].integer);
+
+ if (!_audioAliases.contains(parsedCmd.device)) {
+ warning("func_mci(): Unknown alias %s", parsedCmd.device.c_str());
+ return;
+ }
+
+ uint32 from = parsedCmd.parameters["from"].integer;
+ uint32 to = parsedCmd.parameters.contains("to") ? parsedCmd.parameters["to"].integer : -1;
+
+ _vm->getCurrentWindow()->getSoundManager()->playMCI(*_audioAliases[parsedCmd.device], from, to);
+ }
+ break;
+ default:
+ warning("func_mci: Unhandled MCI command: %d", parsedCmd.id); /* TODO: Convert MCITokenType into string */
+ }
+}
+
+void Lingo::func_mciwait(const Common::String &name) {
+ warning("STUB: MCI wait file: %s", name.c_str());
+}
+
+} // End of namespace Director
diff --git a/engines/director/module.mk b/engines/director/module.mk
index 2d0ba9ccb47..fb0d095fb49 100644
--- a/engines/director/module.mk
+++ b/engines/director/module.mk
@@ -34,6 +34,7 @@ MODULE_OBJS = \
lingo/lingo-codegen.o \
lingo/lingo-events.o \
lingo/lingo-funcs.o \
+ lingo/lingo-mci.o \
lingo/lingo-gr.o \
lingo/lingo-lex.o \
lingo/lingo-object.o \
More information about the Scummvm-git-logs
mailing list