| 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 |
#ifdef HAVE_CONFIG_H |
|---|
| 26 |
# include "config.h" |
|---|
| 27 |
#endif |
|---|
| 28 |
|
|---|
| 29 |
#include <vlc_common.h> |
|---|
| 30 |
#include <vlc_plugin.h> |
|---|
| 31 |
#include <vlc_playlist.h> |
|---|
| 32 |
#include <vlc_meta.h> |
|---|
| 33 |
#include <vlc_demux.h> |
|---|
| 34 |
#include <vlc_strings.h> |
|---|
| 35 |
#include <vlc_charset.h> |
|---|
| 36 |
|
|---|
| 37 |
#ifdef WIN32 |
|---|
| 38 |
# include <io.h> |
|---|
| 39 |
#else |
|---|
| 40 |
# include <unistd.h> |
|---|
| 41 |
#endif |
|---|
| 42 |
|
|---|
| 43 |
#include <fileref.h> |
|---|
| 44 |
#include <tag.h> |
|---|
| 45 |
#include <tstring.h> |
|---|
| 46 |
#include <id3v2tag.h> |
|---|
| 47 |
#include <textidentificationframe.h> |
|---|
| 48 |
#include <tbytevector.h> |
|---|
| 49 |
#include <mpegfile.h> |
|---|
| 50 |
#include <attachedpictureframe.h> |
|---|
| 51 |
|
|---|
| 52 |
#include <flacfile.h> |
|---|
| 53 |
#include <flacproperties.h> |
|---|
| 54 |
#include <vorbisfile.h> |
|---|
| 55 |
#include <vorbisproperties.h> |
|---|
| 56 |
#include <xiphcomment.h> |
|---|
| 57 |
#include <uniquefileidentifierframe.h> |
|---|
| 58 |
#include <textidentificationframe.h> |
|---|
| 59 |
|
|---|
| 60 |
|
|---|
| 61 |
static int ReadMeta ( vlc_object_t * ); |
|---|
| 62 |
static int DownloadArt ( vlc_object_t * ); |
|---|
| 63 |
static int WriteMeta ( vlc_object_t * ); |
|---|
| 64 |
|
|---|
| 65 |
vlc_module_begin(); |
|---|
| 66 |
set_capability( "meta reader", 1000 ); |
|---|
| 67 |
set_callbacks( ReadMeta, NULL ); |
|---|
| 68 |
add_submodule(); |
|---|
| 69 |
set_capability( "art downloader", 50 ); |
|---|
| 70 |
set_callbacks( DownloadArt, NULL ); |
|---|
| 71 |
add_submodule(); |
|---|
| 72 |
set_capability( "meta writer", 50 ); |
|---|
| 73 |
set_callbacks( WriteMeta, NULL ); |
|---|
| 74 |
vlc_module_end(); |
|---|
| 75 |
|
|---|
| 76 |
using namespace TagLib; |
|---|
| 77 |
|
|---|
| 78 |
|
|---|
| 79 |
static void DetectImage( FileRef f, demux_t *p_demux ) |
|---|
| 80 |
{ |
|---|
| 81 |
demux_meta_t *p_demux_meta = (demux_meta_t *)p_demux->p_private; |
|---|
| 82 |
vlc_meta_t *p_meta = p_demux_meta->p_meta; |
|---|
| 83 |
int i_score = -1; |
|---|
| 84 |
|
|---|
| 85 |
|
|---|
| 86 |
|
|---|
| 87 |
|
|---|
| 88 |
static const int pi_cover_score[] = { |
|---|
| 89 |
0, |
|---|
| 90 |
5, |
|---|
| 91 |
4, |
|---|
| 92 |
20, |
|---|
| 93 |
19, |
|---|
| 94 |
13, |
|---|
| 95 |
18, |
|---|
| 96 |
17, |
|---|
| 97 |
16, |
|---|
| 98 |
14, |
|---|
| 99 |
15, |
|---|
| 100 |
9, |
|---|
| 101 |
8, |
|---|
| 102 |
7, |
|---|
| 103 |
10, |
|---|
| 104 |
11, |
|---|
| 105 |
6, |
|---|
| 106 |
1, |
|---|
| 107 |
12, |
|---|
| 108 |
3, |
|---|
| 109 |
2 |
|---|
| 110 |
}; |
|---|
| 111 |
|
|---|
| 112 |
if( MPEG::File *mpeg = dynamic_cast<MPEG::File *>(f.file() ) ) |
|---|
| 113 |
{ |
|---|
| 114 |
ID3v2::Tag *p_tag = mpeg->ID3v2Tag(); |
|---|
| 115 |
if( !p_tag ) |
|---|
| 116 |
return; |
|---|
| 117 |
ID3v2::FrameList list = p_tag->frameListMap()[ "APIC" ]; |
|---|
| 118 |
if( list.isEmpty() ) |
|---|
| 119 |
return; |
|---|
| 120 |
ID3v2::AttachedPictureFrame *p_apic; |
|---|
| 121 |
|
|---|
| 122 |
TAB_INIT( p_demux_meta->i_attachments, p_demux_meta->attachments ); |
|---|
| 123 |
for( ID3v2::FrameList::Iterator iter = list.begin(); |
|---|
| 124 |
iter != list.end(); iter++ ) |
|---|
| 125 |
{ |
|---|
| 126 |
p_apic = dynamic_cast<ID3v2::AttachedPictureFrame*>(*iter); |
|---|
| 127 |
input_attachment_t *p_attachment; |
|---|
| 128 |
|
|---|
| 129 |
const char *psz_name, *psz_mime, *psz_description; |
|---|
| 130 |
ByteVector p_data_taglib; const char *p_data; int i_data; |
|---|
| 131 |
|
|---|
| 132 |
psz_mime = p_apic->mimeType().toCString(true); |
|---|
| 133 |
psz_description = psz_name = p_apic->description().toCString(true); |
|---|
| 134 |
|
|---|
| 135 |
|
|---|
| 136 |
|
|---|
| 137 |
|
|---|
| 138 |
|
|---|
| 139 |
if( !strncmp( psz_mime, "PNG", 3 ) || |
|---|
| 140 |
!strncmp( psz_name, "\xC2\x89PNG", 5 ) ) |
|---|
| 141 |
{ |
|---|
| 142 |
msg_Warn( p_demux, |
|---|
| 143 |
"%s: Invalid picture embedded by broken iTunes version, " |
|---|
| 144 |
"you really shouldn't use this crappy software.", |
|---|
| 145 |
(const char *)f.file()->name() ); |
|---|
| 146 |
break; |
|---|
| 147 |
} |
|---|
| 148 |
|
|---|
| 149 |
p_data_taglib = p_apic->picture(); |
|---|
| 150 |
p_data = p_data_taglib.data(); |
|---|
| 151 |
i_data = p_data_taglib.size(); |
|---|
| 152 |
|
|---|
| 153 |
msg_Dbg( p_demux, "Found embedded art: %s (%s) is %i bytes", |
|---|
| 154 |
psz_name, psz_mime, i_data ); |
|---|
| 155 |
|
|---|
| 156 |
p_attachment = vlc_input_attachment_New( psz_name, psz_mime, |
|---|
| 157 |
psz_description, p_data, i_data ); |
|---|
| 158 |
TAB_APPEND_CAST( (input_attachment_t**), |
|---|
| 159 |
p_demux_meta->i_attachments, p_demux_meta->attachments, |
|---|
| 160 |
p_attachment ); |
|---|
| 161 |
|
|---|
| 162 |
if( pi_cover_score[p_apic->type()] > i_score ) |
|---|
| 163 |
{ |
|---|
| 164 |
i_score = pi_cover_score[p_apic->type()]; |
|---|
| 165 |
char *psz_url; |
|---|
| 166 |
if( asprintf( &psz_url, "attachment://%s", |
|---|
| 167 |
p_attachment->psz_name ) == -1 ) |
|---|
| 168 |
return; |
|---|
| 169 |
vlc_meta_SetArtURL( p_meta, psz_url ); |
|---|
| 170 |
free( psz_url ); |
|---|
| 171 |
} |
|---|
| 172 |
} |
|---|
| 173 |
} |
|---|
| 174 |
else |
|---|
| 175 |
if( Ogg::Vorbis::File *oggv = dynamic_cast<Ogg::Vorbis::File *>(f.file() ) ) |
|---|
| 176 |
{ |
|---|
| 177 |
Ogg::XiphComment *p_tag = oggv->tag(); |
|---|
| 178 |
if( !p_tag ) |
|---|
| 179 |
return; |
|---|
| 180 |
|
|---|
| 181 |
StringList mime_list = p_tag->fieldListMap()[ "COVERARTMIME" ]; |
|---|
| 182 |
StringList art_list = p_tag->fieldListMap()[ "COVERART" ]; |
|---|
| 183 |
|
|---|
| 184 |
|
|---|
| 185 |
if( mime_list.size() != 1 || art_list.size() != 1 ) |
|---|
| 186 |
return; |
|---|
| 187 |
|
|---|
| 188 |
input_attachment_t *p_attachment; |
|---|
| 189 |
|
|---|
| 190 |
const char *psz_name, *psz_mime, *psz_description; |
|---|
| 191 |
uint8_t *p_data; |
|---|
| 192 |
int i_data; |
|---|
| 193 |
|
|---|
| 194 |
psz_name = "cover"; |
|---|
| 195 |
psz_mime = mime_list[0].toCString(true); |
|---|
| 196 |
psz_description = "cover"; |
|---|
| 197 |
|
|---|
| 198 |
i_data = vlc_b64_decode_binary( &p_data, art_list[0].toCString(true) ); |
|---|
| 199 |
|
|---|
| 200 |
msg_Dbg( p_demux, "Found embedded art: %s (%s) is %i bytes", |
|---|
| 201 |
psz_name, psz_mime, i_data ); |
|---|
| 202 |
|
|---|
| 203 |
TAB_INIT( p_demux_meta->i_attachments, p_demux_meta->attachments ); |
|---|
| 204 |
p_attachment = vlc_input_attachment_New( psz_name, psz_mime, |
|---|
| 205 |
psz_description, p_data, i_data ); |
|---|
| 206 |
free( p_data ); |
|---|
| 207 |
|
|---|
| 208 |
TAB_APPEND_CAST( (input_attachment_t**), |
|---|
| 209 |
p_demux_meta->i_attachments, p_demux_meta->attachments, |
|---|
| 210 |
p_attachment ); |
|---|
| 211 |
|
|---|
| 212 |
vlc_meta_SetArtURL( p_meta, "attachment://cover" ); |
|---|
| 213 |
} |
|---|
| 214 |
|
|---|
| 215 |
#if 0 |
|---|
| 216 |
|
|---|
| 217 |
else if( FLAC::File *flac = |
|---|
| 218 |
dynamic_cast<FLAC::File *>(f.file() ) ) |
|---|
| 219 |
{ |
|---|
| 220 |
p_tag = flac->ID3v2Tag(); |
|---|
| 221 |
if( p_tag ) |
|---|
| 222 |
return; |
|---|
| 223 |
ID3v2::FrameList l = p_tag->frameListMap()[ "APIC" ]; |
|---|
| 224 |
if( l.isEmpty() ) |
|---|
| 225 |
return; |
|---|
| 226 |
vlc_meta_SetArtURL( p_meta, "APIC" ); |
|---|
| 227 |
} |
|---|
| 228 |
#endif |
|---|
| 229 |
#if 0 |
|---|
| 230 |
|
|---|
| 231 |
else if( MP4::File *mp4 = |
|---|
| 232 |
dynamic_cast<MP4::File *>( f.file() ) ) |
|---|
| 233 |
{ |
|---|
| 234 |
MP4::Tag *mp4tag = |
|---|
| 235 |
dynamic_cast<MP4::Tag *>( mp4->tag() ); |
|---|
| 236 |
if( mp4tag && mp4tag->cover().size() ) |
|---|
| 237 |
vlc_meta_SetArtURL( p_meta, "MP4C" ); |
|---|
| 238 |
} |
|---|
| 239 |
#endif |
|---|
| 240 |
} |
|---|
| 241 |
|
|---|
| 242 |
static int ReadMeta( vlc_object_t *p_this ) |
|---|
| 243 |
{ |
|---|
| 244 |
demux_t *p_demux = (demux_t *)p_this; |
|---|
| 245 |
demux_meta_t *p_demux_meta = (demux_meta_t*)p_demux->p_private; |
|---|
| 246 |
vlc_meta_t *p_meta; |
|---|
| 247 |
TagLib::FileRef f; |
|---|
| 248 |
|
|---|
| 249 |
TAB_INIT( p_demux_meta->i_attachments, p_demux_meta->attachments ); |
|---|
| 250 |
p_demux_meta->p_meta = NULL; |
|---|
| 251 |
|
|---|
| 252 |
#if defined(WIN32) || defined (UNDER_CE) |
|---|
| 253 |
if(GetVersion() < 0x80000000) |
|---|
| 254 |
{ |
|---|
| 255 |
wchar_t wpath[MAX_PATH + 1]; |
|---|
| 256 |
if( !MultiByteToWideChar( CP_UTF8, 0, p_demux->psz_path, -1, wpath, MAX_PATH) ) |
|---|
| 257 |
return VLC_EGENERIC; |
|---|
| 258 |
|
|---|
| 259 |
wpath[MAX_PATH] = L'0'; |
|---|
| 260 |
f = FileRef( wpath ); |
|---|
| 261 |
} |
|---|
| 262 |
else return VLC_EGENERIC; |
|---|
| 263 |
#else |
|---|
| 264 |
const char *local_name = ToLocale( p_demux->psz_path ); |
|---|
| 265 |
|
|---|
| 266 |
if( local_name == NULL ) |
|---|
| 267 |
return VLC_EGENERIC; |
|---|
| 268 |
|
|---|
| 269 |
f = FileRef( local_name ); |
|---|
| 270 |
LocaleFree( local_name ); |
|---|
| 271 |
#endif |
|---|
| 272 |
|
|---|
| 273 |
if( f.isNull() ) |
|---|
| 274 |
return VLC_EGENERIC; |
|---|
| 275 |
|
|---|
| 276 |
if ( !f.tag() || f.tag()->isEmpty() ) |
|---|
| 277 |
return VLC_EGENERIC; |
|---|
| 278 |
|
|---|
| 279 |
p_demux_meta->p_meta = p_meta = vlc_meta_New(); |
|---|
| 280 |
Tag *p_tag = f.tag(); |
|---|
| 281 |
|
|---|
| 282 |
if( MPEG::File *p_mpeg = |
|---|
| 283 |
dynamic_cast<MPEG::File *>(f.file() ) ) |
|---|
| 284 |
{ |
|---|
| 285 |
if( p_mpeg->ID3v2Tag() ) |
|---|
| 286 |
{ |
|---|
| 287 |
ID3v2::Tag *p_tag = p_mpeg->ID3v2Tag(); |
|---|
| 288 |
ID3v2::FrameList list = p_tag->frameListMap()["UFID"]; |
|---|
| 289 |
ID3v2::UniqueFileIdentifierFrame* p_ufid; |
|---|
| 290 |
for( ID3v2::FrameList::Iterator iter = list.begin(); |
|---|
| 291 |
iter != list.end(); iter++ ) |
|---|
| 292 |
{ |
|---|
| 293 |
p_ufid = dynamic_cast<ID3v2::UniqueFileIdentifierFrame*>(*iter); |
|---|
| 294 |
const char *owner = p_ufid->owner().toCString(); |
|---|
| 295 |
if (!strcmp( owner, "http://musicbrainz.org" )) |
|---|
| 296 |
{ |
|---|
| 297 |
|
|---|
| 298 |
|
|---|
| 299 |
|
|---|
| 300 |
char *psz_ufid = (char*) malloc( 64 ); |
|---|
| 301 |
int j = 0; |
|---|
| 302 |
if( psz_ufid ) |
|---|
| 303 |
{ |
|---|
| 304 |
while( ( j < 63 ) && |
|---|
| 305 |
( j < p_ufid->identifier().size() ) ) |
|---|
| 306 |
psz_ufid[j] = p_ufid->identifier()[j++]; |
|---|
| 307 |
psz_ufid[j] = '\0'; |
|---|
| 308 |
vlc_meta_SetTrackID( p_meta, psz_ufid ); |
|---|
| 309 |
free( psz_ufid ); |
|---|
| 310 |
} |
|---|
| 311 |
} |
|---|
| 312 |
} |
|---|
| 313 |
|
|---|
| 314 |
list = p_tag->frameListMap()["TXXX"]; |
|---|
| 315 |
ID3v2::UserTextIdentificationFrame* p_txxx; |
|---|
| 316 |
for( ID3v2::FrameList::Iterator iter = list.begin(); |
|---|
| 317 |
iter != list.end(); iter++ ) |
|---|
| 318 |
{ |
|---|
| 319 |
p_txxx = dynamic_cast<ID3v2::UserTextIdentificationFrame*>(*iter); |
|---|
| 320 |
const char *psz_desc= p_txxx->description().toCString(); |
|---|
| 321 |
vlc_meta_AddExtra( p_meta, psz_desc, |
|---|
| 322 |
p_txxx->fieldList().toString().toCString()); |
|---|
| 323 |
} |
|---|
| 324 |
#if 0 |
|---|
| 325 |
list = p_tag->frameListMap()["RVA2"]; |
|---|
| 326 |
ID3v2::RelativeVolumeFrame* p_rva2; |
|---|
| 327 |
for( ID3v2::FrameList::Iterator iter = list.begin(); |
|---|
| 328 |
iter != list.end(); iter++ ) |
|---|
| 329 |
{ |
|---|
| 330 |
p_rva2 = dynamic_cast<ID3v2::RelativeVolumeFrame*>(*iter); |
|---|
| 331 |
|
|---|
| 332 |
} |
|---|
| 333 |
#endif |
|---|
| 334 |
list = p_tag->frameList(); |
|---|
| 335 |
ID3v2::Frame* p_t; |
|---|
| 336 |
char psz_tag[4]; |
|---|
| 337 |
for( ID3v2::FrameList::Iterator iter = list.begin(); |
|---|
| 338 |
iter != list.end(); iter++ ) |
|---|
| 339 |
{ |
|---|
| 340 |
p_t = dynamic_cast<ID3v2::Frame*> (*iter); |
|---|
| 341 |
memcpy( psz_tag, p_t->frameID().data(), 4); |
|---|
| 342 |
|
|---|
| 343 |
#define SET( foo, bar ) if( !strncmp( psz_tag, foo, 4 ) ) \ |
|---|
| 344 |
vlc_meta_Set##bar( p_meta, p_t->toString().toCString(true)) |
|---|
| 345 |
SET( "TPUB", Publisher ); |
|---|
| 346 |
SET( "TCOP", Copyright ); |
|---|
| 347 |
SET( "TENC", EncodedBy ); |
|---|
| 348 |
SET( "TLAN", Language ); |
|---|
| 349 |
|
|---|
| 350 |
|
|---|
| 351 |
|
|---|
| 352 |
#undef SET |
|---|
| 353 |
} |
|---|
| 354 |
} |
|---|
| 355 |
} |
|---|
| 356 |
|
|---|
| 357 |
else if( Ogg::Vorbis::File *p_ogg_v = |
|---|
| 358 |
dynamic_cast<Ogg::Vorbis::File *>(f.file() ) ) |
|---|
| 359 |
{ |
|---|
| 360 |
int i_ogg_v_length = p_ogg_v->audioProperties()->length(); |
|---|
| 361 |
|
|---|
| 362 |
input_thread_t *p_input = (input_thread_t *) |
|---|
| 363 |
vlc_object_find( p_demux,VLC_OBJECT_INPUT, FIND_PARENT ); |
|---|
| 364 |
if( p_input ) |
|---|
| 365 |
{ |
|---|
| 366 |
input_item_t *p_item = input_GetItem( p_input ); |
|---|
| 367 |
if( p_item ) |
|---|
| 368 |
input_item_SetDuration( p_item, |
|---|
| 369 |
(mtime_t) i_ogg_v_length * 1000000 ); |
|---|
| 370 |
vlc_object_release( p_input ); |
|---|
| 371 |
} |
|---|
| 372 |
|
|---|
| 373 |
} |
|---|
| 374 |
#if 0 |
|---|
| 375 |
* becauses type detection is based on file extension: |
|---|
| 376 |
* ogg = ogg/vorbis |
|---|
| 377 |
* flac = flac |
|---|
| 378 |
* ø = ogg/flac |
|---|
| 379 |
*/ |
|---|
| 380 |
else if( Ogg::FLAC::File *p_ogg_f = |
|---|
| 381 |
dynamic_cast<Ogg::FLAC::File *>(f.file() ) ) |
|---|
| 382 |
{ |
|---|
| 383 |
long i_ogg_f_length = p_ogg_f->streamLength(); |
|---|
| 384 |
input_thread_t *p_input = (input_thread_t *) |
|---|
| 385 |
vlc_object_find( p_demux, VLC_OBJECT_INPUT, FIND_PARENT ); |
|---|
| 386 |
if( p_input ) |
|---|
| 387 |
{ |
|---|
| 388 |
input_item_t *p_item = input_GetItem( p_input ); |
|---|
| 389 |
if( p_item ) |
|---|
| 390 |
input_item_SetDuration( p_item, |
|---|
| 391 |
(mtime_t) i_ogg_f_length * 1000000 ); |
|---|
| 392 |
vlc_object_release( p_input ); |
|---|
| 393 |
} |
|---|
| 394 |
} |
|---|
| 395 |
#endif |
|---|
| 396 |
else if( FLAC::File *p_flac = |
|---|
| 397 |
dynamic_cast<FLAC::File *>(f.file() ) ) |
|---|
| 398 |
{ |
|---|
| 399 |
long i_flac_length = p_flac->audioProperties()->length(); |
|---|
| 400 |
input_thread_t *p_input = (input_thread_t *) |
|---|
| 401 |
vlc_object_find( p_demux, VLC_OBJECT_INPUT, FIND_PARENT ); |
|---|
| 402 |
if( p_input ) |
|---|
| 403 |
{ |
|---|
| 404 |
input_item_t *p_item = input_GetItem( p_input ); |
|---|
| 405 |
if( p_item ) |
|---|
| 406 |
input_item_SetDuration( p_item, |
|---|
| 407 |
(mtime_t) i_flac_length * 1000000 ); |
|---|
| 408 |
vlc_object_release( p_input ); |
|---|
| 409 |
} |
|---|
| 410 |
} |
|---|
| 411 |
|
|---|
| 412 |
#define SET( foo, bar ) vlc_meta_Set##foo( p_meta, p_tag->bar ().toCString(true)) |
|---|
| 413 |
#define SETINT( foo, bar ) { \ |
|---|
| 414 |
char psz_tmp[10]; \ |
|---|
| 415 |
snprintf( (char*)psz_tmp, 10, "%d", p_tag->bar() ); \ |
|---|
| 416 |
vlc_meta_Set##foo( p_meta, (char*)psz_tmp ); \ |
|---|
| 417 |
} |
|---|
| 418 |
|
|---|
| 419 |
SET( Title, title ); |
|---|
| 420 |
SET( Artist, artist ); |
|---|
| 421 |
SET( Album, album ); |
|---|
| 422 |
SET( Description, comment ); |
|---|
| 423 |
SET( Genre, genre ); |
|---|
| 424 |
SETINT( Date, year ); |
|---|
| 425 |
SETINT( Tracknum , track ); |
|---|
| 426 |
#undef SET |
|---|
| 427 |
#undef SETINT |
|---|
| 428 |
|
|---|
| 429 |
DetectImage( f, p_demux ); |
|---|
| 430 |
|
|---|
| 431 |
return VLC_SUCCESS; |
|---|
| 432 |
} |
|---|
| 433 |
|
|---|
| 434 |
static int WriteMeta( vlc_object_t *p_this ) |
|---|
| 435 |
{ |
|---|
| 436 |
playlist_t *p_playlist = (playlist_t *)p_this; |
|---|
| 437 |
meta_export_t *p_export = (meta_export_t *)p_playlist->p_private; |
|---|
| 438 |
input_item_t *p_item = p_export->p_item; |
|---|
| 439 |
|
|---|
| 440 |
if( p_item == NULL ) |
|---|
| 441 |
{ |
|---|
| 442 |
msg_Err( p_this, "Can't save meta data of an empty input" ); |
|---|
| 443 |
return VLC_EGENERIC; |
|---|
| 444 |
} |
|---|
| 445 |
|
|---|
| 446 |
FileRef f( p_export->psz_file ); |
|---|
| 447 |
if( f.isNull() || !f.tag() || f.file()->readOnly() ) |
|---|
| 448 |
{ |
|---|
| 449 |
msg_Err( p_this, "File %s can't be opened for tag writing\n", |
|---|
| 450 |
p_export->psz_file ); |
|---|
| 451 |
return VLC_EGENERIC; |
|---|
| 452 |
} |
|---|
| 453 |
|
|---|
| 454 |
msg_Dbg( p_this, "Writing metadata for %s", p_export->psz_file ); |
|---|
| 455 |
|
|---|
| 456 |
Tag *p_tag = f.tag(); |
|---|
| 457 |
|
|---|
| 458 |
char *psz_meta; |
|---|
| 459 |
|
|---|
| 460 |
#define SET(a,b) \ |
|---|
| 461 |
if(b) { \ |
|---|
| 462 |
String *psz_##a = new String( b, \ |
|---|
| 463 |
String::UTF8 ); \ |
|---|
| 464 |
p_tag->set##a( *psz_##a ); \ |
|---|
| 465 |
delete psz_##a; \ |
|---|
| 466 |
} |
|---|
| 467 |
|
|---|
| 468 |
|
|---|
| 469 |
psz_meta = input_item_GetArtist( p_item ); |
|---|
| 470 |
SET( Artist, psz_meta ); |
|---|
| 471 |
free( psz_meta ); |
|---|
| 472 |
|
|---|
| 473 |
psz_meta = input_item_GetTitle( p_item ); |
|---|
| 474 |
if( !psz_meta ) psz_meta = input_item_GetName( p_item ); |
|---|
| 475 |
String *psz_title = new String( psz_meta, |
|---|
| 476 |
String::UTF8 ); |
|---|
| 477 |
p_tag->setTitle( *psz_title ); |
|---|
| 478 |
delete psz_title; |
|---|
| 479 |
free( psz_meta ); |
|---|
| 480 |
|
|---|
| 481 |
psz_meta = input_item_GetAlbum( p_item ); |
|---|
| 482 |
SET( Album, psz_meta ); |
|---|
| 483 |
free( psz_meta ); |
|---|
| 484 |
|
|---|
| 485 |
psz_meta = input_item_GetGenre( p_item ); |
|---|
| 486 |
SET( Genre, psz_meta ); |
|---|
| 487 |
free( psz_meta ); |
|---|
| 488 |
|
|---|
| 489 |
#undef SET |
|---|
| 490 |
|
|---|
| 491 |
psz_meta = input_item_GetDate( p_item ); |
|---|
| 492 |
if( psz_meta ) p_tag->setYear( atoi( psz_meta ) ); |
|---|
| 493 |
free( psz_meta ); |
|---|
| 494 |
|
|---|
| 495 |
psz_meta = input_item_GetTrackNum( p_item ); |
|---|
| 496 |
if( psz_meta ) p_tag->setTrack( atoi( psz_meta ) ); |
|---|
| 497 |
free( psz_meta ); |
|---|
| 498 |
|
|---|
| 499 |
if( ID3v2::Tag *p_id3tag = |
|---|
| 500 |
dynamic_cast<ID3v2::Tag *>(p_tag) ) |
|---|
| 501 |
{ |
|---|
| 502 |
#define WRITE( foo, bar ) \ |
|---|
| 503 |
psz_meta = input_item_Get##foo( p_item ); \ |
|---|
| 504 |
if( psz_meta ) \ |
|---|
| 505 |
{ \ |
|---|
| 506 |
ByteVector p_byte( bar, 4 ); \ |
|---|
| 507 |
ID3v2::TextIdentificationFrame p_frame( p_byte ); \ |
|---|
| 508 |
p_frame.setText( psz_meta ); \ |
|---|
| 509 |
p_id3tag->addFrame( &p_frame ); \ |
|---|
| 510 |
free( psz_meta ); \ |
|---|
| 511 |
} \ |
|---|
| 512 |
|
|---|
| 513 |
WRITE( Publisher, "TPUB" ); |
|---|
| 514 |
WRITE( Copyright, "TCOP" ); |
|---|
| 515 |
WRITE( EncodedBy, "TENC" ); |
|---|
| 516 |
WRITE( Language, "TLAN" ); |
|---|
| 517 |
|
|---|
| 518 |
#undef WRITE |
|---|
| 519 |
} |
|---|
| 520 |
|
|---|
| 521 |
f.save(); |
|---|
| 522 |
return VLC_SUCCESS; |
|---|
| 523 |
} |
|---|
| 524 |
|
|---|
| 525 |
static int DownloadArt( vlc_object_t *p_this ) |
|---|
| 526 |
{ |
|---|
| 527 |
|
|---|
| 528 |
|
|---|
| 529 |
|
|---|
| 530 |
return VLC_EGENERIC; |
|---|
| 531 |
} |
|---|
| 532 |
|
|---|