Source

libtaginfo / libtaginfo / asfinfo.cc

/*
 * Copyright (C) 2008-2013 J.Rios <anonbeat@gmail.com>
 * Copyright (C) 2013 Jörn Magens
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This Program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; see the file LICENSE.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth 
 * Floor, Boston, MA  02110-1301  USA
 * https://www.gnu.org/licenses/lgpl-2.1.txt
 *
 * Author:
 * 	Jörn Magens <shuerhaaken@googlemail.com>
 * 	Matias De lellis <mati86dl@gmail.com>
 * 	Pavel Vasin <rat4vier@gmail.com>
 */




#include "taginfo.h"
#include "taginfo_internal.h"
#include "taginfo_asftags.h"


#include <asffile.h>


#define COMPILATION_FLAG         "WM/PartOfACompilation"
#define PICTURE_FLAG             "WM/Picture"


using namespace TagInfo;



inline int wm_rating_to_rating(const int rating) {
    if(rating <= 0)
        return 0;
    if(rating < 25)
        return 1;
    if(rating < 50)
        return 2;
    if(rating < 75)
        return 3;
    if(rating < 99)
        return 4;
    return 5;
}


AsfInfo::AsfInfo(const String &filename) : Info(filename) {
    if(!file_name.isEmpty() && !setup_file_ref())
        printf("Error creating file ref! %s\n", filename.toCString());
    if(taglib_file) {
        asf_tag = ((TagLib::ASF::File *) taglib_file)->tag();
        if(!asf_tag)
            valid = false;
    }
    else {
        printf("Cant get xiphcomment from '%s'\n", file_name.toCString(false));
        asf_tag = NULL;
        valid = false;
    }
}


AsfInfo::~AsfInfo() {

}


bool AsfInfo::setup_file_ref() {
    if(file_name.isEmpty())
        return false;
    taglib_file = new TagLib::ASF::File(file_name.toCString(false), true, TagLib::AudioProperties::Fast);
    if(taglib_file) {
        return true;
    }
    else {
        printf("TagLib::File creation failed for '%s'\n", file_name.toCString(false));
        return false;
    }
}


bool AsfInfo::load(void) {
    if(Info::load()) {
        if(asf_tag) {
            load_base_tags((TagLib::Tag *)asf_tag);
            
            if(asf_tag->attributeListMap().contains("WM/PartOfSet")) {
                volume_number = 
                    atol(asf_tag->attributeListMap()[ "WM/PartOfSet" ].front().toString().toCString(false));
            }
            if(asf_tag->attributeListMap().contains("WM/Composer")) {
                composer = asf_tag->attributeListMap()[ "WM/Composer" ].front().toString();
            }
            if(asf_tag->attributeListMap().contains("WM/OriginalArtist")) {
                original_artist = asf_tag->attributeListMap()[ "WM/OriginalArtist" ].front().toString();
            }
            if(asf_tag->attributeListMap().contains("Copyright")) {
                copyright = asf_tag->attributeListMap()[ "Copyright" ].front().toString();
            }
            if(asf_tag->attributeListMap().contains("WM/EncodedBy")) {
                encoder = asf_tag->attributeListMap()[ "WM/EncodedBy" ].front().toString();
            }
            if(asf_tag->attributeListMap().contains("URL")) {
                homepage = asf_tag->attributeListMap()[ "URL" ].front().toString();
            }
            if(asf_tag->attributeListMap().contains(COMPILATION_FLAG)) {
                is_compilation =
                    asf_tag->attributeListMap()[COMPILATION_FLAG].front().toString() == String("1");
            }
            if(asf_tag->attributeListMap().contains("WM/AlbumArtist")) {
                album_artist = asf_tag->attributeListMap()[ "WM/AlbumArtist" ].front().toString();
            }
            long rat = 0;
            if(asf_tag->attributeListMap().contains("WM/SharedUserRating")) {
                rat = atol(asf_tag->attributeListMap()[ "WM/SharedUserRating" ].front().toString().toCString(false));
            }
            if(!rat && asf_tag->attributeListMap().contains("Rating")) {
                rat = atol(asf_tag->attributeListMap()[ "Rating" ].front().toString().toCString(false));
            }
            if(rat) {
                if(rat > 5) {
                    rating = wm_rating_to_rating(rat);
                }
                else
                {
                    rating = rat;
                }
            }
            if(track_labels.size() == 0) {
                if(asf_tag->attributeListMap().contains("TRACK_LABELS")) {
                    track_labels_string = asf_tag->attributeListMap()[ "TRACK_LABELS" ].front().toString();
                    track_labels = split(track_labels_string, "|");
                }
            }
            if(artist_labels.size() == 0) {
                if(asf_tag->attributeListMap().contains("ARTIST_LABELS")) {
                    artist_labels_string = asf_tag->attributeListMap()[ "ARTIST_LABELS" ].front().toString();
                    artist_labels = split(artist_labels_string, "|");
                }
            }
            if(album_labels.size() == 0) {
                if(asf_tag->attributeListMap().contains("ALBUM_LABELS")) {
                    album_labels_string = asf_tag->attributeListMap()[ "ALBUM_LABELS" ].front().toString();
                    album_labels = split(album_labels_string, "|");
                }
            }
        }
    }
    else {
        printf("Error: Could not load tags from file '%s'\n", file_name.toCString(true));
        return false; 
    }
    return true;
}


void check_asf_label_frame(ASF::Tag * asftag, const char * description, const String &value) {
    if(asftag->attributeListMap().contains(description))
        asftag->removeItem(description);
    if(!value.isEmpty()) {
            asftag->setAttribute(description, value);
    }
}


bool AsfInfo::save(void) {
    if(asf_tag) {
        if(changedflag) {
            if(changedflag & CHANGED_DATA_VOL_NUM) {
                asf_tag->removeItem("WM/PartOfSet");
                asf_tag->setAttribute("WM/PartOfSet", format("%u", volume_number));
            }
            if(changedflag & CHANGED_COMPOSER_TAG) {
                asf_tag->removeItem("WM/Composer");
                asf_tag->setAttribute("WM/Composer", composer);
            }
            if(changedflag & CHANGED_ORIGINALARTIST_TAG) {
                asf_tag->removeItem("WM/OriginalArtist");
                asf_tag->setAttribute("WM/OriginalArtist", original_artist);
            }
            if(changedflag & CHANGED_COPYRIGHT_TAG) {
                asf_tag->removeItem("Copyright");
                asf_tag->setAttribute("Copyright", copyright);
            }
            if(changedflag & CHANGED_ENCODER_TAG) {
                asf_tag->removeItem("WM/EncodedBy");
                asf_tag->setAttribute("WM/EncodedBy", encoder);
            }
            if(changedflag & CHANGED_HOMEPAGE_TAG) {
                asf_tag->removeItem("URL");
                asf_tag->setAttribute("URL", homepage);
            }
            if(changedflag & CHANGED_IS_COMPILATION_TAG) {
                asf_tag->removeItem(COMPILATION_FLAG);
                if(is_compilation)
                    asf_tag->setAttribute(COMPILATION_FLAG, String("1"));
                else
                    asf_tag->setAttribute(COMPILATION_FLAG, String("0"));
            }
            if(changedflag & CHANGED_DATA_ALBUMARTIST) {
                asf_tag->removeItem("WM/AlbumArtist");
                asf_tag->setAttribute("WM/AlbumArtist", album_artist);
            }
            if(changedflag & CHANGED_DATA_RATING) {
                asf_tag->removeItem("WM/SharedUserRating");
                int WMRatings[] = { 0, 0, 1, 25, 50, 75, 99 };
                asf_tag->setAttribute("WM/SharedUserRating", format("%i", WMRatings[ rating + 1 ]));
            }
            // The Labels
            if(changedflag & CHANGED_TRACK_LABELS)
                check_asf_label_frame(asf_tag, "TRACK_LABELS", track_labels_string);
            if(changedflag & CHANGED_ARTIST_LABELS)
                check_asf_label_frame(asf_tag, "ARTIST_LABELS", artist_labels_string);
            if(changedflag & CHANGED_ALBUM_LABELS)
                check_asf_label_frame(asf_tag, "ALBUM_LABELS", album_labels_string);
            save_base_tags((TagLib::Tag *)asf_tag);
        }
    }
    return Info::save();
}




Image ** AsfInfo::get_images(int &image_count) const {
    image_count = 0;
    if(asf_tag) {
        Image** images;
        if(asf_tag->attributeListMap().contains(PICTURE_FLAG)) {
            ASF::Attribute attr = asf_tag->attributeListMap()[PICTURE_FLAG].front(); 
            // TODO more pictures
            ASF::Picture pict = attr.toPicture();
            if(!pict.isValid())
                return NULL;
            images = new Image*[1];
            ByteVector pict_data = pict.picture();
            Image * image = new Image();
            if(pict_data.size() > 0) {
                image->data_length = pict_data.size();
                image->data = new char[image->data_length];
                memcpy(image->data, pict_data.data(), pict_data.size());
                
                String mimetype = pict.mimeType();
                if(mimetype.find("/jpeg") != -1 || mimetype.find("/jpg") != -1)
                    image->image_file_type = IMAGE_FILE_TYPE_JPEG;
                else if(mimetype.find("/png") != -1)
                    image->image_file_type = IMAGE_FILE_TYPE_PNG;
                else if(mimetype.find("/bmp") != -1)
                    image->image_file_type = IMAGE_FILE_TYPE_BMP;
                else if(mimetype.find("/gif") != -1)
                    image->image_file_type = IMAGE_FILE_TYPE_GIF;
                
                image->image_type = IMAGE_TYPE_COVER_FRONT;
                
                if(image->data && image->data_length > 0) {
                    image_count = 0;
                    images[0] = image;
                }
            }
        }
        return images;
    }
    return NULL;
}

void AsfInfo::set_images(const Image ** images, const int image_count) {
    if(asf_tag) {
        if(asf_tag->attributeListMap().contains(PICTURE_FLAG))
            asf_tag->removeItem(PICTURE_FLAG);
        
        
        for(int p = 0; p < image_count; p++) {
            const Image * image = images[p];
            if(!image->data || image->data_length == 0)
                continue;
            ASF::Picture picture = ASF::Picture();
            if(image->image_file_type == IMAGE_FILE_TYPE_JPEG || 
               image->image_file_type == IMAGE_FILE_TYPE_UNKNOWN) //default to jpeg
                picture.setMimeType("image/jpeg");
            if(image->image_file_type == IMAGE_FILE_TYPE_PNG)
                picture.setMimeType("image/png");
            
            ByteVector ImgData = ByteVector((TagLib::uint) image->data_length);
            memcpy(ImgData.data(), image->data, image->data_length);
            
            picture.setPicture(ImgData);
            ASF::Attribute attr = ASF::Attribute(picture);
            asf_tag->setAttribute(PICTURE_FLAG, attr);
        }
    }
}


String AsfInfo::get_lyrics(void) const {
    if(asf_tag) {
            if(asf_tag->attributeListMap().contains("WM/Lyrics")) {
            return asf_tag->attributeListMap()[ "WM/Lyrics" ].front().toString();
        }
    }
    return String();
}


bool AsfInfo::set_lyrics(const String &lyrics) {
    if(asf_tag) {
        asf_tag->removeItem("WM/Lyrics");
        asf_tag->setAttribute("WM/Lyrics", lyrics);
        return true;
    }
    return false;
}