Commit 4c3e6a04 authored by Hugo Beauzée-Luyssen's avatar Hugo Beauzée-Luyssen

Add a network filesystem implementation

This can be used to use the regular FsDiscoverer with network shares
parent 299ccdbe
......@@ -56,10 +56,14 @@ libmedialibrary_la_SOURCES = \
src/discoverer/DiscovererWorker.cpp \
src/discoverer/FsDiscoverer.cpp \
src/factory/FileSystemFactory.cpp \
src/factory/NetworkFileSystemFactory.cpp \
src/factory/DeviceListerFactory.cpp \
src/filesystem/common/CommonDevice.cpp \
src/filesystem/common/CommonFile.cpp \
src/filesystem/common/CommonDirectory.cpp \
src/filesystem/network/Directory.cpp \
src/filesystem/network/File.cpp \
src/filesystem/network/Device.cpp \
src/logging/IostreamLogger.cpp \
src/logging/Logger.cpp \
src/metadata_services/MetadataParser.cpp \
......@@ -111,6 +115,7 @@ noinst_HEADERS = \
src/discoverer/DiscovererWorker.h \
src/discoverer/FsDiscoverer.h \
src/factory/FileSystemFactory.h \
src/factory/NetworkFileSystemFactory.h \
src/factory/DeviceListerFactory.h \
src/File.h \
src/filesystem/common/CommonFile.h \
......@@ -119,6 +124,9 @@ noinst_HEADERS = \
src/filesystem/unix/Device.h \
src/filesystem/unix/Directory.h \
src/filesystem/unix/File.h \
src/filesystem/network/Device.h \
src/filesystem/network/Directory.h \
src/filesystem/network/File.h \
src/filesystem/unix/DeviceLister.h \
src/filesystem/win32/Directory.h \
src/filesystem/win32/File.h \
......
/*****************************************************************************
* 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.
*****************************************************************************/
#if HAVE_CONFIG_H
#include "config.h"
#endif
#include "NetworkFileSystemFactory.h"
#include "filesystem/network/Directory.h"
#include "utils/VLCInstance.h"
#include "MediaLibrary.h"
#include <algorithm>
namespace medialibrary
{
namespace factory
{
NetworkFileSystemFactory::NetworkFileSystemFactory( const std::string& protocol, const std::string& name )
: m_discoverer( VLCInstance::get(), name )
, m_mediaList( m_discoverer.mediaList() )
, m_protocol( protocol )
{
auto& em = m_mediaList->eventManager();
em.onItemAdded( [this]( VLC::MediaPtr m, int ) { onDeviceAdded( m ); } );
em.onItemDeleted( [this]( VLC::MediaPtr m, int ) { onDeviceRemoved( m ); } );
m_discoverer.start();
}
std::shared_ptr<fs::IDirectory> NetworkFileSystemFactory::createDirectory( const std::string& path )
{
return std::make_shared<fs::NetworkDirectory>( path, *this );
}
std::shared_ptr<fs::IDevice> NetworkFileSystemFactory::createDevice( const std::string& mrl )
{
std::shared_ptr<fs::IDevice> res;
std::unique_lock<compat::Mutex> lock( m_devicesLock );
m_deviceCond.wait_for( lock, std::chrono::seconds{ 5 }, [this, &res, &mrl]() {
auto it = std::find_if( begin( m_devices ), end( m_devices ), [&mrl]( const Device& d ) {
return d.mrl == mrl;
});
if ( it == end( m_devices ) )
return false;
res = it->device;
return true;
});
return res;
}
std::shared_ptr<fs::IDevice> NetworkFileSystemFactory::createDeviceFromPath( const std::string& path )
{
std::lock_guard<compat::Mutex> lock( m_devicesLock );
auto it = std::find_if( begin( m_devices ), end( m_devices ), [&path]( const Device& d ) {
return path.compare( 0, d.mrl.length(), d.mrl );
});
if ( it == end( m_devices ) )
return nullptr;
return it->device;
}
bool NetworkFileSystemFactory::refreshDevices()
{
return true;
}
bool NetworkFileSystemFactory::isPathSupported( const std::string& path ) const
{
const auto idx = m_protocol.length();
if ( path.compare( 0, idx, m_protocol ) != 0 )
return false;
return path[idx] == ':' && path[idx + 1] == '/' && path[idx + 2] == '/';
}
bool NetworkFileSystemFactory::isNetworkFileSystem() const
{
return true;
}
void NetworkFileSystemFactory::onDeviceAdded( VLC::MediaPtr media )
{
const auto& mrl = media->mrl();
if ( mrl.compare( 0, m_protocol.length(), m_protocol ) != 0 )
return;
std::lock_guard<compat::Mutex> lock( m_devicesLock );
auto it = std::find_if( begin( m_devices ), end( m_devices ), [&mrl]( const Device& d ) {
return d.mrl== mrl;
});
if ( it != end( m_devices ) )
return;
const auto idx = m_protocol.length();
if ( mrl[idx] != ':' || mrl[idx + 1] != '/' || mrl[idx + 2] != '/' )
return;
auto name = mrl.substr( idx + 3 );
m_devices.emplace_back( name, mrl, *media );
m_deviceCond.notify_one();
}
void NetworkFileSystemFactory::onDeviceRemoved( VLC::MediaPtr media )
{
std::lock_guard<compat::Mutex> lock( m_devicesLock );
const auto& mrl = media->mrl();
std::remove_if( begin( m_devices ), end( m_devices ), [&mrl]( const Device& d ) {
return d.mrl == mrl;
});
}
}
}
/*****************************************************************************
* 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.
*****************************************************************************/
#include "factory/IFileSystem.h"
#include "filesystem/network/Device.h"
#include "compat/ConditionVariable.h"
#include "compat/Mutex.h"
#include <vlcpp/vlc.hpp>
namespace medialibrary
{
class IMediaLibraryCb;
namespace factory
{
class NetworkFileSystemFactory : public factory::IFileSystem
{
public:
/**
* @brief NetworkFileSystemFactory Constructs a network protocol specific filesystem factory
* @param protocol The protocol name
*/
NetworkFileSystemFactory( const std::string& protocol, const std::string& name );
virtual std::shared_ptr<fs::IDirectory> createDirectory( const std::string& path ) override;
virtual std::shared_ptr<fs::IDevice> createDevice( const std::string& uuid ) override;
virtual std::shared_ptr<fs::IDevice> createDeviceFromPath( const std::string& path ) override;
virtual bool refreshDevices() override;
virtual bool isPathSupported( const std::string& path ) const override;
virtual bool isNetworkFileSystem() const override;
private:
void onDeviceAdded( VLC::MediaPtr media );
void onDeviceRemoved( VLC::MediaPtr media );
private:
struct Device
{
Device( const std::string& name, const std::string& mrl, VLC::Media media )
: name( name )
, mrl( mrl )
, media( media )
, device( std::make_shared<fs::NetworkDevice>( name, mrl ) )
{}
std::string name;
std::string mrl;
VLC::Media media;
std::shared_ptr<fs::NetworkDevice> device;
};
VLC::MediaDiscoverer m_discoverer;
std::shared_ptr<VLC::MediaList> m_mediaList;
const std::string m_protocol;
IMediaLibraryCb* m_cb;
compat::Mutex m_devicesLock;
compat::ConditionVariable m_deviceCond;
std::vector<Device> m_devices;
};
}
}
/*****************************************************************************
* 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.
*****************************************************************************/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include "Device.h"
namespace medialibrary
{
namespace fs
{
NetworkDevice::NetworkDevice( const std::string& name, const std::string& mrl )
: CommonDevice( name, mrl, true )
{
}
}
}
/*****************************************************************************
* 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.
*****************************************************************************/
#pragma once
#include "filesystem/common/CommonDevice.h"
#include <memory>
#include <unordered_map>
namespace medialibrary
{
namespace fs
{
class NetworkDevice : public CommonDevice
{
public:
NetworkDevice( const std::string& name, const std::string& mrl );
};
}
}
/*****************************************************************************
* 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.
*****************************************************************************/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include "Directory.h"
#include "File.h"
#include "utils/VLCInstance.h"
#include "compat/ConditionVariable.h"
#include "compat/Mutex.h"
#include <vlcpp/vlc.hpp>
namespace medialibrary
{
namespace fs
{
NetworkDirectory::NetworkDirectory( const std::string& path, factory::IFileSystem& fsFactory )
: CommonDirectory( path, fsFactory )
{
}
void NetworkDirectory::read() const
{
VLC::Media media( VLCInstance::get(), m_path, VLC::Media::FromLocation );
assert( media.parsedStatus() != VLC::Media::ParsedStatus::Done );
compat::Mutex mutex;
compat::ConditionVariable cond;
VLC::Media::ParsedStatus res = VLC::Media::ParsedStatus::Skipped;
media.eventManager().onParsedChanged([&mutex, &cond, &res]( VLC::Media::ParsedStatus status) {
std::lock_guard<compat::Mutex> lock( mutex );
res = status;
});
std::unique_lock<compat::Mutex> lock( mutex );
media.parseWithOptions( VLC::Media::ParseFlags::Network | VLC::Media::ParseFlags::Local |
VLC::Media::ParseFlags::FetchLocal | VLC::Media::ParseFlags::FetchNetwork, -1 );
bool timeout = cond.wait_for( lock, std::chrono::seconds{ 5 }, [res]() {
return res != VLC::Media::ParsedStatus::Skipped;
});
if ( timeout == true )
throw std::runtime_error( "Failed to browse network directory: Network is too slow" );
if ( res == VLC::Media::ParsedStatus::Failed )
throw std::runtime_error( "Failed to browse network directory: Unknown error" );
auto subItems = media.subitems();
for ( auto i = 0; i < subItems->count(); ++i )
{
auto m = subItems->itemAtIndex( i );
if ( m->type() == VLC::Media::Type::Directory )
m_dirs.push_back( std::make_shared<fs::NetworkDirectory>( m->mrl(), m_fsFactory ) );
else
m_files.push_back( std::make_shared<fs::NetworkFile>( m->mrl() ) );
}
}
}
}
/*****************************************************************************
* 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.
*****************************************************************************/
#include "filesystem/common/CommonDirectory.h"
namespace medialibrary
{
namespace fs
{
class NetworkDirectory : public CommonDirectory
{
public:
NetworkDirectory( const std::string& path, factory::IFileSystem& fsFactory );
private:
virtual void read() const override;
};
}
}
/*****************************************************************************
* 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.
*****************************************************************************/
#if HAVE_CONFIG_H
#include "config.h"
#endif
#include "File.h"
namespace medialibrary
{
namespace fs
{
NetworkFile::NetworkFile( const std::string& filePath )
: CommonFile( filePath )
{
}
unsigned int NetworkFile::lastModificationDate() const
{
return 0;
}
}
}
/*****************************************************************************
* 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.
*****************************************************************************/
#pragma once
#include "filesystem/common/CommonFile.h"
namespace medialibrary
{
namespace fs
{
class NetworkFile : public CommonFile
{
public:
NetworkFile( const std::string& filePath );
virtual unsigned int lastModificationDate() const override;
};
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment