text/plain
•
4.52 KB
•
148 lines
#include "../src/audio_player.h"
#include "../src/audio_metadata.h"
#include <SDL.h>
#include <SDL_mixer.h>
#include <string.h>
#include <stdio.h>
static Mix_Music *current_music = NULL;
static audio_state_t current_state = AUDIO_STATE_STOPPED;
static uint8_t current_volume = 100;
static char current_filename[64] = {0};
static audio_metadata_t current_metadata;
static char current_display_title[128];
bool audio_player_init(void) {
if (Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 2048) < 0) {
fprintf(stderr, "SDL_mixer init failed: %s\n", Mix_GetError());
return false;
}
return true;
}
bool audio_player_play(const char *path) {
audio_player_stop();
// Build path relative to sdcard directory
char full_path[256];
snprintf(full_path, sizeof(full_path), "./sdcard%s", path);
current_music = Mix_LoadMUS(full_path);
if (!current_music) {
fprintf(stderr, "Failed to load %s: %s\n", full_path, Mix_GetError());
return false;
}
// Extract filename for display
const char *name = strrchr(path, '/');
name = name ? name + 1 : path;
strncpy(current_filename, name, sizeof(current_filename) - 1);
current_filename[sizeof(current_filename) - 1] = '\0';
// Parse metadata for duration and tags
memset(¤t_metadata, 0, sizeof(current_metadata));
current_display_title[0] = '\0';
if (audio_metadata_get(full_path, ¤t_metadata)) {
if (current_metadata.artist[0] && current_metadata.title[0]) {
snprintf(current_display_title, sizeof(current_display_title), "%.60s - %.60s",
current_metadata.artist, current_metadata.title);
} else if (current_metadata.title[0]) {
snprintf(current_display_title, sizeof(current_display_title), "%.127s",
current_metadata.title);
}
}
// Set volume and play
Mix_VolumeMusic((int)(current_volume * MIX_MAX_VOLUME / 100));
if (Mix_PlayMusic(current_music, 0) < 0) {
fprintf(stderr, "Failed to play: %s\n", Mix_GetError());
Mix_FreeMusic(current_music);
current_music = NULL;
return false;
}
current_state = AUDIO_STATE_PLAYING;
return true;
}
void audio_player_stop(void) {
if (current_music) {
Mix_HaltMusic();
Mix_FreeMusic(current_music);
current_music = NULL;
}
current_state = AUDIO_STATE_STOPPED;
current_filename[0] = '\0';
current_display_title[0] = '\0';
memset(¤t_metadata, 0, sizeof(current_metadata));
}
void audio_player_pause(void) {
if (current_state == AUDIO_STATE_PLAYING) {
Mix_PauseMusic();
current_state = AUDIO_STATE_PAUSED;
}
}
void audio_player_resume(void) {
if (current_state == AUDIO_STATE_PAUSED) {
Mix_ResumeMusic();
current_state = AUDIO_STATE_PLAYING;
}
}
audio_state_t audio_player_get_state(void) {
// Check if music finished playing
if (current_state == AUDIO_STATE_PLAYING && !Mix_PlayingMusic()) {
current_state = AUDIO_STATE_STOPPED;
if (current_music) {
Mix_FreeMusic(current_music);
current_music = NULL;
}
current_filename[0] = '\0';
}
return current_state;
}
void audio_player_set_volume(uint8_t volume) {
current_volume = volume > 100 ? 100 : volume;
Mix_VolumeMusic((int)(current_volume * MIX_MAX_VOLUME / 100));
}
const char *audio_player_get_filename(void) {
return current_filename[0] ? current_filename : NULL;
}
const char *audio_player_get_title(void) {
if (current_display_title[0]) return current_display_title;
return current_filename[0] ? current_filename : NULL;
}
void audio_player_update(void) {
// Check if music finished
audio_player_get_state();
}
uint32_t audio_player_get_position_ms(void) {
if (!current_music || current_state == AUDIO_STATE_STOPPED) return 0;
double pos = Mix_GetMusicPosition(current_music);
if (pos < 0) return 0;
return (uint32_t)(pos * 1000.0);
}
uint32_t audio_player_get_duration_ms(void) {
return current_metadata.duration_ms;
}
uint8_t audio_player_get_progress(void) {
uint32_t duration = current_metadata.duration_ms;
if (duration == 0) return 0;
uint32_t position = audio_player_get_position_ms();
uint32_t progress = (position * 100) / duration;
return (uint8_t)(progress > 100 ? 100 : progress);
}
bool audio_player_seek_ms(uint32_t position_ms) {
if (!current_music || current_state == AUDIO_STATE_STOPPED) return false;
return Mix_SetMusicPosition(position_ms / 1000.0) == 0;
}