Task.h 7.73 KB
Newer Older
1 2 3 4 5 6
/*****************************************************************************
 * Media Library
 *****************************************************************************
 * Copyright (C) 2015 Hugo Beauzée-Luyssen, Videolabs
 *
 * Authors: Hugo Beauzée-Luyssen<hugo@beauzee.fr>
7
 *          Alexandre Fernandez <nerf@boboop.fr>
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
 *
 * This program 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 Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#pragma once

#include <memory>
27
#include <utility>
28
#include <vector>
29
#include <string>
30
#include <unordered_map>
31

32
#include "database/DatabaseHelpers.h"
33
#include "medialibrary/parser/IItem.h"
34
#include "medialibrary/parser/Parser.h"
35

36 37 38
namespace medialibrary
{

39 40 41 42 43 44
namespace fs
{
class IDirectory;
class IFile;
}

45 46
class Media;
class File;
47
class Folder;
48
class Playlist;
49

50 51
namespace parser
{
52 53
class Task;
}
54

55 56 57
namespace parser
{

58 59 60 61 62 63 64
class ITaskCb
{
public:
    virtual ~ITaskCb() = default;
    virtual bool updateFileId( int64_t fileId ) = 0;
};

65
class Task : public DatabaseHelpers<Task>, private ITaskCb
66
{
67
public:
68 69 70 71 72 73
    struct Table
    {
        static const std::string Name;
        static const std::string PrimaryKeyColumn;
        static int64_t parser::Task::*const PrimaryKey;
    };
74
    class Item : public IItem
75
    {
76
    public:
77 78 79 80 81 82 83 84
        struct MetadataHash
        {
            size_t operator()(IItem::Metadata m) const
            {
                return static_cast<size_t>( m );
            }
        };

85
        Item() = default;
86 87 88 89 90 91 92
        /**
         * @brief Item Construct a parser item with a given mrl and subitem index
         * @param mrl The item's mrl
         * @param subitemPosition A potential subitem index, if any, or 0 if none.
         *
         * The position is used to keep subitems ordering for playlists
         */
93
        Item( ITaskCb* taskCb, std::string mrl, unsigned int subitemIndex, bool isRefresh );
94
        Item( ITaskCb* taskCb, std::shared_ptr<fs::IFile> fileFs,
95
              std::shared_ptr<Folder> folder, std::shared_ptr<fs::IDirectory> folderFs,
96 97 98
              std::shared_ptr<Playlist> parentPlaylist, unsigned int parentPlaylistIndex,
              bool isRefresh );
        Item( ITaskCb* taskCb, std::shared_ptr<File> file, std::shared_ptr<fs::IFile> fileFs );
99

100

101 102
        virtual std::string meta( Metadata type ) const override;
        virtual void setMeta( Metadata type, std::string value ) override;
103

104
        virtual const std::string& mrl() const override;
105
        void setMrl( std::string mrl );
106

107 108 109
        virtual size_t nbSubItems() const override;
        virtual const IItem& subItem( unsigned int index ) const override;
        virtual IItem& createSubItem( std::string mrl, unsigned int playlistIndex ) override;
110

111 112
        virtual int64_t duration() const override;
        virtual void setDuration( int64_t duration ) override;
113

114 115
        virtual const std::vector<Track>& tracks() const override;
        virtual void addTrack( Track t ) override;
116

117 118
        virtual MediaPtr media() override;
        virtual void setMedia( MediaPtr media ) override;
119

120 121
        virtual FilePtr file() override;
        virtual bool setFile( FilePtr file ) override;
122

123
        virtual FolderPtr parentFolder() override;
124

125
        virtual std::shared_ptr<fs::IFile> fileFs() override;
126

127
        virtual std::shared_ptr<fs::IDirectory> parentFolderFs() override;
128

129
        virtual PlaylistPtr parentPlaylist() override;
130

131
        virtual unsigned int parentPlaylistIndex() const override;
132

133 134
        virtual bool isRefresh() const override;

135
    private:
136 137
        ITaskCb* m_taskCb;

138
        std::string m_mrl;
139
        std::unordered_map<Metadata, std::string, MetadataHash> m_metadata;
140
        std::vector<Item> m_subItems;
141
        std::vector<Track> m_tracks;
142
        int64_t m_duration;
143 144
        MediaPtr m_media;
        FilePtr m_file;
145
        std::shared_ptr<fs::IFile> m_fileFs;
146
        FolderPtr m_parentFolder;
147
        std::shared_ptr<fs::IDirectory> m_parentFolderFs;
148
        PlaylistPtr m_parentPlaylist;
149
        unsigned int m_parentPlaylistIndex;
150
        bool m_isRefresh;
151 152
    };

153 154
    static_assert( std::is_move_assignable<Item>::value, "Item must be move assignable" );

155

156 157 158 159 160
    /*
     * Constructs a task to be resumed.
     * The Media is provided as a parameter to avoid this to implicitely query
     * the database for the media associated to the provided file
     */
161 162
    Task( MediaLibraryPtr ml, sqlite::Row& row );
    Task( MediaLibraryPtr ml, std::shared_ptr<fs::IFile> fileFs,
163
          std::shared_ptr<Folder> parentFolder,
164
          std::shared_ptr<fs::IDirectory> parentFolderFs,
165
          std::shared_ptr<Playlist> parentPlaylist,
166
          unsigned int parentPlaylistIndex );
167 168
    Task( MediaLibraryPtr ml, std::shared_ptr<File> file,
          std::shared_ptr<fs::IFile> fileFs );
169

170 171 172 173 174 175 176
    /*
     * We need to decouple the current parser state and the saved one.
     * For instance, metadata extraction won't save anything in DB, so while
     * we might want to know that it's been processed and metadata have been
     * extracted, in case we were to restart the parsing, we would need to
     * extract the same information again
     */
177
    void markStepCompleted( parser::Step stepCompleted );
178
    bool saveParserStep();
179 180 181 182
    // Reset the retry count to 0 but doesn't advance the step.
    // This is intended to be used when a step requires its completion not to be
    // saved in database, but to avoid having a retry_count being incremented again
    // when starting next step.
183
    bool decrementRetryCount();
184
    bool isCompleted() const;
185
    bool isStepCompleted( parser::Step step ) const;
186 187 188 189 190
    /**
     * @brief startParserStep Do some internal book keeping to avoid restarting a step too many time
     */
    void startParserStep();

191
    virtual bool updateFileId( int64_t fileId ) override;
192
    int64_t id() const;
193

194
    Item& item();
195

196 197
    // Restore attached entities such as media/files
    bool restoreLinkedEntities();
198
    void setMrl( std::string mrl );
199

200
    unsigned int                    currentService;
201 202 203 204

    static void createTable( sqlite::Connection* dbConnection );
    static void resetRetryCount( MediaLibraryPtr ml );
    static void resetParsing( MediaLibraryPtr ml );
205
    static std::vector<std::shared_ptr<Task>> fetchUncompleted( MediaLibraryPtr ml );
206 207 208
    static std::shared_ptr<Task> create( MediaLibraryPtr ml, std::shared_ptr<fs::IFile> fileFs,
                                         std::shared_ptr<Folder> parentFolder,
                                         std::shared_ptr<fs::IDirectory> parentFolderFs,
209 210
                                         std::pair<std::shared_ptr<Playlist>,
                                         unsigned int> parentPlaylist );
211
    static std::shared_ptr<Task> createRefreshTask( MediaLibraryPtr ml, std::shared_ptr<File> file,
212
                                         std::shared_ptr<fs::IFile> fsFile );
213
    static void recoverUnscannedFiles( MediaLibraryPtr ml );
214 215 216 217

private:
    MediaLibraryPtr m_ml;
    int64_t     m_id;
218
    Step        m_step;
219 220 221 222
    int         m_retryCount;
    int64_t     m_fileId;
    int64_t     m_parentFolderId;
    int64_t     m_parentPlaylistId;
223
    Item        m_item;
224

225
    friend Task::Table;
226 227 228
};

}
229 230

}