Revision 45:0033259c6772

View differences:

common/FeatureFileIndex.cpp
22 22
}
23 23

  
24 24
FeatureFileIndex::FeatureFileIndex() :
25
    m_bs(0),
25 26
    m_index(0)
26 27
{
27 28
    try {
......
31 32
        return;
32 33
    }
33 34

  
34
    m_index = new BasicStore;
35
    m_bs = new BasicStore;
36
    m_index = new TransactionalStore(m_bs);
35 37

  
36
    TypeRegistrar::addMappings(m_index, 0);
38
    TypeRegistrar::addMappings(m_bs, 0);
37 39

  
38 40
    if (QFile(m_indexFileName).exists()) {
39
	m_index->import(QUrl::fromLocalFile(m_indexFileName),
40
			BasicStore::ImportIgnoreDuplicates);
41
	m_bs->import(QUrl::fromLocalFile(m_indexFileName),
42
                     BasicStore::ImportIgnoreDuplicates);
41 43
	//!!! catch
42 44
    }
43 45
}
44 46

  
45 47
FeatureFileIndex::~FeatureFileIndex()
46 48
{
49
    delete m_index;
50
    delete m_bs;
47 51
}
48 52

  
49 53
QString
......
77 81
}
78 82

  
79 83
void
80
FeatureFileIndex::loadFor(TrackFile *tf, BasicStore *store)
84
FeatureFileIndex::loadFor(AudioFile *tf, Store *store)
81 85
{
82 86
    if (!m_index) {
83 87
	std::cerr << "FeatureFileIndex::loadFor: No index!" << std::endl;
......
85 89
    }
86 90
    updateIndex();
87 91

  
88
    //...
92
    // The AudioFile object has a URI and a hash.  Feature files
93
    // generated for this AudioFile should ideally have a matching
94
    // hash; if they have no hash, then the URI should match.  If the
95
    // hash is present in the feature file but does not match, then it
96
    // cannot be the right track even if the URI matches.
97

  
98
    Triple t(Node(), "foaf:primaryTopic", tf->uri());
99
    Triples results = m_index->match(t);
100
    std::cerr << "FeatureFileIndex::loadFor: " << results.size() << " feature file(s) for audio file " << tf->uri() << std::endl;
101

  
102
    t = Triple(Node(), "foaf:primaryTopic",
103
               Uri(QString::fromUtf8(QUrl(tf->uri().toString()).toEncoded())));
104
    Triples moreResults = m_index->match(t);
105
    std::cerr << "FeatureFileIndex::loadFor: " << moreResults.size() << " feature file(s) for audio file " << t.c << std::endl;
106

  
107
    //!!! what's the right approach here?
108

  
109
    if (results.empty() && moreResults.empty()) {
110
        return;
111
    }
112

  
113
    
89 114
}
90 115

  
91 116
void
117
FeatureFileIndex::featureFileAdded(QString filepath)
118
{
119
    index(QUrl::fromLocalFile(filepath));
120
}    
121

  
122
void
92 123
FeatureFileIndex::updateIndex()
93 124
{
94 125
    QMutexLocker locker(&m_mutex);
......
106 137
    featureDir.setFilter(QDir::Files);
107 138

  
108 139
    for (unsigned int i = 0; i < featureDir.count(); ++i) {
109

  
110 140
        QFileInfo fi(featureDir.filePath(featureDir[i]));
111

  
112 141
        if (fi.isFile() && fi.isReadable()) {
113
	    QUrl fileUrl(QUrl::fromLocalFile(fi.filePath()));
114
            try {
115
                BasicStore *b = BasicStore::load(fileUrl);
116
                Triples ts = b->match
117
                    (Triple(Node(), "a", m_index->expand("mo:AudioFile")));
118
                foreach (Triple t, ts) {
119
                    m_index->add(Triple(Uri(fileUrl), "a", m_index->expand("foaf:Document")));
120
                    m_index->add(Triple(Uri(fileUrl), "foaf:primaryTopic", t.a));;
121
                }
122
            } catch (...) { }
142
            index(QUrl::fromLocalFile(fi.filePath()));
123 143
        }
124 144
    }
125 145

  
126 146
    //!!! remove triples from index that refer to nonexistent files?
127 147

  
128 148
    std::cerr << "Saving index to " << m_indexFileName.toStdString() << std::endl;
129
    m_index->save(m_indexFileName);
149
    m_bs->save(m_indexFileName);
150
}
151

  
152
void
153
FeatureFileIndex::index(QUrl fileUrl)
154
{
155
    Triple typeTriple(Uri(fileUrl), "a", m_index->expand("foaf:Document"));
156

  
157
    if (m_index->contains(typeTriple)) {
158
        return;
159
    }
160

  
161
    Transaction *tx = m_index->startTransaction();
162
    tx->add(typeTriple);
163

  
164
    try {
165
        BasicStore *b = BasicStore::load(fileUrl);
166
        Triples ts = b->match
167
            (Triple(Node(), "a", m_index->expand("mo:AudioFile")));
168
        foreach (Triple t, ts) {
169
            tx->add(Triple(Uri(fileUrl), "foaf:primaryTopic", t.a));;
170
        }
171
    } catch (...) { }
172

  
173
    delete tx;
130 174
}
131 175

  
132 176

  
common/FeatureFileIndex.h
6 6
#include "Objects.h"
7 7

  
8 8
#include <dataquay/BasicStore.h>
9
#include <dataquay/TransactionalStore.h>
9 10

  
10 11
#include <QMutex>
11 12

  
12 13
namespace ClassicalData {
13 14

  
14
class FeatureFileIndex
15
class FeatureFileIndex : public QObject
15 16
{
17
    Q_OBJECT
18

  
16 19
public:
17 20
    static FeatureFileIndex *getInstance();
18 21
    
19 22
    FeatureFileIndex();
20 23
    ~FeatureFileIndex();
21 24

  
22
    void loadFor(TrackFile *, Dataquay::BasicStore *);
25
    void loadFor(AudioFile *, Dataquay::Store *);
26

  
27
public slots:
28
    void featureFileAdded(QString filepath);
23 29

  
24 30
private:
25 31
    QMutex m_mutex;
26 32
    QString m_indexFileName;
27
    Dataquay::BasicStore *m_index;
33
    Dataquay::BasicStore *m_bs;
34
    Dataquay::TransactionalStore *m_index;
28 35
    QString getIndexFileName();
29 36
    QString getFeatureDirectoryName();
30 37
    void updateIndex();
38
    void index(QUrl);
31 39
};
32 40

  
33 41
}
common/Objects.cpp
825 825
    }
826 826
}
827 827

  
828
TrackFile::TrackFile(QObject *parent) :
829
    QObject(parent),
830
    m_composer(0),
831
    m_work(0),
832
    m_movement(0)
828
AudioFile::AudioFile(QObject *parent) :
829
    QObject(parent)
833 830
{
834 831
}
835 832

  
836
TrackFile::TrackFile(FileSource source, QObject *parent) :
837
    QObject(parent),
838
    m_composer(0),
839
    m_work(0),
840
    m_movement(0)
833
AudioFile::AudioFile(FileSource source, QObject *parent) :
834
    QObject(parent)
841 835
{
842 836
    if (source.isAvailable()) {
843 837
        QFile f(source.getLocalFilename());
844 838
        f.open(QIODevice::ReadOnly);
845
        //!!! data may be too large!
839
        //!!! stream this!
846 840
        QByteArray ba = f.readAll();
847 841
        m_hash = QString::fromAscii
848 842
            (QCryptographicHash::hash(ba, QCryptographicHash::Sha1).toHex());
......
859 853
            m_uri = Dataquay::Uri("file://" + QFileInfo(location).canonicalFilePath());
860 854
        }
861 855
    }
862
    std::cerr << "TrackFile::TrackFile: hash = " << m_hash.toStdString()
856

  
857
    std::cerr << "AudioFile::AudioFile: hash = " << m_hash.toStdString()
863 858
              << ", uri = " << m_uri.toString().toStdString() << std::endl;
864 859
}
865 860

  
common/Objects.h
580 580
    static QMutex m_mutex;
581 581
};
582 582

  
583
class TrackFile : public QObject
583
// Separate AudioFile and Signal, to correspond with 
584

  
585
class AudioFile : public QObject
584 586
{
585 587
    Q_OBJECT
586 588

  
587 589
    Q_PROPERTY(QString hash READ hash WRITE setHash NOTIFY hashChanged STORED true)
588 590
    Q_PROPERTY(Dataquay::Uri uri READ uri WRITE setUri NOTIFY uriChanged STORED true)
589
    Q_PROPERTY(QString ofaFingerprint READ ofaFingerprint WRITE setOfaFingerprint NOTIFY ofaFingerprintChanged STORED true)
590
    Q_PROPERTY(QString puid READ puid WRITE setPuid NOTIFY puidChanged STORED true)
591
    Q_PROPERTY(ClassicalData::Composer *composer READ composer WRITE setComposer NOTIFY composerChanged STORED true)
592
    Q_PROPERTY(ClassicalData::Work *work READ work WRITE setWork NOTIFY workChanged STORED true)
593
    Q_PROPERTY(ClassicalData::Movement *movement READ movement WRITE setMovement NOTIFY movementChanged STORED true)
594
    Q_PROPERTY(QSet<Dataquay::Uri> otherURIs READ otherURIs WRITE setOtherURIs NOTIFY otherURIsChanged STORED true)
595 591

  
596 592
public:
597
    TrackFile(QObject *parent = 0);
598
    TrackFile(FileSource file, QObject *parent = 0);
599
    
593
    AudioFile(QObject *parent = 0);
594
    AudioFile(FileSource file, QObject *parent = 0);
595

  
596
    /// The URI is set automatically from the FileSource at construction
597
    Dataquay::Uri uri() const { return m_uri; }
598
    void setUri(Dataquay::Uri u) { m_uri = u; emit uriChanged(u); }
599

  
600 600
    /// The hash is set automatically from the FileSource at construction
601 601
    QString hash() const { return m_hash; }
602 602
    void setHash(QString hash) { m_hash = hash; emit hashChanged(hash); }
603 603

  
604
    /// The URI is set automatically from the FileSource at construction
605
    Dataquay::Uri uri() const { return m_uri; }
606
    void setUri(Dataquay::Uri u) { m_uri = u; emit uriChanged(u); }
604
signals:
605
    void uriChanged(Dataquay::Uri);
606
    void hashChanged(QString);
607

  
608
private:
609
    Dataquay::Uri m_uri;
610
    QString m_hash;
611
};
612

  
613
class Signal : public QObject
614
{
615
    Q_OBJECT
616

  
617
    Q_PROPERTY(QString ofaFingerprint READ ofaFingerprint WRITE setOfaFingerprint NOTIFY ofaFingerprintChanged STORED true)
618
    Q_PROPERTY(QString puid READ puid WRITE setPuid NOTIFY puidChanged STORED true)
619
    Q_PROPERTY(QSet<ClassicalData::AudioFile *> availableAs READ availableAs WRITE setAvailableAs NOTIFY availableAsChanged STORED true)
620
    Q_PROPERTY(ClassicalData::Composer *composer READ composer WRITE setComposer NOTIFY composerChanged STORED true)
621
    Q_PROPERTY(ClassicalData::Work *work READ work WRITE setWork NOTIFY workChanged STORED true)
622
    Q_PROPERTY(ClassicalData::Movement *movement READ movement WRITE setMovement NOTIFY movementChanged STORED true)
623

  
624
public:
625
    Signal() : m_composer(0), m_work(0), m_movement(0) { }
607 626

  
608 627
    QString ofaFingerprint() const { return m_ofaFingerprint; }
609 628
    void setOfaFingerprint(QString fprint) { m_ofaFingerprint = fprint; emit ofaFingerprintChanged(fprint); }
......
611 630
    QString puid() const { return m_puid; }
612 631
    void setPuid(QString puid) { m_puid = puid; emit puidChanged(puid); }
613 632

  
633
    QSet<AudioFile *> availableAs() const { return m_availableAs; }
634
    void setAvailableAs(QSet<AudioFile *> aa) { m_availableAs = aa; emit availableAsChanged(m_availableAs); }
635
    void addAvailableAs(AudioFile *aa) { m_availableAs.insert(aa); emit availableAsChanged(m_availableAs); }
636

  
614 637
    Composer *composer() const { return m_composer; }
615 638
    void setComposer(Composer *c) { m_composer = c; emit composerChanged(c); }
616 639

  
......
620 643
    Movement *movement() const { return m_movement; }
621 644
    void setMovement(Movement *m) { m_movement = m; emit movementChanged(m); }
622 645

  
623
    QSet<Dataquay::Uri> otherURIs() const { return m_otherURIs; }
624
    void addOtherURI(Dataquay::Uri u) { m_otherURIs.insert(u); emit otherURIsChanged(m_otherURIs); }
625
    void setOtherURIs(QSet<Dataquay::Uri> u) { m_otherURIs = u; emit otherURIsChanged(u); }
626

  
627 646
signals:
628
    void uriChanged(Dataquay::Uri);
629
    void hashChanged(QString);
630 647
    void ofaFingerprintChanged(QString);
631 648
    void puidChanged(QString);
632 649
    void composerChanged(Composer *);
633 650
    void workChanged(Work *);
634 651
    void movementChanged(Movement *);
635
    void otherURIsChanged(QSet<Dataquay::Uri>);
652
    void availableAsChanged(QSet<AudioFile *>);
636 653

  
637 654
private:
638
    Dataquay::Uri m_uri;
639
    QString m_hash;
640 655
    QString m_ofaFingerprint;
641 656
    QString m_puid;
642 657
    Composer *m_composer;
643 658
    Work *m_work;
644 659
    Movement *m_movement;
645
    QSet<Dataquay::Uri> m_otherURIs;
660
    QSet<AudioFile *> m_availableAs;
646 661
};
647 662

  
648 663
}
......
655 670
Q_DECLARE_METATYPE(ClassicalData::Work*);
656 671
Q_DECLARE_METATYPE(ClassicalData::Movement*);
657 672
Q_DECLARE_METATYPE(ClassicalData::Document*);
673
Q_DECLARE_METATYPE(ClassicalData::AudioFile*);
674
Q_DECLARE_METATYPE(ClassicalData::Signal*);
658 675
Q_DECLARE_METATYPE(QSet<QString>);
659 676
Q_DECLARE_METATYPE(QSet<Dataquay::Uri>);
660 677
Q_DECLARE_METATYPE(QSet<ClassicalData::Work*>);
661 678
Q_DECLARE_METATYPE(QSet<ClassicalData::Movement*>);
662 679
Q_DECLARE_METATYPE(QSet<ClassicalData::Document*>);
680
Q_DECLARE_METATYPE(QSet<ClassicalData::AudioFile*>);
681
Q_DECLARE_METATYPE(QSet<ClassicalData::Signal*>);
663 682
Q_DECLARE_METATYPE(ClassicalData::Composer*);
664 683
Q_DECLARE_METATYPE(ClassicalData::Form*);
665 684
Q_DECLARE_METATYPE(QSet<ClassicalData::Form*>);
common/TypeRegistrar.cpp
47 47
	("QSet<QString>");
48 48
    qRegisterMetaType<QSet<Dataquay::Uri> >
49 49
	("QSet<Dataquay::Uri>");
50
    qRegisterMetaType<AudioFile *>
51
	("ClassicalData::AudioFile*");
52
    qRegisterMetaType<QSet<AudioFile *> >
53
	("QSet<ClassicalData::AudioFile*>");
54
    qRegisterMetaType<Signal *>
55
	("ClassicalData::Signal*");
50 56

  
51 57
    Node::registerDatatype(Uri("http://www.w3.org/2001/XMLSchema#gYear"),
52 58
			   "ClassicalData::Year", new Year::Encoder());
......
69 75
	<Document, QObject>("ClassicalData::Document*");
70 76
    ObjectBuilder::getInstance()->registerClass
71 77
	<Form, QObject>("ClassicalData::Form*");
78
    ObjectBuilder::getInstance()->registerClass
79
	<AudioFile>("ClassicalData::AudioFile*");
72 80

  
73 81
    ContainerBuilder::getInstance()->registerContainer
74 82
	<QString, QSet<QString> >
......
97 105
	<Form*, QSet<Form*> >
98 106
	("ClassicalData::Form*", "QSet<ClassicalData::Form*>",
99 107
	 ContainerBuilder::SetKind);
108

  
109
    ContainerBuilder::getInstance()->registerContainer
110
	<AudioFile*, QSet<AudioFile*> >
111
	("ClassicalData::AudioFile*", "QSet<ClassicalData::AudioFile*>",
112
	 ContainerBuilder::SetKind);
100 113
}
101 114

  
102 115
void
......
180 193
	mapping->addPropertyMapping("ClassicalData::Composition", "composer", store->expand("mo:composer"));
181 194
	mapping->addPropertyMapping("ClassicalData::Composition", "works", store->expand("mo:produced_work"));
182 195

  
183
	mapping->addTypeMapping("ClassicalData::TrackFile", store->expand("mo:AudioFile"));
196
	mapping->addTypeMapping("ClassicalData::AudioFile", store->expand("mo:AudioFile"));
197
	mapping->addPropertyMapping("ClassicalData::AudioFile", "hash", store->expand("foaf:sha1"));
198

  
199
	mapping->addTypeMapping("ClassicalData::Signal", store->expand("mo:Signal"));
200
	mapping->addPropertyMapping("ClassicalData::Signal", "availableAs", store->expand("mo:available_as"));
201
	mapping->addPropertyMapping("ClassicalData::Signal", "puid", store->expand("mo:puid"));
202
	mapping->addPropertyMapping("ClassicalData::Signal", "composer", store->expand("mo:composer"));
203
	mapping->addPropertyMapping("ClassicalData::Signal", "work", store->expand("mo:"));
204
	mapping->addPropertyMapping("ClassicalData::Signal", "availableAs", store->expand("mo:available_as"));
184 205
    }
185 206
}
186 207

  
utilities/the-application/the-application.cpp
457 457
    guessWorkFromTitle(filepart, scale, composer, guesses);
458 458
}
459 459

  
460
TrackFile *
460
Signal *
461 461
guess(QString track)
462 462
{
463 463
    cout << endl;
464 464
    cout << "Guessing composer for: " << track << endl;
465 465

  
466
//    cerr << "Creating TrackFile object...";
466
//    cerr << "Creating Signal object...";
467 467
    FileSource fs(track);
468
    TrackFile *tf = new TrackFile(fs);
468
    Signal *tf = new Signal;
469
    tf->addAvailableAs(new AudioFile(fs));
469 470
//    cerr << "done" << endl;
470 471
//    cerr << "hash = " << tf->hash() << endl;
471 472

  
......
633 634

  
634 635
    FeatureFileIndex *ffi = FeatureFileIndex::getInstance();
635 636

  
636
    ffi->loadFor(0, 0);
637
    QStringList args;
638
    for (int i = 1; i < argc; ++i) {
639
        args.push_back(argv[i]);
640
    }
641

  
642
    BasicStore bs;
643
    if (!args.empty()) {
644
        foreach (QString track, args) {
645
            FileSource fs(track);
646
            AudioFile af(fs);
647
            ffi->loadFor(&af, &bs);
648
        }
649
    } 
650

  
637 651
    
638 652
/*
639 653
    BasicStore *index = new BasicStore;
......
759 773
    if (command == "guess") {
760 774
        if (args.empty()) usage(argv[0]);
761 775
        foreach (QString track, args) {
762
            TrackFile *tf = guess(track);
776
            Signal *tf = guess(track);
763 777
            localStorer->store(tf);
764 778
        }
765 779
    } 
utilities/track/track.cpp
454 454
    guessWorkFromTitle(filepart, scale, composer, guesses);
455 455
}
456 456

  
457
TrackFile *
457
Signal *
458 458
guess(QString track)
459 459
{
460 460
    cout << endl;
461 461
    cout << "Guessing composer for: " << track << endl;
462 462

  
463
//    cerr << "Creating TrackFile object...";
463
//    cerr << "Creating Signal...";
464 464
    FileSource fs(track);
465
    TrackFile *tf = new TrackFile(fs);
465
    Signal *tf = new Signal;
466
    tf->addAvailableAs(new AudioFile(fs));
466 467
//    cerr << "done" << endl;
467 468
//    cerr << "hash = " << tf->hash() << endl;
468 469

  
......
701 702

  
702 703
    ObjectStorer *localStorer = new ObjectStorer(&localStore);
703 704
    localStorer->setTypeMapping(tm);
704
//    localStorer->setFollowPolicy(ObjectStorer::FollowObjectProperties);
705
    localStorer->setFollowPolicy(ObjectStorer::FollowObjectProperties);
706
    localStorer->setPropertyStorePolicy(ObjectStorer::StoreIfChanged);
705 707

  
706 708
    if (command == "guess") {
707 709
        if (args.empty()) usage(argv[0]);
708 710
        foreach (QString track, args) {
709
            TrackFile *tf = guess(track);
711
            Signal *tf = guess(track);
710 712
            localStorer->store(tf);
711 713
        }
712
    } 
714
    } else {
715
        usage(argv[0]);
716
    }
713 717

  
714 718
    delete localStorer;
715 719
    localStore.save("local.ttl");

Also available in: Unified diff