17 scheduler_,
"cassetteplayer")
18 , cassettePlayer(cassettePlayer_)
23 std::span<const TclObject> tokens,
TclObject& result, EmuTime::param time)
25 if (!cassettePlayer) {
29 auto stopRecording = [&] {
32 cassettePlayer->playTape(cassettePlayer->
getImageName(), time);
41 if (tokens.size() == 1) {
49 }
else if (tokens[1] ==
"new") {
50 std::string_view prefix =
"openmsx";
52 (tokens.size() == 3) ? tokens[2].getString() :
string{},
54 cassettePlayer->recordTape(
Filename(filename), time);
56 "Created new cassette image file: ", filename,
57 ", inserted it and set recording mode.");
59 }
else if (tokens[1] ==
"insert" && tokens.size() == 3) {
61 result =
"Changing tape";
63 cassettePlayer->playTape(filename, time);
68 }
else if (tokens[1] ==
"motorcontrol" && tokens.size() == 3) {
69 if (tokens[2] ==
"on") {
70 cassettePlayer->setMotorControl(
true, time);
71 result =
"Motor control enabled.";
72 }
else if (tokens[2] ==
"off") {
73 cassettePlayer->setMotorControl(
false, time);
74 result =
"Motor control disabled.";
79 }
else if (tokens[1] ==
"setpos" && tokens.size() == 3) {
81 cassettePlayer->setTapePos(time, tokens[2].getDouble(
getInterpreter()));
83 }
else if (tokens.size() != 2) {
86 }
else if (tokens[1] ==
"motorcontrol") {
88 (cassettePlayer->motorControl ?
"on" :
"off"));
90 }
else if (tokens[1] ==
"record") {
91 result =
"TODO: implement this... (sorry)";
93 }
else if (tokens[1] ==
"play") {
94 if (stopRecording()) {
95 result =
"Play mode set, rewinding tape.";
100 result =
"Already in play mode.";
103 }
else if (tokens[1] ==
"eject") {
104 result =
"Tape ejected";
105 cassettePlayer->removeTape(time);
107 }
else if (tokens[1] ==
"rewind") {
108 string r = stopRecording() ?
"First stopping recording... " :
"";
109 cassettePlayer->rewind(time);
113 }
else if (tokens[1] ==
"getpos") {
116 }
else if (tokens[1] ==
"getlength") {
121 result =
"Changing tape";
123 cassettePlayer->playTape(filename, time);
136 if (tokens.size() >= 2) {
137 if (tokens[1] ==
"eject") {
139 "Well, just eject the cassette from the cassette "
141 }
else if (tokens[1] ==
"rewind") {
143 "Indeed, rewind the tape that is currently in the "
144 "cassette player/recorder...";
145 }
else if (tokens[1] ==
"motorcontrol") {
147 "Setting this to 'off' is equivalent to "
148 "disconnecting the black remote plug from the "
149 "cassette player: it makes the cassette player "
150 "run (if in play mode); the motor signal from the "
151 "MSX will be ignored. Normally this is set to "
152 "'on': the cassetteplayer obeys the motor control "
153 "signal from the MSX.";
154 }
else if (tokens[1] ==
"play") {
156 "Go to play mode. Only useful if you were in "
157 "record mode (which is currently the only other "
159 }
else if (tokens[1] ==
"new") {
161 "Create a new cassette image. If the file name is "
162 "omitted, one will be generated in the default "
163 "directory for tape recordings. Implies going to "
164 "record mode (why else do you want a new cassette "
166 }
else if (tokens[1] ==
"insert") {
168 "Inserts the specified cassette image into the "
169 "cassette player, rewinds it and switches to play "
171 }
else if (tokens[1] ==
"record") {
173 "Go to record mode. NOT IMPLEMENTED YET. Will be "
174 "used to be able to resume recording to an "
175 "existing cassette image, previously inserted with "
176 "the insert command.";
177 }
else if (tokens[1] ==
"getpos") {
179 "Return the position of the tape, in seconds from "
180 "the beginning of the tape.";
181 }
else if (tokens[1] ==
"setpos") {
183 "Wind the tape to the given position, in seconds from "
184 "the beginning of the tape.";
185 }
else if (tokens[1] ==
"getlength") {
187 "Return the length of the tape in seconds.";
191 "cassetteplayer eject "
192 ": remove tape from virtual player\n"
193 "cassetteplayer rewind "
194 ": rewind tape in virtual player\n"
195 "cassetteplayer motorcontrol "
196 ": enables or disables motor control (remote)\n"
197 "cassetteplayer play "
198 ": change to play mode (default)\n"
199 "cassetteplayer record "
200 ": change to record mode (NOT IMPLEMENTED YET)\n"
201 "cassetteplayer new [<filename>] "
202 ": create and insert new tape image file and go to record mode\n"
203 "cassetteplayer insert <filename> "
204 ": insert (a different) tape file\n"
205 "cassetteplayer getpos "
206 ": query the position of the tape\n"
207 "cassetteplayer setpos <new-pos> "
208 ": wind the tape to the given position\n"
209 "cassetteplayer getlength "
210 ": query the total length of the tape\n"
211 "cassetteplayer <filename> "
212 ": insert (a different) tape file\n";
219 using namespace std::literals;
220 if (tokens.size() == 2) {
221 static constexpr std::array cmds = {
222 "eject"sv,
"rewind"sv,
"motorcontrol"sv,
"insert"sv,
"new"sv,
223 "play"sv,
"getpos"sv,
"setpos"sv,
"getlength"sv,
227 }
else if ((tokens.size() == 3) && (tokens[1] ==
"insert")) {
229 }
else if ((tokens.size() == 3) && (tokens[1] ==
"motorcontrol")) {
230 static constexpr std::array extra = {
"on"sv,
"off"sv};
237 return tokens.size() > 1;
bool needRecord(std::span< const TclObject > tokens) const override
It's possible that in some cases the command doesn't need to be recorded after all (e....
void tabCompletion(std::vector< std::string > &tokens) const override
Attempt tab completion for this command.
CassettePlayerCommand(CassettePlayer *cassettePlayer_, CommandController &commandController, StateChangeDistributor &stateChangeDistributor, Scheduler &scheduler)
void execute(std::span< const TclObject > tokens, TclObject &result, EmuTime::param time) override
This is like the execute() method of the Command class, it only has an extra time parameter.
std::string help(std::span< const TclObject > tokens) const override
Print help for this command.
static constexpr std::string_view TAPE_RECORDING_DIR
const Filename & getImageName() const
double getTapePos(EmuTime::param time)
Returns the position of the tape, in seconds from the beginning of the tape.
static constexpr std::string_view TAPE_RECORDING_EXTENSION
double getTapeLength(EmuTime::param time)
Returns the length of the tape in seconds.
Interpreter & getInterpreter() const final
static void completeFileName(std::vector< std::string > &tokens, const FileContext &context, const RANGE &extra)
static void completeString(std::vector< std::string > &tokens, ITER begin, ITER end, bool caseSensitive=true)
const std::string & getName() const
This class represents a filename.
const std::string & getResolved() const &
Commands that directly influence the MSX state should send and events so that they can be recorded by...
void addListElement(const T &t)
string parseCommandFileArgument(string_view argument, string_view directory, string_view prefix, string_view extension)
Helper function for parsing filename arguments in Tcl commands.
This file implemented 3 utility functions:
const FileContext & userFileContext()
TclObject makeTclList(Args &&... args)
TemporaryString tmpStrCat(Ts &&... ts)