1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
|
#include "player.h"
#include <ctype.h>
#include <stdio.h>
#include <string.h>
/* ------------------------------------------------------------------ */
/* Helpers (module-private) */
/* ------------------------------------------------------------------ */
static int ext_equals_nocase(const char *a, const char *b)
{
while (*a && *b) {
if (tolower((unsigned char)*a) != tolower((unsigned char)*b)) return 1;
a++; b++;
}
return *a != *b;
}
static const char *basename_from_path(const char *path)
{
const char *last = path;
for (const char *p = path; *p; p++) {
if (*p == '/' || *p == '\\') last = p + 1;
}
return last;
}
/* ------------------------------------------------------------------ */
/* Public API */
/* ------------------------------------------------------------------ */
bool player_load(PlayerState *state, const char *path)
{
const char *ext = GetFileExtension(path);
if (ext == NULL || ext_equals_nocase(ext, ".mp3") != 0) return false;
if (state->loaded) {
StopMusicStream(state->music);
UnloadMusicStream(state->music);
state->loaded = false;
state->playing = false;
}
state->music = LoadMusicStream(path);
state->duration = GetMusicTimeLength(state->music);
state->loaded = true;
state->playing = true;
const char *base = basename_from_path(path);
strncpy(state->filename, base, sizeof(state->filename) - 1);
state->filename[sizeof(state->filename) - 1] = '\0';
PlayMusicStream(state->music);
return true;
}
void player_unload(PlayerState *state)
{
if (!state->loaded) return;
StopMusicStream(state->music);
UnloadMusicStream(state->music);
state->loaded = false;
state->playing = false;
}
void player_play(PlayerState *state)
{
if (!state->loaded || state->playing) return;
ResumeMusicStream(state->music);
state->playing = true;
}
void player_pause(PlayerState *state)
{
if (!state->loaded || !state->playing) return;
PauseMusicStream(state->music);
state->playing = false;
}
void player_seek(PlayerState *state, float target)
{
if (!state->loaded) return;
if (target < 0.0f) target = 0.0f;
if (target > state->duration) target = state->duration;
SeekMusicStream(state->music, target);
state->currentTime = target;
state->skipAutoUpdate = 3; /* skip a few frames to let audio engine catch up */
}
void player_update(PlayerState *state)
{
if (!state->loaded) return;
UpdateMusicStream(state->music);
if (state->playing) {
if (state->skipAutoUpdate > 0) {
state->skipAutoUpdate--;
} else {
state->currentTime = GetMusicTimePlayed(state->music);
}
}
}
void player_format_time(float seconds, char *buf, int bufsize)
{
int total = (int)seconds;
if (total < 0) total = 0;
int h = total / 3600;
int m = (total % 3600) / 60;
int s = total % 60;
if (h > 0)
snprintf(buf, bufsize, "%d:%02d:%02d", h, m, s);
else
snprintf(buf, bufsize, "%d:%02d", m, s);
}
|