[Scummvm-git-logs] scummvm master -> bf233f00764b630ec4db2eeda2a024a70719f109
sev-
noreply at scummvm.org
Thu Nov 30 00:41:15 UTC 2023
This automated email contains information about 4 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
1492866d59 COMMON: reorient cue around tracks
e8e5263bb1 COMMON: avoid inserting null tracks
3967c4f196 BACKENDS: allow audio CDs to play absolute position
bf233f0076 DIRECTOR: CD xlibs support absolute positioning
Commit: 1492866d59bd641e20a5ad531563be92d1b5f3b6
https://github.com/scummvm/scummvm/commit/1492866d59bd641e20a5ad531563be92d1b5f3b6
Author: Misty De Meo (mistydemeo at gmail.com)
Date: 2023-11-30T01:41:10+01:00
Commit Message:
COMMON: reorient cue around tracks
Changed paths:
common/formats/cue.cpp
common/formats/cue.h
diff --git a/common/formats/cue.cpp b/common/formats/cue.cpp
index 14ef4a6acc3..0af2fd380aa 100644
--- a/common/formats/cue.cpp
+++ b/common/formats/cue.cpp
@@ -252,14 +252,16 @@ void CueSheet::parseFilesContext(const char *line) {
if (trackNum < 0 || (_currentTrack > 0 && _currentTrack + 1 != trackNum)) {
warning("CueSheet: Incorrect track number. Expected %d but got %d at line %d", _currentTrack + 1, trackNum, _lineNum);
} else {
- for (int i = (int)_files[_currentFile].tracks.size(); i <= trackNum; i++)
- _files[_currentFile].tracks.push_back(CueTrack());
+ for (int i = (int)_tracks.size(); i <= trackNum; i++)
+ _tracks.push_back(CueTrack());
_currentTrack = trackNum;
- _files[_currentFile].tracks[_currentTrack].type = (TrackType)lookupInTable(trackTypes, trackType.c_str());
- _files[_currentFile].tracks[_currentTrack].size = lookupInTable(trackTypesSectorSizes, trackType.c_str());
+ _tracks[_currentTrack].number = trackNum;
+ _tracks[_currentTrack].type = (TrackType)lookupInTable(trackTypes, trackType.c_str());
+ _tracks[_currentTrack].size = lookupInTable(trackTypesSectorSizes, trackType.c_str());
+ _tracks[_currentTrack].file = _files[_currentFile];
- debug(5, "Track: %d type: %s (%d)", trackNum, trackType.c_str(), _files[_currentFile].tracks[_currentTrack].type);
+ debug(5, "Track: %d type: %s (%d)", trackNum, trackType.c_str(), _tracks[_currentTrack].type);
}
_context = kContextTracks;
@@ -285,23 +287,23 @@ void CueSheet::parseTracksContext(const char *line) {
if (command == "TRACK") {
parseFilesContext(line);
} else if (command == "TITLE") {
- _files[_currentFile].tracks[_currentTrack].title = nexttok(s, &s);
+ _tracks[_currentTrack].title = nexttok(s, &s);
- debug(5, "Track title: %s", _files[_currentFile].tracks[_currentTrack].title.c_str());
+ debug(5, "Track title: %s", _tracks[_currentTrack].title.c_str());
} else if (command == "INDEX") {
int indexNum = atoi(nexttok(s, &s).c_str());
int frames = parseMSF(nexttok(s, &s).c_str());
- for (int i = (int)_files[_currentFile].tracks[_currentTrack].indices.size(); i <= indexNum; i++)
- _files[_currentFile].tracks[_currentTrack].indices.push_back(0);
+ for (int i = (int)_tracks[_currentTrack].indices.size(); i <= indexNum; i++)
+ _tracks[_currentTrack].indices.push_back(0);
- _files[_currentFile].tracks[_currentTrack].indices[indexNum] = frames;
+ _tracks[_currentTrack].indices[indexNum] = frames;
debug(5, "Index: %d, frames: %d", indexNum, frames);
} else if (command == "PREGAP") {
- _files[_currentFile].tracks[_currentTrack].pregap = parseMSF(nexttok(s, &s).c_str());
+ _tracks[_currentTrack].pregap = parseMSF(nexttok(s, &s).c_str());
- debug(5, "Track pregap: %d", _files[_currentFile].tracks[_currentTrack].pregap);
+ debug(5, "Track pregap: %d", _tracks[_currentTrack].pregap);
} else if (command == "FLAGS") {
String flag;
uint32 flags = 0;
@@ -312,18 +314,73 @@ void CueSheet::parseTracksContext(const char *line) {
flags |= lookupInTable(trackFlags, flag.c_str());
}
- _files[_currentFile].tracks[_currentTrack].flags = flags;
+ _tracks[_currentTrack].flags = flags;
- debug(5, "Track flags: %d", _files[_currentFile].tracks[_currentTrack].flags);
+ debug(5, "Track flags: %d", _tracks[_currentTrack].flags);
} else if (command == "FILE") {
parseHeaderContext(line);
} else if (command == "PERFORMER") {
- _files[_currentFile].tracks[_currentTrack].performer = nexttok(s, &s);
+ _tracks[_currentTrack].performer = nexttok(s, &s);
- debug(5, "Track performer: %s", _files[_currentFile].tracks[_currentTrack].performer.c_str());
+ debug(5, "Track performer: %s", _tracks[_currentTrack].performer.c_str());
} else {
warning("CueSheet: Unprocessed track command %s at line %d", command.c_str(), _lineNum);
}
}
+Array<CueSheet::CueFile> CueSheet::files() {
+ return _files;
+}
+
+Array<CueSheet::CueTrack> CueSheet::tracks() {
+ return _tracks;
+}
+
+CueSheet::CueTrack *CueSheet::getTrack(int tracknum) {
+ for (uint i = 0; i < _tracks.size(); i++) {
+ if (_tracks[i].number == tracknum) {
+ return &_tracks[i];
+ }
+ }
+
+ return nullptr;
+}
+
+CueSheet::CueTrack *CueSheet::getTrackAtFrame(int frame) {
+ for (uint i = 0; i < _tracks.size(); i++) {
+ if (_tracks[i].indices.size() == 0) {
+ continue;
+ }
+
+ // Inside pregap
+ if (frame >= _tracks[i].indices[0] && frame < _tracks[i].indices.back()) {
+ debug(5, "CueSheet::getTrackAtFrame: Returning track %i (pregap)", i);
+ return &_tracks[i];
+ }
+
+ // Between index 1 and the start of the subsequent track
+ if (i < _tracks.size() && frame > _tracks[i].indices.back() && frame < _tracks[i+1].indices[0]) {
+ debug(5, "CueSheet::getTrackAtFrame: Returning track %i (inside content)", i);
+ return &_tracks[i];
+ }
+ }
+
+ // Not found within any tracks, but could be in the final track.
+ // Note: this looks weird, but is correct (or correct-ish).
+ // The cuesheet tracks the *starting* index of a song, but not
+ // the *duration* of a track. Without having access to the raw
+ // disc data, we don't actually know how long this track is.
+ // As a result, if we see any frame that comes after the
+ // start of the final track, we need to assume it's
+ // a part of that track.
+ if (frame > _tracks.back().indices.back()) {
+ debug(5, "CueSheet::getTrackAtFrame: Returning final track");
+ return &_tracks.back();
+ }
+
+ // Still not found; could indicate a gap between indices
+ warning("CueSheet::getTrackAtFrame: Not returning a track; does the cuesheet have a gap between indices?");
+ return nullptr;
+}
+
} // End of namespace Common
diff --git a/common/formats/cue.h b/common/formats/cue.h
index 95d8ce9acf8..f754f9bb3b8 100644
--- a/common/formats/cue.h
+++ b/common/formats/cue.h
@@ -67,8 +67,14 @@ public:
kTrackFlagSCMS = 1 << 3, // Serial copy management system
};
+ struct CueFile {
+ String name;
+ FileType type = kFileTypeBinary;
+ };
+
struct CueTrack {
int number = 0;
+ CueFile file;
TrackType type;
String title;
String performer;
@@ -78,12 +84,6 @@ public:
int size = 2352;
};
- struct CueFile {
- String name;
- FileType type = kFileTypeBinary;
- Array<CueTrack> tracks;
- };
-
struct CueMetadata {
String title;
String date;
@@ -94,6 +94,11 @@ public:
struct LookupTable;
+ Array<CueFile> files();
+ Array<CueTrack> tracks();
+ CueTrack *getTrack(int tracknum);
+ CueTrack *getTrackAtFrame(int frame);
+
private:
void parse(const char *sheet);
@@ -111,6 +116,7 @@ private:
int _currentTrack = -1;
Array<CueFile> _files;
+ Array<CueTrack> _tracks;
CueMetadata _metadata;
};
Commit: e8e5263bb16183692a2c095e1f4acd202610cf0d
https://github.com/scummvm/scummvm/commit/e8e5263bb16183692a2c095e1f4acd202610cf0d
Author: Misty De Meo (mistydemeo at gmail.com)
Date: 2023-11-30T01:41:10+01:00
Commit Message:
COMMON: avoid inserting null tracks
Changed paths:
common/formats/cue.cpp
diff --git a/common/formats/cue.cpp b/common/formats/cue.cpp
index 0af2fd380aa..c5d9025ab81 100644
--- a/common/formats/cue.cpp
+++ b/common/formats/cue.cpp
@@ -249,13 +249,17 @@ void CueSheet::parseFilesContext(const char *line) {
int trackNum = atoi(nexttok(s, &s).c_str());
String trackType = nexttok(s, &s);
- if (trackNum < 0 || (_currentTrack > 0 && _currentTrack + 1 != trackNum)) {
+ // We have to add + 2 here because _currentTrack is a counter
+ // for the array, which is 0-indexed, while the disc's track
+ // numbers are 1-indexed. The next track, in disc numbering,
+ // will be two greater than _currentTrack.
+ if (trackNum < 0 || (_currentTrack > 0 && _currentTrack + 2 != trackNum)) {
warning("CueSheet: Incorrect track number. Expected %d but got %d at line %d", _currentTrack + 1, trackNum, _lineNum);
} else {
- for (int i = (int)_tracks.size(); i <= trackNum; i++)
- _tracks.push_back(CueTrack());
+ _tracks.push_back(CueTrack());
- _currentTrack = trackNum;
+ // Array is 0-indexed, track numbers are 1-indexed
+ _currentTrack = trackNum - 1;
_tracks[_currentTrack].number = trackNum;
_tracks[_currentTrack].type = (TrackType)lookupInTable(trackTypes, trackType.c_str());
_tracks[_currentTrack].size = lookupInTable(trackTypesSectorSizes, trackType.c_str());
@@ -348,10 +352,6 @@ CueSheet::CueTrack *CueSheet::getTrack(int tracknum) {
CueSheet::CueTrack *CueSheet::getTrackAtFrame(int frame) {
for (uint i = 0; i < _tracks.size(); i++) {
- if (_tracks[i].indices.size() == 0) {
- continue;
- }
-
// Inside pregap
if (frame >= _tracks[i].indices[0] && frame < _tracks[i].indices.back()) {
debug(5, "CueSheet::getTrackAtFrame: Returning track %i (pregap)", i);
Commit: 3967c4f196609fe350fa65392e7e05cc47cd5826
https://github.com/scummvm/scummvm/commit/3967c4f196609fe350fa65392e7e05cc47cd5826
Author: Misty De Meo (mistydemeo at gmail.com)
Date: 2023-11-30T01:41:10+01:00
Commit Message:
BACKENDS: allow audio CDs to play absolute position
Changed paths:
backends/audiocd/audiocd.h
backends/audiocd/default/default-audiocd.cpp
backends/audiocd/default/default-audiocd.h
diff --git a/backends/audiocd/audiocd.h b/backends/audiocd/audiocd.h
index 67b6f9a8e0a..3cf6a5f2e12 100644
--- a/backends/audiocd/audiocd.h
+++ b/backends/audiocd/audiocd.h
@@ -72,6 +72,20 @@ public:
virtual bool play(int track, int numLoops, int startFrame, int duration, bool onlyEmulate = false,
Audio::Mixer::SoundType soundType = Audio::Mixer::kMusicSoundType) = 0;
+ /**
+ * Start audio CD playback at a specific absolute timestamp
+ * @param startFrame the frame at which playback should start (75 frames = 1 second).
+ * @param numLoops how often playback should be repeated (<=0 means infinitely often).
+ * @param duration the number of frames to play.
+ * @param onlyEmulate determines if the track should be emulated only
+ * @param soundType What sound type to play as. By default, it's as music
+ * @param cuesheet The name of the cuesheet to use for timing data
+ * @note The @c onlyEmulate parameter is deprecated.
+ * @return @c true if the track started playing, @c false otherwise
+ */
+ virtual bool playAbsolute(int startFrame, int numLoops, int duration, bool onlyEmulate = false,
+ Audio::Mixer::SoundType soundType = Audio::Mixer::kMusicSoundType, const char *cuesheet = "disc.cue") = 0;
+
/**
* Get if audio is being played.
* @return true if CD audio is playing
diff --git a/backends/audiocd/default/default-audiocd.cpp b/backends/audiocd/default/default-audiocd.cpp
index 2620081c5fc..54e4d54263b 100644
--- a/backends/audiocd/default/default-audiocd.cpp
+++ b/backends/audiocd/default/default-audiocd.cpp
@@ -25,6 +25,7 @@
#include "common/file.h"
#include "common/system.h"
#include "common/util.h"
+#include "common/formats/cue.h"
DefaultAudioCDManager::DefaultAudioCDManager() {
_cd.playing = false;
@@ -134,6 +135,27 @@ bool DefaultAudioCDManager::play(int track, int numLoops, int startFrame, int du
return false;
}
+bool DefaultAudioCDManager::playAbsolute(int startFrame, int numLoops, int duration, bool onlyEmulate,
+ Audio::Mixer::SoundType soundType, const char *cuesheet) {
+
+ Common::File *cuefile = new Common::File();
+ if (!cuefile->open(cuesheet)) {
+ return false;
+ }
+ Common::String cuestring = cuefile->readString(0, cuefile->size());
+ Common::CueSheet cue(cuestring.c_str());
+
+ Common::CueSheet::CueTrack *track = cue.getTrackAtFrame(startFrame);
+ if (track == nullptr) {
+ warning("Unable to locate track for frame %i", startFrame);
+ return false;
+ } else {
+ warning("Playing from frame %i", startFrame);
+ }
+
+ return play(track->number, numLoops, startFrame - track->indices[0], duration, onlyEmulate);
+}
+
void DefaultAudioCDManager::stop() {
if (_emulating) {
// Audio CD emulation
diff --git a/backends/audiocd/default/default-audiocd.h b/backends/audiocd/default/default-audiocd.h
index 5af7fe95efc..af18d30fb2c 100644
--- a/backends/audiocd/default/default-audiocd.h
+++ b/backends/audiocd/default/default-audiocd.h
@@ -41,6 +41,8 @@ public:
virtual void close();
virtual bool play(int track, int numLoops, int startFrame, int duration, bool onlyEmulate = false,
Audio::Mixer::SoundType soundType = Audio::Mixer::kMusicSoundType);
+ virtual bool playAbsolute(int startFrame, int numLoops, int duration, bool onlyEmulate = false,
+ Audio::Mixer::SoundType soundType = Audio::Mixer::kMusicSoundType, const char *cuesheet = "disc.cue");
virtual void stop();
virtual bool isPlaying() const;
virtual void setVolume(byte volume);
Commit: bf233f00764b630ec4db2eeda2a024a70719f109
https://github.com/scummvm/scummvm/commit/bf233f00764b630ec4db2eeda2a024a70719f109
Author: Misty De Meo (mistydemeo at gmail.com)
Date: 2023-11-30T01:41:10+01:00
Commit Message:
DIRECTOR: CD xlibs support absolute positioning
Changed paths:
engines/director/lingo/xlibs/applecdxobj.cpp
engines/director/lingo/xlibs/applecdxobj.h
engines/director/lingo/xlibs/cdromxobj.cpp
diff --git a/engines/director/lingo/xlibs/applecdxobj.cpp b/engines/director/lingo/xlibs/applecdxobj.cpp
index df6652ee140..a346afd07de 100644
--- a/engines/director/lingo/xlibs/applecdxobj.cpp
+++ b/engines/director/lingo/xlibs/applecdxobj.cpp
@@ -22,6 +22,7 @@
/*************************************
*
* USED IN:
+ * Classical Cats
* The Daedalus Encounter
*
*************************************/
@@ -84,6 +85,9 @@
* --
*/
+#include "backends/audiocd/audiocd.h"
+#include "common/file.h"
+#include "common/formats/cue.h"
#include "director/director.h"
#include "director/lingo/lingo.h"
#include "director/lingo/lingo-object.h"
@@ -101,8 +105,15 @@ const char *AppleCDXObj::fileNames[] = {
static MethodProto xlibMethods[] = {
{ "new", AppleCDXObj::m_new, 0, 0, 400 }, // D4
{ "Service", AppleCDXObj::m_service, 0, 0, 400 }, // D4
+ { "Still", AppleCDXObj::m_still, 0, 0, 400 }, // D4
{ "ReadStatus", AppleCDXObj::m_readStatus, 0, 0, 400 }, // D4
+ { "GetValue", AppleCDXObj::m_getValue, 0, 0, 400 }, // D4
{ "Eject", AppleCDXObj::m_eject, 0, 0, 400 }, // D4
+ { "SetInPoint", AppleCDXObj::m_setInPoint, 1, 1, 400 }, // D4
+ { "SetOutPoint", AppleCDXObj::m_setOutPoint, 1, 1, 400 }, // D4
+ { "PlayCue", AppleCDXObj::m_playCue, 0, 0, 400 }, // D4
+ { "PlaySegment", AppleCDXObj::m_playSegment, 0, 0, 400 }, // D4
+ { "ReadPos", AppleCDXObj::m_readPos, 0, 0, 400 }, // D4
{ nullptr, nullptr, 0, 0, 0 }
};
@@ -124,12 +135,28 @@ void AppleCDXObj::close(int type) {
AppleCDXObject::AppleCDXObject(ObjectType ObjectType) :Object<AppleCDXObject>("AppleCD") {
_objType = ObjectType;
+ _inpoint = 0;
+ _outpoint = 0;
+ _cue = nullptr;
+
+ Common::File *cuefile = new Common::File();
+ if (cuefile->open("disc.cue")) {
+ Common::String cuestring = cuefile->readString(0, cuefile->size());
+
+ _cue = new Common::CueSheet(cuestring.c_str());
+ }
}
void AppleCDXObj::m_new(int nargs) {
g_lingo->push(g_lingo->_state->me);
}
+void AppleCDXObj::m_still(int nargs) {
+ g_director->_system->getAudioCDManager()->stop();
+}
+
+// Not implemented yet; needs to be able to return appropriate values
+// for playing/paused.
void AppleCDXObj::m_service(int nargs) {
g_lingo->push(Datum(0));
}
@@ -137,6 +164,55 @@ void AppleCDXObj::m_service(int nargs) {
void AppleCDXObj::m_readStatus(int nargs) {
}
+void AppleCDXObj::m_getValue(int nargs) {
+ AppleCDXObject *me = static_cast<AppleCDXObject *>(g_lingo->_state->me.u.obj);
+
+ g_lingo->push(Datum(me->_returnValue));
+}
+
+void AppleCDXObj::m_setInPoint(int nargs) {
+ AppleCDXObject *me = static_cast<AppleCDXObject *>(g_lingo->_state->me.u.obj);
+
+ int inpoint = g_lingo->pop().asInt();
+ debug(5, "AppleCDXObj::setInPoint: %i", inpoint);
+ me->_inpoint = inpoint;
+}
+
+void AppleCDXObj::m_setOutPoint(int nargs) {
+ AppleCDXObject *me = static_cast<AppleCDXObject *>(g_lingo->_state->me.u.obj);
+
+ int outpoint = g_lingo->pop().asInt();
+ debug(5, "AppleCDXObj::setOutPoint: %i", outpoint);
+ me->_outpoint = outpoint;
+}
+
+void AppleCDXObj::m_playCue(int nargs) {
+ // Essentially a noop for us; this asks the drive to seek to that point,
+ // then poll until it does. We don't have seek times, so we'll
+ // simply noop.
+}
+
+void AppleCDXObj::m_playSegment(int nargs) {
+ // Performs playback at the pre-specified absolute point on the disc,
+ // using the values from setInPoint and setOutPoint
+ AppleCDXObject *me = static_cast<AppleCDXObject *>(g_lingo->_state->me.u.obj);
+
+ g_director->_system->getAudioCDManager()->playAbsolute(me->_inpoint, -1, 0, 0);
+}
+
+void AppleCDXObj::m_readPos(int nargs) {
+ AppleCDXObject *me = static_cast<AppleCDXObject *>(g_lingo->_state->me.u.obj);
+
+ AudioCDManager::Status status = g_director->_system->getAudioCDManager()->getStatus();
+ if (me->_cue) {
+ // ScummVM currently doesn't support specifying the exact frame, so we pretend we're at the first frame of the song
+ Common::CueSheet::CueTrack *track = me->_cue->getTrack(status.track);
+ if (track != nullptr) {
+ me->_returnValue = track->indices[0];
+ }
+ }
+}
+
void AppleCDXObj::m_eject(int nargs) {
debug(5, "AppleCDXObj::eject: Ejecting CD");
}
diff --git a/engines/director/lingo/xlibs/applecdxobj.h b/engines/director/lingo/xlibs/applecdxobj.h
index ef88ec7cb85..78cb773994e 100644
--- a/engines/director/lingo/xlibs/applecdxobj.h
+++ b/engines/director/lingo/xlibs/applecdxobj.h
@@ -22,11 +22,22 @@
#ifndef DIRECTOR_LINGO_XLIBS_APPLECDXOBJ_H
#define DIRECTOR_LINGO_XLIBS_APPLECDXOBJ_H
+namespace Common {
+ class CueSheet;
+}
+
namespace Director {
class AppleCDXObject : public Object<AppleCDXObject> {
public:
AppleCDXObject(ObjectType objType);
+ int _inpoint;
+ int _outpoint;
+ // Instead of immediately returning values, methods which return
+ // a value store it internally and return it via a subsequent
+ // call to mGetValue.
+ int _returnValue;
+ Common::CueSheet *_cue;
};
namespace AppleCDXObj {
@@ -38,8 +49,15 @@ void open(int type);
void close(int type);
void m_new(int nargs);
+void m_still(int nargs);
void m_service(int nargs);
void m_readStatus(int nargs);
+void m_getValue(int nargs);
+void m_setInPoint(int nargs);
+void m_setOutPoint(int nargs);
+void m_playCue(int nargs);
+void m_playSegment(int nargs);
+void m_readPos(int nargs);
void m_eject(int nargs);
} // End of namespace AppleCDXObj
diff --git a/engines/director/lingo/xlibs/cdromxobj.cpp b/engines/director/lingo/xlibs/cdromxobj.cpp
index a84bee5ea92..742971cdc77 100644
--- a/engines/director/lingo/xlibs/cdromxobj.cpp
+++ b/engines/director/lingo/xlibs/cdromxobj.cpp
@@ -23,6 +23,7 @@
*
* USED IN:
* The Apartment 2.0
+ * Cellofania
*
*************************************/
@@ -294,12 +295,17 @@ void CDROMXObj::m_playName(int nargs) {
}
void CDROMXObj::m_playAbsTime(int nargs) {
+ CDROMXObject *me = static_cast<CDROMXObject *>(g_lingo->_state->me.u.obj);
+
Datum min = g_lingo->pop();
Datum sec = g_lingo->pop();
Datum frac = g_lingo->pop();
- // Can't implement this without implementing a full CD TOC, since
- // it doesn't interact with songs at the "track" level.
- debug(5, "STUB: CDROMXObj::m_playAbsTime Request to play starting at %i:%i.%i", min.asInt(), sec.asInt(), frac.asInt());
+
+ int startFrame = (min.asInt() * 60 * 75) + (sec.asInt() * 75) + frac.asInt();
+ debug(5, "CDROMXObj::m_playAbsTime: playing at frame %i", startFrame);
+ g_director->_system->getAudioCDManager()->playAbsolute(startFrame, -1, 0);
+ me->_cdda_status = g_director->_system->getAudioCDManager()->getStatus();
+
g_lingo->push(Datum());
}
More information about the Scummvm-git-logs
mailing list