From 8bad2664cb6f8ab191d44647937acfd45b977920 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sl=C3=A1vek=20Banko?= Date: Sun, 12 May 2013 12:22:21 +0200 Subject: [PATCH 1/2] Add mp4v2 MP4Tags* API support This resolves Bug 346 --- amarok/configure.in.in | 20 +++++- amarok/src/metadata/mp4/mp4file.cpp | 66 ++++++++++++++++++- amarok/src/metadata/mp4/mp4properties.h | 7 ++ amarok/src/metadata/mp4/mp4tag.cpp | 56 +++++++++++++++- amarok/src/metadata/mp4/mp4tag.h | 7 ++ .../mp4/taglib_mp4filetyperesolver.cpp | 4 ++ config.h.in | 3 + 7 files changed, 155 insertions(+), 8 deletions(-) diff --git a/amarok/configure.in.in b/amarok/configure.in.in index 67f53d6c..9c7be42d 100644 --- a/amarok/configure.in.in +++ b/amarok/configure.in.in @@ -995,15 +995,29 @@ if test "$have_mp4v2" != "no"; then ac_cppflags_save=$CPPFLAGS CPPFLAGS="$CPPFLAGS -I." AC_CHECK_HEADERS(systems.h) - AC_CHECK_HEADERS([mp4v2/mp4v2.h], [have_mp4_h=yes], [], + AC_CHECK_HEADERS([mp4v2/mp4v2.h], [have_mp4v2_h=yes], [], [#ifdef HAVE_SYSTEMS_H # include #endif ]) + if test "$have_mp4v2_h" = "yes"; then + AC_DEFINE(HAVE_MP4V2_H, 1, [have mp4v2 h]) + else + AC_CHECK_HEADERS([mp4.h], [have_mp4_h=yes], [], + [#ifdef HAVE_SYSTEMS_H + # include + #endif + ]) + if test "$have_mp4_h" = "yes"; then + AC_DEFINE(HAVE_MP4_H, 1, [have mp4 h]) + fi + fi - AC_CHECK_LIB( mp4v2, MP4Read, have_mp4v2=yes, have_mp4v2=no ) + if test "$have_mp4v2_h" = "yes" -o "$have_mp4_h" = "yes"; then + AC_CHECK_LIB( mp4v2, MP4Read, have_mp4v2=yes, have_mp4v2=no ) + fi - if test "$have_mp4v2" = "yes" -a "$have_mp4_h" = "yes"; then + if test "$have_mp4v2" = "yes"; then AC_DEFINE(HAVE_MP4V2, 1, [have mp4v2]) MP4V2_INCLUDES="-I$mp4v2_dir/include" MP4V2_LIBS="-L$mp4v2_dir/lib -lmp4v2" diff --git a/amarok/src/metadata/mp4/mp4file.cpp b/amarok/src/metadata/mp4/mp4file.cpp index 3019e37a..536955c3 100644 --- a/amarok/src/metadata/mp4/mp4file.cpp +++ b/amarok/src/metadata/mp4/mp4file.cpp @@ -23,6 +23,8 @@ email : aumuell@reserv.at * MA 02110-1301 USA * ***************************************************************************/ +#include + #include "mp4file.h" #include "mp4tag.h" @@ -34,7 +36,11 @@ email : aumuell@reserv.at #include #include +#ifdef HAVE_MP4V2_H +#define USE_ITMF_TAGS +#else #define MP4V2_HAS_WRITE_BUG 1 +#endif namespace TagLib { //////////////////////////////////////////////////////////////////////////////// @@ -102,6 +108,11 @@ bool MP4::File::save() return false; } +#ifdef USE_ITMF_TAGS + const MP4Tags* filetags = MP4TagsAlloc(); + MP4TagsFetch(filetags, handle); +#endif + #ifdef MP4V2_HAS_WRITE_BUG /* according to gtkpod we have to delete all meta data before modifying it, save the stuff we would not touch */ @@ -117,7 +128,14 @@ bool MP4::File::save() #endif - +#ifdef USE_ITMF_TAGS + MP4TagsSetName(filetags, mp4tag->title().isNull() ? "" : mp4tag->title().toCString(true)); + MP4TagsSetArtist(filetags, mp4tag->artist().isNull() ? "" : mp4tag->artist().toCString(true)); + MP4TagsSetAlbum(filetags, mp4tag->album().isNull() ? "" : mp4tag->album().toCString(true)); + MP4TagsSetComments(filetags, mp4tag->comment().isNull() ? "" : mp4tag->comment().toCString(true)); + MP4TagsSetGenre(filetags, mp4tag->genre().isNull() ? "" : mp4tag->genre().toCString(true)); + MP4TagsSetComposer(filetags, mp4tag->composer().isNull() ? "" : mp4tag->composer().toCString(true)); +#else #define setmeta(val, tag) \ if(mp4tag->val().isNull()) { \ /*MP4DeleteMetadata##tag(handle);*/ \ @@ -125,27 +143,65 @@ bool MP4::File::save() } else { \ MP4SetMetadata##tag(handle, mp4tag->val().toCString(true)); \ } - setmeta(title, Name); setmeta(artist, Artist); setmeta(album, Album); setmeta(comment, Comment); setmeta(genre, Genre); + setmeta(composer, Writer); +#endif char buf[100] = ""; if(mp4tag->year()) snprintf(buf, sizeof(buf), "%u", mp4tag->year()); +#ifdef USE_ITMF_TAGS + MP4TagsSetReleaseDate(filetags, buf); +#else MP4SetMetadataYear(handle, buf); +#endif u_int16_t t1, t2; + +#ifdef USE_ITMF_TAGS + MP4TagTrack track = *filetags->track; + track.index = t1; + MP4TagsSetTrack(filetags, &track); +#else MP4GetMetadataTrack(handle, &t1, &t2); MP4SetMetadataTrack(handle, mp4tag->track(), t2); - if(mp4tag->bpm() != 0) +#endif + if(mp4tag->bpm() != 0) { +#ifdef USE_ITMF_TAGS + u_int16_t tempo = mp4tag->bpm(); + MP4TagsSetTempo(filetags, &tempo); +#else MP4SetMetadataTempo(handle, mp4tag->bpm()); +#endif + } if(mp4tag->compilation() != MP4::Tag::Undefined) { +#ifdef USE_ITMF_TAGS + u_int8_t compilation = mp4tag->compilation(); + MP4TagsSetCompilation(filetags, &compilation); +#else MP4SetMetadataCompilation(handle, mp4tag->compilation()); +#endif } +#ifdef USE_ITMF_TAGS + if(mp4tag->cover().size()) { + MP4TagArtwork art; + art.size = mp4tag->cover().size(); + art.data = mp4tag->cover().size() ? const_cast( reinterpret_cast( mp4tag->cover().data() ) ) : 0; + art.type = MP4_ART_UNDEFINED; // delegate typing to libmp4v2 + if(filetags->artworkCount > 0) { + MP4TagsSetArtwork(filetags, 0, &art); + } + else { + MP4TagsAddArtwork(filetags, &art); + } + } +#else MP4SetMetadataCoverArt(handle, mp4tag->cover().size() ? const_cast( reinterpret_cast( mp4tag->cover().data() ) ) : 0, mp4tag->cover().size()); +#endif #ifdef MP4V2_HAS_WRITE_BUG // set the saved data again @@ -159,6 +215,10 @@ bool MP4::File::save() } #endif +#ifdef USE_ITMF_TAGS + MP4TagsStore(filetags, handle); + MP4TagsFree(filetags); +#endif MP4Close(handle); mp4file = MP4Read(name()); diff --git a/amarok/src/metadata/mp4/mp4properties.h b/amarok/src/metadata/mp4/mp4properties.h index 95c83035..bbe3fa48 100644 --- a/amarok/src/metadata/mp4/mp4properties.h +++ b/amarok/src/metadata/mp4/mp4properties.h @@ -22,13 +22,20 @@ email : andrew.leadbetter@gmail.com #ifndef TAGLIB_MP4PROPERTIES_H #define TAGLIB_MP4PROPERTIES_H +#include + #include #include +#ifdef HAVE_MP4V2_H #include +#endif +#ifdef HAVE_MP4_H +#include // mp4.h drags in mp4_config.h that defines these // get rid of them so they don't conflict with our config.h #undef VERSION #undef PACKAGE +#endif namespace TagLib { diff --git a/amarok/src/metadata/mp4/mp4tag.cpp b/amarok/src/metadata/mp4/mp4tag.cpp index ee032d3a..642df2b1 100644 --- a/amarok/src/metadata/mp4/mp4tag.cpp +++ b/amarok/src/metadata/mp4/mp4tag.cpp @@ -20,6 +20,8 @@ email : andrew.leadbetter@gmail.com * MA 02110-1301 USA * ***************************************************************************/ +#include + #include "mp4tag.h" #include @@ -29,6 +31,10 @@ email : andrew.leadbetter@gmail.com #include #include +#ifdef HAVE_MP4V2_H +#define USE_ITMF_TAGS +#endif + using namespace TagLib; MP4::Tag::Tag() : TagLib::Tag::Tag() { @@ -67,21 +73,66 @@ void MP4::Tag::duplicate(const Tag *source, Tag *target, bool overwrite) { // Duplicate standard information Tag::duplicate(source, target, overwrite); - if (overwrite || target->compilation() == Undefined && source->compilation() != Undefined) + if ((overwrite || target->compilation() == Undefined) && (source->compilation() != Undefined)) { target->setCompilation(source->compilation()); + } - if (overwrite || target->cover().size() == 0) + if (overwrite || target->cover().size() == 0) { target->setCover(source->cover()); + } } void MP4::Tag::readTags( MP4FileHandle mp4file ) { // Now parse tag. +#ifdef USE_ITMF_TAGS + const MP4Tags* filetags = MP4TagsAlloc(); + MP4TagsFetch(filetags, mp4file); + + if(filetags->name != NULL) { + m_title = String(filetags->name, String::UTF8); + } + if(filetags->artist != NULL) { + m_artist = String(filetags->artist, String::UTF8); + } + if(filetags->comments != NULL) { + m_comment = String(filetags->comments, String::UTF8); + } + if(filetags->releaseDate != NULL) { + m_year = strtol(filetags->releaseDate, NULL, 0); + } + if(filetags->album != NULL) { + m_album = String(filetags->album, String::UTF8); + } + if(filetags->track != NULL) { + m_track = filetags->track->index; + } + if(filetags->disk != NULL) { + m_disk = filetags->disk->index; + } + if(filetags->tempo != NULL) { + m_bpm = *filetags->tempo; + } + if(filetags->compilation != NULL) { + m_compilation = *filetags->compilation; + } + if(filetags->genre != NULL) { + m_genre = String(filetags->genre, String::UTF8); + } + if(filetags->composer != NULL) { + m_composer = String(filetags->composer, String::UTF8); + } + if(filetags->artworkCount > 0) { + m_image.setData(reinterpret_cast( filetags->artwork[0].data ), filetags->artwork[0].size); + } + MP4TagsFree(filetags); +#else char *value; uint8_t boolvalue; uint16_t numvalue, numvalue2; uint8_t *image; uint32_t imageSize; + if (MP4GetMetadataName(mp4file, &value) && value != NULL) { m_title = String(value, String::UTF8); free(value); @@ -128,4 +179,5 @@ void MP4::Tag::readTags( MP4FileHandle mp4file ) m_image.setData(reinterpret_cast( image ), imageSize); free(image); } +#endif } diff --git a/amarok/src/metadata/mp4/mp4tag.h b/amarok/src/metadata/mp4/mp4tag.h index 9ba20bc0..34f95054 100644 --- a/amarok/src/metadata/mp4/mp4tag.h +++ b/amarok/src/metadata/mp4/mp4tag.h @@ -21,9 +21,16 @@ email : andrew.leadbetter@gmail.com #ifndef TAGLIB_MP4TAG_H #define TAGLIB_MP4TAG_H +#include + #include #include "mp4file.h" +#ifdef HAVE_MP4V2_H #include +#endif +#ifdef HAVE_MP4_H +#include +#endif namespace TagLib { diff --git a/amarok/src/metadata/mp4/taglib_mp4filetyperesolver.cpp b/amarok/src/metadata/mp4/taglib_mp4filetyperesolver.cpp index 43edd197..e179da5d 100644 --- a/amarok/src/metadata/mp4/taglib_mp4filetyperesolver.cpp +++ b/amarok/src/metadata/mp4/taglib_mp4filetyperesolver.cpp @@ -36,7 +36,11 @@ TagLib::File *MP4FileTypeResolver::createFile(const char *fileName, || !strcasecmp(ext, ".mp4") || !strcasecmp(ext, ".m4v") || !strcasecmp(ext, ".mp4v"))) { +#if defined(MP4V2_PROJECT_version_hex) && MP4V2_PROJECT_version_hex >= 0x00020000 + MP4FileHandle h = MP4Read(fileName); +#else MP4FileHandle h = MP4Read(fileName, 0); +#endif if(MP4_INVALID_FILE_HANDLE == h) { return 0; diff --git a/config.h.in b/config.h.in index 9645ebf9..86dab1c2 100644 --- a/config.h.in +++ b/config.h.in @@ -106,6 +106,9 @@ /* have mp4v2 */ #undef HAVE_MP4V2 +/* Define to 1 if you have the header file. */ +#undef HAVE_MP4V2_H + /* Define to 1 if you have the header file. */ #undef HAVE_MP4_H From 5fc2ad73cc00132503b3cf958327be19ca3a695a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sl=C3=A1vek=20Banko?= Date: Sun, 12 May 2013 12:26:39 +0200 Subject: [PATCH 2/2] Add cmake support for mp4v2 --- CMakeLists.txt | 1 + ConfigureChecks.cmake | 20 ++++++++++++++++ amarok/src/metadata/m4a/CMakeLists.txt | 5 ++-- amarok/src/metadata/mp4/CMakeLists.txt | 33 ++++++++++++++++++++++++++ config.h.cmake | 4 +++- 5 files changed, 60 insertions(+), 3 deletions(-) create mode 100644 amarok/src/metadata/mp4/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 0a095c86..6080c379 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -54,6 +54,7 @@ option( WITH_NJB "Enable njb support" OFF ) option( WITH_MTP "Enable mtp support" OFF ) option( WITH_RIOKARMA "Enable riokarma support" OFF ) option( WITH_DAAP "Enable daap support" OFF ) +option( WITH_MP4V2 "Enable mp4v2 support" OFF ) option( WITH_INOTIFY "Enable inotify support" OFF ) diff --git a/ConfigureChecks.cmake b/ConfigureChecks.cmake index 377fa4d3..d6891aa7 100644 --- a/ConfigureChecks.cmake +++ b/ConfigureChecks.cmake @@ -222,3 +222,23 @@ if( WITH_KONQSIDEBAR ) tde_message_fatal( "konqsidebarplugin.h are requested, but not found on your system" ) endif( ) endif( ) + +##### check for mp4v2 ########################### + +if( WITH_MP4V2 ) + check_include_file( "mp4v2/mp4v2.h" MP4V2_H_FOUND ) + if( MP4V2_H_FOUND ) + set( HAVE_MP4V2_H 1) + else( MP4V2_H_FOUND ) + check_include_file( "mp4.h" MP4_H_FOUND ) + if( MP4_H_FOUND ) + set( HAVE_MP4_H 1) + endif( MP4_H_FOUND ) + endif( MP4V2_H_FOUND ) + + if( HAVE_MP4V2_H OR HAVE_MP4_H ) + set( HAVE_MP4V2 1 ) + else( ) + tde_message_fatal( "MP4V2 support was requested, but not found on your system" ) + endif( ) +endif( ) diff --git a/amarok/src/metadata/m4a/CMakeLists.txt b/amarok/src/metadata/m4a/CMakeLists.txt index ea1f4046..0043d271 100644 --- a/amarok/src/metadata/m4a/CMakeLists.txt +++ b/amarok/src/metadata/m4a/CMakeLists.txt @@ -10,15 +10,16 @@ ################################################# include_directories( + ${CMAKE_BINARY_DIR} ${TDE_INCLUDE_DIR} ${TQT_INCLUDE_DIRS} ${TAGLIB_INCLUDE_DIRS} ) -##### tagmp4 (static) ########################### +##### tagm4a (static) ########################### -tde_add_library( tagmp4 STATIC_PIC +tde_add_library( tagm4a STATIC_PIC SOURCES taglib_mp4filetyperesolver.cpp mp4file.cpp mp4itunestag.cpp mp4isobox.cpp mp4isofullbox.cpp mp4skipbox.cpp mp4moovbox.cpp mp4mvhdbox.cpp diff --git a/amarok/src/metadata/mp4/CMakeLists.txt b/amarok/src/metadata/mp4/CMakeLists.txt new file mode 100644 index 00000000..a3149dd2 --- /dev/null +++ b/amarok/src/metadata/mp4/CMakeLists.txt @@ -0,0 +1,33 @@ +################################################# +# +# (C) 2010-2013 Darrell Anderson +# humanreadable (AT) yahoo.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +include_directories( + ${CMAKE_BINARY_DIR} + ${TDE_INCLUDE_DIR} + ${TQT_INCLUDE_DIRS} + ${TAGLIB_INCLUDE_DIRS} + ${MP4V2_INCLUDE_DIRS} +) + +link_directories( + ${MP4V2_LIBRARY_DIRS} +) + + +##### tagmp4 (static) ########################### + +tde_add_library( tagmp4 STATIC_PIC + SOURCES + mp4file.cpp mp4file.h mp4properties.cpp mp4properties.h mp4tag.cpp mp4tag.h + taglib_mp4filetyperesolver.cpp taglib_mp4filetyperesolver.h + LINK + mp4v2 +) diff --git a/config.h.cmake b/config.h.cmake index b895f46f..caddad59 100644 --- a/config.h.cmake +++ b/config.h.cmake @@ -12,8 +12,10 @@ #cmakedefine HAVE_ITDB_MEDIATYPE 1 #cmakedefine HAVE_LIBGPOD_060 1 #cmakedefine HAVE_MP4V2 1 +#cmakedefine HAVE_MP4V2_H 1 +#cmakedefine HAVE_MP4_H 1 #cmakedefine HAVE_TUNEPIMP 1 #cmakedefine TAGLIB_15 1 #cmakedefine HAVE_QGLWIDGET 1 -#cmakedefine HAVE_OLD_RUBY @HAVE_OLD_RUBY@ \ No newline at end of file +#cmakedefine HAVE_OLD_RUBY @HAVE_OLD_RUBY@