Task.h 8.52 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;
};

Hugo Beauzée-Luyssen's avatar
Hugo Beauzée-Luyssen committed
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 94
        Item( ITaskCb* taskCb, std::string mrl, IFile::Type fileType,
              unsigned int subitemIndex, bool isRefresh );
95
        Item( ITaskCb* taskCb, std::string mrl, std::shared_ptr<fs::IFile> fileFs,
96
              std::shared_ptr<Folder> folder, std::shared_ptr<fs::IDirectory> folderFs,
97
              IFile::Type fileType,
Hugo Beauzée-Luyssen's avatar
Hugo Beauzée-Luyssen committed
98 99 100
              std::shared_ptr<Playlist> parentPlaylist, unsigned int parentPlaylistIndex,
              bool isRefresh );
        Item( ITaskCb* taskCb, std::shared_ptr<File> file, std::shared_ptr<fs::IFile> fileFs );
Hugo Beauzée-Luyssen's avatar
Hugo Beauzée-Luyssen committed
101

102

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

106
        virtual const std::string& mrl() const override;
107
        void setMrl( std::string mrl );
108

109 110
        virtual IFile::Type fileType() const override;

111 112 113
        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;
114

115 116
        virtual int64_t duration() const override;
        virtual void setDuration( int64_t duration ) override;
117

118
        virtual const std::vector<Track>& tracks() const override;
119
        virtual void addTrack( Track&& t ) override;
120

121 122
        virtual MediaPtr media() override;
        virtual void setMedia( MediaPtr media ) override;
123

124 125
        virtual FilePtr file() override;
        virtual bool setFile( FilePtr file ) override;
126

127
        virtual FolderPtr parentFolder() override;
128

129
        virtual std::shared_ptr<fs::IFile> fileFs() override;
130

131
        virtual std::shared_ptr<fs::IDirectory> parentFolderFs() override;
132

133
        virtual PlaylistPtr parentPlaylist() override;
134

135
        virtual unsigned int parentPlaylistIndex() const override;
136

137 138
        virtual bool isRefresh() const override;

139
    private:
140 141
        ITaskCb* m_taskCb;

142
        std::string m_mrl;
143
        IFile::Type m_fileType;
Hugo Beauzée-Luyssen's avatar
Hugo Beauzée-Luyssen committed
144
        std::unordered_map<Metadata, std::string, MetadataHash> m_metadata;
145
        std::vector<Item> m_subItems;
146
        std::vector<Track> m_tracks;
147
        int64_t m_duration;
148 149
        MediaPtr m_media;
        FilePtr m_file;
150
        std::shared_ptr<fs::IFile> m_fileFs;
151
        FolderPtr m_parentFolder;
152
        std::shared_ptr<fs::IDirectory> m_parentFolderFs;
153
        PlaylistPtr m_parentPlaylist;
154
        unsigned int m_parentPlaylistIndex;
155
        bool m_isRefresh;
156 157
    };

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

160

161
    Task( MediaLibraryPtr ml, sqlite::Row& row );
162 163 164 165 166 167 168 169 170 171
    /**
     * @brief Task Construct a task for a newly detected file
     * @param ml A pointer to the medialibrary instance
     * @param fileFs The file, as seen on the filesystem
     * @param parentFolder The parent folder, in DB
     * @param parentFolderFs The parent folder, as seen on the filesystem
     * @param fileType The newly detected file type
     * @param parentPlaylist A parent playlist, if any
     * @param parentPlaylistIndex The index in the playlist
     */
172
    Task( MediaLibraryPtr ml, std::string mrl, std::shared_ptr<fs::IFile> fileFs,
173
          std::shared_ptr<Folder> parentFolder,
174
          std::shared_ptr<fs::IDirectory> parentFolderFs,
175
          IFile::Type fileType,
176
          std::shared_ptr<Playlist> parentPlaylist,
177
          unsigned int parentPlaylistIndex );
178 179 180 181 182 183
    /**
     * @brief Task Constructor for refresh tasks
     * @param ml A medialibrary instance pointer
     * @param file The known file, to be refreshed
     * @param fileFs The updated file, on the filesystem
     */
Hugo Beauzée-Luyssen's avatar
Hugo Beauzée-Luyssen committed
184 185
    Task( MediaLibraryPtr ml, std::shared_ptr<File> file,
          std::shared_ptr<fs::IFile> fileFs );
186

187 188 189 190 191 192 193
    /*
     * 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
     */
194
    void markStepCompleted( parser::Step stepCompleted );
195
    bool saveParserStep();
196 197 198 199
    // 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.
200
    bool decrementRetryCount();
201
    bool isCompleted() const;
202
    bool isStepCompleted( parser::Step step ) const;
203 204 205 206 207
    /**
     * @brief startParserStep Do some internal book keeping to avoid restarting a step too many time
     */
    void startParserStep();

208
    virtual bool updateFileId( int64_t fileId ) override;
209
    int64_t id() const;
210

211
    Item& item();
212

213 214
    // Restore attached entities such as media/files
    bool restoreLinkedEntities();
215
    void setMrl( std::string mrl );
216

217
    unsigned int                    currentService;
218 219 220 221

    static void createTable( sqlite::Connection* dbConnection );
    static void resetRetryCount( MediaLibraryPtr ml );
    static void resetParsing( MediaLibraryPtr ml );
222
    static std::vector<std::shared_ptr<Task>> fetchUncompleted( MediaLibraryPtr ml );
223
    static std::shared_ptr<Task> create( MediaLibraryPtr ml, std::string mrl, std::shared_ptr<fs::IFile> fileFs,
224 225
                                         std::shared_ptr<Folder> parentFolder,
                                         std::shared_ptr<fs::IDirectory> parentFolderFs,
226
                                         IFile::Type fileType,
227 228
                                         std::pair<std::shared_ptr<Playlist>,
                                         unsigned int> parentPlaylist );
229
    static std::shared_ptr<Task> createRefreshTask( MediaLibraryPtr ml, std::shared_ptr<File> file,
Hugo Beauzée-Luyssen's avatar
Hugo Beauzée-Luyssen committed
230
                                         std::shared_ptr<fs::IFile> fsFile );
231
    static void recoverUnscannedFiles( MediaLibraryPtr ml );
232 233 234 235

private:
    MediaLibraryPtr m_ml;
    int64_t     m_id;
236
    Step        m_step;
237 238 239 240
    int         m_retryCount;
    int64_t     m_fileId;
    int64_t     m_parentFolderId;
    int64_t     m_parentPlaylistId;
241
    Item        m_item;
242

243
    friend Task::Table;
244 245 246
};

}
247 248

}