Login
1 branch 0 tags
Ben (Desktop/Arch) Put backlight controls into separate source file e41d4ae 1 month ago 76 Commits
moon / src / audio_metadata.c
#include "audio_metadata.h"
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// Implemented in metadata/
bool parse_m4a(const char* path, audio_metadata_t* meta);
bool parse_mp3(const char* path, audio_metadata_t* meta);
bool parse_wav(const char* path, audio_metadata_t* meta);
bool parse_flac(const char* path, audio_metadata_t* meta);
bool parse_ogg(const char* path, audio_metadata_t* meta);

// Helper to get file extension (lowercase)
static const char* get_extension(const char* path) {
	const char* dot = strrchr(path, '.');
	return dot ? dot + 1 : "";
}

// Helper to extract filename without extension for fallback title
static void extract_filename(const char* path, char* buf, size_t buf_size) {
	const char* name = strrchr(path, '/');
	name = name ? name + 1 : path;

	const char* dot = strrchr(name, '.');
	size_t len = dot ? (size_t)(dot - name) : strlen(name);
	if (len >= buf_size) {
		len = buf_size - 1;
	}

	memcpy(buf, name, len);
	buf[len] = '\0';
}

bool audio_metadata_get(const char* path, audio_metadata_t* meta) {
	if (!path || !meta) {
		return false;
	}

	// Initialize metadata
	memset(meta, 0, sizeof(*meta));

	// Set filename as fallback title
	extract_filename(path, meta->title, sizeof(meta->title));

	// Get extension
	const char* ext = get_extension(path);

	// Dispatch to format-specific parser
	bool success = false;

	if (strcasecmp(ext, "mp3") == 0) {
		success = parse_mp3(path, meta);
	} else if (strcasecmp(ext, "m4a") == 0 || strcasecmp(ext, "m4b") == 0 ||
	           strcasecmp(ext, "mp4") == 0 || strcasecmp(ext, "aac") == 0) {
		success = parse_m4a(path, meta);
	} else if (strcasecmp(ext, "wav") == 0) {
		success = parse_wav(path, meta);
	} else if (strcasecmp(ext, "flac") == 0) {
		success = parse_flac(path, meta);
	} else if (strcasecmp(ext, "ogg") == 0 || strcasecmp(ext, "opus") == 0 ||
	           strcasecmp(ext, "opu") == 0) {
		success = parse_ogg(path, meta);
	}

	// If parsing failed but we have a filename, still return partial success
	if (!success && meta->title[0] != '\0') {
		meta->valid = false;  // Indicate metadata is incomplete
	}

	return success;
}