14
juillet
2012
Lecture & écriture des tags mp3 en Vala (suite)
juillet
2012
Un article de Rachel
Pas de commentaires
Voilà, j’ai bien avancé sur le sujet. On peut maintenant lire tous les tags et écrire tous les tags de type string & int. malheureusement je coince sur l’édition des images (de type uint8[]).
voici le code pour les tags Id3V2 :
using System;
namespace TagLib.Id3V2
{
public class File
{
uint8[] data;
TagLib.Id3V2.Header header;
List<Frame> frames;
TagLib.Id3V2.Tag tag;
Bytes raw_data;
File(){}
public static File Create(string filename)
{
File file = new File();
FileUtils.get_data (filename, out file.data);
for(int i=0; i<450; i++)
stdout.printf(file.data[i].to_string()+"="+((char)file.data[i]).to_string()+" : ");
file.header = new TagLib.Id3V2.Header(new Bytes(file.data));
file.frames = new List<Frame>();
Frame frame = new Frame(file.header.RawData);
for(int i=0; i<23; i++){
file.frames.append(frame);
if(frame.Type=="APIC"){
break;
}
frame = new Frame(frame.NextData);
}
file.raw_data = frame.NextData;
file.tag = new TagLib.Id3V2.Tag(file.frames);
return file;
}
public TagLib.Id3V2.Tag Tag {
get{return tag;}
}
public void Save(TagLib.Id3V2.Tag tags)
{
ByteArray array = new ByteArray();
ByteArray array2;
foreach(Frame frame in frames)
{
array2 = new ByteArray();
switch(frame.Type){
case "TIT2":
append(ref array2, tags.Title, "TIT2");
break;
case "TALB":
append(ref array2, tags.Album, "TALB");
break;
case "TPE1":
append(ref array2, tags.JoinedPerformers, "TPE1");
break;/*
case "TYER":
append(ref array2, tags.Year.to_string(), "TYER");
break;
case "TCON":
append(ref array2, tags.JoinedGenres, "TCON");
break;*/
case "TRCK":
append(ref array2, "1/1", "TRCK");
break;
}
array.append(array2.data);
}
array.prepend(Convert.ToBytes.from_integer(array.data.length));
array.prepend(new uint8[]{(uint8)'I',(uint8)'D',(uint8)'3',3,0,0});
array.append(raw_data.get_data());
FileUtils.set_data("temp.mp3",array.data);
}
void append(ref ByteArray array, string string_value, string type)
{
array.append(new uint8[]{0,0,1,255,254});
for(int i=0; i<string_value.length; i++){
array.append(new uint8[]{(uint8)string_value.get_char(i),0});
}
array.prepend(Convert.ToBytes.from_integer(array.data.length-2));
array.prepend(Convert.ToBytes.from_string(type));
}
}
public class Tag
{
string title;
string album;
string performers;
string genres;
string[] array_genre;
string[] array_performer;
int track;
int track_count;
int year;
Picture[] pictures;
public Tag(List<Frame> frames)
{
List<Picture> list = new List<Picture>();
foreach(Frame frame in frames)
{
Bytes data = frame.Data;
switch(frame.Type)
{
case "TIT2":
title = Convert.ToString.from_bytes(data.slice(3,data.length));
break;
case "TALB":
album = Convert.ToString.from_bytes(data.slice(3,data.length));
break;
case "TPE1":
performers = Convert.ToString.from_bytes(data.slice(3,data.length));
array_performer = performers.split("/",0);
break;
case "TRCK":
string[] trck = Convert.ToString.from_bytes(data.slice(3,data.length)).split("/",0);
track = int.parse(trck[0]);
track_count = int.parse(trck[1]);
break;
case "TCON":
genres = Convert.ToString.from_bytes(data.slice(3,data.length));
array_genre = genres.split("/",0);
break;
case "TYER":
year = int.parse(Convert.ToString.from_bytes(data.slice(3,data.length)));
break;
case "APIC":
list.append(new Picture(frame.RawData));
break;
}
}
pictures = new Picture[list.length()];
for(int i=0;i<list.length();i++)
{
pictures[i] = list.nth_data(i);
}
}
public string Title {get{return title;} set{title = value;}}
public string Album {get{return album;} set{album = value;}}
public string JoinedGenres {get{return genres;}}
public string[] Genres{
get{return array_genre;}
set{genres = string.joinv("/",value);}
}
public string FirstGenre {get{return array_genre[0];}}
public string JoinedPerformers {get{return performers;}}
public string[] Performers {
get{return array_performer;}
set{performers = string.joinv("/",value);}
}
public string FirstPerformer {get{return array_performer[0];}}
public int Track {get{return track;} set{track = value;}}
public int TrackCount {get{return track_count;} set{track_count = value;}}
public int Year {get{return year;} set{year = value;}}
public Picture[] Pictures {get{return pictures;}}
}
public class Picture
{
uint8[] buffer;
uint8[] description;
string mime_type;
Bytes raw_data;
public Picture(Bytes data)
{
raw_data = data;
for(int i=0;i<data.length;i++)
{
if(data[i]==255&&data[i+1]==216&&data[i+2]==255&&data[i+3]==224)
{
buffer = data.slice(i,data.length+1).get_data();
description = data.slice(8,i).get_data();
mime_type = "image/jpeg";
}
}
}
public string MimeType {get{return mime_type;}}
public uint8[] Buffer {get{return buffer;} set{buffer = value;}}
public uint8[] Description {get{return description;}}
public Bytes RawData {
get{
ByteArray array = new ByteArray();
array.append(description);
array.append(buffer);
array.prepend(Convert.ToBytes.from_integer(array.data.length-2));
array.prepend(Convert.ToBytes.from_string("APIC"));
raw_data = new Bytes(array.data);
return raw_data;
}
}
}
public class Header
{
uint8[] data;
Bytes raw_data;
int size;
public Header(Bytes bytes)
{
data = bytes.slice(0,9).get_data();
size = Convert.ToInt32.from_bytes(bytes.slice(6,9));
raw_data = bytes.slice(10,bytes.length-1);
}
public int Size {get{return size;}}
public Bytes RawData {get{return raw_data;}}
}
public class Frame
{
string type;
int size;
Bytes data;
Bytes next_data;
Bytes raw_data;
public Frame(Bytes bytes)
{
type = Convert.ToString.from_bytes(bytes.slice(0,4));
List<uint8> list = new List<uint8>();
list.append(bytes[4]);
list.append(bytes[5]);
list.append(bytes[6]);
list.append(bytes[7]);
size = Convert.ToInt32.from_list_uint8(list);
data = bytes.slice(10,9+size);
raw_data = bytes.slice(0,9+size);
next_data = bytes.slice(10+size,bytes.length-1);
if(type=="APIC"){
for(int i=0; i<30; i++)
stdout.printf(bytes[size+i].to_string()+"="+((char)bytes[i+size]).to_string()+" : ");
stdout.printf("\n");
}
}
public string Type {get{return type;}}
public int Size {get{return size;}}
public Bytes Data {get{return data;}}
public Bytes RawData {get{return raw_data;}}
public Bytes NextData {get{return next_data;}}
}
}
namespace TagLib.Id3V2
{
public class File
{
uint8[] data;
TagLib.Id3V2.Header header;
List<Frame> frames;
TagLib.Id3V2.Tag tag;
Bytes raw_data;
File(){}
public static File Create(string filename)
{
File file = new File();
FileUtils.get_data (filename, out file.data);
for(int i=0; i<450; i++)
stdout.printf(file.data[i].to_string()+"="+((char)file.data[i]).to_string()+" : ");
file.header = new TagLib.Id3V2.Header(new Bytes(file.data));
file.frames = new List<Frame>();
Frame frame = new Frame(file.header.RawData);
for(int i=0; i<23; i++){
file.frames.append(frame);
if(frame.Type=="APIC"){
break;
}
frame = new Frame(frame.NextData);
}
file.raw_data = frame.NextData;
file.tag = new TagLib.Id3V2.Tag(file.frames);
return file;
}
public TagLib.Id3V2.Tag Tag {
get{return tag;}
}
public void Save(TagLib.Id3V2.Tag tags)
{
ByteArray array = new ByteArray();
ByteArray array2;
foreach(Frame frame in frames)
{
array2 = new ByteArray();
switch(frame.Type){
case "TIT2":
append(ref array2, tags.Title, "TIT2");
break;
case "TALB":
append(ref array2, tags.Album, "TALB");
break;
case "TPE1":
append(ref array2, tags.JoinedPerformers, "TPE1");
break;/*
case "TYER":
append(ref array2, tags.Year.to_string(), "TYER");
break;
case "TCON":
append(ref array2, tags.JoinedGenres, "TCON");
break;*/
case "TRCK":
append(ref array2, "1/1", "TRCK");
break;
}
array.append(array2.data);
}
array.prepend(Convert.ToBytes.from_integer(array.data.length));
array.prepend(new uint8[]{(uint8)'I',(uint8)'D',(uint8)'3',3,0,0});
array.append(raw_data.get_data());
FileUtils.set_data("temp.mp3",array.data);
}
void append(ref ByteArray array, string string_value, string type)
{
array.append(new uint8[]{0,0,1,255,254});
for(int i=0; i<string_value.length; i++){
array.append(new uint8[]{(uint8)string_value.get_char(i),0});
}
array.prepend(Convert.ToBytes.from_integer(array.data.length-2));
array.prepend(Convert.ToBytes.from_string(type));
}
}
public class Tag
{
string title;
string album;
string performers;
string genres;
string[] array_genre;
string[] array_performer;
int track;
int track_count;
int year;
Picture[] pictures;
public Tag(List<Frame> frames)
{
List<Picture> list = new List<Picture>();
foreach(Frame frame in frames)
{
Bytes data = frame.Data;
switch(frame.Type)
{
case "TIT2":
title = Convert.ToString.from_bytes(data.slice(3,data.length));
break;
case "TALB":
album = Convert.ToString.from_bytes(data.slice(3,data.length));
break;
case "TPE1":
performers = Convert.ToString.from_bytes(data.slice(3,data.length));
array_performer = performers.split("/",0);
break;
case "TRCK":
string[] trck = Convert.ToString.from_bytes(data.slice(3,data.length)).split("/",0);
track = int.parse(trck[0]);
track_count = int.parse(trck[1]);
break;
case "TCON":
genres = Convert.ToString.from_bytes(data.slice(3,data.length));
array_genre = genres.split("/",0);
break;
case "TYER":
year = int.parse(Convert.ToString.from_bytes(data.slice(3,data.length)));
break;
case "APIC":
list.append(new Picture(frame.RawData));
break;
}
}
pictures = new Picture[list.length()];
for(int i=0;i<list.length();i++)
{
pictures[i] = list.nth_data(i);
}
}
public string Title {get{return title;} set{title = value;}}
public string Album {get{return album;} set{album = value;}}
public string JoinedGenres {get{return genres;}}
public string[] Genres{
get{return array_genre;}
set{genres = string.joinv("/",value);}
}
public string FirstGenre {get{return array_genre[0];}}
public string JoinedPerformers {get{return performers;}}
public string[] Performers {
get{return array_performer;}
set{performers = string.joinv("/",value);}
}
public string FirstPerformer {get{return array_performer[0];}}
public int Track {get{return track;} set{track = value;}}
public int TrackCount {get{return track_count;} set{track_count = value;}}
public int Year {get{return year;} set{year = value;}}
public Picture[] Pictures {get{return pictures;}}
}
public class Picture
{
uint8[] buffer;
uint8[] description;
string mime_type;
Bytes raw_data;
public Picture(Bytes data)
{
raw_data = data;
for(int i=0;i<data.length;i++)
{
if(data[i]==255&&data[i+1]==216&&data[i+2]==255&&data[i+3]==224)
{
buffer = data.slice(i,data.length+1).get_data();
description = data.slice(8,i).get_data();
mime_type = "image/jpeg";
}
}
}
public string MimeType {get{return mime_type;}}
public uint8[] Buffer {get{return buffer;} set{buffer = value;}}
public uint8[] Description {get{return description;}}
public Bytes RawData {
get{
ByteArray array = new ByteArray();
array.append(description);
array.append(buffer);
array.prepend(Convert.ToBytes.from_integer(array.data.length-2));
array.prepend(Convert.ToBytes.from_string("APIC"));
raw_data = new Bytes(array.data);
return raw_data;
}
}
}
public class Header
{
uint8[] data;
Bytes raw_data;
int size;
public Header(Bytes bytes)
{
data = bytes.slice(0,9).get_data();
size = Convert.ToInt32.from_bytes(bytes.slice(6,9));
raw_data = bytes.slice(10,bytes.length-1);
}
public int Size {get{return size;}}
public Bytes RawData {get{return raw_data;}}
}
public class Frame
{
string type;
int size;
Bytes data;
Bytes next_data;
Bytes raw_data;
public Frame(Bytes bytes)
{
type = Convert.ToString.from_bytes(bytes.slice(0,4));
List<uint8> list = new List<uint8>();
list.append(bytes[4]);
list.append(bytes[5]);
list.append(bytes[6]);
list.append(bytes[7]);
size = Convert.ToInt32.from_list_uint8(list);
data = bytes.slice(10,9+size);
raw_data = bytes.slice(0,9+size);
next_data = bytes.slice(10+size,bytes.length-1);
if(type=="APIC"){
for(int i=0; i<30; i++)
stdout.printf(bytes[size+i].to_string()+"="+((char)bytes[i+size]).to_string()+" : ");
stdout.printf("\n");
}
}
public string Type {get{return type;}}
public int Size {get{return size;}}
public Bytes Data {get{return data;}}
public Bytes RawData {get{return raw_data;}}
public Bytes NextData {get{return next_data;}}
}
}
et une classe d’utilité pour la conversion de données
namespace System
{
public class Convert
{
public class ToInt32
{
public static int from_bytes(Bytes bytes)
{
List<uint8> list = new List<uint8>();
foreach(uint8 u in bytes.get_data())
list.append(u);
return from_list_uint8(list);
}
public static int from_list_uint8(List<uint8> bytes)
{
int a = ((int)bytes.nth_data(0))*256*256*256;
int b = ((int)bytes.nth_data(1))*256*256;
int c = ((int)bytes.nth_data(2))*256;
int d = (int)bytes.nth_data(3);
int number = a+b+c+d;
return number;
}
}
public class ToString
{
public static string from_bytes(Bytes bytes)
{
string s = "";
List<uint8> list = new List<uint8>();
foreach(uint8 u in bytes.get_data())
if(u!=0)list.append(u);
foreach(uint8 u in list){
s += ((char)u).to_string();}
return s;
}
}
public class ToBytes
{
public static uint8[] from_string(string str)
{
uint8[] bytes = new uint8[str.length];
for(int i=0;i<str.length;i++){
bytes[i] = (uint8)str.get_char(i);
}
return bytes;
}
public static uint8[] from_integer(int n)
{
uint8[] bytes = new uint8[4];
bytes[0] = (uint8)(n/(256*256*256));
n = n-(int)bytes[0]*256*256*256;
bytes[1] = (uint8)(n/(256*256));
n = n-(int)bytes[1]*256*256;
bytes[2] = (uint8)(n/256);
n = n-(int)bytes[2]*256;
bytes[3] = (uint8)n;
return bytes;
}
}
}
}
{
public class Convert
{
public class ToInt32
{
public static int from_bytes(Bytes bytes)
{
List<uint8> list = new List<uint8>();
foreach(uint8 u in bytes.get_data())
list.append(u);
return from_list_uint8(list);
}
public static int from_list_uint8(List<uint8> bytes)
{
int a = ((int)bytes.nth_data(0))*256*256*256;
int b = ((int)bytes.nth_data(1))*256*256;
int c = ((int)bytes.nth_data(2))*256;
int d = (int)bytes.nth_data(3);
int number = a+b+c+d;
return number;
}
}
public class ToString
{
public static string from_bytes(Bytes bytes)
{
string s = "";
List<uint8> list = new List<uint8>();
foreach(uint8 u in bytes.get_data())
if(u!=0)list.append(u);
foreach(uint8 u in list){
s += ((char)u).to_string();}
return s;
}
}
public class ToBytes
{
public static uint8[] from_string(string str)
{
uint8[] bytes = new uint8[str.length];
for(int i=0;i<str.length;i++){
bytes[i] = (uint8)str.get_char(i);
}
return bytes;
}
public static uint8[] from_integer(int n)
{
uint8[] bytes = new uint8[4];
bytes[0] = (uint8)(n/(256*256*256));
n = n-(int)bytes[0]*256*256*256;
bytes[1] = (uint8)(n/(256*256));
n = n-(int)bytes[1]*256*256;
bytes[2] = (uint8)(n/256);
n = n-(int)bytes[2]*256;
bytes[3] = (uint8)n;
return bytes;
}
}
}
}
j’attends évidemment les questions et réponses, et de l’aide serait bienvenue