16#include "id3dependencies/ByteStream/include/byteStream.h"
17#include "id3dependencies/ByteStream/include/byteInt.h"
30 if (filePath == NULL) {
38 fp = fopen(filePath,
"rb");
80static int internal_id3v1CharsToStructUint8(
const char *src, uint8_t *dest) {
84 const int len = (int) strlen(src);
87 memcpy(dest, (uint8_t *) src, wLen);
101 return (tag == NULL) ? 0 : internal_id3v1CharsToStructUint8(title, tag->
title);
112 return (tag == NULL) ? 0 : internal_id3v1CharsToStructUint8(artist, tag->
artist);
123 return (tag == NULL) ? 0 : internal_id3v1CharsToStructUint8(album, tag->
albumTitle);
150 return (tag == NULL) ? 0 : internal_id3v1CharsToStructUint8(comment, tag->
comment);
193 if (tag1 == NULL || tag2 == NULL) {
241 return "Classic Rock\0";
267 return "Rhythm and Blues\0";
277 return "Industrial\0";
279 return "Alternative\0";
283 return "Death Metal\0";
287 return "Soundtrack\0";
289 return "Euro-Techno\0";
297 return "Jazz and Funk\0";
303 return "Classical\0";
305 return "Instrumental\0";
313 return "Sound Clip\0";
319 return "Alternative Rock\0";
329 return "Meditative\0";
331 return "Instrumental Pop\0";
333 return "Instrumental Rock\0";
341 return "Techno Industrial\0";
343 return "Electronic\0";
347 return "Eurodance\0";
351 return "Southern Rock\0";
361 return "Christian Rap\0";
365 return "Jungle Music\0";
367 return "Native US\0";
373 return "Psychedelic\0";
377 return "Showtunes\0";
385 return "Acid Punk\0";
387 return "Acid Jazz\0";
395 return "Rock and Roll\0";
397 return "Hard Rock\0";
401 return "Folk Rock\0";
403 return "National Folk\0";
407 return "Fast Fusion\0";
417 return "Bluegrass\0";
419 return "Avantgarde\0";
421 return "Gothic Rock\0";
423 return "Progressive Rock\0";
425 return "Psychedelic Rock\0";
427 return "Symphonic Rock\0";
429 return "Slow Rock\0";
435 return "Easy Listening\0";
447 return "Chamber Music\0";
453 return "Booty Bass\0";
457 return "Porn Groove\0";
473 return "Power Ballad\0";
475 return "Rhythmic Soul\0";
477 return "Freestyle\0";
481 return "Punk Rock\0";
483 return "Drum Solo\0";
485 return "A Cappella\0";
487 return "Euro-House\0";
489 return "Dance Hall\0";
491 return "Goa Music\0";
493 return "Drum and Bass\0";
495 return "Club-House\0";
497 return "Hardcore Techno\0";
505 return "Negerpunk\0";
507 return "Polsk Punk\0";
511 return "Christian Gangsta Rap\0";
513 return "Heavy Metal\0";
515 return "Black Metal\0";
517 return "Crossover\0";
519 return "Contemporary Christian\0";
521 return "Christian Rock\0";
527 return "Thrash Metal\0";
543 return "Breakbeat\0";
547 return "Downtempo\0";
557 return "Electroclash\0";
561 return "Experimental\0";
571 return "Industro-Goth\0";
575 return "Krautrock\0";
577 return "Leftfield\0";
581 return "Math Rock\0";
583 return "New Romantic\0";
585 return "Nu-Breakz\0";
587 return "Post-Punk\0";
589 return "Post-Rock\0";
591 return "Psytrance\0";
595 return "Space Rock\0";
597 return "Trop Rock\0";
599 return "World Music\0";
601 return "Neoclassical\0";
603 return "Audiobook\0";
605 return "Audio Theatre\0";
607 return "Neue Deutsche Welle\0";
611 return "Indie-Rock\0";
617 return "Garage Rock\0";
718 json = calloc(memCount,
sizeof(
char));
719 memcpy(json,
"{}\0", memCount);
723 memCount += snprintf(
725 "{\"title\":\"%s\",\"artist\":\"%s\",\"album\":\"%s\",\"year\":%d,\"track\":%d,\"comment\":\"%s\",\"genreNumber\":%d,\"genre\":\"%s\"}",
735 json = calloc(memCount + 1,
sizeof(
char));
736 (void) snprintf(json, memCount,
737 "{\"title\":\"%s\",\"artist\":\"%s\",\"album\":\"%s\",\"year\":%d,\"track\":%d,\"comment\":\"%s\",\"genreNumber\":%d,\"genre\":\"%s\"}",
760 if (filePath == NULL || tag == NULL) {
765 unsigned char byte = 0x00;
777 n = (int) log10(tag->
year) + 1;
779 tmp = calloc(n,
sizeof(
char));
781 for (
int i = n - 1; i >= 0; --i, yearW /= 10) {
782 tmp[i] = (char) ((yearW % 10) +
'0');
792 if (tag->
track <= 0xFF && tag->
track > 0x00) {
793 byteStreamSeek(stream, -1, SEEK_CUR);
794 byte = (
unsigned char) tag->
track & 0xFF;
795 byteStreamWrite(stream, &
byte, 1);
799 byte = (
unsigned char) tag->
genre & 0xFF;
800 byteStreamWrite(stream, &
byte, 1);
802 byteStreamRewind(stream);
804 fp = fopen(filePath,
"r+b");
807 fp = fopen(filePath,
"wb");
809 byteStreamDestroy(stream);
813 if ((fwrite(byteStreamCursor(stream), 1,
ID3V1_MAX_SIZE, fp)) == 0) {
814 byteStreamDestroy(stream);
820 (void) fseek(fp, 0, SEEK_END);
821 const long index = ftell(fp);
829 (void) fseek(fp, 0, SEEK_END);
830 if (fwrite(byteStreamCursor(stream), 1,
ID3V1_MAX_SIZE, fp) != 0) {
831 byteStreamDestroy(stream);
836 byteStreamDestroy(stream);
843 byteStreamDestroy(stream);
850 if (fseek(fp, 0, SEEK_END) != 0) {
851 byteStreamDestroy(stream);
857 byteStreamDestroy(stream);
864 if ((fwrite(byteStreamCursor(stream), 1,
ID3V1_MAX_SIZE, fp)) == 0) {
865 byteStreamDestroy(stream);
871 byteStreamDestroy(stream);
Id3v1Tag * id3v1CopyTag(Id3v1Tag *toCopy)
Creates a deep copy of an Id3v1Tag structure.
char * id3v1ReadComment(const Id3v1Tag *tag)
Reads the comment member from an Id3v1Tag.
int id3v1ReadTrack(const Id3v1Tag *tag)
Reads a track number from a tag.
char * id3v1GenreFromTable(Genre val)
Converts a Genre enum value to it's string representation.
int id3v1WriteArtist(const char *artist, Id3v1Tag *tag)
Writes an artist to an Id3v1Tag.
char * id3v1ReadArtist(const Id3v1Tag *tag)
Reads the artist member from an Id3v1Tag.
int id3v1WriteGenre(Genre genre, Id3v1Tag *tag)
Writes a Genre to an Id3v1Tag.
Genre id3v1ReadGenre(const Id3v1Tag *tag)
Reads a Genre from a tag.
int id3v1WriteTagToFile(const char *filePath, const Id3v1Tag *tag)
Writes/Overwrites an Id3v1Tag to the bottom of a file .
char * id3v1ToJSON(const Id3v1Tag *tag)
Converts an Id3v1Tag to a JSON string representation.
int id3v1WriteComment(const char *comment, Id3v1Tag *tag)
Writes a comment to an Id3v1Tag.
char * id3v1ReadTitle(const Id3v1Tag *tag)
Reads the title member from an Id3v1Tag.
int id3v1ReadYear(const Id3v1Tag *tag)
Reads the year member from an Id3v1Tag.
int id3v1WriteAlbum(const char *album, Id3v1Tag *tag)
Writes an album to an Id3v1Tag.
int id3v1WriteTitle(const char *title, Id3v1Tag *tag)
Writes a title to an Id3v1Tag.
Id3v1Tag * id3v1TagFromFile(const char *filePath)
Creates an Id3v1Tag from a provided file path.
int id3v1WriteTrack(int track, Id3v1Tag *tag)
Writes a track number to an Id3v1Tag.
int id3v1WriteYear(int year, Id3v1Tag *tag)
Writes a year to an Id3v1Tag.
bool id3v1CompareTag(const Id3v1Tag *tag1, const Id3v1Tag *tag2)
Compares two Id3v1Tag structures for equality.
char * id3v1ReadAlbum(const Id3v1Tag *tag)
Reads the album member from an Id3v1Tag.
char * id3v1GenreFromTable(Genre val)
Converts a Genre enum value to it's string representation.
Id3v1Tag * id3v1TagFromBuffer(uint8_t *buffer)
Parses an ID3V1_MAX_SIZE buffer into an Id3v1Tag structure.
bool id3v1HasTag(const uint8_t *buffer)
Checks if a buffer contains a valid ID3v1 tag identifier.
Id3v1Tag * id3v1CreateTag(uint8_t *title, uint8_t *artist, uint8_t *albumTitle, int year, int track, uint8_t *comment, Genre genre)
Creates and allocates a new Id3v1Tag structure.
#define ID3V1_YEAR_SIZE
Size in bytes of the year field in ID3v1 tags (4 bytes)
#define ID3V1_MAX_SIZE
Total size in bytes of a complete ID3v1/ID3v1.1 tag on disk (128 bytes)
#define ID3V1_FIELD_SIZE
Size in bytes of text fields (title, artist, album, comment) in ID3v1 tags (30 bytes)
@ SPACE_GENRE
Space Audio.
@ TECHNO_INDUSTRIAL_GENRE
Techno Industrial Audio.
@ GOSPEL_GENRE
Gospel Audio.
@ DRUM_AND_BASS_GENRE
Drum and Bass Audio.
@ FOLKLORE_GENRE
Folklore Audio.
@ CHAMBER_MUSIC_GENRE
Chamber Audio.
@ ECLECTIC_GENRE
Eclectic Audio.
@ REVIVAL_GENRE
Revival Audio.
@ WORLD_MUSIC_GENRE
World Music Audio.
@ DANCE_GENRE
Dance Audio.
@ HOUSE_GENRE
House Audio.
@ JPOP_GENRE
Japanese Pop Audio.
@ TROP_ROCK_GENRE
Trop Rock Audio.
@ CHRISTIAN_ROCK_GENRE
Christian Rock Audio.
@ ANIME_GENRE
Anime Audio.
@ DOWNTEMPO_GENRE
Down tempo Audio.
@ CLASSICAL_GENRE
Classical Audio.
@ KRAUTROCK_GENRE
Krautrock Audio.
@ MERENGUE_GENRE
Merengue Audio.
@ MUSICAL_GENRE
Audio from Musicals.
@ OTHER_GENRE
Other Music Genres not Defined.
@ DUBSTEP_GENRE
Dubstep Audio.
@ JAZZ_AND_FUNK_GENRE
Jazz and Funk Audio.
@ NEGERPUNK_GENRE
Neger Punk Audio.
@ PORN_GROOVE_GENRE
Porn Groove Audio.
@ DRUM_SOLO_GENRE
Drum Solo Audio.
@ SHOWTUNES_GENRE
Theatre Show Tunes Audio.
@ NATIVE_US_GENRE
Native Audio.
@ SWING_GENRE
Swing Audio.
@ INDUSTRO_GOTH_GENRE
Industro Goth Audio.
@ GOTHIC_ROCK_GENRE
Gothic Rock Audio.
@ AMBIENT_GENRE
Ambient Audio.
@ TRIBAL_GENRE
Tribal Audio.
@ SYNTHPOP_GENRE
Synth Pop Audio.
@ ROCKNROLL_GENRE
Rock and Roll Audio.
@ EXPERIMENTAL_GENRE
Experimental Audio.
@ GLOBAL_GENRE
Global Audio.
@ NEUE_DEUTSCHE_WELLE_GENRE
Neue Deutsche Welle Audio.
@ PSYCHEDELIC_GENRE
Psychedelic Audio.
@ BIG_BEAT_GENRE
Big Beat Audio.
@ SAMBA_GENRE
Samba Audio.
@ ETHNIC_GENRE
Ethnic Audio.
@ SALSA_GENRE
Salsa Audio.
@ SYMPHONY_GENRE
Symphony Audio.
@ LO_FI_GENRE
Lo-Fi Audio.
@ ELECTRONIC_GENRE
Electronic Audio.
@ PROGRESSIVE_ROCK_GENRE
Progressive Audio.
@ GARAGE_ROCK_GENRE
Garage Rock Audio.
@ GARAGE_GENRE
Garage Audio.
@ NOISE_GENRE
Noise Audio.
@ SONATA_GENRE
Sonata Audio.
@ EURO_TECHNO_GENRE
European Techno Audio.
@ CHANSON_GENRE
Chanson Audio.
@ ELECTROCLASH_GENRE
Electro Clash Audio.
@ CELTIC_GENRE
Celtic Audio.
@ HARDCORE_TECHNO_GENRE
Hardcore Techno Audio.
@ ACID_PUNK_GENRE
Acid Punk Audio.
@ BLACK_METAL_GENRE
Black Metal Audio.
@ CROSSOVER_GENRE
Crossover Audio.
@ CHORUS_GENRE
Chorus Audio.
@ DANCE_HALL_GENRE
Dance Hall Audio.
@ BLUEGRASS_GENRE
Blue Grass Audio.
@ BAROQUE_GENRE
Baroque Audio.
@ INSTRUMENTAL_GENRE
Instrumental Audio.
@ POST_PUNK_GENRE
Post Punk Audio.
@ BALLAD_GENRE
Ballad Audio.
@ EASY_LISTENING_GENRE
Easy Listening Audio.
@ NEW_WAVE_GENRE
New Wave Audio.
@ GOTHIC_GENRE
Gothic Audio.
@ TRANCE_GENRE
Trance Audio.
@ PRANKS_GENRE
Pranks Audio.
@ RHYTHMIC_SOUL_GENRE
Rhythmic Soul Audio.
@ POP_FOLK_GENRE
Pop Folk Audio.
@ INSTRUMENTAL_POP_GENRE
Instrumental Pop Audio.
@ BRITPOP_GENRE
Britpop Audio.
@ CLUB_HOUSE_GENRE
Club House Audio.
@ NEOCLASSICAL_GENRE
Neo Classical Audio.
@ AUDIOBOOK_GENRE
Audio Book.
@ G_FUNK_GENRE
G-Funk Audio.
@ BREAKBEAT_GENRE
Beark Beat Audio.
@ PSYTRANCE_GENRE
Psytrance Audio.
@ POLKA_GENRE
Polka Audio.
@ DARKWAVE_GENRE
Darkwave Audio.
@ ILLBIENT_GENRE
Illbient Audio.
@ HARD_ROCK_GENRE
Hard Rock Audio.
@ CHRISTIAN_RAP_GENRE
Christian Rap Audio.
@ SPEECH_GENRE
Speech Audio.
@ INDIE_ROCK_GENRE
Indie Rock Audio.
@ MATH_ROCK_GENRE
Math Rock Audio.
@ ACOUSTIC_GENRE
Acoustic Audio.
@ FAST_FUSION_GENRE
Fast Fusion Audio.
@ HEAVY_METAL_GENRE
Heavy Metal Audio.
@ PRIMUS_GENRE
Primus Audio.
@ SOUNDTRACK_GENRE
Soundtracks and OSTs from other media.
@ FREESTYLE_GENRE
Free Style Audio.
@ LATIN_GENRE
Latin Audio.
@ ACID_JAZZ_GENRE
Acid Jazz Audio.
@ TERROR_GENRE
Terror Audio.
@ ART_ROCK_GENRE
Art Rock Audio.
@ RHYTHM_AND_BLUES_GENRE
Rythem and Blues Audio.
@ TOP_40_GENRE
Top 40 Chart Hits.
@ ALTERNATIVE_GENRE
Alternative Audio.
@ A_CAPPELLA_GENRE
Acappella Audio.
@ COMEDY_GENRE
Comedy Audio.
@ COUNTRY_GENRE
Country Audio.
@ GRUNGE_GENRE
Grunge Audio.
@ PSYCHEDELIC_ROCK_GENRE
Psychedelic Audio.
@ JUNGLE_MUSIC_GENRE
Jungle Audio.
@ LEFTFIELD_GENRE
LeftField Audio.
@ INSTRUMENTAL_ROCK_GENRE
Instrumental Rock Audio.
@ NEW_AGE_GENRE
New Age Audio.
@ NU_BREAKZ_GENRE
Nu-Breakz Audio.
@ SPACE_ROCK_GENRE
Space Rock Audio.
@ REGGAE_GENRE
Reggae Audio.
@ OLDIES_GENRE
Oldies Music, pre-1950s.
@ SATIRE_GENRE
Satire Audio.
@ TECHNO_GENRE
Techno Audio.
@ PODCAST_GENRE
Podcast Audio.
@ ALTERNATIVE_ROCK_GENRE
Alternative Rock Audio.
@ BEBOP_GENRE
Bebop Audio.
@ TRAILER_GENRE
Audio From Media Trailers.
@ INDUSTRIAL_GENRE
Industrial Audio.
@ EURO_HOUSE_GENRE
European House Audio.
@ POWER_BALLAD_GENRE
Power Ballad Audio.
@ NEW_ROMANTIC_GENRE
New Romantic Audio.
@ RETRO_GENRE
Retro Audio.
@ HIP_HOP_GENRE
Hip-Hop Audio.
@ CLASSIC_ROCK_GENRE
Classic Rock.
@ DEATH_METAL_GENRE
Death Metal Audio.
@ FUSION_GENRE
Fusion of Genres.
@ DISCO_GENRE
Disco Audio.
@ JAM_BAND_GENRE
Jam Band Audio.
@ HUMOUR_GENRE
Humour Audio.
@ GAME_GENRE
Video Game Audio.
@ SLOW_JAM_GENRE
Slow Jam Audio.
@ SYMPHONIC_ROCK_GENRE
Symphonic Rock Audio.
@ CHILLOUT_GENRE
Chillout Audio.
@ POP_FUNK_GENRE
Funk Pop Audio.
@ SOUND_CLIP_GENRE
Sound Clip Audio.
@ TRIP_HOP_GENRE
Trip Audio.
@ VOCAL_GENRE
Vocal Audio.
@ MEDITATIVE_GENRE
Meditative Audio.
@ SHOEGAZE_GENRE
Shoegaze Audio.
@ SOUTHERN_ROCK_GENRE
Southern Rock Audio.
@ POLSK_PUNK_GENRE
Polsk Punk Audio.
@ AVANTGARDE_GENRE
Avantgarde Audio.
@ FOLK_ROCK_GENRE
Folk Rock Audio.
@ OPERA_GENRE
Opera Audio.
@ SLOW_ROCK_GENRE
Slow Rock Audio.
@ GOA_MUSIC_GENRE
GOA Audio.
@ CONTEMPORARY_CHRISTIAN_GENRE
Contemporary Christian Audio.
@ PUNK_ROCK_GENRE
Punk Rock Audio.
@ BOOTY_BASS_GENRE
Booty Bass Audio.
@ ELECTRO_GENRE
Electro Audio.
@ THRASH_METAL_GENRE
Thrash Metal Audio.
@ EURODANCE_GENRE
European Dance Audio.
@ ABSTRACT_GENRE
Abstract Audio.
@ DREAM_GENRE
Dream Audio.
@ CABARET_GENRE
Cabaret Audio.
@ CHRISTIAN_GANGSTA_RAP_GENRE
Christian Gangsta Rap Audio.
@ INDIE_GENRE
Indie Audio.
@ GANGSTA_GENRE
Gangsta Audio.
@ LOUNGE_GENRE
Lounge Audio.
@ TANGO_GENRE
Tangp Audio.
@ POST_ROCK_GENRE
Post Rock Audio.
@ BIG_BAND_GENRE
Big Band Audio.
@ NATIONAL_FOLK_GENRE
National Folk Audio.
@ BLUES_GENRE
Blues Audio.
@ PSYBIENT_GENRE
Psybient Audio.
@ METAL_GENRE
Metal Audio.
@ AUDIO_THEATRE_GENRE
Audio Theatre.
#define ID3V1_TAG_ID_SIZE
Size in bytes of the ID3v1 tag identifier "TAG" (3 bytes)
enum _Genre Genre
ID3v1 genre enumeration with Winamp extensions (genres 0-191).
struct _Id3v1Tag Id3v1Tag
ID3v1/ID3v1.1 tag structure containing all metadata fields.
int track
Track number (0 if not present, ID3v1.1 only)
Genre genre
Genre value (0-191, maps to Genre enum)
uint8_t artist[ID3V1_FIELD_SIZE]
Artist name (ID3V1_FIELD_SIZE bytes, null-padded)
uint8_t comment[ID3V1_FIELD_SIZE]
Comment text (ID3V1_FIELD_SIZE bytes, null-padded; ID3V1_FIELD_SIZE - 2 bytes if track number present...
uint8_t title[ID3V1_FIELD_SIZE]
Song title (ID3V1_FIELD_SIZE bytes, null-padded)
int year
Release year (4-digit integer)
uint8_t albumTitle[ID3V1_FIELD_SIZE]
Album title (ID3V1_FIELD_SIZE bytes, null-padded)