openMSX
CassettePlayer.hh
Go to the documentation of this file.
1#ifndef CASSETTEPLAYER_HH
2#define CASSETTEPLAYER_HH
3
4#include "EventListener.hh"
5#include "CassetteDevice.hh"
7#include "MSXMotherBoard.hh"
8#include "RecordedCommand.hh"
9#include "Schedulable.hh"
10#include "ThrottleManager.hh"
11#include "Filename.hh"
12#include "EmuTime.hh"
13#include "BooleanSetting.hh"
14#include "outer.hh"
15#include "serialize_meta.hh"
16#include <array>
17#include <cstdint>
18#include <memory>
19#include <string>
20
21namespace openmsx {
22
23class CassetteImage;
24class HardwareConfig;
25class Wav8Writer;
26
28 , public MediaInfoProvider
29 , private EventListener
30{
31public:
32 static constexpr std::string_view TAPE_RECORDING_DIR = "taperecordings";
33 static constexpr std::string_view TAPE_RECORDING_EXTENSION = ".wav";
34
35public:
36 explicit CassettePlayer(const HardwareConfig& hwConf);
37 ~CassettePlayer() override;
38
39 // CassetteDevice
40 void setMotor(bool status, EmuTime::param time) override;
41 int16_t readSample(EmuTime::param time) override;
42 void setSignal(bool output, EmuTime::param time) override;
43
44 // Pluggable
45 std::string_view getName() const override;
46 std::string_view getDescription() const override;
47 void plugHelper(Connector& connector, EmuTime::param time) override;
48 void unplugHelper(EmuTime::param time) override;
49
50 // SoundDevice
51 void generateChannels(std::span<float*> buffers, unsigned num) override;
52 float getAmplificationFactorImpl() const override;
53
54 // MediaInfoProvider
55 void getMediaInfo(TclObject& result) override;
56
57 template<typename Archive>
58 void serialize(Archive& ar, unsigned version);
59
60 enum State { PLAY, RECORD, STOP }; // public for serialization
61
62private:
63 [[nodiscard]] State getState() const { return state; }
64 [[nodiscard]] std::string getStateString() const;
65 void setState(State newState, const Filename& newImage,
66 EmuTime::param time);
67 void setImageName(const Filename& newImage);
68 const Filename& getImageName() const { return casImage; }
69 void checkInvariants() const;
70
73 void playTape(const Filename& filename, EmuTime::param time);
74 void insertTape(const Filename& filename, EmuTime::param time);
75
78 void removeTape(EmuTime::param time);
79
83 void recordTape(const Filename& filename, EmuTime::param time);
84
89 void rewind(EmuTime::param time);
90
93 void setMotorControl(bool status, EmuTime::param time);
94
98 bool isRolling() const;
99
104 void updateLoadingState(EmuTime::param time);
105
108 double getTapePos(EmuTime::param time);
109
114 double getTapeLength(EmuTime::param time);
115
116 void sync(EmuTime::param time);
117 void updateTapePosition(EmuDuration::param duration, EmuTime::param time);
118 void generateRecordOutput(EmuDuration::param duration);
119
120 void fillBuf(size_t length, double x);
121 void flushOutput();
122 void autoRun();
123
124 // EventListener
125 int signalEvent(const Event& event) override;
126
127 // Schedulable
128 struct SyncEndOfTape final : Schedulable {
129 friend class CassettePlayer;
130 explicit SyncEndOfTape(Scheduler& s) : Schedulable(s) {}
131 void executeUntil(EmuTime::param time) override {
132 auto& cp = OUTER(CassettePlayer, syncEndOfTape);
133 cp.execEndOfTape(time);
134 }
135 } syncEndOfTape;
136 struct SyncAudioEmu final : Schedulable {
137 friend class CassettePlayer;
138 explicit SyncAudioEmu(Scheduler& s) : Schedulable(s) {}
139 void executeUntil(EmuTime::param time) override {
140 auto& cp = OUTER(CassettePlayer, syncAudioEmu);
141 cp.execSyncAudioEmu(time);
142 }
143 } syncAudioEmu;
144
145 void execEndOfTape(EmuTime::param time);
146 void execSyncAudioEmu(EmuTime::param time);
147 EmuTime::param getCurrentTime() const { return syncEndOfTape.getCurrentTime(); }
148
149 std::array<uint8_t, 1024> buf;
150
151 double lastX; // last unfiltered output
152 double lastY; // last filtered output
153 double partialOut;
154 double partialInterval;
155
157 EmuTime tapePos = EmuTime::zero();
158
161 EmuTime prevSyncTime = EmuTime::zero();
162
163 // SoundDevice
164 unsigned audioPos = 0;
165 Filename casImage;
166
167 MSXMotherBoard& motherBoard;
168
169 struct TapeCommand final : RecordedCommand {
170 TapeCommand(CommandController& commandController,
171 StateChangeDistributor& stateChangeDistributor,
172 Scheduler& scheduler);
173 void execute(std::span<const TclObject> tokens, TclObject& result,
174 EmuTime::param time) override;
175 [[nodiscard]] std::string help(std::span<const TclObject> tokens) const override;
176 void tabCompletion(std::vector<std::string>& tokens) const override;
177 [[nodiscard]] bool needRecord(std::span<const TclObject> tokens) const override;
178 } tapeCommand;
179
180 LoadingIndicator loadingIndicator;
181 BooleanSetting autoRunSetting;
182 std::unique_ptr<Wav8Writer> recordImage;
183 std::unique_ptr<CassetteImage> playImage;
184
185 size_t sampCnt = 0;
186 State state = STOP;
187 bool lastOutput = false;
188 bool motor = false, motorControl = true;
189 bool syncScheduled = false;
190};
192
193} // namespace openmsx
194
195#endif
void plugHelper(Connector &connector, EmuTime::param time) override
static constexpr std::string_view TAPE_RECORDING_DIR
float getAmplificationFactorImpl() const override
Get amplification/attenuation factor for this device.
std::string_view getName() const override
Name used to identify this pluggable.
std::string_view getDescription() const override
Description for this pluggable.
void setSignal(bool output, EmuTime::param time) override
Sets the cassette output signal false = low true = high.
void unplugHelper(EmuTime::param time) override
void generateChannels(std::span< float * > buffers, unsigned num) override
Abstract method to generate the actual sound data.
void setMotor(bool status, EmuTime::param time) override
Sets the cassette motor relay false = off true = on.
void serialize(Archive &ar, unsigned version)
int16_t readSample(EmuTime::param time) override
Read wave data from cassette device.
static constexpr std::string_view TAPE_RECORDING_EXTENSION
void getMediaInfo(TclObject &result) override
This method gets called when information is required on the media inserted in the media slot of the p...
Represents something you can plug devices into.
Definition Connector.hh:21
const EmuDuration & param
Schedulable(const Schedulable &)=delete
This file implemented 3 utility functions:
Definition Autofire.cc:11
std::variant< KeyUpEvent, KeyDownEvent, MouseMotionEvent, MouseButtonUpEvent, MouseButtonDownEvent, MouseWheelEvent, JoystickAxisMotionEvent, JoystickHatEvent, JoystickButtonUpEvent, JoystickButtonDownEvent, OsdControlReleaseEvent, OsdControlPressEvent, WindowEvent, TextEvent, FileDropEvent, QuitEvent, FinishFrameEvent, CliCommandEvent, GroupEvent, BootEvent, FrameDrawnEvent, BreakEvent, SwitchRendererEvent, TakeReverseSnapshotEvent, AfterTimedEvent, MachineLoadedEvent, MachineActivatedEvent, MachineDeactivatedEvent, MidiInReaderEvent, MidiInWindowsEvent, MidiInCoreMidiEvent, MidiInCoreMidiVirtualEvent, MidiInALSAEvent, Rs232TesterEvent, Rs232NetEvent, ImGuiDelayedActionEvent, ImGuiActiveEvent > Event
Definition Event.hh:446
#define OUTER(type, member)
Definition outer.hh:42
#define SERIALIZE_CLASS_VERSION(CLASS, VERSION)