summaryrefslogtreecommitdiffstats
path: root/src/library/itunes/itunesdao.h
blob: 79792b89c75771ab4b1227eedb4c5d931b148768 (plain)
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#pragma once

#include <QHash>
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QString>
#include <gsl/pointers>
#include <map>

#include "library/dao/dao.h"
#include "library/itunes/itunespathmapping.h"
#include "library/treeitem.h"

const int kRootITunesPlaylistId = -1;

struct ITunesTrack {
    int id;
    QString artist;
    QString title;
    QString album;
    QString albumArtist;
    QString genre;
    QString grouping;
    int year;
    int duration;
    QString location;
    int rating;
    QString comment;
    int trackNumber;
    int bpm;
    int bitrate;

#if __cplusplus >= 202002L
    bool operator==(const ITunesTrack&) const = default;
    bool operator!=(const ITunesTrack&) const = default;
#else
    bool operator==(const ITunesTrack& other) const {
        return (id == other.id &&
                artist == other.artist &&
                title == other.title &&
                album == other.album &&
                albumArtist == other.albumArtist &&
                genre == other.genre &&
                grouping == other.grouping &&
                year == other.year &&
                duration == other.duration &&
                location == other.location &&
                rating == other.rating &&
                comment == other.comment &&
                trackNumber == other.trackNumber &&
                bpm == other.bpm &&
                bitrate == other.bitrate);
    }
#endif
};

struct ITunesPlaylist {
    int id;
    QString name;

#if __cplusplus >= 202002L
    bool operator==(const ITunesPlaylist&) const = default;
    bool operator!=(const ITunesPlaylist&) const = default;
#else
    bool operator==(const ITunesPlaylist& other) const {
        return (id == other.id &&
                name == other.name);
    }
#endif
};

std::ostream& operator<<(std::ostream& os, const ITunesTrack& track);
std::ostream& operator<<(std::ostream& os, const ITunesPlaylist& playlist);

/// A wrapper around the iTunes database tables. Keeps track of the
/// playlist tree, deals with duplicate disambiguation and can export
/// the tree afterwards.
class ITunesDAO : public DAO {
  public:
    ~ITunesDAO() override = default;

    void initialize(const QSqlDatabase& database) override;

    virtual bool importTrack(const ITunesTrack& track);
    virtual bool importPlaylist(const ITunesPlaylist& playlist);
    virtual bool importPlaylistRelation(int parentId, int childId);
    virtual bool importPlaylistTrack(int playlistId, int trackId, int position);
    virtual bool applyPathMapping(const ITunesPathMapping& pathMapping);

    virtual void appendPlaylistTree(gsl::not_null<TreeItem*> item,
            int playlistId = kRootITunesPlaylistId);

  private:
    QHash<QString, int> m_playlistDuplicatesByName;
    QHash<int, QString> m_playlistNameById;
    std::multimap<int, int> m_playlistIdsByParentId;

    // Keeps track of whether the database has been initialized.
    // In tests the database is not used, so the importer will
    // only be used to construct a TreeItem.
    bool m_isDatabaseInitialized = false;

    // Note that these queries reference the database, which is expected
    // to outlive the DAO.
    QSqlQuery m_insertTrackQuery;
    QSqlQuery m_insertPlaylistQuery;
    QSqlQuery m_insertPlaylistTrackQuery;
    QSqlQuery m_applyPathMappingQuery;

    QString uniquifyPlaylistName(QString name);
};