ModificationsNotifier.cpp 5.97 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
/*****************************************************************************
 * Media Library
 *****************************************************************************
 * Copyright (C) 2015 Hugo Beauzée-Luyssen, Videolabs
 *
 * Authors: Hugo Beauzée-Luyssen<hugo@beauzee.fr>
 *
 * 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.
 *****************************************************************************/

23 24 25 26
#if HAVE_CONFIG_H
# include "config.h"
#endif

27 28
#include <cassert>

29
#include "ModificationsNotifier.h"
30 31
#include "MediaLibrary.h"

32 33 34
namespace medialibrary
{

35
ModificationNotifier::ModificationNotifier( MediaLibraryPtr ml )
36 37
    : m_ml( ml )
    , m_cb( ml->getCb() )
38
    , m_stop( false )
39 40 41
{
}

42
ModificationNotifier::~ModificationNotifier()
43 44 45 46 47 48 49 50 51
{
    if ( m_notifierThread.joinable() == true )
    {
        m_stop = true;
        m_cond.notify_all();
        m_notifierThread.join();
    }
}

52
void ModificationNotifier::start()
53
{
54 55
    assert( m_notifierThread.get_id() == compat::Thread::id{} );
    m_notifierThread = compat::Thread{ &ModificationNotifier::run, this };
56 57
}

58
void ModificationNotifier::notifyMediaCreation( MediaPtr media )
59
{
60
    notifyCreation( std::move( media ), m_media );
61 62
}

63
void ModificationNotifier::notifyMediaModification( MediaPtr media )
64
{
65
    notifyModification( std::move( media ), m_media );
66 67
}

68 69 70 71
void ModificationNotifier::notifyMediaRemoval( int64_t mediaId )
{
    notifyRemoval( mediaId, m_media );
}
72

73 74 75 76 77
void ModificationNotifier::notifyArtistCreation( ArtistPtr artist )
{
    notifyCreation( std::move( artist ), m_artists );
}

78
void ModificationNotifier::notifyArtistModification( ArtistPtr artist )
79 80 81 82 83 84 85 86 87
{
    notifyModification( std::move( artist ), m_artists );
}

void ModificationNotifier::notifyArtistRemoval( int64_t artist )
{
    notifyRemoval( std::move( artist ), m_artists );
}

88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
void ModificationNotifier::notifyAlbumCreation( AlbumPtr album )
{
    notifyCreation( std::move( album ), m_albums );
}

void ModificationNotifier::notifyAlbumModification( AlbumPtr album )
{
    notifyModification( std::move( album ), m_albums );
}

void ModificationNotifier::notifyAlbumRemoval( int64_t albumId )
{
    notifyRemoval( albumId, m_albums );
}

103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
void ModificationNotifier::notifyAlbumTrackCreation( AlbumTrackPtr track )
{
    notifyCreation( std::move( track ), m_tracks );
}

void ModificationNotifier::notifyAlbumTrackModification( AlbumTrackPtr track )
{
    notifyModification( std::move( track ), m_tracks );
}

void ModificationNotifier::notifyAlbumTrackRemoval( int64_t trackId )
{
    notifyRemoval( trackId, m_tracks );
}

118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
void ModificationNotifier::notifyPlaylistCreation( PlaylistPtr playlist )
{
    notifyCreation( std::move( playlist ), m_playlists );
}

void ModificationNotifier::notifyPlaylistModification( PlaylistPtr playlist )
{
    notifyModification( std::move( playlist ), m_playlists );
}

void ModificationNotifier::notifyPlaylistRemoval( int64_t playlistId )
{
    notifyRemoval( playlistId, m_playlists );
}

133
void ModificationNotifier::run()
134
{
135
#if !defined(_LIBCPP_STD_VER) || (_LIBCPP_STD_VER > 11 && !defined(_LIBCPP_HAS_NO_CXX14_CONSTEXPR))
136
    constexpr auto ZeroTimeout = std::chrono::time_point<std::chrono::steady_clock>{};
137 138 139
#else
    const auto ZeroTimeout = std::chrono::time_point<std::chrono::steady_clock>{};
#endif
140 141 142 143

    // Create some other queue to swap with the ones that are used
    // by other threads. That way we can release those early and allow
    // more insertions to proceed
144
    Queue<IMedia> media;
145
    Queue<IArtist> artists;
146
    Queue<IAlbum> albums;
147
    Queue<IAlbumTrack> tracks;
148
    Queue<IPlaylist> playlists;
149 150 151 152

    while ( m_stop == false )
    {
        {
153
            std::unique_lock<compat::Mutex> lock( m_lock );
154 155
            if ( m_timeout == ZeroTimeout )
                m_cond.wait( lock, [this, ZeroTimeout](){ return m_timeout != ZeroTimeout || m_stop == true; } );
156
            m_cond.wait_until( lock, m_timeout, [this]() { return m_stop == true; });
157 158 159 160 161
            if ( m_stop == true )
                break;
            auto now = std::chrono::steady_clock::now();
            auto nextTimeout = ZeroTimeout;
            checkQueue( m_media, media, nextTimeout, now );
162
            checkQueue( m_artists, artists, nextTimeout, now );
163
            checkQueue( m_albums, albums, nextTimeout, now );
164
            checkQueue( m_tracks, tracks, nextTimeout, now );
165
            checkQueue( m_playlists, playlists, nextTimeout, now );
166 167
            m_timeout = nextTimeout;
        }
168
        notify( std::move( media ), &IMediaLibraryCb::onMediaAdded, &IMediaLibraryCb::onMediaUpdated, &IMediaLibraryCb::onMediaDeleted );
169
        notify( std::move( artists ), &IMediaLibraryCb::onArtistsAdded, &IMediaLibraryCb::onArtistsModified, &IMediaLibraryCb::onArtistsDeleted );
170
        notify( std::move( albums ), &IMediaLibraryCb::onAlbumsAdded, &IMediaLibraryCb::onAlbumsModified, &IMediaLibraryCb::onAlbumsDeleted );
171 172 173
        // We pass the onTrackAdded callback twice, to avoid having to do some nifty templates specialization
        // for nullptr callbacks. There is no onTracksModified callback, as tracks are never modified.
        notify( std::move( tracks ), &IMediaLibraryCb::onTracksAdded, &IMediaLibraryCb::onTracksAdded, &IMediaLibraryCb::onTracksDeleted );
174
        notify( std::move( playlists ), &IMediaLibraryCb::onPlaylistsAdded, &IMediaLibraryCb::onPlaylistsAdded, &IMediaLibraryCb::onPlaylistsDeleted );
175 176
    }
}
177 178

}