VLCMetadataService.cpp 5.6 KB
Newer Older
1
2
#include <iostream>

Hugo Beauzée-Luyssen's avatar
Hugo Beauzée-Luyssen committed
3
4
5
6
//debug
#include <chrono>
#include <thread>

7
8
9
10
#include "VLCMetadataService.h"
#include "IFile.h"
#include "IAlbum.h"
#include "IAlbumTrack.h"
11
#include "IShow.h"
12

13
14
#include "File.h"

15
VLCMetadataService::VLCMetadataService( const VLC::Instance& vlc )
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
    : m_instance( vlc )
    , m_cb( nullptr )
    , m_ml( nullptr )
{
}

bool VLCMetadataService::initialize( IMetadataServiceCb* callback, IMediaLibrary* ml )
{
    m_cb = callback;
    m_ml = ml;
    return true;
}

unsigned int VLCMetadataService::priority() const
{
    return 100;
}

34
bool VLCMetadataService::run( FilePtr file, void* data )
35
{
36
37
    LOG_INFO( "Parsing ", file->mrl() );

Hugo Beauzée-Luyssen's avatar
Hugo Beauzée-Luyssen committed
38
39
40
    auto ctx = new Context( file );
    ctx->media = VLC::Media( m_instance, file->mrl(), VLC::Media::FromPath );

41
42
43
44
    std::unique_lock<std::mutex> lock( m_mutex );
    bool parsed;

    ctx->media.eventManager().onParsedChanged([this, ctx, data, &parsed](bool status) mutable {
45
46
        if ( status == false )
            return;
Hugo Beauzée-Luyssen's avatar
Hugo Beauzée-Luyssen committed
47
48
        auto res = handleMediaMeta( ctx->file, ctx->media );
        m_cb->done( ctx->file, res, data );
49
50
51
52

        std::unique_lock<std::mutex> lock( m_mutex );
        parsed = true;
        m_cond.notify_all();
53
    });
Hugo Beauzée-Luyssen's avatar
Hugo Beauzée-Luyssen committed
54
    ctx->media.parseAsync();
55
    m_cond.wait( lock, [&parsed]() { return parsed == true; } );
56
57
58
    return true;
}

59
ServiceStatus VLCMetadataService::handleMediaMeta( FilePtr file, VLC::Media& media ) const
60
{
61
    auto tracks = media.tracks();
62
    if ( tracks.size() == 0 )
63
    {
64
        LOG_ERROR( "Failed to fetch tracks" );
65
66
        return StatusFatal;
    }
67
    bool isAudio = true;
68
    for ( auto& track : tracks )
69
    {
70
71
72
        auto codec = track.codec();
        std::string fcc( (const char*)&codec, 4 );
        if ( track.type() == VLC::MediaTrack::Video )
73
74
        {
            isAudio = false;
75
            auto fps = (float)track.fpsNum() / (float)track.fpsDen();
76
            file->addVideoTrack( fcc, track.width(), track.height(), fps );
77
        }
78
        else if ( track.type() == VLC::MediaTrack::Audio )
79
        {
80
            file->addAudioTrack( fcc, track.bitrate(), track.rate(),
81
                                      track.channels() );
82
83
        }
    }
84
85
    auto duration = media.duration();
    file->setDuration( duration );
86
87
    if ( isAudio == true )
    {
88
        if ( parseAudioFile( file, media ) == false )
89
            return StatusFatal;
90
91
92
    }
    else
    {
93
        if (parseVideoFile( file, media ) == false )
94
            return StatusFatal;
95
    }
96
    return StatusSuccess;
97
98
}

99
bool VLCMetadataService::parseAudioFile( FilePtr file, VLC::Media& media ) const
100
{
101
    file->setType( IFile::Type::AudioType );
102
    auto albumTitle = media.meta( libvlc_meta_Album );
103
104
    if ( albumTitle.length() == 0 )
        return true;
105
106
    auto album = m_ml->album( albumTitle );
    if ( album == nullptr )
107
    {
108
        album = m_ml->createAlbum( albumTitle );
109
110
111
112
113
114
115
        if ( album != nullptr )
        {
            auto date = media.meta( libvlc_meta_Date );
            if ( date.length() > 0 )
                album->setReleaseDate( std::stoul( date ) );
        }
    }
116
117
    if ( album == nullptr )
    {
118
        LOG_ERROR( "Failed to create/get album" );
119
        return false;
120
121
    }

122
    auto trackNbStr = media.meta( libvlc_meta_TrackNumber );
123
    if ( trackNbStr.length() == 0 )
124
    {
125
        LOG_ERROR( "Failed to get track id" );
126
        return false;
127
    }
128
    auto artwork = media.meta( libvlc_meta_ArtworkURL );
129
    if ( artwork.length() != 0 )
130
        album->setArtworkUrl( artwork );
131

132
    auto title = media.meta( libvlc_meta_Title );
133
    if ( title.length() == 0 )
134
    {
135
        LOG_ERROR( "Failed to compute track title" );
136
137
138
        title = "Unknown track #";
        title += trackNbStr;
    }
139
    unsigned int trackNb = std::stoi( trackNbStr );
140
141
142
    auto track = album->addTrack( title, trackNb );
    if ( track == nullptr )
    {
143
        LOG_ERROR( "Failure while creating album track" );
144
        return false;
145
    }
146
    file->setAlbumTrack( track );
147

148
    auto genre = media.meta( libvlc_meta_Genre );
149
    if ( genre.length() != 0 )
150
        track->setGenre( genre );
151

152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
    auto artistName = media.meta( libvlc_meta_Artist );
    if ( artistName.length() != 0 )
    {
        auto artist = m_ml->artist( artistName );
        if ( artist == nullptr )
        {
            artist = m_ml->createArtist( artistName );
            if ( artist == nullptr )
            {
                LOG_ERROR( "Failed to create new artist ", artistName );
                // Consider this a minor failure and go on nevertheless
                return true;
            }
        }
        track->addArtist( artist );
    }
168
    return true;
169
170
}

171
bool VLCMetadataService::parseVideoFile( FilePtr file, VLC::Media& media ) const
172
{
173
    file->setType( IFile::Type::VideoType );
174
    auto title = media.meta( libvlc_meta_Title );
175
176
    if ( title.length() == 0 )
        return true;
177
    auto showName = media.meta( libvlc_meta_ShowName );
178
179
    if ( showName.length() == 0 )
    {
180
        auto show = m_ml->show( showName );
181
182
        if ( show == nullptr )
        {
183
            show = m_ml->createShow( showName );
184
185
186
            if ( show == nullptr )
                return false;
        }
187

188
        auto episodeIdStr = media.meta( libvlc_meta_Episode );
189
190
191
192
193
194
        if ( episodeIdStr.length() > 0 )
        {
            size_t endpos;
            int episodeId = std::stoi( episodeIdStr, &endpos );
            if ( endpos != episodeIdStr.length() )
            {
195
                LOG_ERROR( "Invalid episode id provided" );
196
197
198
199
200
201
202
203
204
205
                return true;
            }
            show->addEpisode( title, episodeId );
        }
    }
    else
    {
        // How do we know if it's a movie or a random video?
    }
    return true;
206
}