mirror of
https://github.com/clangen/musikcube.git
synced 2024-10-02 04:52:32 +00:00
Added global looping option to the GmeDecoder and fixed the way the end
of song is detected.
This commit is contained in:
parent
87c9598c97
commit
3888535c83
@ -189,7 +189,16 @@ struct musik::cube::TransportDisplayCache {
|
||||
return stringToColumns[str];
|
||||
}
|
||||
|
||||
std::string CurrentTime(int secondsCurrent) {
|
||||
if (secondsTotal != INT_MIN) {
|
||||
secondsCurrent = std::min(secondsCurrent, secondsTotal);
|
||||
}
|
||||
return musik::core::duration::Duration(secondsCurrent);
|
||||
}
|
||||
|
||||
void Update(ITransport& transport, TrackPtr track) {
|
||||
/* some params don't update regularly at all, so we can safely
|
||||
cache them as long as the track hasn't actually changed. */
|
||||
if (this->track != track) {
|
||||
this->Reset();
|
||||
|
||||
@ -207,9 +216,15 @@ struct musik::cube::TransportDisplayCache {
|
||||
artist = this->track->GetString(constants::Track::ARTIST);
|
||||
artist = artist.size() ? artist : Strings.EMPTY_ARTIST;
|
||||
artistCols = u8cols(artist);
|
||||
}
|
||||
}
|
||||
|
||||
secondsTotal = (int)transport.GetDuration();
|
||||
if (secondsTotal <= 0) {
|
||||
/* we check duration even if the track is the same because
|
||||
looping params may have changed. */
|
||||
auto updatedTotal = (int)transport.GetDuration();
|
||||
if (updatedTotal != secondsTotal) {
|
||||
secondsTotal = updatedTotal;
|
||||
if (secondsTotal <= 0 && secondsTotal != INT_MIN) {
|
||||
std::string duration =
|
||||
this->track->GetString(constants::Track::DURATION);
|
||||
|
||||
@ -218,9 +233,14 @@ struct musik::cube::TransportDisplayCache {
|
||||
}
|
||||
}
|
||||
|
||||
if (secondsTotal >= 0) {
|
||||
totalTime = musik::core::duration::Duration(secondsTotal);
|
||||
totalTimeCols = u8cols(totalTime);
|
||||
}
|
||||
else {
|
||||
totalTime = "∞";
|
||||
}
|
||||
|
||||
totalTimeCols = u8cols(totalTime);
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -657,8 +677,8 @@ void TransportWindow::Update(TimeMode timeMode) {
|
||||
secondsCurrent = (int) round(this->lastTime);
|
||||
}
|
||||
|
||||
const std::string currentTime = musik::core::duration::Duration(
|
||||
std::min(secondsCurrent, displayCache->secondsTotal));
|
||||
const std::string currentTime =
|
||||
displayCache->CurrentTime(secondsCurrent);
|
||||
|
||||
const std::string replayGain = replayGainEnabled ? "rg" : "";
|
||||
|
||||
|
@ -57,6 +57,8 @@
|
||||
|
||||
static const char* PLUGIN_NAME = "GME IDecoder";
|
||||
|
||||
static const char* KEY_ALWAYS_LOOP_FOREVER = "always_loop_forever";
|
||||
static const bool DEFAULT_ALWAYS_LOOP_FOREVER = false;
|
||||
static const char* KEY_DEFAULT_TRACK_LENGTH = "default_track_length_secs";
|
||||
static const double DEFAULT_TRACK_LENGTH = 60.0 * 3.0;
|
||||
static const char* KEY_TRACK_FADE_OUT_LENGTH = "track_fade_out_length_secs";
|
||||
@ -94,6 +96,7 @@ static inline std::wstring u8to16(const char* utf8) {
|
||||
|
||||
static inline musik::core::sdk::ISchema* CreateSchema() {
|
||||
auto schema = new musik::core::sdk::TSchema<>();
|
||||
schema->AddBool(KEY_ALWAYS_LOOP_FOREVER, DEFAULT_ALWAYS_LOOP_FOREVER);
|
||||
schema->AddDouble(KEY_DEFAULT_TRACK_LENGTH, DEFAULT_TRACK_LENGTH);
|
||||
schema->AddDouble(KEY_TRACK_FADE_OUT_LENGTH, DEFAULT_FADE_OUT_LENGTH);
|
||||
schema->AddBool(KEY_ENABLE_M3U, DEFAULT_ENABLE_M3U);
|
||||
|
@ -35,15 +35,18 @@
|
||||
#include "Constants.h"
|
||||
#include "GmeDecoder.h"
|
||||
#include <core/sdk/IPreferences.h>
|
||||
#include <core/sdk/IDebug.h>
|
||||
#include <cassert>
|
||||
|
||||
static const int BUFFER_SAMPLE_COUNT = 2048;
|
||||
static const int CHANNELS = 2;
|
||||
static const int SAMPLE_RATE = 44100;
|
||||
static const int SAMPLE_RATE = 48000;
|
||||
static const int SAMPLES_PER_MS = (SAMPLE_RATE * CHANNELS) / 1000;
|
||||
static const double LENGTH_FOREVER = INT_MIN;
|
||||
static const float F_SHRT_MAX = (float) SHRT_MAX;
|
||||
|
||||
extern IPreferences* prefs;
|
||||
extern IDebug* debug;
|
||||
|
||||
GmeDecoder::GmeDecoder() {
|
||||
this->buffer = new short[BUFFER_SAMPLE_COUNT];
|
||||
@ -84,7 +87,10 @@ bool GmeDecoder::Open(musik::core::sdk::IDataStream *stream) {
|
||||
this->info = nullptr;
|
||||
}
|
||||
else {
|
||||
if (this->info->length == -1) {
|
||||
if (prefs->GetBool(KEY_ALWAYS_LOOP_FOREVER, DEFAULT_ALWAYS_LOOP_FOREVER)) {
|
||||
this->length = LENGTH_FOREVER;
|
||||
}
|
||||
else if (this->info->length == -1) {
|
||||
this->length = prefs->GetDouble(
|
||||
KEY_DEFAULT_TRACK_LENGTH, DEFAULT_TRACK_LENGTH);
|
||||
|
||||
@ -97,9 +103,11 @@ bool GmeDecoder::Open(musik::core::sdk::IDataStream *stream) {
|
||||
(int)(fadeLength * 1000.0));
|
||||
}
|
||||
else {
|
||||
this->length = (double) this->info->length / 1000.0;
|
||||
this->length = (double) this->info->play_length / 1000.0;
|
||||
}
|
||||
}
|
||||
|
||||
this->totalSamples = (int)(this->length * SAMPLE_RATE * CHANNELS);
|
||||
}
|
||||
}
|
||||
delete[] data;
|
||||
@ -111,9 +119,13 @@ void GmeDecoder::Release() {
|
||||
}
|
||||
|
||||
double GmeDecoder::SetPosition(double seconds) {
|
||||
std::unique_lock<decltype(this->mutex)> lock(this->mutex);
|
||||
if (this->gme) {
|
||||
gme_seek(this->gme, (int)(seconds * 1000.0));
|
||||
return (double) gme_tell(this->gme) / 1000.0;
|
||||
auto err = gme_seek(this->gme, (int)(seconds * 1000.0));
|
||||
if (err) { debug->Error(PLUGIN_NAME, err); }
|
||||
double position = (double)gme_tell(this->gme) / 1000.0;
|
||||
this->samplesPlayed = (int)(position * SAMPLE_RATE * CHANNELS);
|
||||
return position;
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
@ -123,26 +135,36 @@ double GmeDecoder::GetDuration() {
|
||||
}
|
||||
|
||||
bool GmeDecoder::GetBuffer(IBuffer *target) {
|
||||
std::unique_lock<decltype(this->mutex)> lock(this->mutex);
|
||||
if (this->gme) {
|
||||
if (!gme_track_ended(this->gme) &&
|
||||
!gme_play(this->gme, BUFFER_SAMPLE_COUNT, this->buffer))
|
||||
int samplesRemaining = totalSamples - samplesPlayed;
|
||||
|
||||
bool playFullBuffer =
|
||||
(samplesRemaining > BUFFER_SAMPLE_COUNT) ||
|
||||
(this->length == LENGTH_FOREVER);
|
||||
|
||||
int bufferSamples = playFullBuffer
|
||||
? BUFFER_SAMPLE_COUNT : samplesRemaining;
|
||||
|
||||
if (bufferSamples > 0 &&
|
||||
!gme_play(this->gme, bufferSamples, this->buffer))
|
||||
{
|
||||
target->SetChannels(CHANNELS);
|
||||
target->SetSampleRate(SAMPLE_RATE);
|
||||
target->SetSamples(BUFFER_SAMPLE_COUNT);
|
||||
target->SetSamples(bufferSamples);
|
||||
|
||||
float* dst = target->BufferPointer();
|
||||
for (size_t i = 0; i < BUFFER_SAMPLE_COUNT; i++) {
|
||||
dst[i] = (float) this->buffer[i] / F_SHRT_MAX;
|
||||
}
|
||||
samplesPlayed += bufferSamples;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
this->exhausted = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GmeDecoder::Exhausted() {
|
||||
if (this->gme) {
|
||||
return gme_track_ended(this->gme);
|
||||
}
|
||||
return true;
|
||||
return this->exhausted;
|
||||
}
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include "GmeDataStream.h"
|
||||
#include <stddef.h>
|
||||
#include <gme.h>
|
||||
#include <mutex>
|
||||
|
||||
using namespace musik::core::sdk;
|
||||
|
||||
@ -60,5 +61,9 @@ class GmeDecoder: public musik::core::sdk::IDecoder {
|
||||
gme_t* gme { nullptr };
|
||||
gme_info_t* info { nullptr };
|
||||
short* buffer;
|
||||
double length = -1.0;
|
||||
double length{ -1.0 };
|
||||
int totalSamples { 0 };
|
||||
int samplesPlayed { 0 };
|
||||
bool exhausted { false };
|
||||
std::mutex mutex;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user