Logo Search packages:      
Sourcecode: zinf version File versions  Download package

metadatadb.cpp

/*____________________________________________________________________________

        Zinf - Zinf Is Not FreeA*p (The Free MP3 Player)

        Portions Copyright (C) 1999 EMusic.com

        This program is free software; you can redistribute it and/or modify
        it under the terms of the GNU General Public License as published by
        the Free Software Foundation; either version 2 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; if not, write to the Free Software
        Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

        $Id: metadatadb.cpp,v 1.3 2003/11/11 19:59:07 kgk Exp $
____________________________________________________________________________*/


#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>

#include <iostream>
#include <set>

#include "metadatadb.h"

using namespace std;


const std::string Metadata::kUrl("url");
const std::string Metadata::kType("type");
const std::string Metadata::kTitle("title");
const std::string Metadata::kArtist("artist");
const std::string Metadata::kAlbum("album");
const std::string Metadata::kGenre("genre");
const std::string Metadata::kComment("comment");
const std::string Metadata::kTrack("track");
const std::string Metadata::kYear("year");
const std::string Metadata::kGuid("guid");
const std::string Metadata::kTime("time");
const std::string Metadata::kSize("size");
const std::string Metadata::kExt("extension");

static const char*std_tags[] = {
    "url",
    "type", 
    "title",       
    "artist",      
    "album",
    "genre",
    "comment",
    "track",
    "year"
};
#define TAG_COUNT (sizeof(std_tags)/sizeof(char*))

vector<string> Metadata::kStandardTags(std_tags, std_tags+TAG_COUNT);




void Metadata::setTag(const std::string&tag, const std::string&val)
{
}
void Metadata::setTag(const std::string&tag, const int32_t&val)
{
}
void Metadata::getTag(const std::string&tag, std::string&val) const
{
    map_t::const_iterator f = m_pairs.find(tag);
    if (f != m_pairs.end())
        val = (*f).second;
}
void Metadata::getTag(const std::string&tag, int32_t&val)const
{
    map_t::const_iterator f = m_pairs.find(tag);
    if (f != m_pairs.end())
        val = atoi((*f).second.c_str());
}

00089 void Metadata::initialize_tags(){
    vector<string>::iterator t = kStandardTags.begin();
    for (;t != kStandardTags.end();  ++t)
        m_pairs.insert(make_pair(*t, string()));
}



Metadata::operator string()
{
    string r;
    r+='[';
    for (map_t::iterator p=m_pairs.begin();p!=m_pairs.end();p++){
        r+='(';
        r+=(*p).first;
        r+=':';
        r+=(*p).second;
        r+=')';
    }
    r+=']';
    return r;
}

MetadataDB::MetadataDB()
{
}
MetadataDB::~MetadataDB()
{
}
bool 
MetadataDB::add(const url_t&url, const Metadata&m)
{
    return false;
}
bool 
MetadataDB::remove(const url_t&url)
{
    return false;
}
bool 
MetadataDB::contains(const url_t&url)
{
    return false;
}


bool 
MetadataDB::getMetadata(const url_t&url, Metadata&m)
{
    return false;
}

bool 
MetadataDB::setMetadata(const url_t&url, const Metadata&m)
{
    return false;
}

Error 
00148 MetadataDB::query (const std::string&target, 
             const params_t& params,
             result_t& results)
{
    return kError_InvalidParam;
}

void
MetadataDB::commit()
{
}


void MetadataDB::log(const string&val)
{
    fprintf(stderr, "%s\n", val.c_str());
}

void MetadataDB::log(boost::format &f)
{
    cerr << f << endl;
}



MetadataCollection::MetadataCollection(const url_t&name)
    : m_name (name)
{
}
MetadataCollection::~MetadataCollection()
{
}


void MetadataCollection::append(MetadataDB*db)
{
    m_path.push_back(db);
}

bool 
MetadataCollection::add(const url_t&url, const Metadata &m)
{
    fprintf(stderr, "MetadataCollection::add\n");

    Metadata md(m);

    // Add the standard keys for metadata
    vector<string>::iterator t = Metadata::kStandardTags.begin();
    for (; t != Metadata::kStandardTags.end(); t++ ) {
        if (!md.hasKey (*t)) {
            md[*t] = "";
        }
    }
    // And read as much as you can.
    readMetadata(url, md);

    for (metapath_type::iterator ldb = m_path.begin();
         ldb != m_path.end(); ldb++) {
        (*ldb)->add(url, md);
    }
    return true;
}
bool 
MetadataCollection::remove(const url_t&url)
{
    for (metapath_type::iterator ldb = m_path.begin();
         ldb != m_path.end(); 
         ldb++) {
        (*ldb)->remove(url);
    }

    return true;
}

bool 
MetadataCollection::contains(const url_t&url)
{
    // Check each library
    for (metapath_type::iterator ldb = m_path.begin();
         ldb != m_path.end(); 
         ldb++) {
        if ((*ldb)->contains(url))
            return true;
    }
    return false;
}

Error
MetadataCollection::query(const string&target, 
                           const params_t& params, 
                           result_t& results)
{
    Metadata md;
    for (metapath_type::iterator ldb = m_path.begin();
         ldb != m_path.end(); 
         ldb++) {
        (*ldb)->query(target, params, results);
    }
    return kError_NoErr;
}

bool 
00250 MetadataCollection::readMetadata(const url_t&url, Metadata&md)
{
    // Search through the hierarchy of meta sources until
    // All requested tags are determined.

    map<string,int32_t> levels;
    set<string> needed_keys;
    set<string> found_keys;
    set<string> missing;

    string ms,f;
    for (Metadata::iterator k = md.begin(); k != md.end(); k++){
        needed_keys.insert((*k).first);

        // BO DEBUG
        ms += (*k).first;
        ms += ';';
    }
    
    fprintf(stderr, "needed keys %s\n", ms.c_str());
    // EO DEBUG


    metapath_type::iterator mpi = m_path.begin();
    MetadataDB *mdb = *mpi;
    Metadata m( md );
    while (mpi != m_path.end()) {
        int32_t dbpriority = mdb->getPriority();

        mdb->getMetadata(url, m);

        fprintf(stderr, "found %s\n", ((string)m).c_str());

        //  Each metadata DB has a set priority that determines
        //  whether the elemental value may overwrite those already
        //  found.  We keep a special map with tuples formed by
        //  (tag,val,priority).  A tag value pair is inserted into the
        //  final metadata only if the the tag does not exist or the
        //  it exists, but with a lower priority.

        for (Metadata::iterator t = m.begin(); t != m.end(); t++){
            // Check whether the we have seen a tag/val of greater
            // priority before.
            if ((*t).second.size()!=0) {
                const string& tag = (*t).first;

                map<string,int32_t>::iterator l = levels.find(tag);
                if (l != levels.end() && (*l).second > dbpriority)
                    continue;
                
                // Replace the current tag with the higher priority
                levels[tag] = dbpriority;
                Metadata::iterator old = md.find(tag);
                if (old != md.end()) md.erase(old);
                md.insert(*t);
                found_keys.insert(tag);
            }
        }

        // Exit when all the requested tags have been satisfied.
        missing.clear();
        set_difference(needed_keys.begin(), needed_keys.end(),
                       found_keys.begin(), found_keys.end(),
                       inserter(missing, missing.begin()));

        cerr << boost::format("mdb missing %1%") % missing.size() << endl;

        if (missing.size() == 0) break;

        // Otherwise get the next level database and try there.
        mpi++;
        mdb = *mpi;
    }

    // After searching make sure all writable levels
    // have the most uptodate metadata.  This will ensure
    // that on subsequent reads, we used the most up-to-date
    // cached data.
//     MetadataDB *ldb = m_rootdb;
//     while (mdb != ldb) { 
//         ldb->setMetadata(url, md);
//         ldb = ldb->getParent();
//     }

    return true;
}

bool 
MetadataCollection::saveMetadata(const url_t&url, Metadata&md)
{
    // Save the current metadata tag/vals to each level
    // that allows writes.
    for (metapath_type::iterator ldb = m_path.begin();
         ldb != m_path.end(); 
         ldb++) {
        (*ldb)->setMetadata(url, md);
    }

    return true;
}






/* arch-tag: 125ff791-4523-4dc9-b757-d3d7bb9f430c */

Generated by  Doxygen 1.6.0   Back to index