Upgraded code to switch to C++17. Tested on Debian Buster
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
Installation Instructions
|
||||
*************************
|
||||
|
||||
Copyright (C) 1994-1996, 1999-2002, 2004-2013 Free Software Foundation,
|
||||
Inc.
|
||||
Copyright (C) 1994-1996, 1999-2002, 2004-2016 Free Software
|
||||
Foundation, Inc.
|
||||
|
||||
Copying and distribution of this file, with or without modification,
|
||||
are permitted in any medium without royalty provided the copyright
|
||||
@@ -12,97 +12,96 @@ without warranty of any kind.
|
||||
Basic Installation
|
||||
==================
|
||||
|
||||
Briefly, the shell command `./configure && make && make install'
|
||||
Briefly, the shell command './configure && make && make install'
|
||||
should configure, build, and install this package. The following
|
||||
more-detailed instructions are generic; see the `README' file for
|
||||
more-detailed instructions are generic; see the 'README' file for
|
||||
instructions specific to this package. Some packages provide this
|
||||
`INSTALL' file but do not implement all of the features documented
|
||||
'INSTALL' file but do not implement all of the features documented
|
||||
below. The lack of an optional feature in a given package is not
|
||||
necessarily a bug. More recommendations for GNU packages can be found
|
||||
in *note Makefile Conventions: (standards)Makefile Conventions.
|
||||
|
||||
The `configure' shell script attempts to guess correct values for
|
||||
The 'configure' shell script attempts to guess correct values for
|
||||
various system-dependent variables used during compilation. It uses
|
||||
those values to create a `Makefile' in each directory of the package.
|
||||
It may also create one or more `.h' files containing system-dependent
|
||||
definitions. Finally, it creates a shell script `config.status' that
|
||||
those values to create a 'Makefile' in each directory of the package.
|
||||
It may also create one or more '.h' files containing system-dependent
|
||||
definitions. Finally, it creates a shell script 'config.status' that
|
||||
you can run in the future to recreate the current configuration, and a
|
||||
file `config.log' containing compiler output (useful mainly for
|
||||
debugging `configure').
|
||||
file 'config.log' containing compiler output (useful mainly for
|
||||
debugging 'configure').
|
||||
|
||||
It can also use an optional file (typically called `config.cache'
|
||||
and enabled with `--cache-file=config.cache' or simply `-C') that saves
|
||||
the results of its tests to speed up reconfiguring. Caching is
|
||||
disabled by default to prevent problems with accidental use of stale
|
||||
cache files.
|
||||
It can also use an optional file (typically called 'config.cache' and
|
||||
enabled with '--cache-file=config.cache' or simply '-C') that saves the
|
||||
results of its tests to speed up reconfiguring. Caching is disabled by
|
||||
default to prevent problems with accidental use of stale cache files.
|
||||
|
||||
If you need to do unusual things to compile the package, please try
|
||||
to figure out how `configure' could check whether to do them, and mail
|
||||
diffs or instructions to the address given in the `README' so they can
|
||||
to figure out how 'configure' could check whether to do them, and mail
|
||||
diffs or instructions to the address given in the 'README' so they can
|
||||
be considered for the next release. If you are using the cache, and at
|
||||
some point `config.cache' contains results you don't want to keep, you
|
||||
some point 'config.cache' contains results you don't want to keep, you
|
||||
may remove or edit it.
|
||||
|
||||
The file `configure.ac' (or `configure.in') is used to create
|
||||
`configure' by a program called `autoconf'. You need `configure.ac' if
|
||||
you want to change it or regenerate `configure' using a newer version
|
||||
of `autoconf'.
|
||||
The file 'configure.ac' (or 'configure.in') is used to create
|
||||
'configure' by a program called 'autoconf'. You need 'configure.ac' if
|
||||
you want to change it or regenerate 'configure' using a newer version of
|
||||
'autoconf'.
|
||||
|
||||
The simplest way to compile this package is:
|
||||
|
||||
1. `cd' to the directory containing the package's source code and type
|
||||
`./configure' to configure the package for your system.
|
||||
1. 'cd' to the directory containing the package's source code and type
|
||||
'./configure' to configure the package for your system.
|
||||
|
||||
Running `configure' might take a while. While running, it prints
|
||||
Running 'configure' might take a while. While running, it prints
|
||||
some messages telling which features it is checking for.
|
||||
|
||||
2. Type `make' to compile the package.
|
||||
2. Type 'make' to compile the package.
|
||||
|
||||
3. Optionally, type `make check' to run any self-tests that come with
|
||||
3. Optionally, type 'make check' to run any self-tests that come with
|
||||
the package, generally using the just-built uninstalled binaries.
|
||||
|
||||
4. Type `make install' to install the programs and any data files and
|
||||
4. Type 'make install' to install the programs and any data files and
|
||||
documentation. When installing into a prefix owned by root, it is
|
||||
recommended that the package be configured and built as a regular
|
||||
user, and only the `make install' phase executed with root
|
||||
user, and only the 'make install' phase executed with root
|
||||
privileges.
|
||||
|
||||
5. Optionally, type `make installcheck' to repeat any self-tests, but
|
||||
5. Optionally, type 'make installcheck' to repeat any self-tests, but
|
||||
this time using the binaries in their final installed location.
|
||||
This target does not install anything. Running this target as a
|
||||
regular user, particularly if the prior `make install' required
|
||||
regular user, particularly if the prior 'make install' required
|
||||
root privileges, verifies that the installation completed
|
||||
correctly.
|
||||
|
||||
6. You can remove the program binaries and object files from the
|
||||
source code directory by typing `make clean'. To also remove the
|
||||
files that `configure' created (so you can compile the package for
|
||||
a different kind of computer), type `make distclean'. There is
|
||||
also a `make maintainer-clean' target, but that is intended mainly
|
||||
source code directory by typing 'make clean'. To also remove the
|
||||
files that 'configure' created (so you can compile the package for
|
||||
a different kind of computer), type 'make distclean'. There is
|
||||
also a 'make maintainer-clean' target, but that is intended mainly
|
||||
for the package's developers. If you use it, you may have to get
|
||||
all sorts of other programs in order to regenerate files that came
|
||||
with the distribution.
|
||||
|
||||
7. Often, you can also type `make uninstall' to remove the installed
|
||||
7. Often, you can also type 'make uninstall' to remove the installed
|
||||
files again. In practice, not all packages have tested that
|
||||
uninstallation works correctly, even though it is required by the
|
||||
GNU Coding Standards.
|
||||
|
||||
8. Some packages, particularly those that use Automake, provide `make
|
||||
8. Some packages, particularly those that use Automake, provide 'make
|
||||
distcheck', which can by used by developers to test that all other
|
||||
targets like `make install' and `make uninstall' work correctly.
|
||||
targets like 'make install' and 'make uninstall' work correctly.
|
||||
This target is generally not run by end users.
|
||||
|
||||
Compilers and Options
|
||||
=====================
|
||||
|
||||
Some systems require unusual options for compilation or linking that
|
||||
the `configure' script does not know about. Run `./configure --help'
|
||||
the 'configure' script does not know about. Run './configure --help'
|
||||
for details on some of the pertinent environment variables.
|
||||
|
||||
You can give `configure' initial values for configuration parameters
|
||||
by setting variables in the command line or in the environment. Here
|
||||
is an example:
|
||||
You can give 'configure' initial values for configuration parameters
|
||||
by setting variables in the command line or in the environment. Here is
|
||||
an example:
|
||||
|
||||
./configure CC=c99 CFLAGS=-g LIBS=-lposix
|
||||
|
||||
@@ -113,21 +112,21 @@ Compiling For Multiple Architectures
|
||||
|
||||
You can compile the package for more than one kind of computer at the
|
||||
same time, by placing the object files for each architecture in their
|
||||
own directory. To do this, you can use GNU `make'. `cd' to the
|
||||
own directory. To do this, you can use GNU 'make'. 'cd' to the
|
||||
directory where you want the object files and executables to go and run
|
||||
the `configure' script. `configure' automatically checks for the
|
||||
source code in the directory that `configure' is in and in `..'. This
|
||||
is known as a "VPATH" build.
|
||||
the 'configure' script. 'configure' automatically checks for the source
|
||||
code in the directory that 'configure' is in and in '..'. This is known
|
||||
as a "VPATH" build.
|
||||
|
||||
With a non-GNU `make', it is safer to compile the package for one
|
||||
With a non-GNU 'make', it is safer to compile the package for one
|
||||
architecture at a time in the source code directory. After you have
|
||||
installed the package for one architecture, use `make distclean' before
|
||||
installed the package for one architecture, use 'make distclean' before
|
||||
reconfiguring for another architecture.
|
||||
|
||||
On MacOS X 10.5 and later systems, you can create libraries and
|
||||
executables that work on multiple system types--known as "fat" or
|
||||
"universal" binaries--by specifying multiple `-arch' options to the
|
||||
compiler but only a single `-arch' option to the preprocessor. Like
|
||||
"universal" binaries--by specifying multiple '-arch' options to the
|
||||
compiler but only a single '-arch' option to the preprocessor. Like
|
||||
this:
|
||||
|
||||
./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
|
||||
@@ -136,105 +135,104 @@ this:
|
||||
|
||||
This is not guaranteed to produce working output in all cases, you
|
||||
may have to build one architecture at a time and combine the results
|
||||
using the `lipo' tool if you have problems.
|
||||
using the 'lipo' tool if you have problems.
|
||||
|
||||
Installation Names
|
||||
==================
|
||||
|
||||
By default, `make install' installs the package's commands under
|
||||
`/usr/local/bin', include files under `/usr/local/include', etc. You
|
||||
can specify an installation prefix other than `/usr/local' by giving
|
||||
`configure' the option `--prefix=PREFIX', where PREFIX must be an
|
||||
By default, 'make install' installs the package's commands under
|
||||
'/usr/local/bin', include files under '/usr/local/include', etc. You
|
||||
can specify an installation prefix other than '/usr/local' by giving
|
||||
'configure' the option '--prefix=PREFIX', where PREFIX must be an
|
||||
absolute file name.
|
||||
|
||||
You can specify separate installation prefixes for
|
||||
architecture-specific files and architecture-independent files. If you
|
||||
pass the option `--exec-prefix=PREFIX' to `configure', the package uses
|
||||
pass the option '--exec-prefix=PREFIX' to 'configure', the package uses
|
||||
PREFIX as the prefix for installing programs and libraries.
|
||||
Documentation and other data files still use the regular prefix.
|
||||
|
||||
In addition, if you use an unusual directory layout you can give
|
||||
options like `--bindir=DIR' to specify different values for particular
|
||||
kinds of files. Run `configure --help' for a list of the directories
|
||||
you can set and what kinds of files go in them. In general, the
|
||||
default for these options is expressed in terms of `${prefix}', so that
|
||||
specifying just `--prefix' will affect all of the other directory
|
||||
options like '--bindir=DIR' to specify different values for particular
|
||||
kinds of files. Run 'configure --help' for a list of the directories
|
||||
you can set and what kinds of files go in them. In general, the default
|
||||
for these options is expressed in terms of '${prefix}', so that
|
||||
specifying just '--prefix' will affect all of the other directory
|
||||
specifications that were not explicitly provided.
|
||||
|
||||
The most portable way to affect installation locations is to pass the
|
||||
correct locations to `configure'; however, many packages provide one or
|
||||
correct locations to 'configure'; however, many packages provide one or
|
||||
both of the following shortcuts of passing variable assignments to the
|
||||
`make install' command line to change installation locations without
|
||||
'make install' command line to change installation locations without
|
||||
having to reconfigure or recompile.
|
||||
|
||||
The first method involves providing an override variable for each
|
||||
affected directory. For example, `make install
|
||||
affected directory. For example, 'make install
|
||||
prefix=/alternate/directory' will choose an alternate location for all
|
||||
directory configuration variables that were expressed in terms of
|
||||
`${prefix}'. Any directories that were specified during `configure',
|
||||
but not in terms of `${prefix}', must each be overridden at install
|
||||
time for the entire installation to be relocated. The approach of
|
||||
makefile variable overrides for each directory variable is required by
|
||||
the GNU Coding Standards, and ideally causes no recompilation.
|
||||
However, some platforms have known limitations with the semantics of
|
||||
shared libraries that end up requiring recompilation when using this
|
||||
method, particularly noticeable in packages that use GNU Libtool.
|
||||
'${prefix}'. Any directories that were specified during 'configure',
|
||||
but not in terms of '${prefix}', must each be overridden at install time
|
||||
for the entire installation to be relocated. The approach of makefile
|
||||
variable overrides for each directory variable is required by the GNU
|
||||
Coding Standards, and ideally causes no recompilation. However, some
|
||||
platforms have known limitations with the semantics of shared libraries
|
||||
that end up requiring recompilation when using this method, particularly
|
||||
noticeable in packages that use GNU Libtool.
|
||||
|
||||
The second method involves providing the `DESTDIR' variable. For
|
||||
example, `make install DESTDIR=/alternate/directory' will prepend
|
||||
`/alternate/directory' before all installation names. The approach of
|
||||
`DESTDIR' overrides is not required by the GNU Coding Standards, and
|
||||
The second method involves providing the 'DESTDIR' variable. For
|
||||
example, 'make install DESTDIR=/alternate/directory' will prepend
|
||||
'/alternate/directory' before all installation names. The approach of
|
||||
'DESTDIR' overrides is not required by the GNU Coding Standards, and
|
||||
does not work on platforms that have drive letters. On the other hand,
|
||||
it does better at avoiding recompilation issues, and works well even
|
||||
when some directory options were not specified in terms of `${prefix}'
|
||||
at `configure' time.
|
||||
when some directory options were not specified in terms of '${prefix}'
|
||||
at 'configure' time.
|
||||
|
||||
Optional Features
|
||||
=================
|
||||
|
||||
If the package supports it, you can cause programs to be installed
|
||||
with an extra prefix or suffix on their names by giving `configure' the
|
||||
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
|
||||
with an extra prefix or suffix on their names by giving 'configure' the
|
||||
option '--program-prefix=PREFIX' or '--program-suffix=SUFFIX'.
|
||||
|
||||
Some packages pay attention to `--enable-FEATURE' options to
|
||||
`configure', where FEATURE indicates an optional part of the package.
|
||||
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
|
||||
is something like `gnu-as' or `x' (for the X Window System). The
|
||||
`README' should mention any `--enable-' and `--with-' options that the
|
||||
Some packages pay attention to '--enable-FEATURE' options to
|
||||
'configure', where FEATURE indicates an optional part of the package.
|
||||
They may also pay attention to '--with-PACKAGE' options, where PACKAGE
|
||||
is something like 'gnu-as' or 'x' (for the X Window System). The
|
||||
'README' should mention any '--enable-' and '--with-' options that the
|
||||
package recognizes.
|
||||
|
||||
For packages that use the X Window System, `configure' can usually
|
||||
For packages that use the X Window System, 'configure' can usually
|
||||
find the X include and library files automatically, but if it doesn't,
|
||||
you can use the `configure' options `--x-includes=DIR' and
|
||||
`--x-libraries=DIR' to specify their locations.
|
||||
you can use the 'configure' options '--x-includes=DIR' and
|
||||
'--x-libraries=DIR' to specify their locations.
|
||||
|
||||
Some packages offer the ability to configure how verbose the
|
||||
execution of `make' will be. For these packages, running `./configure
|
||||
execution of 'make' will be. For these packages, running './configure
|
||||
--enable-silent-rules' sets the default to minimal output, which can be
|
||||
overridden with `make V=1'; while running `./configure
|
||||
overridden with 'make V=1'; while running './configure
|
||||
--disable-silent-rules' sets the default to verbose, which can be
|
||||
overridden with `make V=0'.
|
||||
overridden with 'make V=0'.
|
||||
|
||||
Particular systems
|
||||
==================
|
||||
|
||||
On HP-UX, the default C compiler is not ANSI C compatible. If GNU
|
||||
CC is not installed, it is recommended to use the following options in
|
||||
On HP-UX, the default C compiler is not ANSI C compatible. If GNU CC
|
||||
is not installed, it is recommended to use the following options in
|
||||
order to use an ANSI C compiler:
|
||||
|
||||
./configure CC="cc -Ae -D_XOPEN_SOURCE=500"
|
||||
|
||||
and if that doesn't work, install pre-built binaries of GCC for HP-UX.
|
||||
|
||||
HP-UX `make' updates targets which have the same time stamps as
|
||||
their prerequisites, which makes it generally unusable when shipped
|
||||
generated files such as `configure' are involved. Use GNU `make'
|
||||
instead.
|
||||
HP-UX 'make' updates targets which have the same time stamps as their
|
||||
prerequisites, which makes it generally unusable when shipped generated
|
||||
files such as 'configure' are involved. Use GNU 'make' instead.
|
||||
|
||||
On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
|
||||
parse its `<wchar.h>' header file. The option `-nodtk' can be used as
|
||||
a workaround. If GNU CC is not installed, it is therefore recommended
|
||||
to try
|
||||
parse its '<wchar.h>' header file. The option '-nodtk' can be used as a
|
||||
workaround. If GNU CC is not installed, it is therefore recommended to
|
||||
try
|
||||
|
||||
./configure CC="cc"
|
||||
|
||||
@@ -242,26 +240,26 @@ and if that doesn't work, try
|
||||
|
||||
./configure CC="cc -nodtk"
|
||||
|
||||
On Solaris, don't put `/usr/ucb' early in your `PATH'. This
|
||||
On Solaris, don't put '/usr/ucb' early in your 'PATH'. This
|
||||
directory contains several dysfunctional programs; working variants of
|
||||
these programs are available in `/usr/bin'. So, if you need `/usr/ucb'
|
||||
in your `PATH', put it _after_ `/usr/bin'.
|
||||
these programs are available in '/usr/bin'. So, if you need '/usr/ucb'
|
||||
in your 'PATH', put it _after_ '/usr/bin'.
|
||||
|
||||
On Haiku, software installed for all users goes in `/boot/common',
|
||||
not `/usr/local'. It is recommended to use the following options:
|
||||
On Haiku, software installed for all users goes in '/boot/common',
|
||||
not '/usr/local'. It is recommended to use the following options:
|
||||
|
||||
./configure --prefix=/boot/common
|
||||
|
||||
Specifying the System Type
|
||||
==========================
|
||||
|
||||
There may be some features `configure' cannot figure out
|
||||
There may be some features 'configure' cannot figure out
|
||||
automatically, but needs to determine by the type of machine the package
|
||||
will run on. Usually, assuming the package is built to be run on the
|
||||
_same_ architectures, `configure' can figure that out, but if it prints
|
||||
_same_ architectures, 'configure' can figure that out, but if it prints
|
||||
a message saying it cannot guess the machine type, give it the
|
||||
`--build=TYPE' option. TYPE can either be a short name for the system
|
||||
type, such as `sun4', or a canonical name which has the form:
|
||||
'--build=TYPE' option. TYPE can either be a short name for the system
|
||||
type, such as 'sun4', or a canonical name which has the form:
|
||||
|
||||
CPU-COMPANY-SYSTEM
|
||||
|
||||
@@ -270,101 +268,101 @@ where SYSTEM can have one of these forms:
|
||||
OS
|
||||
KERNEL-OS
|
||||
|
||||
See the file `config.sub' for the possible values of each field. If
|
||||
`config.sub' isn't included in this package, then this package doesn't
|
||||
See the file 'config.sub' for the possible values of each field. If
|
||||
'config.sub' isn't included in this package, then this package doesn't
|
||||
need to know the machine type.
|
||||
|
||||
If you are _building_ compiler tools for cross-compiling, you should
|
||||
use the option `--target=TYPE' to select the type of system they will
|
||||
use the option '--target=TYPE' to select the type of system they will
|
||||
produce code for.
|
||||
|
||||
If you want to _use_ a cross compiler, that generates code for a
|
||||
platform different from the build platform, you should specify the
|
||||
"host" platform (i.e., that on which the generated programs will
|
||||
eventually be run) with `--host=TYPE'.
|
||||
eventually be run) with '--host=TYPE'.
|
||||
|
||||
Sharing Defaults
|
||||
================
|
||||
|
||||
If you want to set default values for `configure' scripts to share,
|
||||
you can create a site shell script called `config.site' that gives
|
||||
default values for variables like `CC', `cache_file', and `prefix'.
|
||||
`configure' looks for `PREFIX/share/config.site' if it exists, then
|
||||
`PREFIX/etc/config.site' if it exists. Or, you can set the
|
||||
`CONFIG_SITE' environment variable to the location of the site script.
|
||||
A warning: not all `configure' scripts look for a site script.
|
||||
If you want to set default values for 'configure' scripts to share,
|
||||
you can create a site shell script called 'config.site' that gives
|
||||
default values for variables like 'CC', 'cache_file', and 'prefix'.
|
||||
'configure' looks for 'PREFIX/share/config.site' if it exists, then
|
||||
'PREFIX/etc/config.site' if it exists. Or, you can set the
|
||||
'CONFIG_SITE' environment variable to the location of the site script.
|
||||
A warning: not all 'configure' scripts look for a site script.
|
||||
|
||||
Defining Variables
|
||||
==================
|
||||
|
||||
Variables not defined in a site shell script can be set in the
|
||||
environment passed to `configure'. However, some packages may run
|
||||
environment passed to 'configure'. However, some packages may run
|
||||
configure again during the build, and the customized values of these
|
||||
variables may be lost. In order to avoid this problem, you should set
|
||||
them in the `configure' command line, using `VAR=value'. For example:
|
||||
them in the 'configure' command line, using 'VAR=value'. For example:
|
||||
|
||||
./configure CC=/usr/local2/bin/gcc
|
||||
|
||||
causes the specified `gcc' to be used as the C compiler (unless it is
|
||||
causes the specified 'gcc' to be used as the C compiler (unless it is
|
||||
overridden in the site shell script).
|
||||
|
||||
Unfortunately, this technique does not work for `CONFIG_SHELL' due to
|
||||
an Autoconf limitation. Until the limitation is lifted, you can use
|
||||
this workaround:
|
||||
Unfortunately, this technique does not work for 'CONFIG_SHELL' due to an
|
||||
Autoconf limitation. Until the limitation is lifted, you can use this
|
||||
workaround:
|
||||
|
||||
CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash
|
||||
|
||||
`configure' Invocation
|
||||
'configure' Invocation
|
||||
======================
|
||||
|
||||
`configure' recognizes the following options to control how it
|
||||
'configure' recognizes the following options to control how it
|
||||
operates.
|
||||
|
||||
`--help'
|
||||
`-h'
|
||||
Print a summary of all of the options to `configure', and exit.
|
||||
'--help'
|
||||
'-h'
|
||||
Print a summary of all of the options to 'configure', and exit.
|
||||
|
||||
`--help=short'
|
||||
`--help=recursive'
|
||||
'--help=short'
|
||||
'--help=recursive'
|
||||
Print a summary of the options unique to this package's
|
||||
`configure', and exit. The `short' variant lists options used
|
||||
only in the top level, while the `recursive' variant lists options
|
||||
also present in any nested packages.
|
||||
'configure', and exit. The 'short' variant lists options used only
|
||||
in the top level, while the 'recursive' variant lists options also
|
||||
present in any nested packages.
|
||||
|
||||
`--version'
|
||||
`-V'
|
||||
Print the version of Autoconf used to generate the `configure'
|
||||
'--version'
|
||||
'-V'
|
||||
Print the version of Autoconf used to generate the 'configure'
|
||||
script, and exit.
|
||||
|
||||
`--cache-file=FILE'
|
||||
'--cache-file=FILE'
|
||||
Enable the cache: use and save the results of the tests in FILE,
|
||||
traditionally `config.cache'. FILE defaults to `/dev/null' to
|
||||
traditionally 'config.cache'. FILE defaults to '/dev/null' to
|
||||
disable caching.
|
||||
|
||||
`--config-cache'
|
||||
`-C'
|
||||
Alias for `--cache-file=config.cache'.
|
||||
'--config-cache'
|
||||
'-C'
|
||||
Alias for '--cache-file=config.cache'.
|
||||
|
||||
`--quiet'
|
||||
`--silent'
|
||||
`-q'
|
||||
'--quiet'
|
||||
'--silent'
|
||||
'-q'
|
||||
Do not print messages saying which checks are being made. To
|
||||
suppress all normal output, redirect it to `/dev/null' (any error
|
||||
suppress all normal output, redirect it to '/dev/null' (any error
|
||||
messages will still be shown).
|
||||
|
||||
`--srcdir=DIR'
|
||||
'--srcdir=DIR'
|
||||
Look for the package's source code in directory DIR. Usually
|
||||
`configure' can determine that directory automatically.
|
||||
'configure' can determine that directory automatically.
|
||||
|
||||
`--prefix=DIR'
|
||||
Use DIR as the installation prefix. *note Installation Names::
|
||||
for more details, including other options available for fine-tuning
|
||||
the installation locations.
|
||||
'--prefix=DIR'
|
||||
Use DIR as the installation prefix. *note Installation Names:: for
|
||||
more details, including other options available for fine-tuning the
|
||||
installation locations.
|
||||
|
||||
`--no-create'
|
||||
`-n'
|
||||
'--no-create'
|
||||
'-n'
|
||||
Run the configure checks, but stop before creating any output
|
||||
files.
|
||||
|
||||
`configure' also accepts some other, not widely useful, options. Run
|
||||
`configure --help' for more details.
|
||||
'configure' also accepts some other, not widely useful, options. Run
|
||||
'configure --help' for more details.
|
||||
|
||||
@@ -48,9 +48,11 @@ __Note__: since _LMS_ stores hashed and salted passwords, it cannot handle the _
|
||||
|
||||
## Installation
|
||||
|
||||
__Note__: this installation process and the default values of the configuration file and the _systemd_ service file have been written for _Debian Stretch_. Therefore, you may have to adapt commands and/or paths in order to fit to your distribution.
|
||||
__Note__: this installation process and the default values of the configuration file and the _systemd_ service file have been written for _Debian Buster_. Therefore, you may have to adapt commands and/or paths in order to fit to your distribution.
|
||||
|
||||
### Build dependencies
|
||||
|
||||
__Note__: a C++17 compiler is needed to compile _LMS_
|
||||
```sh
|
||||
apt-get install g++ autoconf automake libboost-filesystem-dev libboost-system-dev libavcodec-dev libavutil-dev libavformat-dev libav-tools libmagick++-dev libpstreams-dev libconfig++-dev libpstreams-dev ffmpeg libtag1-dev
|
||||
```
|
||||
|
||||
+9
-10
@@ -5,7 +5,6 @@ AC_CONFIG_HEADER(src/config/config.h)
|
||||
|
||||
AC_LANG_CPLUSPLUS
|
||||
|
||||
# Checks for programs
|
||||
AC_PROG_CXX
|
||||
|
||||
PKG_CHECK_MODULES(IMAGEMAGICKXX, "ImageMagick++", [ HAVE_IMAGEMAGICKXX=yes ], [ ])
|
||||
@@ -20,10 +19,15 @@ AC_CHECK_HEADERS([Wt/WApplication.h pstreams/pstream.h],
|
||||
[],
|
||||
[AC_MSG_ERROR([Header not found or unusable !])])
|
||||
|
||||
AC_CHECK_LIB( [pthread],
|
||||
[pthread_rwlock_unlock],
|
||||
,
|
||||
[AC_MSG_ERROR([libpthread not found!])])
|
||||
AC_CHECK_LIB([stdc++fs],
|
||||
[main],
|
||||
,
|
||||
[AC_MSG_ERROR([lib filesystem not found!])])
|
||||
|
||||
AC_CHECK_LIB([pthread],
|
||||
[pthread_rwlock_unlock],
|
||||
,
|
||||
[AC_MSG_ERROR([libpthread not found!])])
|
||||
|
||||
AC_CHECK_LIB([wt],
|
||||
[main],
|
||||
@@ -66,11 +70,6 @@ AC_CHECK_LIB([boost_system],
|
||||
,
|
||||
[AC_MSG_ERROR([libboost_system not found!])])
|
||||
|
||||
AC_CHECK_LIB( [boost_filesystem],
|
||||
[main],
|
||||
,
|
||||
[AC_MSG_ERROR([libboost_filesystem not found!])])
|
||||
|
||||
AC_CHECK_LIB( [tag],
|
||||
[main],
|
||||
,
|
||||
|
||||
+3
-3
@@ -25,8 +25,8 @@ lms_SOURCES = \
|
||||
$(srcdir)/database/Artist.hpp \
|
||||
$(srcdir)/database/Cluster.cpp \
|
||||
$(srcdir)/database/Cluster.hpp \
|
||||
$(srcdir)/database/Database.cpp \
|
||||
$(srcdir)/database/Database.hpp \
|
||||
$(srcdir)/database/Db.cpp \
|
||||
$(srcdir)/database/Db.hpp \
|
||||
$(srcdir)/database/TrackArtistLink.cpp \
|
||||
$(srcdir)/database/TrackArtistLink.hpp \
|
||||
$(srcdir)/database/TrackFeatures.cpp \
|
||||
@@ -147,6 +147,6 @@ lms_SOURCES = \
|
||||
$(srcdir)/utils/Utils.cpp \
|
||||
$(srcdir)/utils/Utils.hpp
|
||||
|
||||
lms_CXXFLAGS=-std=c++14 -Wall -I$(srcdir)/ui $(MAGICKXX_CFLAGS) -D_REENTRANT
|
||||
lms_CXXFLAGS=-std=c++17 -I$(srcdir)/ui $(MAGICKXX_CFLAGS) -D_REENTRANT
|
||||
lms_LDADD=$(MAGICKXX_LIBS)
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
namespace API::Subsonic
|
||||
{
|
||||
|
||||
boost::optional<Id>
|
||||
std::optional<Id>
|
||||
IdFromString(const std::string& id)
|
||||
{
|
||||
if (id == "root")
|
||||
@@ -35,7 +35,7 @@ IdFromString(const std::string& id)
|
||||
|
||||
std::vector<std::string> values {splitString(id, "-")};
|
||||
if (values.size() != 2)
|
||||
return boost::none;
|
||||
return std::nullopt;
|
||||
|
||||
Id res;
|
||||
|
||||
@@ -49,11 +49,11 @@ IdFromString(const std::string& id)
|
||||
else if (type == "pl")
|
||||
res.type = Id::Type::Playlist;
|
||||
else
|
||||
return boost::none;
|
||||
return std::nullopt;
|
||||
|
||||
auto optId {readAs<Database::IdType>(values[1])};
|
||||
if (!optId)
|
||||
return boost::none;
|
||||
return std::nullopt;
|
||||
|
||||
res.value = *optId;
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <boost/optional.hpp>
|
||||
#include <optional>
|
||||
|
||||
#include "database/Types.hpp"
|
||||
|
||||
@@ -39,7 +39,7 @@ struct Id
|
||||
Database::IdType value {};
|
||||
};
|
||||
|
||||
boost::optional<Id> IdFromString(const std::string& id);
|
||||
std::optional<Id> IdFromString(const std::string& id);
|
||||
std::string IdToString(const Id& id);
|
||||
|
||||
} // namespace API::Subsonic
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "cover/CoverArtGrabber.hpp"
|
||||
#include "database/Artist.hpp"
|
||||
#include "database/Cluster.hpp"
|
||||
#include "database/Db.hpp"
|
||||
#include "database/Release.hpp"
|
||||
#include "database/Track.hpp"
|
||||
#include "database/TrackList.hpp"
|
||||
@@ -53,14 +54,14 @@ static const Av::Encoding transcodeEncoding {Av::Encoding::MP3};
|
||||
static const std::string reportedStarredDate {"2000-01-01T00:00:00"};
|
||||
|
||||
template<>
|
||||
boost::optional<API::Subsonic::Id>
|
||||
std::optional<API::Subsonic::Id>
|
||||
readAs(const std::string& str)
|
||||
{
|
||||
return API::Subsonic::IdFromString(str);
|
||||
}
|
||||
|
||||
template<>
|
||||
boost::optional<bool>
|
||||
std::optional<bool>
|
||||
readAs(const std::string& str)
|
||||
{
|
||||
if (str == "true")
|
||||
@@ -82,31 +83,31 @@ struct ClientVersion
|
||||
}
|
||||
|
||||
template<>
|
||||
boost::optional<API::Subsonic::ClientVersion>
|
||||
std::optional<API::Subsonic::ClientVersion>
|
||||
readAs(const std::string& str)
|
||||
{
|
||||
// Expects "X.Y.Z"
|
||||
const auto numbers {splitString(str, ".")};
|
||||
if (numbers.size() < 2 || numbers.size() > 3)
|
||||
return boost::none;
|
||||
return std::nullopt;
|
||||
|
||||
API::Subsonic::ClientVersion version;
|
||||
|
||||
auto number {readAs<unsigned>(numbers[0])};
|
||||
if (!number)
|
||||
return boost::none;
|
||||
return std::nullopt;
|
||||
version.major = *number;
|
||||
|
||||
number = {readAs<unsigned>(numbers[1])};
|
||||
if (!number)
|
||||
return boost::none;
|
||||
return std::nullopt;
|
||||
version.minor = *number;
|
||||
|
||||
if (numbers.size() == 3)
|
||||
{
|
||||
number = {readAs<unsigned>(numbers[2])};
|
||||
if (!number)
|
||||
return boost::none;
|
||||
return std::nullopt;
|
||||
version.patch = *number;
|
||||
}
|
||||
|
||||
@@ -132,12 +133,12 @@ struct RequestContext
|
||||
std::string userName;
|
||||
};
|
||||
|
||||
using SessionMap = std::map<Database::Database*, std::unique_ptr<Session>>;
|
||||
using SessionMap = std::map<Db*, std::unique_ptr<Session>>;
|
||||
static std::map<std::thread::id, SessionMap> dbSessions;
|
||||
|
||||
static
|
||||
Session&
|
||||
getOrCreateDbSession(Database::Database& db)
|
||||
getOrCreateDbSession(Db& db)
|
||||
{
|
||||
static std::mutex mutex;
|
||||
|
||||
@@ -152,12 +153,12 @@ getOrCreateDbSession(Database::Database& db)
|
||||
if (it != std::end(*sessionMap))
|
||||
return *it->second;
|
||||
|
||||
auto res {sessionMap->emplace(&db, db.createSession())};
|
||||
auto res { sessionMap->try_emplace(&db, db.createSession())};
|
||||
assert(res.second);
|
||||
|
||||
LMS_LOG(API_SUBSONIC, DEBUG) << "Created db session";
|
||||
|
||||
return *(res.first->second);
|
||||
return *res.first->second;
|
||||
}
|
||||
|
||||
static
|
||||
@@ -209,7 +210,7 @@ getMandatoryMultiParametersAs(const Wt::Http::ParameterMap& parameterMap, const
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
boost::optional<T>
|
||||
std::optional<T>
|
||||
getParameterAs(const Wt::Http::ParameterMap& parameterMap, const std::string& param)
|
||||
{
|
||||
std::vector<T> params {getMultiParametersAs<T>(parameterMap, param)};
|
||||
@@ -277,7 +278,7 @@ struct MediaRetrievalResult
|
||||
Wt::cpp17::any continuationData;
|
||||
};
|
||||
|
||||
SubsonicResource::SubsonicResource(Database::Database& db)
|
||||
SubsonicResource::SubsonicResource(Db& db)
|
||||
: _db {db}
|
||||
{
|
||||
}
|
||||
@@ -571,7 +572,7 @@ userToResponseNode(const User::pointer& user)
|
||||
|
||||
static
|
||||
Response
|
||||
handlePingRequest(RequestContext& context)
|
||||
handlePingRequest(RequestContext&)
|
||||
{
|
||||
return Response::createOkResponse();
|
||||
}
|
||||
@@ -731,12 +732,12 @@ handleDeleteUserRequest(RequestContext& context)
|
||||
|
||||
static
|
||||
Response
|
||||
handleGetLicenseRequest(RequestContext& context)
|
||||
handleGetLicenseRequest(RequestContext&)
|
||||
{
|
||||
Response response {Response::createOkResponse()};
|
||||
|
||||
Response::Node& licenseNode {response.createNode("license")};
|
||||
licenseNode.setAttribute("licenseExpires", "2019-09-03T14:46:43");
|
||||
licenseNode.setAttribute("licenseExpires", "2025-09-03T14:46:43");
|
||||
licenseNode.setAttribute("email", "foo@bar.com");
|
||||
licenseNode.setAttribute("valid", "true");
|
||||
|
||||
@@ -748,7 +749,7 @@ Response
|
||||
handleGetRandomSongsRequest(RequestContext& context)
|
||||
{
|
||||
// Optional params
|
||||
std::size_t size {getParameterAs<std::size_t>(context.parameters, "size").get_value_or(50)};
|
||||
std::size_t size {getParameterAs<std::size_t>(context.parameters, "size").value_or(50)};
|
||||
size = std::min(size, std::size_t {500});
|
||||
|
||||
auto transaction {context.dbSession.createSharedTransaction()};
|
||||
@@ -776,8 +777,8 @@ handleGetAlbumListRequestCommon(const RequestContext& context, bool id3)
|
||||
std::string type {getMandatoryParameterAs<std::string>(context.parameters, "type")};
|
||||
|
||||
// Optional params
|
||||
std::size_t size {getParameterAs<std::size_t>(context.parameters, "size").get_value_or(10)};
|
||||
std::size_t offset {getParameterAs<std::size_t>(context.parameters, "offset").get_value_or(0)};
|
||||
std::size_t size {getParameterAs<std::size_t>(context.parameters, "size").value_or(10)};
|
||||
std::size_t offset {getParameterAs<std::size_t>(context.parameters, "offset").value_or(0)};
|
||||
|
||||
std::vector<Release::pointer> releases;
|
||||
|
||||
@@ -932,7 +933,7 @@ handleGetArtistInfoRequestCommon(RequestContext& context, bool id3)
|
||||
throw BadParameterGenericError {"id"};
|
||||
|
||||
// Optional params
|
||||
std::size_t count {getParameterAs<std::size_t>(context.parameters, "count").get_value_or(20)};
|
||||
std::size_t count {getParameterAs<std::size_t>(context.parameters, "count").value_or(20)};
|
||||
|
||||
Response response {Response::createOkResponse()};
|
||||
Response::Node& artistInfoNode {response.createNode(id3 ? "artistInfo2" : "artistInfo")};
|
||||
@@ -1075,7 +1076,7 @@ handleGetMusicDirectoryRequest(RequestContext& context)
|
||||
|
||||
static
|
||||
Response
|
||||
handleGetMusicFoldersRequest(RequestContext& context)
|
||||
handleGetMusicFoldersRequest(RequestContext&)
|
||||
{
|
||||
Response response {Response::createOkResponse()};
|
||||
Response::Node& musicFoldersNode {response.createNode("musicFolders")};
|
||||
@@ -1142,7 +1143,7 @@ handleGetSimilarSongsRequestCommon(RequestContext& context, bool id3)
|
||||
throw BadParameterGenericError {"id"};
|
||||
|
||||
// Optional params
|
||||
std::size_t count {getParameterAs<std::size_t>(context.parameters, "count").get_value_or(50)};
|
||||
std::size_t count {getParameterAs<std::size_t>(context.parameters, "count").value_or(50)};
|
||||
|
||||
auto similarArtistsId {getService<Similarity::Searcher>()->getSimilarArtists(context.dbSession, id.value, 5)};
|
||||
|
||||
@@ -1248,7 +1249,7 @@ handleGetStarred2Request(RequestContext& context)
|
||||
|
||||
static
|
||||
Response::Node
|
||||
tracklistToResponseNode(const TrackList::pointer& tracklist, Session& dbSession)
|
||||
tracklistToResponseNode(const TrackList::pointer& tracklist, Session&)
|
||||
{
|
||||
Response::Node playlistNode;
|
||||
|
||||
@@ -1322,10 +1323,10 @@ handleGetSongsByGenreRequest(RequestContext& context)
|
||||
std::string genre {getMandatoryParameterAs<std::string>(context.parameters, "genre")};
|
||||
|
||||
// Optional params
|
||||
std::size_t size {getParameterAs<std::size_t>(context.parameters, "count").get_value_or(10)};
|
||||
std::size_t size {getParameterAs<std::size_t>(context.parameters, "count").value_or(10)};
|
||||
size = std::min(size, std::size_t {500});
|
||||
|
||||
std::size_t offset {getParameterAs<std::size_t>(context.parameters, "offset").get_value_or(0)};
|
||||
std::size_t offset {getParameterAs<std::size_t>(context.parameters, "offset").value_or(0)};
|
||||
|
||||
auto transaction {context.dbSession.createSharedTransaction()};
|
||||
|
||||
@@ -1398,12 +1399,12 @@ handleSearchRequestCommon(RequestContext& context, bool id3)
|
||||
std::vector<std::string> keywords {splitString(query, " ")};
|
||||
|
||||
// Optional params
|
||||
std::size_t artistCount {getParameterAs<std::size_t>(context.parameters, "artistCount").get_value_or(20)};
|
||||
std::size_t artistOffset {getParameterAs<std::size_t>(context.parameters, "artistOffset").get_value_or(0)};
|
||||
std::size_t albumCount {getParameterAs<std::size_t>(context.parameters, "albumCount").get_value_or(20)};
|
||||
std::size_t albumOffset {getParameterAs<std::size_t>(context.parameters, "albumOffset").get_value_or(0)};
|
||||
std::size_t songCount {getParameterAs<std::size_t>(context.parameters, "songCount").get_value_or(20)};
|
||||
std::size_t songOffset {getParameterAs<std::size_t>(context.parameters, "songOffset").get_value_or(0)};
|
||||
std::size_t artistCount {getParameterAs<std::size_t>(context.parameters, "artistCount").value_or(20)};
|
||||
std::size_t artistOffset {getParameterAs<std::size_t>(context.parameters, "artistOffset").value_or(0)};
|
||||
std::size_t albumCount {getParameterAs<std::size_t>(context.parameters, "albumCount").value_or(20)};
|
||||
std::size_t albumOffset {getParameterAs<std::size_t>(context.parameters, "albumOffset").value_or(0)};
|
||||
std::size_t songCount {getParameterAs<std::size_t>(context.parameters, "songCount").value_or(20)};
|
||||
std::size_t songOffset {getParameterAs<std::size_t>(context.parameters, "songOffset").value_or(0)};
|
||||
|
||||
auto transaction {context.dbSession.createSharedTransaction()};
|
||||
|
||||
@@ -1585,8 +1586,8 @@ Response
|
||||
handleUpdateUserRequest(RequestContext& context)
|
||||
{
|
||||
std::string username {getMandatoryParameterAs<std::string>(context.parameters, "username")};
|
||||
boost::optional<std::string> password {getParameterAs<std::string>(context.parameters, "password")};
|
||||
boost::optional<Bitrate> maxBitRate {getParameterAs<Bitrate>(context.parameters, "maxBitRate")};
|
||||
std::optional<std::string> password {getParameterAs<std::string>(context.parameters, "password")};
|
||||
std::optional<Bitrate> maxBitRate {getParameterAs<Bitrate>(context.parameters, "maxBitRate")};
|
||||
|
||||
User::PasswordHash hash;
|
||||
if (password)
|
||||
@@ -1693,9 +1694,9 @@ createTranscoder(RequestContext& context)
|
||||
Id id {getMandatoryParameterAs<Id>(context.parameters, "id")};
|
||||
|
||||
// Optional params
|
||||
boost::optional<std::size_t> maxBitRate {getParameterAs<std::size_t>(context.parameters, "maxBitRate")};
|
||||
std::optional<std::size_t> maxBitRate {getParameterAs<std::size_t>(context.parameters, "maxBitRate")};
|
||||
|
||||
boost::filesystem::path trackPath;
|
||||
std::filesystem::path trackPath;
|
||||
{
|
||||
auto transaction {context.dbSession.createSharedTransaction()};
|
||||
|
||||
@@ -1771,7 +1772,7 @@ handleGetCoverArt(RequestContext& context, Wt::Http::ResponseContinuation*)
|
||||
// Mandatory params
|
||||
Id id {getMandatoryParameterAs<Id>(context.parameters, "id")};
|
||||
|
||||
std::size_t size {getParameterAs<std::size_t>(context.parameters, "size").get_value_or(256)};
|
||||
std::size_t size {getParameterAs<std::size_t>(context.parameters, "size").value_or(256)};
|
||||
size = clamp(size, std::size_t {32}, std::size_t {1024});
|
||||
|
||||
MediaRetrievalResult res;
|
||||
@@ -1861,7 +1862,7 @@ SubsonicResource::handleRequest(const Wt::Http::Request &request, Wt::Http::Resp
|
||||
const Wt::Http::ParameterMap& parameters {request.getParameterMap()};
|
||||
|
||||
// Optional parameters
|
||||
ResponseFormat format {getParameterAs<std::string>(parameters, "f").get_value_or("xml") == "json" ? ResponseFormat::json : ResponseFormat::xml};
|
||||
const ResponseFormat format {getParameterAs<std::string>(parameters, "f").value_or("xml") == "json" ? ResponseFormat::json : ResponseFormat::xml};
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
@@ -18,12 +18,13 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
#include <Wt/WResource.h>
|
||||
#include <Wt/Http/Response.h>
|
||||
|
||||
#include "database/Database.hpp"
|
||||
namespace Database
|
||||
{
|
||||
class Db;
|
||||
}
|
||||
|
||||
namespace API::Subsonic
|
||||
{
|
||||
@@ -31,7 +32,7 @@ namespace API::Subsonic
|
||||
class SubsonicResource final : public Wt::WResource
|
||||
{
|
||||
public:
|
||||
SubsonicResource(Database::Database& db);
|
||||
SubsonicResource(Database::Db& db);
|
||||
~SubsonicResource();
|
||||
|
||||
static std::string getPath() { return "/rest/"; }
|
||||
@@ -39,7 +40,7 @@ class SubsonicResource final : public Wt::WResource
|
||||
|
||||
void handleRequest(const Wt::Http::Request &request, Wt::Http::Response &response) override;
|
||||
|
||||
Database::Database& _db;
|
||||
Database::Db& _db;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -62,7 +62,7 @@ AuthTokenService::createAuthToken(Database::Session& session, Database::IdType u
|
||||
}
|
||||
|
||||
static
|
||||
boost::optional<AuthTokenService::AuthTokenProcessResult::AuthTokenInfo>
|
||||
std::optional<AuthTokenService::AuthTokenProcessResult::AuthTokenInfo>
|
||||
processAuthToken(Database::Session& session, const std::string& secret)
|
||||
{
|
||||
const std::string secretHash {sha1Function.compute(secret, {})};
|
||||
@@ -71,12 +71,12 @@ processAuthToken(Database::Session& session, const std::string& secret)
|
||||
|
||||
Database::AuthToken::pointer authToken {Database::AuthToken::getByValue(session, secretHash)};
|
||||
if (!authToken)
|
||||
return boost::none;
|
||||
return std::nullopt;
|
||||
|
||||
if (authToken->getExpiry() < Wt::WDateTime::currentDateTime())
|
||||
{
|
||||
authToken.remove();
|
||||
return boost::none;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
LMS_LOG(UI, DEBUG) << "Found auth token for user '" << authToken->getUser()->getLoginName() << "'!";
|
||||
|
||||
@@ -21,9 +21,9 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
#include <boost/optional.hpp>
|
||||
#include <boost/asio/ip/address.hpp>
|
||||
|
||||
#include "LoginThrottler.hpp"
|
||||
@@ -69,8 +69,8 @@ namespace Auth {
|
||||
Wt::WDateTime expiry;
|
||||
};
|
||||
|
||||
State state;
|
||||
boost::optional<AuthTokenInfo> authTokenInfo;
|
||||
State state {State::NotFound};
|
||||
std::optional<AuthTokenInfo> authTokenInfo {};
|
||||
};
|
||||
|
||||
// Removed if found
|
||||
|
||||
@@ -83,7 +83,7 @@ LoginThrottler::onGoodClientAttempt(const boost::asio::ip::address& address)
|
||||
{
|
||||
const boost::asio::ip::address clientAddress {getAddressToThrottle(address)};
|
||||
|
||||
_attemptsInfo.erase(address);
|
||||
_attemptsInfo.erase(clientAddress);
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -91,7 +91,7 @@ LoginThrottler::isClientThrottled(const boost::asio::ip::address& address) const
|
||||
{
|
||||
const boost::asio::ip::address clientAddress {getAddressToThrottle(address)};
|
||||
|
||||
auto it {_attemptsInfo.find(address)};
|
||||
auto it {_attemptsInfo.find(clientAddress)};
|
||||
if (it == _attemptsInfo.end())
|
||||
return false;
|
||||
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <boost/optional.hpp>
|
||||
#include <boost/asio/ip/address.hpp>
|
||||
|
||||
#include "LoginThrottler.hpp"
|
||||
@@ -81,7 +80,7 @@ namespace Auth {
|
||||
};
|
||||
|
||||
State state;
|
||||
boost::optional<AuthTokenInfo> authTokenInfo;
|
||||
std::optional<AuthTokenInfo> authTokenInfo;
|
||||
};
|
||||
|
||||
// Removed if found
|
||||
|
||||
+4
-12
@@ -43,16 +43,8 @@ MediaFileException::MediaFileException(int avError)
|
||||
{
|
||||
}
|
||||
|
||||
void AvInit()
|
||||
{
|
||||
/* register all the codecs */
|
||||
avcodec_register_all();
|
||||
av_register_all();
|
||||
LMS_LOG(AV, INFO) << "avcodec version = " << avcodec_version();
|
||||
}
|
||||
|
||||
|
||||
MediaFile::MediaFile(const boost::filesystem::path& p)
|
||||
MediaFile::MediaFile(const std::filesystem::path& p)
|
||||
: _p {p}
|
||||
{
|
||||
int error = avformat_open_input(&_context, _p.string().c_str(), nullptr, nullptr);
|
||||
@@ -155,7 +147,7 @@ MediaFile::getStreamInfo() const
|
||||
return res;
|
||||
}
|
||||
|
||||
boost::optional<std::size_t>
|
||||
std::optional<std::size_t>
|
||||
MediaFile::getBestStream() const
|
||||
{
|
||||
int res = av_find_best_stream(_context,
|
||||
@@ -166,7 +158,7 @@ MediaFile::getBestStream() const
|
||||
0);
|
||||
|
||||
if (res < 0)
|
||||
return boost::none;
|
||||
return std::nullopt;
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -238,7 +230,7 @@ MediaFile::getAttachedPictures(std::size_t nbMaxPictures) const
|
||||
return pictures;
|
||||
}
|
||||
|
||||
boost::optional<MediaFileFormat> guessMediaFileFormat(const boost::filesystem::path& file)
|
||||
std::optional<MediaFileFormat> guessMediaFileFormat(const std::filesystem::path& file)
|
||||
{
|
||||
AVOutputFormat* format {av_guess_format(NULL,file.string().c_str(),NULL)};
|
||||
if (!format || !format->name)
|
||||
|
||||
+10
-12
@@ -29,14 +29,12 @@ extern "C"
|
||||
#include <libavutil/error.h>
|
||||
}
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <cstdint>
|
||||
#include <map>
|
||||
#include <chrono>
|
||||
|
||||
#include <boost/optional.hpp>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <filesystem>
|
||||
#include <map>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "AvTypes.hpp"
|
||||
|
||||
@@ -66,7 +64,7 @@ class MediaFileException : public AvException
|
||||
class MediaFile
|
||||
{
|
||||
public:
|
||||
MediaFile(const boost::filesystem::path& p);
|
||||
MediaFile(const std::filesystem::path& p);
|
||||
~MediaFile();
|
||||
|
||||
MediaFile(const MediaFile&) = delete;
|
||||
@@ -76,19 +74,19 @@ class MediaFile
|
||||
|
||||
std::string getFormatName() const;
|
||||
|
||||
const boost::filesystem::path& getPath() const {return _p;};
|
||||
const std::filesystem::path& getPath() const {return _p;};
|
||||
|
||||
std::chrono::milliseconds getDuration() const;
|
||||
std::map<std::string, std::string> getMetaData(void);
|
||||
|
||||
std::vector<StreamInfo> getStreamInfo() const;
|
||||
boost::optional<std::size_t> getBestStream() const; // none if failure/unknown
|
||||
std::optional<std::size_t> getBestStream() const; // none if failure/unknown
|
||||
bool hasAttachedPictures(void) const;
|
||||
std::vector<Picture> getAttachedPictures(std::size_t nbMaxPictures) const;
|
||||
|
||||
private:
|
||||
|
||||
boost::filesystem::path _p;
|
||||
std::filesystem::path _p;
|
||||
AVFormatContext* _context {};
|
||||
};
|
||||
|
||||
@@ -99,7 +97,7 @@ struct MediaFileFormat
|
||||
std::string format;
|
||||
};
|
||||
|
||||
boost::optional<MediaFileFormat> guessMediaFileFormat(const boost::filesystem::path& file);
|
||||
std::optional<MediaFileFormat> guessMediaFileFormat(const std::filesystem::path& file);
|
||||
|
||||
} // namespace Av
|
||||
|
||||
|
||||
+47
-47
@@ -37,16 +37,15 @@ static const std::vector<std::string> execNames =
|
||||
"ffmpeg",
|
||||
};
|
||||
|
||||
static std::mutex transcoderMutex;
|
||||
static boost::filesystem::path avConvPath = boost::filesystem::path();
|
||||
static std::filesystem::path avConvPath = std::filesystem::path();
|
||||
static std::atomic<size_t> globalId = {0};
|
||||
|
||||
void
|
||||
Transcoder::init()
|
||||
{
|
||||
for (std::string execName : execNames)
|
||||
for (const std::string& execName : execNames)
|
||||
{
|
||||
boost::filesystem::path p = searchExecPath(execName);
|
||||
const std::filesystem::path p {searchExecPath(execName)};
|
||||
if (!p.empty())
|
||||
{
|
||||
avConvPath = p;
|
||||
@@ -60,11 +59,10 @@ Transcoder::init()
|
||||
throw AvException("Cannot find any transcoder binary!");
|
||||
}
|
||||
|
||||
Transcoder::Transcoder(boost::filesystem::path filePath, TranscodeParameters parameters)
|
||||
: _filePath(filePath),
|
||||
_parameters(parameters),
|
||||
_isComplete(false),
|
||||
_id(globalId++)
|
||||
Transcoder::Transcoder(const std::filesystem::path& filePath, const TranscodeParameters& parameters)
|
||||
: _filePath {filePath},
|
||||
_parameters {parameters},
|
||||
_id {globalId++}
|
||||
{
|
||||
|
||||
}
|
||||
@@ -72,84 +70,84 @@ Transcoder::Transcoder(boost::filesystem::path filePath, TranscodeParameters par
|
||||
bool
|
||||
Transcoder::start()
|
||||
{
|
||||
if (!boost::filesystem::exists(_filePath))
|
||||
if (!std::filesystem::exists(_filePath))
|
||||
return false;
|
||||
else if (!boost::filesystem::is_regular( _filePath) )
|
||||
else if (!std::filesystem::is_regular_file( _filePath) )
|
||||
return false;
|
||||
|
||||
LMS_LOG_TRANSCODE(INFO) << "Transcoding file '" << _filePath.string() << "'";
|
||||
|
||||
std::vector<std::string> args;
|
||||
|
||||
args.push_back(avConvPath.string());
|
||||
args.emplace_back(avConvPath.string());
|
||||
|
||||
// Make sure we do not produce anything in the stderr output
|
||||
// in order not to block the whole forked process
|
||||
args.push_back("-loglevel");
|
||||
args.push_back("quiet");
|
||||
args.push_back("-nostdin");
|
||||
args.emplace_back("-loglevel");
|
||||
args.emplace_back("quiet");
|
||||
args.emplace_back("-nostdin");
|
||||
|
||||
// input Offset
|
||||
if (_parameters.offset)
|
||||
{
|
||||
args.push_back("-ss");
|
||||
args.push_back(std::to_string((*_parameters.offset).count()));
|
||||
args.emplace_back("-ss");
|
||||
args.emplace_back(std::to_string((*_parameters.offset).count()));
|
||||
}
|
||||
|
||||
// Input file
|
||||
args.push_back("-i");
|
||||
args.push_back(_filePath.string());
|
||||
args.emplace_back("-i");
|
||||
args.emplace_back(_filePath.string());
|
||||
|
||||
// Stream mapping, if set
|
||||
if (_parameters.stream)
|
||||
{
|
||||
args.push_back("-map");
|
||||
args.push_back("0:" + std::to_string(*_parameters.stream));
|
||||
args.emplace_back("-map");
|
||||
args.emplace_back("0:" + std::to_string(*_parameters.stream));
|
||||
}
|
||||
|
||||
if (_parameters.stripMetadata)
|
||||
{
|
||||
// Strip metadata
|
||||
args.push_back("-map_metadata");
|
||||
args.push_back("-1");
|
||||
args.emplace_back("-map_metadata");
|
||||
args.emplace_back("-1");
|
||||
}
|
||||
|
||||
// Skip video flows (including covers)
|
||||
args.push_back("-vn");
|
||||
args.emplace_back("-vn");
|
||||
|
||||
// Codecs and formats
|
||||
if (_parameters.encoding)
|
||||
{
|
||||
// Output bitrates
|
||||
args.push_back("-b:a");
|
||||
args.push_back(std::to_string(_parameters.bitrate));
|
||||
args.emplace_back("-b:a");
|
||||
args.emplace_back(std::to_string(_parameters.bitrate));
|
||||
|
||||
switch (*_parameters.encoding)
|
||||
{
|
||||
case Encoding::MP3:
|
||||
args.push_back("-f");
|
||||
args.push_back("mp3");
|
||||
args.emplace_back("-f");
|
||||
args.emplace_back("mp3");
|
||||
break;
|
||||
|
||||
case Encoding::OGG_OPUS:
|
||||
args.push_back("-acodec");
|
||||
args.push_back("libopus");
|
||||
args.push_back("-f");
|
||||
args.push_back("ogg");
|
||||
args.emplace_back("-acodec");
|
||||
args.emplace_back("libopus");
|
||||
args.emplace_back("-f");
|
||||
args.emplace_back("ogg");
|
||||
break;
|
||||
|
||||
case Encoding::OGG_VORBIS:
|
||||
args.push_back("-acodec");
|
||||
args.push_back("libvorbis");
|
||||
args.push_back("-f");
|
||||
args.push_back("ogg");
|
||||
args.emplace_back("-acodec");
|
||||
args.emplace_back("libvorbis");
|
||||
args.emplace_back("-f");
|
||||
args.emplace_back("ogg");
|
||||
break;
|
||||
|
||||
case Encoding::WEBM_VORBIS:
|
||||
args.push_back("-acodec");
|
||||
args.push_back("libvorbis");
|
||||
args.push_back("-f");
|
||||
args.push_back("webm");
|
||||
args.emplace_back("-acodec");
|
||||
args.emplace_back("libvorbis");
|
||||
args.emplace_back("-f");
|
||||
args.emplace_back("webm");
|
||||
break;
|
||||
|
||||
|
||||
@@ -169,23 +167,25 @@ Transcoder::start()
|
||||
return false;
|
||||
}
|
||||
|
||||
args.push_back("-acodec");
|
||||
args.push_back("copy");
|
||||
args.push_back("-f");
|
||||
args.push_back(mediaFileFormat->format);
|
||||
args.emplace_back("-acodec");
|
||||
args.emplace_back("copy");
|
||||
args.emplace_back("-f");
|
||||
args.emplace_back(mediaFileFormat->format);
|
||||
|
||||
_outputMimeType = mediaFileFormat->mimeType;
|
||||
}
|
||||
|
||||
args.push_back("pipe:1");
|
||||
args.emplace_back("pipe:1");
|
||||
|
||||
LMS_LOG_TRANSCODE(DEBUG) << "Dumping args (" << args.size() << ")";
|
||||
for (std::string arg : args)
|
||||
for (const std::string& arg : args)
|
||||
LMS_LOG_TRANSCODE(DEBUG) << "Arg = '" << arg << "'";
|
||||
|
||||
// make sure only one thread is executing this part of code
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(transcoderMutex);
|
||||
static std::mutex transcoderMutex;
|
||||
|
||||
std::lock_guard<std::mutex> lock {transcoderMutex};
|
||||
|
||||
_child = std::make_shared<redi::ipstream>();
|
||||
|
||||
|
||||
+17
-20
@@ -20,12 +20,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <chrono>
|
||||
#include <filesystem>
|
||||
#include <optional>
|
||||
|
||||
#include <pstreams/pstream.h>
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
#include "AvTypes.hpp"
|
||||
|
||||
namespace Av {
|
||||
@@ -34,10 +33,10 @@ namespace Av {
|
||||
|
||||
struct TranscodeParameters
|
||||
{
|
||||
boost::optional<Encoding> encoding; // If not set, no transcoding is performed
|
||||
std::optional<Encoding> encoding; // If not set, no transcoding is performed
|
||||
std::size_t bitrate {128000};
|
||||
boost::optional<std::size_t> stream; // Id of the stream to be transcoded (auto detect by default)
|
||||
boost::optional<std::chrono::seconds> offset {};
|
||||
std::optional<std::size_t> stream; // Id of the stream to be transcoded (auto detect by default)
|
||||
std::optional<std::chrono::seconds> offset {};
|
||||
bool stripMetadata {true};
|
||||
};
|
||||
|
||||
@@ -46,32 +45,30 @@ class Transcoder
|
||||
public:
|
||||
static void init();
|
||||
|
||||
Transcoder(boost::filesystem::path file, TranscodeParameters parameters);
|
||||
Transcoder(const std::filesystem::path& file, const TranscodeParameters& parameters);
|
||||
~Transcoder();
|
||||
|
||||
// non copyable
|
||||
Transcoder(const Transcoder&) = delete;
|
||||
Transcoder& operator=(const Transcoder&) = delete;
|
||||
Transcoder(Transcoder&&) = delete;
|
||||
Transcoder& operator=(Transcoder&&) = delete;
|
||||
|
||||
bool start();
|
||||
const std::string& getOutputMimeType() const { return _outputMimeType; }
|
||||
void process(std::vector<unsigned char>& output, std::size_t maxSize);
|
||||
bool isComplete(void) const { return _isComplete; }
|
||||
bool start();
|
||||
const std::string& getOutputMimeType() const { return _outputMimeType; }
|
||||
void process(std::vector<unsigned char>& output, std::size_t maxSize);
|
||||
bool isComplete(void) const { return _isComplete; }
|
||||
|
||||
const TranscodeParameters& getParameters() const { return _parameters; }
|
||||
|
||||
|
||||
private:
|
||||
Transcoder();
|
||||
|
||||
boost::filesystem::path _filePath;
|
||||
TranscodeParameters _parameters;
|
||||
const std::filesystem::path _filePath;
|
||||
const TranscodeParameters _parameters;
|
||||
|
||||
std::shared_ptr<redi::ipstream> _child;
|
||||
|
||||
bool _isComplete = false;
|
||||
std::size_t _total = 0;
|
||||
std::size_t _id;
|
||||
bool _isComplete {};
|
||||
std::size_t _total {};
|
||||
const std::size_t _id {};
|
||||
std::string _outputMimeType;
|
||||
};
|
||||
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
#include "utils/Exception.hpp"
|
||||
|
||||
|
||||
@@ -19,8 +19,6 @@
|
||||
|
||||
#include "CoverArtGrabber.hpp"
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
#include "av/AvInfo.hpp"
|
||||
|
||||
#include "database/Release.hpp"
|
||||
@@ -32,9 +30,9 @@
|
||||
namespace {
|
||||
|
||||
bool
|
||||
isFileSupported(const boost::filesystem::path& file, const std::vector<boost::filesystem::path> extensions)
|
||||
isFileSupported(const std::filesystem::path& file, const std::vector<std::filesystem::path> extensions)
|
||||
{
|
||||
boost::filesystem::path fileExtension = file.extension();
|
||||
std::filesystem::path fileExtension = file.extension();
|
||||
|
||||
for (auto extension : extensions)
|
||||
{
|
||||
@@ -54,7 +52,7 @@ Grabber::Grabber()
|
||||
}
|
||||
|
||||
void
|
||||
Grabber::setDefaultCover(boost::filesystem::path p)
|
||||
Grabber::setDefaultCover(const std::filesystem::path& p)
|
||||
{
|
||||
if (!_defaultCover.load(p))
|
||||
throw LmsException("Cannot read default cover file '" + p.string() + "'");
|
||||
@@ -84,7 +82,7 @@ Grabber::getDefaultCover(std::size_t size)
|
||||
return it->second;
|
||||
}
|
||||
|
||||
static boost::optional<Image::Image>
|
||||
static std::optional<Image::Image>
|
||||
getFromAvMediaFile(const Av::MediaFile& input)
|
||||
{
|
||||
std::vector<Image::Image> res;
|
||||
@@ -100,11 +98,11 @@ getFromAvMediaFile(const Av::MediaFile& input)
|
||||
}
|
||||
|
||||
LMS_LOG(COVER, DEBUG) << "No cover found in media file '" << input.getPath().string() << "'";
|
||||
return boost::none;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
boost::optional<Image::Image>
|
||||
Grabber::getFromDirectory(const boost::filesystem::path& p) const
|
||||
std::optional<Image::Image>
|
||||
Grabber::getFromDirectory(const std::filesystem::path& p) const
|
||||
{
|
||||
for (auto coverPath : getCoverPaths(p))
|
||||
{
|
||||
@@ -117,33 +115,33 @@ Grabber::getFromDirectory(const boost::filesystem::path& p) const
|
||||
}
|
||||
|
||||
LMS_LOG(COVER, DEBUG) << "No cover found in directory '" << p.string() << "'";
|
||||
return boost::none;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::vector<boost::filesystem::path>
|
||||
Grabber::getCoverPaths(const boost::filesystem::path& directoryPath) const
|
||||
std::vector<std::filesystem::path>
|
||||
Grabber::getCoverPaths(const std::filesystem::path& directoryPath) const
|
||||
{
|
||||
std::vector<boost::filesystem::path> res;
|
||||
boost::system::error_code ec;
|
||||
std::vector<std::filesystem::path> res;
|
||||
std::error_code ec;
|
||||
|
||||
// TODO handle preferred file names
|
||||
|
||||
boost::filesystem::directory_iterator itPath(directoryPath, ec);
|
||||
boost::filesystem::directory_iterator itEnd;
|
||||
std::filesystem::directory_iterator itPath(directoryPath, ec);
|
||||
std::filesystem::directory_iterator itEnd;
|
||||
while (!ec && itPath != itEnd)
|
||||
{
|
||||
boost::filesystem::path path = *itPath;
|
||||
std::filesystem::path path = *itPath;
|
||||
itPath.increment(ec);
|
||||
|
||||
if (!boost::filesystem::is_regular(path))
|
||||
if (!std::filesystem::is_regular_file(path))
|
||||
continue;
|
||||
|
||||
if (!isFileSupported(path, _fileExtensions))
|
||||
continue;
|
||||
|
||||
if (boost::filesystem::file_size(path) > _maxFileSize)
|
||||
if (std::filesystem::file_size(path) > _maxFileSize)
|
||||
{
|
||||
LMS_LOG(COVER, INFO) << "Cover file '" << path.string() << " is too big (" << boost::filesystem::file_size(path) << "), limit is " << _maxFileSize;
|
||||
LMS_LOG(COVER, INFO) << "Cover file '" << path.string() << " is too big (" << std::filesystem::file_size(path) << "), limit is " << _maxFileSize;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -153,8 +151,8 @@ Grabber::getCoverPaths(const boost::filesystem::path& directoryPath) const
|
||||
return res;
|
||||
}
|
||||
|
||||
boost::optional<Image::Image>
|
||||
Grabber::getFromTrack(const boost::filesystem::path& p) const
|
||||
std::optional<Image::Image>
|
||||
Grabber::getFromTrack(const std::filesystem::path& p) const
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -165,7 +163,7 @@ Grabber::getFromTrack(const boost::filesystem::path& p) const
|
||||
catch (Av::MediaFileException& e)
|
||||
{
|
||||
LMS_LOG(COVER, ERROR) << "Cannot get covers from track " << p.string() << ": " << e.what();
|
||||
return boost::none;
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,10 +172,10 @@ Grabber::getFromTrack(Database::Session& dbSession, Database::IdType trackId, st
|
||||
{
|
||||
using namespace Database;
|
||||
|
||||
boost::optional<Image::Image> cover;
|
||||
std::optional<Image::Image> cover;
|
||||
|
||||
bool hasCover {};
|
||||
boost::filesystem::path trackPath;
|
||||
std::filesystem::path trackPath;
|
||||
|
||||
{
|
||||
auto transaction {dbSession.createSharedTransaction()};
|
||||
@@ -208,9 +206,9 @@ Grabber::getFromTrack(Database::Session& dbSession, Database::IdType trackId, st
|
||||
Image::Image
|
||||
Grabber::getFromRelease(Database::Session& session, Database::IdType releaseId, std::size_t size)
|
||||
{
|
||||
boost::optional<Image::Image> cover;
|
||||
std::optional<Image::Image> cover;
|
||||
|
||||
boost::optional<Database::IdType> trackId;
|
||||
std::optional<Database::IdType> trackId;
|
||||
{
|
||||
auto transaction {session.createSharedTransaction()};
|
||||
|
||||
@@ -239,7 +237,8 @@ Grabber::getFromTrack(Database::Session& session, Database::IdType trackId, Imag
|
||||
{
|
||||
const Image::Image cover {getFromTrack(session, trackId, size)};
|
||||
|
||||
return cover.save(Image::Format::JPEG);
|
||||
assert(format == Image::Format::JPEG);
|
||||
return cover.save(format);
|
||||
}
|
||||
|
||||
std::vector<uint8_t>
|
||||
@@ -247,7 +246,8 @@ Grabber::getFromRelease(Database::Session& session, Database::IdType releaseId,
|
||||
{
|
||||
const Image::Image cover {getFromRelease(session, releaseId, size)};
|
||||
|
||||
return cover.save(Image::Format::JPEG);
|
||||
assert(format == Image::Format::JPEG);
|
||||
return cover.save(format);
|
||||
}
|
||||
|
||||
} // namespace CoverArt
|
||||
|
||||
@@ -19,12 +19,12 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <filesystem>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
#include "database/Types.hpp"
|
||||
|
||||
#include "image/Image.hpp"
|
||||
@@ -44,7 +44,7 @@ class Grabber
|
||||
Grabber(Grabber&&) = delete;
|
||||
Grabber& operator=(Grabber&&) = delete;
|
||||
|
||||
void setDefaultCover(boost::filesystem::path defaultCoverPath);
|
||||
void setDefaultCover(const std::filesystem::path& defaultCoverPath);
|
||||
|
||||
std::vector<uint8_t> getFromTrack(Database::Session& dbSession, Database::IdType trackId, Image::Format format, std::size_t size);
|
||||
std::vector<uint8_t> getFromRelease(Database::Session& dbSession, Database::IdType releaseId, Image::Format format, std::size_t size);
|
||||
@@ -54,9 +54,9 @@ class Grabber
|
||||
Image::Image getFromTrack(Database::Session& dbSession, Database::IdType trackId, std::size_t size);
|
||||
Image::Image getFromRelease(Database::Session& dbSession, Database::IdType releaseId, std::size_t size);
|
||||
|
||||
boost::optional<Image::Image> getFromTrack(const boost::filesystem::path& path) const;
|
||||
std::vector<boost::filesystem::path> getCoverPaths(const boost::filesystem::path& directoryPath) const;
|
||||
boost::optional<Image::Image> getFromDirectory(const boost::filesystem::path& path) const;
|
||||
std::optional<Image::Image> getFromTrack(const std::filesystem::path& path) const;
|
||||
std::vector<std::filesystem::path> getCoverPaths(const std::filesystem::path& directoryPath) const;
|
||||
std::optional<Image::Image> getFromDirectory(const std::filesystem::path& path) const;
|
||||
|
||||
Image::Image getDefaultCover(std::size_t size);
|
||||
|
||||
@@ -65,12 +65,12 @@ class Grabber
|
||||
std::mutex _mutex;
|
||||
std::map<std::size_t /* size */, Image::Image> _defaultCovers;
|
||||
|
||||
std::vector<boost::filesystem::path> _fileExtensions
|
||||
std::vector<std::filesystem::path> _fileExtensions
|
||||
= {".jpg", ".jpeg", ".png", ".bmp"}; // TODO parametrize
|
||||
|
||||
std::size_t _maxFileSize = 5000000;
|
||||
|
||||
std::vector<boost::filesystem::path> _preferredFileNames
|
||||
std::vector<std::filesystem::path> _preferredFileNames
|
||||
= {"cover", "front"}; // TODO parametrize
|
||||
};
|
||||
|
||||
|
||||
+13
-8
@@ -75,7 +75,7 @@ Artist::create(Session& session, const std::string& name, const std::string& MBI
|
||||
}
|
||||
|
||||
std::vector<Artist::pointer>
|
||||
Artist::getAll(Session& session, boost::optional<std::size_t> offset, boost::optional<std::size_t> size)
|
||||
Artist::getAll(Session& session, std::optional<std::size_t> offset, std::optional<std::size_t> size)
|
||||
{
|
||||
session.checkSharedLocked();
|
||||
Wt::Dbo::collection<pointer> res = session.getDboSession().find<Artist>()
|
||||
@@ -151,8 +151,8 @@ std::vector<Artist::pointer>
|
||||
Artist::getByFilter(Session& session,
|
||||
const std::set<IdType>& clusters,
|
||||
const std::vector<std::string>& keywords,
|
||||
boost::optional<std::size_t> offset,
|
||||
boost::optional<std::size_t> size,
|
||||
std::optional<std::size_t> offset,
|
||||
std::optional<std::size_t> size,
|
||||
bool& moreResults)
|
||||
{
|
||||
session.checkSharedLocked();
|
||||
@@ -174,7 +174,7 @@ Artist::getByFilter(Session& session,
|
||||
}
|
||||
|
||||
std::vector<Artist::pointer>
|
||||
Artist::getLastAdded(Session& session, Wt::WDateTime after, boost::optional<std::size_t> limit)
|
||||
Artist::getLastAdded(Session& session, Wt::WDateTime after, std::optional<std::size_t> limit)
|
||||
{
|
||||
session.checkSharedLocked();
|
||||
Wt::Dbo::collection<Artist::pointer> res = session.getDboSession().query<Artist::pointer>("SELECT a from artist a INNER JOIN track_artist_link t_a_l ON t_a_l.artist_id = a.id INNER JOIN track t ON t.id = t_a_l.track_id")
|
||||
@@ -243,7 +243,7 @@ Artist::getReleaseCount() const
|
||||
}
|
||||
|
||||
std::vector<Wt::Dbo::ptr<Track>>
|
||||
Artist::getTracks(boost::optional<TrackArtistLink::Type> linkType) const
|
||||
Artist::getTracks(std::optional<TrackArtistLink::Type> linkType) const
|
||||
{
|
||||
assert(self());
|
||||
assert(IdIsValid(self()->id()));
|
||||
@@ -262,22 +262,27 @@ Artist::getTracks(boost::optional<TrackArtistLink::Type> linkType) const
|
||||
}
|
||||
|
||||
std::vector<Wt::Dbo::ptr<Track>>
|
||||
Artist::getTracksWithRelease(boost::optional<TrackArtistLink::Type> linkType) const
|
||||
Artist::getTracksWithRelease(std::optional<TrackArtistLink::Type> linkType) const
|
||||
{
|
||||
assert(self());
|
||||
assert(IdIsValid(self()->id()));
|
||||
assert(session());
|
||||
|
||||
Wt::Dbo::collection<Wt::Dbo::ptr<Track>> tracks {session()->query<Wt::Dbo::ptr<Track>>("SELECT t FROM track t INNER JOIN artist a ON a.id = t_a_l.artist_id INNER JOIN track_artist_link t_a_l ON t_a_l.track_id = t.id INNER JOIN release r ON r.id = t.release_id")
|
||||
auto query {session()->query<Wt::Dbo::ptr<Track>>("SELECT t FROM track t INNER JOIN artist a ON a.id = t_a_l.artist_id INNER JOIN track_artist_link t_a_l ON t_a_l.track_id = t.id INNER JOIN release r ON r.id = t.release_id")
|
||||
.where("a.id = ?").bind(self()->id())
|
||||
.orderBy("t.year,r.name,t.disc_number,t.track_number")};
|
||||
|
||||
if (linkType)
|
||||
query.where("t_a_l.type = ?").bind(*linkType);
|
||||
|
||||
Wt::Dbo::collection<Wt::Dbo::ptr<Track>> tracks {query.resultList()};
|
||||
|
||||
return std::vector<Wt::Dbo::ptr<Track>>(tracks.begin(), tracks.end());
|
||||
}
|
||||
|
||||
|
||||
std::vector<Wt::Dbo::ptr<Track>>
|
||||
Artist::getRandomTracks(boost::optional<std::size_t> count) const
|
||||
Artist::getRandomTracks(std::optional<std::size_t> count) const
|
||||
{
|
||||
assert(self());
|
||||
assert(IdIsValid(self()->id()));
|
||||
|
||||
@@ -19,11 +19,10 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
#include <Wt/WDateTime.h>
|
||||
#include <Wt/Dbo/Dbo.h>
|
||||
|
||||
@@ -58,13 +57,13 @@ class Artist : public Wt::Dbo::Dbo<Artist>
|
||||
static std::vector<pointer> getByFilter(Session& session,
|
||||
const std::set<IdType>& clusters, // at least one track that belongs to these clusters
|
||||
const std::vector<std::string>& keywords, // name must match all of these keywords
|
||||
boost::optional<std::size_t> offset,
|
||||
boost::optional<std::size_t> size,
|
||||
std::optional<std::size_t> offset,
|
||||
std::optional<std::size_t> size,
|
||||
bool& moreExpected);
|
||||
|
||||
static std::vector<pointer> getAll(Session& session, boost::optional<std::size_t> offset = {}, boost::optional<std::size_t> size = {});
|
||||
static std::vector<pointer> getAll(Session& session, std::optional<std::size_t> offset = {}, std::optional<std::size_t> size = {});
|
||||
static std::vector<pointer> getAllOrphans(Session& session); // No track related
|
||||
static std::vector<pointer> getLastAdded(Session& session, Wt::WDateTime after, boost::optional<std::size_t> size = {});
|
||||
static std::vector<pointer> getLastAdded(Session& session, Wt::WDateTime after, std::optional<std::size_t> size = {});
|
||||
|
||||
// Accessors
|
||||
const std::string& getName(void) const { return _name; }
|
||||
@@ -72,9 +71,9 @@ class Artist : public Wt::Dbo::Dbo<Artist>
|
||||
|
||||
std::vector<Wt::Dbo::ptr<Release>> getReleases(const std::set<IdType>& clusterIds = std::set<IdType>()) const;
|
||||
std::size_t getReleaseCount() const;
|
||||
std::vector<Wt::Dbo::ptr<Track>> getTracks(boost::optional<TrackArtistLink::Type> linkType = {}) const;
|
||||
std::vector<Wt::Dbo::ptr<Track>> getTracksWithRelease(boost::optional<TrackArtistLink::Type> linkType = {}) const;
|
||||
std::vector<Wt::Dbo::ptr<Track>> getRandomTracks(boost::optional<std::size_t> count) const;
|
||||
std::vector<Wt::Dbo::ptr<Track>> getTracks(std::optional<TrackArtistLink::Type> linkType = {}) const;
|
||||
std::vector<Wt::Dbo::ptr<Track>> getTracksWithRelease(std::optional<TrackArtistLink::Type> linkType = {}) const;
|
||||
std::vector<Wt::Dbo::ptr<Track>> getRandomTracks(std::optional<std::size_t> count) const;
|
||||
|
||||
// Get the cluster of the tracks made by this artist
|
||||
// Each clusters are grouped by cluster type, sorted by the number of occurence
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Database.hpp"
|
||||
#include "Db.hpp"
|
||||
|
||||
#include <Wt/Dbo/FixedSqlConnectionPool.h>
|
||||
#include <Wt/Dbo/backend/Sqlite3.h>
|
||||
@@ -28,7 +28,7 @@
|
||||
namespace Database {
|
||||
|
||||
// Session living class handling the database and the login
|
||||
Database::Database(const boost::filesystem::path& dbPath)
|
||||
Db::Db(const std::filesystem::path& dbPath)
|
||||
{
|
||||
LMS_LOG(DB, INFO) << "Creating connection pool on file " << dbPath.string();
|
||||
|
||||
@@ -49,9 +49,9 @@ Database::Database(const boost::filesystem::path& dbPath)
|
||||
}
|
||||
|
||||
std::unique_ptr<Session>
|
||||
Database::createSession()
|
||||
Db::createSession()
|
||||
{
|
||||
return std::unique_ptr<Session>{new Session {_sharedMutex, *_connectionPool.get()}};
|
||||
return std::unique_ptr<Session>(new Session {_sharedMutex, *_connectionPool.get()});
|
||||
}
|
||||
|
||||
} // namespace Database
|
||||
@@ -19,10 +19,9 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <filesystem>
|
||||
#include <shared_mutex>
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
#include <Wt/Dbo/SqlConnectionPool.h>
|
||||
|
||||
#include "Session.hpp"
|
||||
@@ -30,17 +29,17 @@
|
||||
namespace Database {
|
||||
|
||||
// Session living class handling the database and the login
|
||||
class Database
|
||||
class Db
|
||||
{
|
||||
public:
|
||||
|
||||
Database(const boost::filesystem::path& dbPath);
|
||||
Db(const std::filesystem::path& dbPath);
|
||||
|
||||
std::unique_ptr<Session> createSession();
|
||||
|
||||
private:
|
||||
std::shared_timed_mutex _sharedMutex;
|
||||
std::unique_ptr<Wt::Dbo::SqlConnectionPool> _connectionPool;
|
||||
std::shared_mutex _sharedMutex;
|
||||
std::unique_ptr<Wt::Dbo::SqlConnectionPool> _connectionPool;
|
||||
};
|
||||
|
||||
} // namespace Database
|
||||
+18
-18
@@ -84,7 +84,7 @@ Release::getCount(Session& session)
|
||||
}
|
||||
|
||||
std::vector<Release::pointer>
|
||||
Release::getAll(Session& session, boost::optional<std::size_t> offset, boost::optional<std::size_t> size)
|
||||
Release::getAll(Session& session, std::optional<std::size_t> offset, std::optional<std::size_t> size)
|
||||
{
|
||||
session.checkSharedLocked();
|
||||
|
||||
@@ -97,7 +97,7 @@ Release::getAll(Session& session, boost::optional<std::size_t> offset, boost::op
|
||||
}
|
||||
|
||||
std::vector<Release::pointer>
|
||||
Release::getAllOrderedByArtist(Session& session, boost::optional<std::size_t> offset, boost::optional<std::size_t> size)
|
||||
Release::getAllOrderedByArtist(Session& session, std::optional<std::size_t> offset, std::optional<std::size_t> size)
|
||||
{
|
||||
session.checkSharedLocked();
|
||||
|
||||
@@ -114,7 +114,7 @@ Release::getAllOrderedByArtist(Session& session, boost::optional<std::size_t> of
|
||||
}
|
||||
|
||||
std::vector<Release::pointer>
|
||||
Release::getAllRandom(Session& session, boost::optional<std::size_t> size)
|
||||
Release::getAllRandom(Session& session, std::optional<std::size_t> size)
|
||||
{
|
||||
session.checkSharedLocked();
|
||||
|
||||
@@ -136,7 +136,7 @@ Release::getAllOrphans(Session& session)
|
||||
}
|
||||
|
||||
std::vector<Release::pointer>
|
||||
Release::getLastAdded(Session& session, const Wt::WDateTime& after, boost::optional<std::size_t> offset, boost::optional<std::size_t> limit)
|
||||
Release::getLastAdded(Session& session, const Wt::WDateTime& after, std::optional<std::size_t> offset, std::optional<std::size_t> limit)
|
||||
{
|
||||
session.checkSharedLocked();
|
||||
|
||||
@@ -151,7 +151,7 @@ Release::getLastAdded(Session& session, const Wt::WDateTime& after, boost::optio
|
||||
}
|
||||
|
||||
std::vector<Release::pointer>
|
||||
Release::getByYear(Session& session, int yearFrom, int yearTo, boost::optional<std::size_t> offset, boost::optional<std::size_t> limit)
|
||||
Release::getByYear(Session& session, int yearFrom, int yearTo, std::optional<std::size_t> offset, std::optional<std::size_t> limit)
|
||||
{
|
||||
Wt::Dbo::collection<Release::pointer> res = session.getDboSession().query<Release::pointer>
|
||||
("SELECT DISTINCT r from release r INNER JOIN track t ON r.id = t.release_id")
|
||||
@@ -216,8 +216,8 @@ std::vector<Release::pointer>
|
||||
Release::getByFilter(Session& session,
|
||||
const std::set<IdType>& clusterIds,
|
||||
const std::vector<std::string>& keywords,
|
||||
boost::optional<std::size_t> offset,
|
||||
boost::optional<std::size_t> size,
|
||||
std::optional<std::size_t> offset,
|
||||
std::optional<std::size_t> size,
|
||||
bool& moreResults)
|
||||
{
|
||||
Wt::Dbo::collection<pointer> collection = getQuery(session, clusterIds, keywords)
|
||||
@@ -237,19 +237,19 @@ Release::getByFilter(Session& session,
|
||||
return res;
|
||||
}
|
||||
|
||||
boost::optional<std::size_t>
|
||||
std::optional<std::size_t>
|
||||
Release::getTotalTrackNumber(void) const
|
||||
{
|
||||
return (_totalTrackNumber > 0) ? boost::make_optional<std::size_t>(_totalTrackNumber) : boost::none;
|
||||
return (_totalTrackNumber > 0) ? std::make_optional<std::size_t>(_totalTrackNumber) : std::nullopt;
|
||||
}
|
||||
|
||||
boost::optional<std::size_t>
|
||||
std::optional<std::size_t>
|
||||
Release::getTotalDiscNumber(void) const
|
||||
{
|
||||
return (_totalDiscNumber > 0) ? boost::make_optional<std::size_t>(_totalDiscNumber) : boost::none;
|
||||
return (_totalDiscNumber > 0) ? std::make_optional<std::size_t>(_totalDiscNumber) : std::nullopt;
|
||||
}
|
||||
|
||||
boost::optional<int>
|
||||
std::optional<int>
|
||||
Release::getReleaseYear(bool original) const
|
||||
{
|
||||
assert(session());
|
||||
@@ -264,17 +264,17 @@ Release::getReleaseYear(bool original) const
|
||||
|
||||
// various dates => no date
|
||||
if (dates.empty() || dates.size() > 1)
|
||||
return boost::none;
|
||||
return std::nullopt;
|
||||
|
||||
auto date {dates.front()};
|
||||
|
||||
if (date > 0)
|
||||
return date;
|
||||
else
|
||||
return boost::none;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
boost::optional<std::string>
|
||||
std::optional<std::string>
|
||||
Release::getCopyright() const
|
||||
{
|
||||
assert(session());
|
||||
@@ -289,12 +289,12 @@ Release::getCopyright() const
|
||||
|
||||
// various copyrights => no copyright
|
||||
if (values.empty() || values.size() > 1 || values.front().empty())
|
||||
return boost::none;
|
||||
return std::nullopt;
|
||||
|
||||
return values.front();
|
||||
}
|
||||
|
||||
boost::optional<std::string>
|
||||
std::optional<std::string>
|
||||
Release::getCopyrightURL() const
|
||||
{
|
||||
assert(session());
|
||||
@@ -309,7 +309,7 @@ Release::getCopyrightURL() const
|
||||
|
||||
// various copyright URLs => no copyright URL
|
||||
if (values.empty() || values.size() > 1 || values.front().empty())
|
||||
return boost::none;
|
||||
return std::nullopt;
|
||||
|
||||
return values.front();
|
||||
}
|
||||
|
||||
+13
-13
@@ -19,7 +19,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <boost/optional.hpp>
|
||||
#include <optional>
|
||||
|
||||
#include <Wt/Dbo/WtSqlTraits.h>
|
||||
|
||||
@@ -51,18 +51,18 @@ class Release : public Wt::Dbo::Dbo<Release>
|
||||
static std::vector<pointer> getByName(Session& session, const std::string& name);
|
||||
static pointer getById(Session& session, IdType id);
|
||||
static std::vector<pointer> getAllOrphans(Session& session); // no track related
|
||||
static std::vector<pointer> getAll(Session& session, boost::optional<std::size_t> offset = {}, boost::optional<std::size_t> size = {});
|
||||
static std::vector<pointer> getAllOrderedByArtist(Session& session, boost::optional<std::size_t> offset = {}, boost::optional<std::size_t> size = {});
|
||||
static std::vector<pointer> getAllRandom(Session& session, boost::optional<std::size_t> size = {});
|
||||
static std::vector<pointer> getLastAdded(Session& session, const Wt::WDateTime& after, boost::optional<std::size_t> offset = {}, boost::optional<std::size_t> size = {});
|
||||
static std::vector<pointer> getByYear(Session& session, int yearFrom, int yearTo, boost::optional<std::size_t> offset = {}, boost::optional<std::size_t> size = {});
|
||||
static std::vector<pointer> getAll(Session& session, std::optional<std::size_t> offset = {}, std::optional<std::size_t> size = {});
|
||||
static std::vector<pointer> getAllOrderedByArtist(Session& session, std::optional<std::size_t> offset = {}, std::optional<std::size_t> size = {});
|
||||
static std::vector<pointer> getAllRandom(Session& session, std::optional<std::size_t> size = {});
|
||||
static std::vector<pointer> getLastAdded(Session& session, const Wt::WDateTime& after, std::optional<std::size_t> offset = {}, std::optional<std::size_t> size = {});
|
||||
static std::vector<pointer> getByYear(Session& session, int yearFrom, int yearTo, std::optional<std::size_t> offset = {}, std::optional<std::size_t> size = {});
|
||||
|
||||
static std::vector<pointer> getByFilter(Session& session, const std::set<IdType>& clusters);
|
||||
static std::vector<pointer> getByFilter(Session& session,
|
||||
const std::set<IdType>& clusters, // at least one track that belongs to these clusters
|
||||
const std::vector<std::string>& keywords, // name must match all of these keywords
|
||||
boost::optional<std::size_t> offset,
|
||||
boost::optional<std::size_t> size,
|
||||
std::optional<std::size_t> offset,
|
||||
std::optional<std::size_t> size,
|
||||
bool& moreExpected);
|
||||
|
||||
std::vector<Wt::Dbo::ptr<Track>> getTracks(const std::set<IdType>& clusters = std::set<IdType>()) const;
|
||||
@@ -77,9 +77,9 @@ class Release : public Wt::Dbo::Dbo<Release>
|
||||
static pointer create(Session& session, const std::string& name, const std::string& MBID = "");
|
||||
|
||||
// Utility functions
|
||||
boost::optional<int> getReleaseYear(bool originalDate = false) const; // 0 if unknown or various
|
||||
boost::optional<std::string> getCopyright() const;
|
||||
boost::optional<std::string> getCopyrightURL() const;
|
||||
std::optional<int> getReleaseYear(bool originalDate = false) const; // 0 if unknown or various
|
||||
std::optional<std::string> getCopyright() const;
|
||||
std::optional<std::string> getCopyrightURL() const;
|
||||
|
||||
// Modifiers
|
||||
void setTotalDiscNumber(std::size_t num) { _totalDiscNumber = static_cast<int>(num); }
|
||||
@@ -88,8 +88,8 @@ class Release : public Wt::Dbo::Dbo<Release>
|
||||
// Accessors
|
||||
std::string getName() const { return _name; }
|
||||
std::string getMBID() const { return _MBID; }
|
||||
boost::optional<std::size_t> getTotalTrackNumber() const;
|
||||
boost::optional<std::size_t> getTotalDiscNumber() const;
|
||||
std::optional<std::size_t> getTotalTrackNumber() const;
|
||||
std::optional<std::size_t> getTotalDiscNumber() const;
|
||||
std::chrono::milliseconds getDuration() const;
|
||||
|
||||
// Get the artists of this release
|
||||
|
||||
@@ -62,11 +62,11 @@ ScanSettings::get(Session& session)
|
||||
return session.getDboSession().find<ScanSettings>();
|
||||
}
|
||||
|
||||
std::set<boost::filesystem::path>
|
||||
std::set<std::filesystem::path>
|
||||
ScanSettings::getAudioFileExtensions() const
|
||||
{
|
||||
auto extensions = splitString(_audioFileExtensions, " ");
|
||||
return std::set<boost::filesystem::path>(std::cbegin(extensions), std::cend(extensions));
|
||||
return std::set<std::filesystem::path>(std::cbegin(extensions), std::cend(extensions));
|
||||
}
|
||||
|
||||
std::vector<ClusterType::pointer>
|
||||
@@ -76,7 +76,7 @@ ScanSettings::getClusterTypes() const
|
||||
}
|
||||
|
||||
void
|
||||
ScanSettings::setMediaDirectory(boost::filesystem::path p)
|
||||
ScanSettings::setMediaDirectory(std::filesystem::path p)
|
||||
{
|
||||
_mediaDirectory = stringTrimEnd(p.string(), "/\\");
|
||||
}
|
||||
@@ -85,7 +85,7 @@ template <typename It>
|
||||
std::set<std::string> getNames(It begin, It end)
|
||||
{
|
||||
std::set<std::string> names;
|
||||
std::transform(begin, end, std::inserter(names, std::begin(names)),
|
||||
std::transform(begin, end, std::inserter(names, std::cbegin(names)),
|
||||
[](const ClusterType::pointer& clusterType)
|
||||
{
|
||||
return clusterType->getName();
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <filesystem>
|
||||
|
||||
#include <Wt/Dbo/Dbo.h>
|
||||
#include <Wt/WTime.h>
|
||||
@@ -47,18 +47,18 @@ class ScanSettings : public Wt::Dbo::Dbo<ScanSettings>
|
||||
|
||||
// Getters
|
||||
std::size_t getScanVersion() const { return _scanVersion; }
|
||||
boost::filesystem::path getMediaDirectory() const { return _mediaDirectory; }
|
||||
std::filesystem::path getMediaDirectory() const { return _mediaDirectory; }
|
||||
Wt::WTime getUpdateStartTime() const { return _startTime; }
|
||||
UpdatePeriod getUpdatePeriod() const { return _updatePeriod; }
|
||||
std::vector<Wt::Dbo::ptr<ClusterType>> getClusterTypes() const;
|
||||
std::set<boost::filesystem::path> getAudioFileExtensions() const;
|
||||
std::set<std::filesystem::path> getAudioFileExtensions() const;
|
||||
|
||||
// Setters
|
||||
void setMediaDirectory(boost::filesystem::path p);
|
||||
void setMediaDirectory(std::filesystem::path p);
|
||||
void setUpdateStartTime(Wt::WTime t) { _startTime = t; }
|
||||
void setUpdatePeriod(UpdatePeriod p) { _updatePeriod = p; }
|
||||
void setClusterTypes(Session& session, const std::set<std::string>& clusterTypeNames);
|
||||
void setAudioFileExtensions(std::set<boost::filesystem::path> fileExtensions);
|
||||
void setAudioFileExtensions(std::set<std::filesystem::path> fileExtensions);
|
||||
|
||||
template<class Action>
|
||||
void persist(Action& a)
|
||||
|
||||
@@ -110,7 +110,7 @@ Session::doDatabaseMigrationIfNeeded()
|
||||
VersionInfo::get(*this).modify()->setVersion(LMS_DATABASE_VERSION);
|
||||
}
|
||||
|
||||
Session::Session(std::shared_timed_mutex& mutex, Wt::Dbo::SqlConnectionPool& connectionPool)
|
||||
Session::Session(std::shared_mutex& mutex, Wt::Dbo::SqlConnectionPool& connectionPool)
|
||||
: _mutex {mutex}
|
||||
{
|
||||
_session.setConnectionPool(connectionPool);
|
||||
@@ -140,9 +140,9 @@ enum class OwnedLock
|
||||
Unique,
|
||||
};
|
||||
|
||||
static thread_local std::map<std::shared_timed_mutex*, OwnedLock> lockDebug;
|
||||
static thread_local std::map<std::shared_mutex*, OwnedLock> lockDebug;
|
||||
|
||||
UniqueTransaction::UniqueTransaction(std::shared_timed_mutex& mutex, Wt::Dbo::Session& session)
|
||||
UniqueTransaction::UniqueTransaction(std::shared_mutex& mutex, Wt::Dbo::Session& session)
|
||||
: _lock {mutex},
|
||||
_transaction {session}
|
||||
{
|
||||
@@ -156,7 +156,7 @@ UniqueTransaction::~UniqueTransaction()
|
||||
lockDebug[_lock.mutex()] = OwnedLock::None;
|
||||
}
|
||||
|
||||
SharedTransaction::SharedTransaction(std::shared_timed_mutex& mutex, Wt::Dbo::Session& session)
|
||||
SharedTransaction::SharedTransaction(std::shared_mutex& mutex, Wt::Dbo::Session& session)
|
||||
: _lock {mutex},
|
||||
_transaction {session}
|
||||
{
|
||||
@@ -182,16 +182,16 @@ Session::checkSharedLocked()
|
||||
assert(lockDebug[&_mutex] != OwnedLock::None);
|
||||
}
|
||||
|
||||
std::unique_ptr<UniqueTransaction>
|
||||
UniqueTransaction
|
||||
Session::createUniqueTransaction()
|
||||
{
|
||||
return std::unique_ptr<UniqueTransaction>(new UniqueTransaction{_mutex, _session});
|
||||
return UniqueTransaction{_mutex, _session};
|
||||
}
|
||||
|
||||
std::unique_ptr<SharedTransaction>
|
||||
SharedTransaction
|
||||
Session::createSharedTransaction()
|
||||
{
|
||||
return std::unique_ptr<SharedTransaction>(new SharedTransaction{_mutex, _session});
|
||||
return SharedTransaction{_mutex, _session};
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
+10
-11
@@ -21,7 +21,6 @@
|
||||
|
||||
#include <shared_mutex>
|
||||
#include <mutex>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <memory>
|
||||
|
||||
#include <Wt/Dbo/Dbo.h>
|
||||
@@ -36,9 +35,9 @@ class UniqueTransaction
|
||||
|
||||
private:
|
||||
friend class Session;
|
||||
UniqueTransaction(std::shared_timed_mutex& mutex, Wt::Dbo::Session& session);
|
||||
UniqueTransaction(std::shared_mutex& mutex, Wt::Dbo::Session& session);
|
||||
|
||||
std::unique_lock<std::shared_timed_mutex> _lock;
|
||||
std::unique_lock<std::shared_mutex> _lock;
|
||||
Wt::Dbo::Transaction _transaction;
|
||||
};
|
||||
|
||||
@@ -49,9 +48,9 @@ class SharedTransaction
|
||||
|
||||
private:
|
||||
friend class Session;
|
||||
SharedTransaction(std::shared_timed_mutex& mutex, Wt::Dbo::Session& session);
|
||||
SharedTransaction(std::shared_mutex& mutex, Wt::Dbo::Session& session);
|
||||
|
||||
std::shared_lock<std::shared_timed_mutex> _lock;
|
||||
std::shared_lock<std::shared_mutex> _lock;
|
||||
Wt::Dbo::Transaction _transaction;
|
||||
};
|
||||
|
||||
@@ -63,8 +62,8 @@ class Session
|
||||
Session& operator=(const Session&) = delete;
|
||||
Session& operator=(Session&&) = delete;
|
||||
|
||||
std::unique_ptr<UniqueTransaction> createUniqueTransaction();
|
||||
std::unique_ptr<SharedTransaction> createSharedTransaction();
|
||||
UniqueTransaction createUniqueTransaction();
|
||||
SharedTransaction createSharedTransaction();
|
||||
|
||||
void checkUniqueLocked();
|
||||
void checkSharedLocked();
|
||||
@@ -74,15 +73,15 @@ class Session
|
||||
Wt::Dbo::Session& getDboSession() { return _session; }
|
||||
|
||||
private:
|
||||
friend class Database;
|
||||
friend class Db;
|
||||
|
||||
Session(std::shared_timed_mutex& mutex, Wt::Dbo::SqlConnectionPool& connectionPool);
|
||||
Session(std::shared_mutex& mutex, Wt::Dbo::SqlConnectionPool& connectionPool);
|
||||
|
||||
void doDatabaseMigrationIfNeeded();
|
||||
void prepareTables(); // need to run only once at startup
|
||||
|
||||
std::shared_timed_mutex& _mutex;
|
||||
Wt::Dbo::Session _session;
|
||||
std::shared_mutex& _mutex;
|
||||
Wt::Dbo::Session _session;
|
||||
};
|
||||
|
||||
} // namespace Database
|
||||
|
||||
+23
-23
@@ -32,14 +32,14 @@
|
||||
|
||||
namespace Database {
|
||||
|
||||
Track::Track(const boost::filesystem::path& p)
|
||||
Track::Track(const std::filesystem::path& p)
|
||||
:
|
||||
_filePath( p.string() )
|
||||
{
|
||||
}
|
||||
|
||||
std::vector<Track::pointer>
|
||||
Track::getAll(Session& session, boost::optional<std::size_t> limit)
|
||||
Track::getAll(Session& session, std::optional<std::size_t> limit)
|
||||
{
|
||||
session.checkSharedLocked();
|
||||
|
||||
@@ -50,7 +50,7 @@ Track::getAll(Session& session, boost::optional<std::size_t> limit)
|
||||
}
|
||||
|
||||
std::vector<Track::pointer>
|
||||
Track::getAllRandom(Session& session, boost::optional<std::size_t> limit)
|
||||
Track::getAllRandom(Session& session, std::optional<std::size_t> limit)
|
||||
{
|
||||
session.checkSharedLocked();
|
||||
|
||||
@@ -71,7 +71,7 @@ Track::getAllIds(Session& session)
|
||||
}
|
||||
|
||||
Track::pointer
|
||||
Track::getByPath(Session& session, const boost::filesystem::path& p)
|
||||
Track::getByPath(Session& session, const std::filesystem::path& p)
|
||||
{
|
||||
session.checkSharedLocked();
|
||||
|
||||
@@ -97,7 +97,7 @@ Track::getByMBID(Session& session, const std::string& mbid)
|
||||
}
|
||||
|
||||
Track::pointer
|
||||
Track::create(Session& session, const boost::filesystem::path& p)
|
||||
Track::create(Session& session, const std::filesystem::path& p)
|
||||
{
|
||||
session.checkUniqueLocked();
|
||||
|
||||
@@ -107,13 +107,13 @@ Track::create(Session& session, const boost::filesystem::path& p)
|
||||
return res;
|
||||
}
|
||||
|
||||
std::vector<boost::filesystem::path>
|
||||
std::vector<std::filesystem::path>
|
||||
Track::getAllPaths(Session& session)
|
||||
{
|
||||
session.checkSharedLocked();
|
||||
|
||||
Wt::Dbo::collection<std::string> res = session.getDboSession().query<std::string>("SELECT file_path FROM track");
|
||||
return std::vector<boost::filesystem::path>(res.begin(), res.end());
|
||||
return std::vector<std::filesystem::path>(res.begin(), res.end());
|
||||
}
|
||||
|
||||
std::vector<Track::pointer>
|
||||
@@ -126,7 +126,7 @@ Track::getMBIDDuplicates(Session& session)
|
||||
}
|
||||
|
||||
std::vector<Track::pointer>
|
||||
Track::getLastAdded(Session& session, const Wt::WDateTime& after, boost::optional<std::size_t> limit)
|
||||
Track::getLastAdded(Session& session, const Wt::WDateTime& after, std::optional<std::size_t> limit)
|
||||
{
|
||||
session.checkSharedLocked();
|
||||
|
||||
@@ -151,7 +151,7 @@ Track::getAllWithMBIDAndMissingFeatures(Session& session)
|
||||
}
|
||||
|
||||
std::vector<IdType>
|
||||
Track::getAllIdsWithFeatures(Session& session, boost::optional<std::size_t> limit)
|
||||
Track::getAllIdsWithFeatures(Session& session, std::optional<std::size_t> limit)
|
||||
{
|
||||
session.checkSharedLocked();
|
||||
|
||||
@@ -224,8 +224,8 @@ std::vector<Track::pointer>
|
||||
Track::getByFilter(Session& session,
|
||||
const std::set<IdType>& clusterIds,
|
||||
const std::vector<std::string>& keywords,
|
||||
boost::optional<std::size_t> offset,
|
||||
boost::optional<std::size_t> size,
|
||||
std::optional<std::size_t> offset,
|
||||
std::optional<std::size_t> size,
|
||||
bool& moreResults)
|
||||
{
|
||||
session.checkSharedLocked();
|
||||
@@ -289,40 +289,40 @@ Track::setFeatures(const Wt::Dbo::ptr<TrackFeatures>& features)
|
||||
_trackFeatures = features;
|
||||
}
|
||||
|
||||
boost::optional<std::size_t>
|
||||
std::optional<std::size_t>
|
||||
Track::getTrackNumber(void) const
|
||||
{
|
||||
return (_trackNumber > 0) ? boost::make_optional<std::size_t>(_trackNumber) : boost::none;
|
||||
return (_trackNumber > 0) ? std::make_optional<std::size_t>(_trackNumber) : std::nullopt;
|
||||
}
|
||||
|
||||
boost::optional<std::size_t>
|
||||
std::optional<std::size_t>
|
||||
Track::getDiscNumber(void) const
|
||||
{
|
||||
return (_discNumber > 0) ? boost::make_optional<std::size_t>(_discNumber) : boost::none;
|
||||
return (_discNumber > 0) ? std::make_optional<std::size_t>(_discNumber) : std::nullopt;
|
||||
}
|
||||
|
||||
boost::optional<int>
|
||||
std::optional<int>
|
||||
Track::getYear() const
|
||||
{
|
||||
return (_year > 0) ? boost::make_optional<int>(_year) : boost::none;
|
||||
return (_year > 0) ? std::make_optional<int>(_year) : std::nullopt;
|
||||
}
|
||||
|
||||
boost::optional<int>
|
||||
std::optional<int>
|
||||
Track::getOriginalYear() const
|
||||
{
|
||||
return (_originalYear > 0) ? boost::make_optional<int>(_originalYear) : boost::none;
|
||||
return (_originalYear > 0) ? std::make_optional<int>(_originalYear) : std::nullopt;
|
||||
}
|
||||
|
||||
boost::optional<std::string>
|
||||
std::optional<std::string>
|
||||
Track::getCopyright() const
|
||||
{
|
||||
return _copyright != "" ? boost::make_optional<std::string>(_copyright) : boost::none;
|
||||
return _copyright != "" ? std::make_optional<std::string>(_copyright) : std::nullopt;
|
||||
}
|
||||
|
||||
boost::optional<std::string>
|
||||
std::optional<std::string>
|
||||
Track::getCopyrightURL() const
|
||||
{
|
||||
return _copyrightURL != "" ? boost::make_optional<std::string>(_copyrightURL) : boost::none;
|
||||
return _copyrightURL != "" ? std::make_optional<std::string>(_copyrightURL) : std::nullopt;
|
||||
}
|
||||
|
||||
std::vector<Wt::Dbo::ptr<Artist>>
|
||||
|
||||
+22
-23
@@ -19,12 +19,11 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <chrono>
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
#include <filesystem>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include <Wt/Dbo/Dbo.h>
|
||||
#include <Wt/WDateTime.h>
|
||||
@@ -50,10 +49,10 @@ class Track : public Wt::Dbo::Dbo<Track>
|
||||
using pointer = Wt::Dbo::ptr<Track>;
|
||||
|
||||
Track() {}
|
||||
Track(const boost::filesystem::path& p);
|
||||
Track(const std::filesystem::path& p);
|
||||
|
||||
// Find utility functions
|
||||
static pointer getByPath(Session& session, const boost::filesystem::path& p);
|
||||
static pointer getByPath(Session& session, const std::filesystem::path& p);
|
||||
static pointer getById(Session& session, IdType id);
|
||||
static pointer getByMBID(Session& session, const std::string& MBID);
|
||||
static std::vector<pointer> getByFilter(Session& session,
|
||||
@@ -61,21 +60,21 @@ class Track : public Wt::Dbo::Dbo<Track>
|
||||
static std::vector<pointer> getByFilter(Session& session,
|
||||
const std::set<IdType>& clusters, // tracks that belong to these clusters
|
||||
const std::vector<std::string>& keywords, // name must match all of these keywords
|
||||
boost::optional<std::size_t> offset,
|
||||
boost::optional<std::size_t> size,
|
||||
std::optional<std::size_t> offset,
|
||||
std::optional<std::size_t> size,
|
||||
bool& moreExpected);
|
||||
|
||||
static std::vector<pointer> getAll(Session& session, boost::optional<std::size_t> limit = {});
|
||||
static std::vector<pointer> getAllRandom(Session& session, boost::optional<std::size_t> limit = {});
|
||||
static std::vector<pointer> getAll(Session& session, std::optional<std::size_t> limit = {});
|
||||
static std::vector<pointer> getAllRandom(Session& session, std::optional<std::size_t> limit = {});
|
||||
static std::vector<IdType> getAllIds(Session& session); // nested transaction
|
||||
static std::vector<boost::filesystem::path> getAllPaths(Session& session); // nested transaction
|
||||
static std::vector<std::filesystem::path> getAllPaths(Session& session); // nested transaction
|
||||
static std::vector<pointer> getMBIDDuplicates(Session& session);
|
||||
static std::vector<pointer> getLastAdded(Session& session, const Wt::WDateTime& after, boost::optional<std::size_t> size = 1);
|
||||
static std::vector<pointer> getLastAdded(Session& session, const Wt::WDateTime& after, std::optional<std::size_t> size = 1);
|
||||
static std::vector<pointer> getAllWithMBIDAndMissingFeatures(Session& session);
|
||||
static std::vector<IdType> getAllIdsWithFeatures(Session& session, boost::optional<std::size_t> limit = {});
|
||||
static std::vector<IdType> getAllIdsWithFeatures(Session& session, std::optional<std::size_t> limit = {});
|
||||
|
||||
// Create utility
|
||||
static pointer create(Session& session, const boost::filesystem::path& p);
|
||||
static pointer create(Session& session, const std::filesystem::path& p);
|
||||
|
||||
// Accessors
|
||||
void setScanVersion(std::size_t version) { _scanVersion = version; }
|
||||
@@ -98,20 +97,20 @@ class Track : public Wt::Dbo::Dbo<Track>
|
||||
void setFeatures(const Wt::Dbo::ptr<TrackFeatures>& features);
|
||||
|
||||
std::size_t getScanVersion() const { return _scanVersion; }
|
||||
boost::optional<std::size_t> getTrackNumber() const;
|
||||
boost::optional<std::size_t> getDiscNumber() const;
|
||||
std::optional<std::size_t> getTrackNumber() const;
|
||||
std::optional<std::size_t> getDiscNumber() const;
|
||||
std::string getName() const { return _name; }
|
||||
boost::filesystem::path getPath() const { return _filePath; }
|
||||
std::filesystem::path getPath() const { return _filePath; }
|
||||
std::chrono::milliseconds getDuration() const { return _duration; }
|
||||
boost::optional<int> getYear() const;
|
||||
boost::optional<int> getOriginalYear() const;
|
||||
std::optional<int> getYear() const;
|
||||
std::optional<int> getOriginalYear() const;
|
||||
Wt::WDateTime getLastWriteTime() const { return _fileLastWrite; }
|
||||
Wt::WDateTime getAddedTime() const { return _fileAdded; }
|
||||
bool hasCover() const { return _hasCover; }
|
||||
const std::string& getMBID() const { return _MBID; }
|
||||
boost::optional<std::string> getCopyright() const;
|
||||
boost::optional<std::string> getCopyrightURL() const;
|
||||
std::vector<Wt::Dbo::ptr<Artist>> getArtists(TrackArtistLink::Type type = {TrackArtistLink::Type::Artist}) const;
|
||||
std::optional<std::string> getCopyright() const;
|
||||
std::optional<std::string> getCopyrightURL() const;
|
||||
std::vector<Wt::Dbo::ptr<Artist>> getArtists(TrackArtistLink::Type type = TrackArtistLink::Type::Artist) const;
|
||||
std::vector<Wt::Dbo::ptr<TrackArtistLink>> getArtistLinks() const;
|
||||
Wt::Dbo::ptr<Release> getRelease() const { return _release; }
|
||||
std::vector<Wt::Dbo::ptr<Cluster>> getClusters() const;
|
||||
|
||||
@@ -100,7 +100,7 @@ TrackList::getById(Session& session, IdType id)
|
||||
|
||||
|
||||
std::vector<Wt::Dbo::ptr<TrackListEntry>>
|
||||
TrackList::getEntries(boost::optional<std::size_t> offset, boost::optional<std::size_t> size) const
|
||||
TrackList::getEntries(std::optional<std::size_t> offset, std::optional<std::size_t> size) const
|
||||
{
|
||||
assert(session());
|
||||
assert(IdIsValid(self()->id()));
|
||||
@@ -116,7 +116,7 @@ TrackList::getEntries(boost::optional<std::size_t> offset, boost::optional<std::
|
||||
}
|
||||
|
||||
std::vector<Wt::Dbo::ptr<TrackListEntry>>
|
||||
TrackList::getEntriesReverse(boost::optional<std::size_t> offset, boost::optional<std::size_t> size) const
|
||||
TrackList::getEntriesReverse(std::optional<std::size_t> offset, std::optional<std::size_t> size) const
|
||||
{
|
||||
assert(session());
|
||||
assert(IdIsValid(self()->id()));
|
||||
|
||||
@@ -19,12 +19,11 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <boost/optional.hpp>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
#include <Wt/Dbo/Dbo.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "Types.hpp"
|
||||
|
||||
namespace Database {
|
||||
@@ -79,8 +78,8 @@ class TrackList : public Wt::Dbo::Dbo<TrackList>
|
||||
// Get tracks, ordered by position
|
||||
std::size_t getCount() const;
|
||||
Wt::Dbo::ptr<TrackListEntry> getEntry(std::size_t pos) const;
|
||||
std::vector<Wt::Dbo::ptr<TrackListEntry>> getEntries(boost::optional<std::size_t> offset = {}, boost::optional<std::size_t> size = {}) const;
|
||||
std::vector<Wt::Dbo::ptr<TrackListEntry>> getEntriesReverse(boost::optional<std::size_t> offset = {}, boost::optional<std::size_t> size = {}) const;
|
||||
std::vector<Wt::Dbo::ptr<TrackListEntry>> getEntries(std::optional<std::size_t> offset = {}, std::optional<std::size_t> size = {}) const;
|
||||
std::vector<Wt::Dbo::ptr<TrackListEntry>> getEntriesReverse(std::optional<std::size_t> offset = {}, std::optional<std::size_t> size = {}) const;
|
||||
|
||||
std::vector<IdType> getTrackIds() const;
|
||||
|
||||
|
||||
@@ -247,7 +247,7 @@ User::hasStarredRelease(Wt::Dbo::ptr<Release> release) const
|
||||
}
|
||||
|
||||
std::vector<Wt::Dbo::ptr<Release>>
|
||||
User::getStarredReleases(boost::optional<std::size_t> offset, boost::optional<std::size_t> limit) const
|
||||
User::getStarredReleases(std::optional<std::size_t> offset, std::optional<std::size_t> limit) const
|
||||
{
|
||||
Wt::Dbo::collection<Wt::Dbo::ptr<Release>> res = _starredReleases.find()
|
||||
.offset(offset ? static_cast<int>(*offset) : -1)
|
||||
|
||||
@@ -19,10 +19,9 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
#include <Wt/Dbo/Dbo.h>
|
||||
#include <Wt/WDateTime.h>
|
||||
|
||||
@@ -162,7 +161,7 @@ class User : public Wt::Dbo::Dbo<User>
|
||||
void starRelease(Wt::Dbo::ptr<Release> release);
|
||||
void unstarRelease(Wt::Dbo::ptr<Release> release);
|
||||
bool hasStarredRelease(Wt::Dbo::ptr<Release> release) const;
|
||||
std::vector<Wt::Dbo::ptr<Release>> getStarredReleases(boost::optional<std::size_t> offset = {}, boost::optional<std::size_t> size = {}) const;
|
||||
std::vector<Wt::Dbo::ptr<Release>> getStarredReleases(std::optional<std::size_t> offset = {}, std::optional<std::size_t> size = {}) const;
|
||||
|
||||
void starTrack(Wt::Dbo::ptr<Track> track);
|
||||
void unstarTrack(Wt::Dbo::ptr<Track> track);
|
||||
|
||||
+1
-1
@@ -68,7 +68,7 @@ Image::load(const std::vector<unsigned char>& rawData)
|
||||
}
|
||||
|
||||
bool
|
||||
Image::load(boost::filesystem::path p)
|
||||
Image::load(const std::filesystem::path& p)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
+2
-3
@@ -19,10 +19,9 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <filesystem>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/filesystem/path.hpp>
|
||||
|
||||
#include <Magick++.h>
|
||||
|
||||
namespace Image
|
||||
@@ -49,7 +48,7 @@ class Image
|
||||
|
||||
// input
|
||||
bool load(const std::vector<unsigned char>& rawData);
|
||||
bool load(boost::filesystem::path p);
|
||||
bool load(const std::filesystem::path& p);
|
||||
|
||||
Geometry getSize() const;
|
||||
|
||||
|
||||
+8
-9
@@ -17,7 +17,6 @@
|
||||
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/property_tree/xml_parser.hpp>
|
||||
|
||||
#include <Wt/WServer.h>
|
||||
@@ -29,6 +28,7 @@
|
||||
#include "auth/AuthTokenService.hpp"
|
||||
#include "auth/PasswordService.hpp"
|
||||
#include "cover/CoverArtGrabber.hpp"
|
||||
#include "database/Db.hpp"
|
||||
#include "image/Image.hpp"
|
||||
#include "scanner/MediaScanner.hpp"
|
||||
#include "similarity/features/SimilarityFeaturesScannerAddon.hpp"
|
||||
@@ -42,9 +42,9 @@ std::vector<std::string> generateWtConfig(std::string execPath)
|
||||
{
|
||||
std::vector<std::string> args;
|
||||
|
||||
const boost::filesystem::path wtConfigPath {getService<Config>()->getPath("working-dir") / "wt_config.xml"};
|
||||
const boost::filesystem::path wtLogFilePath {getService<Config>()->getPath("log-file", "/var/log/lms.log")};
|
||||
const boost::filesystem::path wtAccessLogFilePath {getService<Config>()->getPath("access-log-file", "/var/log/lms.access.log")};
|
||||
const std::filesystem::path wtConfigPath {getService<Config>()->getPath("working-dir") / "wt_config.xml"};
|
||||
const std::filesystem::path wtLogFilePath {getService<Config>()->getPath("log-file", "/var/log/lms.log")};
|
||||
const std::filesystem::path wtAccessLogFilePath {getService<Config>()->getPath("access-log-file", "/var/log/lms.access.log")};
|
||||
|
||||
args.push_back(execPath);
|
||||
args.push_back("--config=" + wtConfigPath.string());
|
||||
@@ -86,7 +86,7 @@ std::vector<std::string> generateWtConfig(std::string execPath)
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
boost::filesystem::path configFilePath {"/etc/lms.conf"};
|
||||
std::filesystem::path configFilePath {"/etc/lms.conf"};
|
||||
int res = EXIT_FAILURE;
|
||||
|
||||
assert(argc > 0);
|
||||
@@ -110,8 +110,8 @@ int main(int argc, char* argv[])
|
||||
ServiceProvider<Config>::create(configFilePath);
|
||||
|
||||
// Make sure the working directory exists
|
||||
boost::filesystem::create_directories(getService<Config>()->getPath("working-dir"));
|
||||
boost::filesystem::create_directories(getService<Config>()->getPath("working-dir") / "cache");
|
||||
std::filesystem::create_directories(getService<Config>()->getPath("working-dir"));
|
||||
std::filesystem::create_directories(getService<Config>()->getPath("working-dir") / "cache");
|
||||
|
||||
// Construct WT configuration and get the argc/argv back
|
||||
std::vector<std::string> wtServerArgs = generateWtConfig(argv[0]);
|
||||
@@ -128,11 +128,10 @@ int main(int argc, char* argv[])
|
||||
|
||||
// lib init
|
||||
Image::init(argv[0]);
|
||||
Av::AvInit();
|
||||
Av::Transcoder::init();
|
||||
|
||||
// Initializing a connection pool to the database that will be shared along services
|
||||
Database::Database database {getService<Config>()->getPath("working-dir") / "lms.db"};
|
||||
Database::Db database {getService<Config>()->getPath("working-dir") / "lms.db"};
|
||||
|
||||
UserInterface::LmsApplicationGroupContainer appGroups;
|
||||
|
||||
|
||||
@@ -29,21 +29,21 @@ namespace MetaData
|
||||
|
||||
using MetadataMap = std::map<std::string, std::string>;
|
||||
|
||||
boost::optional<std::string>
|
||||
std::optional<std::string>
|
||||
findFirstValueOf(const MetadataMap& metadataMap, std::initializer_list<std::string> tags)
|
||||
{
|
||||
auto it = std::find_first_of(std::cbegin(metadataMap), std::cend(metadataMap), std::cbegin(tags), std::cend(tags), [](const auto& it, const auto& str) { return it.first == str; });
|
||||
if (it == std::cend(metadataMap))
|
||||
return boost::none;
|
||||
return std::nullopt;
|
||||
|
||||
return stringTrim(it->second);
|
||||
}
|
||||
|
||||
static
|
||||
boost::optional<Album>
|
||||
std::optional<Album>
|
||||
getAlbum(const MetadataMap& metadataMap)
|
||||
{
|
||||
boost::optional<Album> res;
|
||||
std::optional<Album> res;
|
||||
|
||||
auto album {findFirstValueOf(metadataMap, {"ALBUM"})};
|
||||
if (!album)
|
||||
@@ -115,8 +115,8 @@ getArtists(const MetadataMap& metadataMap)
|
||||
return artists;
|
||||
}
|
||||
|
||||
boost::optional<Track>
|
||||
AvFormat::parse(const boost::filesystem::path& p, bool debug)
|
||||
std::optional<Track>
|
||||
AvFormat::parse(const std::filesystem::path& p, bool debug)
|
||||
{
|
||||
Track track;
|
||||
|
||||
@@ -215,7 +215,7 @@ AvFormat::parse(const boost::filesystem::path& p, bool debug)
|
||||
}
|
||||
catch(Av::MediaFileException& e)
|
||||
{
|
||||
return boost::none;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
return track;
|
||||
|
||||
@@ -19,9 +19,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "MetaData.hpp"
|
||||
|
||||
namespace MetaData
|
||||
@@ -31,7 +28,7 @@ namespace MetaData
|
||||
class AvFormat : public Parser
|
||||
{
|
||||
public:
|
||||
boost::optional<Track> parse(const boost::filesystem::path& p, bool debug = false) override;
|
||||
std::optional<Track> parse(const std::filesystem::path& p, bool debug = false) override;
|
||||
};
|
||||
|
||||
} // namespace MetaData
|
||||
|
||||
+10
-11
@@ -20,12 +20,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <chrono>
|
||||
#include <filesystem>
|
||||
#include <map>
|
||||
#include <optional>
|
||||
#include <set>
|
||||
|
||||
#include <boost/optional.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
namespace MetaData
|
||||
{
|
||||
using Clusters = std::map<std::string /* type */, std::set<std::string> /* names */>;
|
||||
@@ -54,15 +53,15 @@ namespace MetaData
|
||||
std::string title;
|
||||
std::string musicBrainzTrackID;
|
||||
std::string musicBrainzRecordID;
|
||||
boost::optional<Album> album;
|
||||
std::optional<Album> album;
|
||||
Clusters clusters;
|
||||
std::chrono::milliseconds duration {};
|
||||
boost::optional<std::size_t> trackNumber;
|
||||
boost::optional<std::size_t> totalTrack;
|
||||
boost::optional<std::size_t> discNumber;
|
||||
boost::optional<std::size_t> totalDisc;
|
||||
boost::optional<int> year;
|
||||
boost::optional<int> originalYear;
|
||||
std::optional<std::size_t> trackNumber;
|
||||
std::optional<std::size_t> totalTrack;
|
||||
std::optional<std::size_t> discNumber;
|
||||
std::optional<std::size_t> totalDisc;
|
||||
std::optional<int> year;
|
||||
std::optional<int> originalYear;
|
||||
bool hasCover {false};
|
||||
std::vector<AudioStream> audioStreams;
|
||||
std::string acoustID;
|
||||
@@ -73,7 +72,7 @@ namespace MetaData
|
||||
class Parser
|
||||
{
|
||||
public:
|
||||
virtual boost::optional<Track> parse(const boost::filesystem::path& p, bool debug = false) = 0;
|
||||
virtual std::optional<Track> parse(const std::filesystem::path& p, bool debug = false) = 0;
|
||||
|
||||
void setClusterTypeNames(const std::set<std::string>& clusterTypeNames) { _clusterTypeNames = clusterTypeNames; }
|
||||
|
||||
|
||||
@@ -126,10 +126,10 @@ getAlbumArtists(const TagLib::PropertyMap& properties)
|
||||
}
|
||||
|
||||
static
|
||||
boost::optional<Album>
|
||||
std::optional<Album>
|
||||
getAlbum(const TagLib::PropertyMap& properties)
|
||||
{
|
||||
boost::optional<Album> res;
|
||||
std::optional<Album> res;
|
||||
|
||||
std::vector<std::string> albumName {getPropertyValues(properties, "ALBUM")};
|
||||
if (albumName.empty())
|
||||
@@ -145,8 +145,8 @@ getAlbum(const TagLib::PropertyMap& properties)
|
||||
return res;
|
||||
}
|
||||
|
||||
boost::optional<Track>
|
||||
TagLibParser::parse(const boost::filesystem::path& p, bool debug)
|
||||
std::optional<Track>
|
||||
TagLibParser::parse(const std::filesystem::path& p, bool debug)
|
||||
{
|
||||
TagLib::FileRef f {p.string().c_str(),
|
||||
true, // read audio properties
|
||||
@@ -155,13 +155,13 @@ TagLibParser::parse(const boost::filesystem::path& p, bool debug)
|
||||
if (f.isNull())
|
||||
{
|
||||
LMS_LOG(METADATA, ERROR) << "File '" << p.string() << "': parsing failed";
|
||||
return boost::none;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
if (!f.audioProperties())
|
||||
{
|
||||
LMS_LOG(METADATA, INFO) << "File '" << p.string() << "': no audio properties";
|
||||
return boost::none;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
Track track;
|
||||
|
||||
@@ -19,9 +19,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "MetaData.hpp"
|
||||
|
||||
namespace MetaData
|
||||
@@ -31,7 +28,7 @@ namespace MetaData
|
||||
class TagLibParser : public Parser
|
||||
{
|
||||
public:
|
||||
boost::optional<Track> parse(const boost::filesystem::path& p, bool debug = false) override;
|
||||
std::optional<Track> parse(const std::filesystem::path& p, bool debug = false) override;
|
||||
};
|
||||
|
||||
} // namespace MetaData
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/asio/placeholders.hpp>
|
||||
|
||||
#include <Wt/WLocalDateTime.h>
|
||||
@@ -63,15 +62,15 @@ getNextFirstOfMonth(Wt::WDate current)
|
||||
}
|
||||
|
||||
bool
|
||||
isFileSupported(const boost::filesystem::path& file, const std::set<boost::filesystem::path>& extensions)
|
||||
isFileSupported(const std::filesystem::path& file, const std::set<std::filesystem::path>& extensions)
|
||||
{
|
||||
return (extensions.find(file.extension()) != extensions.end());
|
||||
}
|
||||
|
||||
bool
|
||||
isPathInParentPath(const boost::filesystem::path& path, const boost::filesystem::path& parentPath)
|
||||
isPathInParentPath(const std::filesystem::path& path, const std::filesystem::path& parentPath)
|
||||
{
|
||||
boost::filesystem::path curPath = path;
|
||||
std::filesystem::path curPath = path;
|
||||
|
||||
while (curPath.has_parent_path())
|
||||
{
|
||||
@@ -327,25 +326,25 @@ MediaScanner::scheduleNextScan()
|
||||
void
|
||||
MediaScanner::countAllFiles(Stats& stats)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
std::error_code ec;
|
||||
|
||||
stats.totalFiles = 0;
|
||||
|
||||
boost::filesystem::recursive_directory_iterator itPath {_mediaDirectory, ec};
|
||||
std::filesystem::recursive_directory_iterator itPath {_mediaDirectory, ec};
|
||||
if (ec)
|
||||
{
|
||||
LMS_LOG(DBUPDATER, ERROR) << "Cannot iterate over '" << _mediaDirectory.string() << "': " << ec.message();
|
||||
return;
|
||||
}
|
||||
|
||||
boost::filesystem::recursive_directory_iterator itEnd;
|
||||
std::filesystem::recursive_directory_iterator itEnd;
|
||||
while (_running && itPath != itEnd)
|
||||
{
|
||||
const boost::filesystem::path& path {*itPath};
|
||||
const std::filesystem::path& path {*itPath};
|
||||
|
||||
if (!ec)
|
||||
{
|
||||
if (boost::filesystem::is_regular(path) && isFileSupported(path, _fileExtensions))
|
||||
if (std::filesystem::is_regular_file(path) && isFileSupported(path, _fileExtensions))
|
||||
stats.totalFiles++;
|
||||
|
||||
if (stats.totalFiles % 250 == 0)
|
||||
@@ -498,11 +497,11 @@ void MediaScanner::notifyInProgressIfNeeded(Stats& stats)
|
||||
}
|
||||
|
||||
void
|
||||
MediaScanner::scanAudioFile(const boost::filesystem::path& file, bool forceScan, Stats& stats)
|
||||
MediaScanner::scanAudioFile(const std::filesystem::path& file, bool forceScan, Stats& stats)
|
||||
{
|
||||
notifyInProgressIfNeeded(stats);
|
||||
|
||||
auto lastWriteTime = Wt::WDateTime::fromTime_t(boost::filesystem::last_write_time(file));
|
||||
const auto lastWriteTime {Wt::WDateTime::fromTimePoint(std::filesystem::last_write_time(file))};
|
||||
|
||||
if (!forceScan)
|
||||
{
|
||||
@@ -518,7 +517,7 @@ MediaScanner::scanAudioFile(const boost::filesystem::path& file, bool forceScan,
|
||||
}
|
||||
}
|
||||
|
||||
boost::optional<MetaData::Track> trackInfo {_metadataParser.parse(file)};
|
||||
std::optional<MetaData::Track> trackInfo {_metadataParser.parse(file)};
|
||||
if (!trackInfo)
|
||||
{
|
||||
stats.scanErrors++;
|
||||
@@ -642,11 +641,11 @@ MediaScanner::scanAudioFile(const boost::filesystem::path& file, bool forceScan,
|
||||
}
|
||||
|
||||
void
|
||||
MediaScanner::scanMediaDirectory(boost::filesystem::path mediaDirectory, bool forceScan, Stats& stats)
|
||||
MediaScanner::scanMediaDirectory(const std::filesystem::path& mediaDirectory, bool forceScan, Stats& stats)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
std::error_code ec;
|
||||
|
||||
boost::filesystem::recursive_directory_iterator itPath(mediaDirectory, ec);
|
||||
std::filesystem::recursive_directory_iterator itPath {mediaDirectory, ec};
|
||||
if (ec)
|
||||
{
|
||||
LMS_LOG(DBUPDATER, ERROR) << "Cannot iterate over '" << mediaDirectory.string() << "': " << ec.message();
|
||||
@@ -654,17 +653,17 @@ MediaScanner::scanMediaDirectory(boost::filesystem::path mediaDirectory, bool fo
|
||||
return;
|
||||
}
|
||||
|
||||
boost::filesystem::recursive_directory_iterator itEnd;
|
||||
std::filesystem::recursive_directory_iterator itEnd;
|
||||
while (_running && itPath != itEnd)
|
||||
{
|
||||
const boost::filesystem::path& path {*itPath};
|
||||
const std::filesystem::path& path {*itPath};
|
||||
|
||||
if (ec)
|
||||
{
|
||||
LMS_LOG(DBUPDATER, ERROR) << "Cannot process entry '" << path.string() << "': " << ec.message();
|
||||
stats.scanErrors++;
|
||||
}
|
||||
else if (boost::filesystem::is_regular(path))
|
||||
else if (std::filesystem::is_regular_file(path))
|
||||
{
|
||||
if (isFileSupported(path, _fileExtensions))
|
||||
scanAudioFile(path, forceScan, stats );
|
||||
@@ -678,14 +677,14 @@ MediaScanner::scanMediaDirectory(boost::filesystem::path mediaDirectory, bool fo
|
||||
|
||||
// Check if a file exists and is still in a media directory
|
||||
static bool
|
||||
checkFile(const boost::filesystem::path& p, const boost::filesystem::path& mediaDirectory, const std::set<boost::filesystem::path>& extensions)
|
||||
checkFile(const std::filesystem::path& p, const std::filesystem::path& mediaDirectory, const std::set<std::filesystem::path>& extensions)
|
||||
{
|
||||
try
|
||||
{
|
||||
// For each track, make sure the the file still exists
|
||||
// and still belongs to a media directory
|
||||
if (!boost::filesystem::exists( p )
|
||||
|| !boost::filesystem::is_regular( p ) )
|
||||
if (!std::filesystem::exists( p )
|
||||
|| !std::filesystem::is_regular_file( p ) )
|
||||
{
|
||||
LMS_LOG(DBUPDATER, INFO) << "Removing '" << p.string() << "': missing";
|
||||
return false;
|
||||
@@ -706,7 +705,7 @@ checkFile(const boost::filesystem::path& p, const boost::filesystem::path& media
|
||||
return true;
|
||||
|
||||
}
|
||||
catch (boost::filesystem::filesystem_error& e)
|
||||
catch (std::filesystem::filesystem_error& e)
|
||||
{
|
||||
LMS_LOG(DBUPDATER, ERROR) << "Caught exception while checking file '" << p.string() << "': " << e.what();
|
||||
return false;
|
||||
@@ -716,7 +715,7 @@ checkFile(const boost::filesystem::path& p, const boost::filesystem::path& media
|
||||
void
|
||||
MediaScanner::removeMissingTracks(Stats& stats)
|
||||
{
|
||||
std::vector<boost::filesystem::path> trackPaths;
|
||||
std::vector<std::filesystem::path> trackPaths;
|
||||
{
|
||||
auto transaction {_dbSession->createSharedTransaction()};
|
||||
trackPaths = Track::getAllPaths(*_dbSession);;
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
#include <chrono>
|
||||
#include <mutex>
|
||||
#include <optional>
|
||||
|
||||
#include <Wt/WDateTime.h>
|
||||
#include <Wt/WIOService.h>
|
||||
@@ -86,8 +87,8 @@ class MediaScanner
|
||||
{
|
||||
State currentState {State::NotScheduled};
|
||||
Wt::WDateTime nextScheduledScan;
|
||||
boost::optional<Stats> lastScanStats;
|
||||
boost::optional<Stats> inProgressStats;
|
||||
std::optional<Stats> lastScanStats;
|
||||
std::optional<Stats> inProgressStats;
|
||||
};
|
||||
|
||||
Status getStatus();
|
||||
@@ -110,7 +111,7 @@ class MediaScanner
|
||||
// Update database (scheduled callback)
|
||||
void scan(boost::system::error_code ec);
|
||||
|
||||
void scanMediaDirectory( boost::filesystem::path mediaDirectory, bool forceScan, Stats& stats);
|
||||
void scanMediaDirectory( const std::filesystem::path& mediaDirectory, bool forceScan, Stats& stats);
|
||||
|
||||
// Helpers
|
||||
void refreshScanSettings();
|
||||
@@ -119,8 +120,8 @@ class MediaScanner
|
||||
void removeMissingTracks(Stats& stats);
|
||||
void removeOrphanEntries();
|
||||
void checkDuplicatedAudioFiles(Stats& stats);
|
||||
void scanAudioFile(const boost::filesystem::path& file, bool forceScan, Stats& stats);
|
||||
Database::IdType doScanAudioFile(const boost::filesystem::path& file, Stats& stats);
|
||||
void scanAudioFile(const std::filesystem::path& file, bool forceScan, Stats& stats);
|
||||
Database::IdType doScanAudioFile(const std::filesystem::path& file, Stats& stats);
|
||||
void notifyInProgressIfNeeded(Stats& stats);
|
||||
void notifyInProgress(Stats& stats);
|
||||
|
||||
@@ -137,16 +138,16 @@ class MediaScanner
|
||||
|
||||
std::mutex _statusMutex;
|
||||
State _curState {State::NotScheduled};
|
||||
boost::optional<Stats> _inProgressStats;
|
||||
boost::optional<Stats> _lastScanStats;
|
||||
std::optional<Stats> _inProgressStats;
|
||||
std::optional<Stats> _lastScanStats;
|
||||
Wt::WDateTime _nextScheduledScan;
|
||||
|
||||
// Current scan settings
|
||||
std::size_t _scanVersion {};
|
||||
Wt::WTime _startTime;
|
||||
Database::ScanSettings::UpdatePeriod _updatePeriod {Database::ScanSettings::UpdatePeriod::Never};
|
||||
std::set<boost::filesystem::path> _fileExtensions;
|
||||
boost::filesystem::path _mediaDirectory;
|
||||
std::set<std::filesystem::path> _fileExtensions;
|
||||
std::filesystem::path _mediaDirectory;
|
||||
|
||||
|
||||
}; // class MediaScanner
|
||||
|
||||
@@ -31,24 +31,24 @@ namespace Similarity {
|
||||
|
||||
|
||||
static
|
||||
boost::filesystem::path getCacheDirectory()
|
||||
std::filesystem::path getCacheDirectory()
|
||||
{
|
||||
return getService<Config>()->getPath("working-dir") / "cache" / "features";
|
||||
}
|
||||
|
||||
static boost::filesystem::path getCacheNetworkFilePath()
|
||||
static std::filesystem::path getCacheNetworkFilePath()
|
||||
{
|
||||
return getCacheDirectory() / "network";
|
||||
};
|
||||
|
||||
static boost::filesystem::path getCacheTrackPositionsFilePath()
|
||||
static std::filesystem::path getCacheTrackPositionsFilePath()
|
||||
{
|
||||
return getCacheDirectory() / "track_positions";
|
||||
}
|
||||
|
||||
static
|
||||
bool
|
||||
networkToCacheFile(const SOM::Network& network, boost::filesystem::path path)
|
||||
networkToCacheFile(const SOM::Network& network, std::filesystem::path path)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -91,8 +91,8 @@ networkToCacheFile(const SOM::Network& network, boost::filesystem::path path)
|
||||
}
|
||||
|
||||
static
|
||||
boost::optional<SOM::Network>
|
||||
createNetworkFromCacheFile(boost::filesystem::path path)
|
||||
std::optional<SOM::Network>
|
||||
createNetworkFromCacheFile(std::filesystem::path path)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -137,13 +137,13 @@ createNetworkFromCacheFile(boost::filesystem::path path)
|
||||
catch (boost::property_tree::ptree_error& error)
|
||||
{
|
||||
LMS_LOG(SIMILARITY, ERROR) << "Cannot read network cache: " << error.what();
|
||||
return boost::none;
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
bool
|
||||
objectPositionToCacheFile(const std::map<Database::IdType, std::set<SOM::Position>>& objectsPosition, boost::filesystem::path path)
|
||||
objectPositionToCacheFile(const std::map<Database::IdType, std::set<SOM::Position>>& objectsPosition, std::filesystem::path path)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -178,8 +178,8 @@ objectPositionToCacheFile(const std::map<Database::IdType, std::set<SOM::Positio
|
||||
}
|
||||
|
||||
static
|
||||
boost::optional<std::map<Database::IdType, std::set<SOM::Position>>>
|
||||
createObjectPositionsFromCacheFile(boost::filesystem::path path)
|
||||
std::optional<std::map<Database::IdType, std::set<SOM::Position>>>
|
||||
createObjectPositionsFromCacheFile(std::filesystem::path path)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -210,21 +210,21 @@ createObjectPositionsFromCacheFile(boost::filesystem::path path)
|
||||
catch (boost::property_tree::ptree_error& error)
|
||||
{
|
||||
LMS_LOG(SIMILARITY, ERROR) << "Cannot create object position from cache file: " << error.what();
|
||||
return boost::none;
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
FeaturesCache::invalidate()
|
||||
{
|
||||
boost::filesystem::remove(getCacheNetworkFilePath());
|
||||
boost::filesystem::remove(getCacheTrackPositionsFilePath());
|
||||
std::filesystem::remove(getCacheNetworkFilePath());
|
||||
std::filesystem::remove(getCacheTrackPositionsFilePath());
|
||||
}
|
||||
|
||||
boost::optional<FeaturesCache>
|
||||
std::optional<FeaturesCache>
|
||||
FeaturesCache::read()
|
||||
{
|
||||
boost::optional<FeaturesCache> res;
|
||||
std::optional<FeaturesCache> res;
|
||||
|
||||
auto network{createNetworkFromCacheFile(getCacheNetworkFilePath())};
|
||||
if (!network)
|
||||
@@ -240,7 +240,7 @@ FeaturesCache::read()
|
||||
void
|
||||
FeaturesCache::write()
|
||||
{
|
||||
boost::filesystem::create_directories(getService<Config>()->getPath("working-dir") / "cache" / "features");
|
||||
std::filesystem::create_directories(getService<Config>()->getPath("working-dir") / "cache" / "features");
|
||||
|
||||
if (!networkToCacheFile(_network, getCacheNetworkFilePath())
|
||||
|| !objectPositionToCacheFile(_trackPositions, getCacheTrackPositionsFilePath()))
|
||||
@@ -250,8 +250,8 @@ FeaturesCache::write()
|
||||
}
|
||||
|
||||
FeaturesCache::FeaturesCache(SOM::Network network, ObjectPositions trackPositions)
|
||||
: _network{std::move(network)},
|
||||
_trackPositions{std::move(trackPositions)}
|
||||
: _network {std::move(network)},
|
||||
_trackPositions {std::move(trackPositions)}
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <optional>
|
||||
#include <set>
|
||||
|
||||
#include "database/Types.hpp"
|
||||
@@ -33,7 +34,7 @@ class FeaturesCache
|
||||
|
||||
static void invalidate();
|
||||
|
||||
static boost::optional<FeaturesCache> read();
|
||||
static std::optional<FeaturesCache> read();
|
||||
void write();
|
||||
|
||||
private:
|
||||
|
||||
@@ -56,7 +56,7 @@ getTracksWithMBIDAndMissingFeatures(Database::Session& dbSession)
|
||||
FeaturesScannerAddon::FeaturesScannerAddon(std::unique_ptr<Database::Session> dbSession)
|
||||
: _dbSession {std::move(dbSession)}
|
||||
{
|
||||
boost::optional<Similarity::FeaturesCache> cache {Similarity::FeaturesCache::read()};
|
||||
std::optional<Similarity::FeaturesCache> cache {Similarity::FeaturesCache::read()};
|
||||
if (cache)
|
||||
{
|
||||
auto searcher {std::make_shared<Similarity::FeaturesSearcher>(*_dbSession.get(), *cache, [&]() { return _stopRequested; })};
|
||||
|
||||
@@ -40,8 +40,8 @@ class FeaturesScannerAddon final : public Scanner::MediaScannerAddon
|
||||
void requestStop() override;
|
||||
void preScanComplete() override;
|
||||
|
||||
void trackAdded(Database::IdType trackId) override {}
|
||||
void trackToRemove(Database::IdType trackId) override {}
|
||||
void trackAdded(Database::IdType) override {}
|
||||
void trackToRemove(Database::IdType) override {}
|
||||
void trackUpdated(Database::IdType trackId) override;
|
||||
|
||||
bool fetchFeatures(Database::IdType trackId, const std::string& MBID);
|
||||
|
||||
@@ -68,10 +68,10 @@ getFeatureInfoMapNbDimensions(const FeatureInfoMap& featureInfoMap)
|
||||
}
|
||||
|
||||
static
|
||||
boost::optional<SOM::InputVector>
|
||||
std::optional<SOM::InputVector>
|
||||
getInputVectorFromTrack(Database::Session& session, Database::IdType trackId, const FeatureInfoMap& featuresInfo, std::size_t nbDimensions)
|
||||
{
|
||||
boost::optional<SOM::InputVector> res {SOM::InputVector {nbDimensions}};
|
||||
std::optional<SOM::InputVector> res {SOM::InputVector {nbDimensions}};
|
||||
|
||||
std::map<std::string, std::vector<double>> features;
|
||||
for (auto itFeatureInfo : featuresInfo)
|
||||
@@ -150,7 +150,7 @@ FeaturesSearcher::FeaturesSearcher(Database::Session& session, std::function<boo
|
||||
if (stopRequested())
|
||||
return;
|
||||
|
||||
boost::optional<SOM::InputVector> inputVector {getInputVectorFromTrack(session, trackId, featuresInfo, nbDimensions)};
|
||||
std::optional<SOM::InputVector> inputVector {getInputVectorFromTrack(session, trackId, featuresInfo, nbDimensions)};
|
||||
if (!inputVector)
|
||||
continue;
|
||||
|
||||
@@ -456,7 +456,7 @@ FeaturesSearcher::getSimilarObjects(const std::set<Database::IdType>& ids,
|
||||
break;
|
||||
|
||||
// If there is not enough objects, try again with closest neighbour until there is too much distance
|
||||
boost::optional<SOM::Position> closestRefVectorPosition {_network->getClosestRefVectorPosition(searchedRefVectorsPosition, _networkRefVectorsDistanceMedian * 0.75)};
|
||||
std::optional<SOM::Position> closestRefVectorPosition {_network->getClosestRefVectorPosition(searchedRefVectorsPosition, _networkRefVectorsDistanceMedian * 0.75)};
|
||||
if (!closestRefVectorPosition)
|
||||
break;
|
||||
|
||||
|
||||
@@ -189,10 +189,10 @@ Network::getClosestRefVectorPosition(const InputVector& data) const
|
||||
});
|
||||
}
|
||||
|
||||
boost::optional<Position>
|
||||
std::optional<Position>
|
||||
Network::getClosestRefVectorPosition(const InputVector& data, InputVector::Distance maxDistance) const
|
||||
{
|
||||
boost::optional<Position> position {getClosestRefVectorPosition(data)};
|
||||
std::optional<Position> position {getClosestRefVectorPosition(data)};
|
||||
|
||||
if (_distanceFunc(data, _refVectors.get(*position), _weights) > maxDistance)
|
||||
position.reset();
|
||||
@@ -200,7 +200,7 @@ Network::getClosestRefVectorPosition(const InputVector& data, InputVector::Dista
|
||||
return position;
|
||||
}
|
||||
|
||||
boost::optional<Position>
|
||||
std::optional<Position>
|
||||
Network::getClosestRefVectorPosition(const std::set<Position>& refVectorsPosition, InputVector::Distance maxDistance) const
|
||||
{
|
||||
std::set<Position> neighboursPosition;
|
||||
@@ -221,7 +221,7 @@ Network::getClosestRefVectorPosition(const std::set<Position>& refVectorsPositio
|
||||
neighboursPosition.erase(refVectorPosition);
|
||||
|
||||
if (neighboursPosition.empty())
|
||||
return boost::none;
|
||||
return std::nullopt;
|
||||
|
||||
// Now compute the distance for each neighbour
|
||||
struct NeighbourInfo
|
||||
@@ -247,9 +247,9 @@ Network::getClosestRefVectorPosition(const std::set<Position>& refVectorsPositio
|
||||
}
|
||||
|
||||
if (neighboursInfo.empty())
|
||||
return boost::none;
|
||||
return std::nullopt;
|
||||
|
||||
auto min {std::min_element(neighboursInfo.begin(), neighboursInfo.end(),
|
||||
auto min {std::min_element(std::cbegin(neighboursInfo), std::cend(neighboursInfo),
|
||||
[&](const auto& a, const auto& b)
|
||||
{
|
||||
return a.distance < b.distance;
|
||||
|
||||
@@ -21,11 +21,10 @@
|
||||
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <optional>
|
||||
#include <ostream>
|
||||
#include <functional>
|
||||
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
#include "utils/Exception.hpp"
|
||||
#include "InputVector.hpp"
|
||||
#include "Matrix.hpp"
|
||||
@@ -70,9 +69,9 @@ class Network
|
||||
|
||||
const InputVector& getRefVector(const Position& position) const;
|
||||
Position getClosestRefVectorPosition(const InputVector& data) const;
|
||||
boost::optional<Position> getClosestRefVectorPosition(const InputVector& data, InputVector::Distance maxDistance) const;
|
||||
std::optional<Position> getClosestRefVectorPosition(const InputVector& data, InputVector::Distance maxDistance) const;
|
||||
|
||||
boost::optional<Position> getClosestRefVectorPosition(const std::set<Position>& refVectorsPosition, InputVector::Distance maxDistance) const;
|
||||
std::optional<Position> getClosestRefVectorPosition(const std::set<Position>& refVectorsPosition, InputVector::Distance maxDistance) const;
|
||||
|
||||
InputVector::Distance getRefVectorsDistance(const Position& position1, const Position& position2) const;
|
||||
|
||||
|
||||
+5
-6
@@ -54,12 +54,12 @@ createAuthToken(Database::IdType userId, const Wt::WDateTime& expiry)
|
||||
}
|
||||
|
||||
|
||||
boost::optional<Database::IdType>
|
||||
std::optional<Database::IdType>
|
||||
processAuthToken(const Wt::WEnvironment& env)
|
||||
{
|
||||
const std::string* authCookie {env.getCookie(authCookieName)};
|
||||
if (!authCookie)
|
||||
return boost::none;
|
||||
return std::nullopt;
|
||||
|
||||
const auto res {getService<::Auth::AuthTokenService>()->processAuthToken(LmsApp->getDbSession(), boost::asio::ip::address::from_string(env.clientAddress()), *authCookie)};
|
||||
switch (res.state)
|
||||
@@ -67,7 +67,7 @@ processAuthToken(const Wt::WEnvironment& env)
|
||||
case ::Auth::AuthTokenService::AuthTokenProcessResult::State::NotFound:
|
||||
case ::Auth::AuthTokenService::AuthTokenProcessResult::State::Throttled:
|
||||
LmsApp->setCookie(authCookieName, std::string {}, 0, "", "", env.urlScheme() == "https");
|
||||
return boost::none;
|
||||
return std::nullopt;
|
||||
|
||||
case ::Auth::AuthTokenService::AuthTokenProcessResult::State::Found:
|
||||
createAuthToken(res.authTokenInfo->userId, res.authTokenInfo->expiry);
|
||||
@@ -107,7 +107,6 @@ class AuthModel : public Wt::WFormModel
|
||||
user.modify()->setLastLogin(Wt::WDateTime::currentDateTime());
|
||||
_userId = user.id();
|
||||
|
||||
const Wt::WDateTime now {Wt::WDateTime::currentDateTime()};
|
||||
isDemo = user->isDemo();
|
||||
}
|
||||
|
||||
@@ -151,11 +150,11 @@ class AuthModel : public Wt::WFormModel
|
||||
return (validation(field).state() == Wt::ValidationState::Valid);
|
||||
}
|
||||
|
||||
boost::optional<Database::IdType> getUserId() const { return _userId; }
|
||||
std::optional<Database::IdType> getUserId() const { return _userId; }
|
||||
|
||||
private:
|
||||
|
||||
boost::optional<Database::IdType> _userId;
|
||||
std::optional<Database::IdType> _userId;
|
||||
};
|
||||
|
||||
const AuthModel::Field AuthModel::LoginNameField {"login-name"};
|
||||
|
||||
+1
-3
@@ -19,15 +19,13 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
#include <Wt/WTemplateFormView.h>
|
||||
|
||||
#include "database/Types.hpp"
|
||||
|
||||
namespace UserInterface {
|
||||
|
||||
boost::optional<Database::IdType>
|
||||
std::optional<Database::IdType>
|
||||
processAuthToken(const Wt::WEnvironment& env);
|
||||
|
||||
class Auth : public Wt::WTemplateFormView
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "cover/CoverArtGrabber.hpp"
|
||||
#include "database/Artist.hpp"
|
||||
#include "database/Cluster.hpp"
|
||||
#include "database/Db.hpp"
|
||||
#include "database/Release.hpp"
|
||||
#include "database/User.hpp"
|
||||
#include "explore/Explore.hpp"
|
||||
@@ -56,7 +57,7 @@
|
||||
namespace UserInterface {
|
||||
|
||||
std::unique_ptr<Wt::WApplication>
|
||||
LmsApplication::create(const Wt::WEnvironment& env, Database::Database& db, LmsApplicationGroupContainer& appGroups)
|
||||
LmsApplication::create(const Wt::WEnvironment& env, Database::Db& db, LmsApplicationGroupContainer& appGroups)
|
||||
{
|
||||
return std::make_unique<LmsApplication>(env, db.createSession(), appGroups);
|
||||
}
|
||||
@@ -496,13 +497,13 @@ LmsApplication::createHome()
|
||||
playqueue->playNext();
|
||||
});
|
||||
|
||||
playqueue->loadTrack.connect([=] (Database::IdType trackId, bool play)
|
||||
playqueue->trackSelected.connect([=] (Database::IdType trackId, bool play)
|
||||
{
|
||||
_events.lastLoadedTrackId = trackId;
|
||||
_events.trackLoaded(trackId, play);
|
||||
});
|
||||
|
||||
playqueue->trackUnload.connect([=]
|
||||
playqueue->trackUnselected.connect([=]
|
||||
{
|
||||
_events.lastLoadedTrackId.reset();
|
||||
_events.trackUnloaded();
|
||||
@@ -555,7 +556,7 @@ LmsApplication::createHome()
|
||||
});
|
||||
|
||||
// Events from Application group
|
||||
_events.appOpen.connect([=] (LmsApplicationInfo info)
|
||||
_events.appOpen.connect([=] (LmsApplicationInfo)
|
||||
{
|
||||
// Only one active session by user
|
||||
if (!LmsApp->isUserDemo())
|
||||
@@ -565,10 +566,10 @@ LmsApplication::createHome()
|
||||
}
|
||||
});
|
||||
|
||||
internalPathChanged().connect(std::bind([=]
|
||||
internalPathChanged().connect([=]
|
||||
{
|
||||
handlePathChange(mainStack, isUserAdmin());
|
||||
}));
|
||||
});
|
||||
|
||||
handlePathChange(mainStack, isUserAdmin());
|
||||
}
|
||||
|
||||
@@ -17,14 +17,12 @@
|
||||
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef LMS_APPLICATION_HPP
|
||||
#define LMS_APPLICATION_HPP
|
||||
#pragma once
|
||||
|
||||
#include <boost/optional.hpp>
|
||||
#include <optional>
|
||||
|
||||
#include <Wt/WApplication.h>
|
||||
|
||||
#include "database/Database.hpp"
|
||||
#include "scanner/MediaScanner.hpp"
|
||||
|
||||
#include "LmsApplicationGroup.hpp"
|
||||
@@ -32,6 +30,7 @@
|
||||
namespace Database {
|
||||
class Artist;
|
||||
class Cluster;
|
||||
class Db;
|
||||
class Release;
|
||||
class User;
|
||||
}
|
||||
@@ -51,7 +50,7 @@ struct Events
|
||||
|
||||
// A track is being loaded
|
||||
Wt::Signal<Database::IdType /* trackId */, bool /* play */> trackLoaded;
|
||||
boost::optional<Database::IdType> lastLoadedTrackId;
|
||||
std::optional<Database::IdType> lastLoadedTrackId;
|
||||
// Unload current track
|
||||
Wt::Signal<> trackUnloaded;
|
||||
|
||||
@@ -75,7 +74,7 @@ class LmsApplication : public Wt::WApplication
|
||||
public:
|
||||
LmsApplication(const Wt::WEnvironment& env, std::unique_ptr<Database::Session> dbSession, LmsApplicationGroupContainer& appGroups);
|
||||
|
||||
static std::unique_ptr<Wt::WApplication> create(const Wt::WEnvironment& env, Database::Database& db, LmsApplicationGroupContainer& appGroups);
|
||||
static std::unique_ptr<Wt::WApplication> create(const Wt::WEnvironment& env, Database::Db& db, LmsApplicationGroupContainer& appGroups);
|
||||
static LmsApplication* instance();
|
||||
|
||||
// Session application data
|
||||
@@ -124,8 +123,8 @@ class LmsApplication : public Wt::WApplication
|
||||
std::unique_ptr<Database::Session> _dbSession;
|
||||
LmsApplicationGroupContainer& _appGroups;
|
||||
Events _events;
|
||||
boost::optional<Database::IdType> _userId;
|
||||
boost::optional<bool> _userAuthStrong;
|
||||
std::optional<Database::IdType> _userId;
|
||||
std::optional<bool> _userAuthStrong;
|
||||
std::shared_ptr<ImageResource> _imageResource;
|
||||
std::shared_ptr<AudioResource> _audioResource;
|
||||
};
|
||||
@@ -136,5 +135,3 @@ class LmsApplication : public Wt::WApplication
|
||||
|
||||
} // namespace UserInterface
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace UserInterface {
|
||||
LmsApplicationInfo
|
||||
LmsApplicationInfo::fromEnvironment(const Wt::WEnvironment& env)
|
||||
{
|
||||
LmsApplicationInfo info = {.userAgent = wApp->environment().agent()};
|
||||
LmsApplicationInfo info = {.userAgent = env.agent()};
|
||||
return info;
|
||||
}
|
||||
|
||||
|
||||
@@ -139,7 +139,7 @@ PlayQueue::PlayQueue()
|
||||
trackPos = LmsApp->getUser()->getCurPlayingTrackPos();
|
||||
}
|
||||
|
||||
load(trackPos, false);
|
||||
loadTrack(trackPos, false);
|
||||
});
|
||||
trackList = LmsApp->getUser()->getQueuedTrackList(LmsApp->getDbSession());
|
||||
}
|
||||
@@ -192,11 +192,11 @@ PlayQueue::stop()
|
||||
{
|
||||
updateCurrentTrack(false);
|
||||
_trackPos.reset();
|
||||
trackUnload.emit();
|
||||
trackUnselected.emit();
|
||||
}
|
||||
|
||||
void
|
||||
PlayQueue::load(std::size_t pos, bool play)
|
||||
PlayQueue::loadTrack(std::size_t pos, bool play)
|
||||
{
|
||||
updateCurrentTrack(false);
|
||||
|
||||
@@ -237,7 +237,7 @@ PlayQueue::load(std::size_t pos, bool play)
|
||||
|
||||
updateCurrentTrack(true);
|
||||
|
||||
loadTrack.emit(trackId, play);
|
||||
trackSelected.emit(trackId, play);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -249,7 +249,7 @@ PlayQueue::playPrevious()
|
||||
if (*_trackPos == 0)
|
||||
stop();
|
||||
else
|
||||
load(*_trackPos - 1, true);
|
||||
loadTrack(*_trackPos - 1, true);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -257,11 +257,11 @@ PlayQueue::playNext()
|
||||
{
|
||||
if (!_trackPos)
|
||||
{
|
||||
load(0, true);
|
||||
loadTrack(0, true);
|
||||
return;
|
||||
}
|
||||
|
||||
load(*_trackPos + 1, true);
|
||||
loadTrack(*_trackPos + 1, true);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -327,7 +327,7 @@ PlayQueue::playTracks(const std::vector<Database::IdType>& trackIds)
|
||||
{
|
||||
clearTracks();
|
||||
enqueueTracks(trackIds);
|
||||
load(0, true);
|
||||
loadTrack(0, true);
|
||||
|
||||
LmsApp->notifyMsg(MsgType::Info, Wt::WString::trn("Lms.PlayQueue.nb-tracks-playing", trackIds.size()).arg(trackIds.size()), std::chrono::milliseconds(2000));
|
||||
}
|
||||
@@ -377,7 +377,7 @@ PlayQueue::addSome()
|
||||
{
|
||||
auto pos = _entriesContainer->indexOf(entry);
|
||||
if (pos >= 0)
|
||||
load(pos, true);
|
||||
loadTrack(pos, true);
|
||||
}));
|
||||
|
||||
Wt::WText* delBtn = entry->bindNew<Wt::WText>("del-btn", Wt::WString::tr("Lms.PlayQueue.template.delete-btn"), Wt::TextFormat::XHTML);
|
||||
|
||||
@@ -19,13 +19,13 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <optional>
|
||||
|
||||
#include <Wt/WContainerWidget.h>
|
||||
#include <Wt/WPushButton.h>
|
||||
#include <Wt/WTemplate.h>
|
||||
#include <Wt/WText.h>
|
||||
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
#include "database/Types.hpp"
|
||||
|
||||
namespace Similarity {
|
||||
@@ -53,10 +53,10 @@ class PlayQueue : public Wt::WTemplate
|
||||
void playPrevious();
|
||||
|
||||
// Signal emitted when a track is to be load(and optionally played)
|
||||
Wt::Signal<Database::IdType /*trackId*/, bool /*play*/> loadTrack;
|
||||
Wt::Signal<Database::IdType /*trackId*/, bool /*play*/> trackSelected;
|
||||
|
||||
// Signal emitted when play has to be stopped
|
||||
Wt::Signal<> trackUnload;
|
||||
// Signal emitted when track is unselected (has to be stopped)
|
||||
Wt::Signal<> trackUnselected;
|
||||
|
||||
private:
|
||||
Wt::Dbo::ptr<Database::TrackList> getTrackList();
|
||||
@@ -71,7 +71,7 @@ class PlayQueue : public Wt::WTemplate
|
||||
void updateRepeatBtn();
|
||||
void updateRadioBtn();
|
||||
|
||||
void load(std::size_t pos, bool play);
|
||||
void loadTrack(std::size_t pos, bool play);
|
||||
void stop();
|
||||
|
||||
void addRadioTrackFromSimilarity(std::shared_ptr<Similarity::Finder> similarityFinder);
|
||||
@@ -85,7 +85,7 @@ class PlayQueue : public Wt::WTemplate
|
||||
Wt::WText* _nbTracks {};
|
||||
Wt::WText* _repeatBtn {};
|
||||
Wt::WText* _radioBtn {};
|
||||
boost::optional<std::size_t> _trackPos; // current track position, if set
|
||||
std::optional<std::size_t> _trackPos; // current track position, if set
|
||||
};
|
||||
|
||||
} // namespace UserInterface
|
||||
|
||||
@@ -53,7 +53,7 @@ class UserModel : public Wt::WFormModel
|
||||
static const Field AudioTranscodeBitrateLimitField;
|
||||
static const Field DemoField;
|
||||
|
||||
UserModel(boost::optional<Database::IdType> userId)
|
||||
UserModel(std::optional<Database::IdType> userId)
|
||||
: Wt::WFormModel(),
|
||||
_userId(userId)
|
||||
{
|
||||
@@ -80,7 +80,7 @@ class UserModel : public Wt::WFormModel
|
||||
|
||||
void saveData()
|
||||
{
|
||||
boost::optional<Database::User::PasswordHash> passwordHash;
|
||||
std::optional<Database::User::PasswordHash> passwordHash;
|
||||
if (!valueText(PasswordField).empty())
|
||||
passwordHash = getService<::Auth::PasswordService>()->hashPassword(valueText(PasswordField).toUTF8());
|
||||
|
||||
@@ -203,7 +203,7 @@ class UserModel : public Wt::WFormModel
|
||||
}
|
||||
|
||||
std::shared_ptr<ValueStringModel<Bitrate>> _bitrateModel;
|
||||
boost::optional<Database::IdType> _userId;
|
||||
std::optional<Database::IdType> _userId;
|
||||
};
|
||||
|
||||
const Wt::WFormModel::Field UserModel::LoginField = "login";
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
#include "Validators.hpp"
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <filesystem>
|
||||
|
||||
#include <Wt/WLengthValidator.h>
|
||||
|
||||
@@ -53,11 +53,11 @@ DirectoryValidator::validate(const Wt::WString& input) const
|
||||
if (input.empty())
|
||||
return Wt::WValidator::validate(input);
|
||||
|
||||
boost::filesystem::path p(input.toUTF8());
|
||||
boost::system::error_code ec;
|
||||
const std::filesystem::path p {input.toUTF8()};
|
||||
std::error_code ec;
|
||||
|
||||
// TODO check rights
|
||||
bool res = boost::filesystem::is_directory(p, ec);
|
||||
bool res = std::filesystem::is_directory(p, ec);
|
||||
if (ec)
|
||||
return Wt::WValidator::Result(Wt::ValidationState::Invalid, ec.message()); // TODO translate common errors
|
||||
else if (res)
|
||||
|
||||
@@ -20,7 +20,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <boost/optional.hpp>
|
||||
#include <optional>
|
||||
|
||||
#include <Wt/WStringListModel.h>
|
||||
|
||||
namespace UserInterface {
|
||||
@@ -41,7 +42,7 @@ class ValueStringModel : public Wt::WStringListModel
|
||||
return Wt::cpp17::any_cast<Wt::WString>(data(index(static_cast<int>(row), 0), Wt::ItemDataRole::Display));
|
||||
}
|
||||
|
||||
boost::optional<std::size_t>
|
||||
std::optional<std::size_t>
|
||||
getRowFromString(const Wt::WString& value)
|
||||
{
|
||||
for (std::size_t i{}; i < static_cast<std::size_t>(rowCount()); ++i)
|
||||
@@ -50,10 +51,10 @@ class ValueStringModel : public Wt::WStringListModel
|
||||
return i;
|
||||
}
|
||||
|
||||
return boost::none;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
boost::optional<std::size_t>
|
||||
std::optional<std::size_t>
|
||||
getRowFromValue(const T& value)
|
||||
{
|
||||
for (std::size_t i{}; i < static_cast<std::size_t>(rowCount()); ++i)
|
||||
@@ -62,7 +63,7 @@ class ValueStringModel : public Wt::WStringListModel
|
||||
return i;
|
||||
}
|
||||
|
||||
return boost::none;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -42,16 +42,16 @@ namespace UserInterface {
|
||||
Artist::Artist(Filters* filters)
|
||||
: _filters(filters)
|
||||
{
|
||||
wApp->internalPathChanged().connect(std::bind([=]
|
||||
wApp->internalPathChanged().connect([=]
|
||||
{
|
||||
refresh();
|
||||
}));
|
||||
});
|
||||
|
||||
refresh();
|
||||
|
||||
filters->updated().connect(std::bind([=] {
|
||||
filters->updated().connect([=] {
|
||||
refresh();
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
@@ -162,13 +162,13 @@ Artist::refresh()
|
||||
entry->bindWidget("artist", LmsApplication::createArtistAnchor(artists.front()));
|
||||
}
|
||||
|
||||
boost::optional<int> year = release->getReleaseYear();
|
||||
std::optional<int> year {release->getReleaseYear()};
|
||||
if (year)
|
||||
{
|
||||
entry->setCondition("if-has-year", true);
|
||||
entry->bindInt("year", *year);
|
||||
|
||||
boost::optional<int> originalYear = release->getReleaseYear(true);
|
||||
std::optional<int> originalYear {release->getReleaseYear(true)};
|
||||
if (originalYear && *originalYear != *year)
|
||||
{
|
||||
entry->setCondition("if-has-orig-year", true);
|
||||
@@ -177,16 +177,16 @@ Artist::refresh()
|
||||
}
|
||||
|
||||
Wt::WText* playBtn = entry->bindNew<Wt::WText>("play-btn", Wt::WString::tr("Lms.Explore.template.play-btn"), Wt::TextFormat::XHTML);
|
||||
playBtn->clicked().connect(std::bind([=]
|
||||
playBtn->clicked().connect([=]
|
||||
{
|
||||
releasesPlay.emit({releaseId});
|
||||
}));
|
||||
});
|
||||
|
||||
Wt::WText* addBtn = entry->bindNew<Wt::WText>("add-btn", Wt::WString::tr("Lms.Explore.template.add-btn"), Wt::TextFormat::XHTML);
|
||||
addBtn->clicked().connect(std::bind([=]
|
||||
addBtn->clicked().connect([=]
|
||||
{
|
||||
releasesAdd.emit({releaseId});
|
||||
}));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -76,8 +76,8 @@ ReleaseInfo::refresh()
|
||||
if (!release)
|
||||
return;
|
||||
|
||||
boost::optional<std::string> copyright {release->getCopyright()};
|
||||
boost::optional<std::string> copyrightURL {release->getCopyrightURL()};
|
||||
std::optional<std::string> copyright {release->getCopyright()};
|
||||
std::optional<std::string> copyrightURL {release->getCopyrightURL()};
|
||||
|
||||
setCondition("if-has-copyright-or-copyright-url", copyright || copyrightURL);
|
||||
|
||||
|
||||
@@ -81,13 +81,13 @@ Release::refresh()
|
||||
|
||||
t->bindString("name", Wt::WString::fromUTF8(release->getName()), Wt::TextFormat::Plain);
|
||||
|
||||
boost::optional<int> year {release->getReleaseYear()};
|
||||
std::optional<int> year {release->getReleaseYear()};
|
||||
if (year)
|
||||
{
|
||||
t->setCondition("if-has-year", true);
|
||||
t->bindInt("year", *year);
|
||||
|
||||
boost::optional<int> originalYear {release->getReleaseYear(true)};
|
||||
std::optional<int> originalYear {release->getReleaseYear(true)};
|
||||
if (originalYear && *originalYear != *year)
|
||||
{
|
||||
t->setCondition("if-has-orig-year", true);
|
||||
|
||||
@@ -135,7 +135,7 @@ Releases::addSome()
|
||||
}
|
||||
|
||||
std::vector<Database::IdType>
|
||||
Releases::getReleases(boost::optional<std::size_t> offset, boost::optional<std::size_t> limit, bool& moreResults) const
|
||||
Releases::getReleases(std::optional<std::size_t> offset, std::optional<std::size_t> limit, bool& moreResults) const
|
||||
{
|
||||
const auto searchKeywords {splitString(_search->text().toUTF8(), " ")};
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <boost/optional.hpp>
|
||||
#include <optional>
|
||||
|
||||
#include <Wt/WContainerWidget.h>
|
||||
#include <Wt/WLineEdit.h>
|
||||
@@ -44,7 +44,7 @@ class Releases : public Wt::WTemplate
|
||||
void refresh();
|
||||
void addSome();
|
||||
|
||||
std::vector<Database::IdType> getReleases(boost::optional<std::size_t> offset, boost::optional<std::size_t> limit, bool& moreResults) const;
|
||||
std::vector<Database::IdType> getReleases(std::optional<std::size_t> offset, std::optional<std::size_t> limit, bool& moreResults) const;
|
||||
std::vector<Database::IdType> getReleases() const;
|
||||
|
||||
Filters* _filters;
|
||||
|
||||
@@ -40,8 +40,8 @@ using namespace Database;
|
||||
namespace UserInterface {
|
||||
|
||||
Tracks::Tracks(Filters* filters)
|
||||
: Wt::WTemplate(Wt::WString::tr("Lms.Explore.Tracks.template")),
|
||||
_filters(filters)
|
||||
: Wt::WTemplate {Wt::WString::tr("Lms.Explore.Tracks.template")},
|
||||
_filters {filters}
|
||||
{
|
||||
addFunction("tr", &Wt::WTemplate::Functions::tr);
|
||||
|
||||
@@ -56,18 +56,18 @@ _filters(filters)
|
||||
});
|
||||
|
||||
Wt::WText* addBtn = bindNew<Wt::WText>("add-btn", Wt::WString::tr("Lms.Explore.template.add-btn"), Wt::TextFormat::XHTML);
|
||||
addBtn->clicked().connect(std::bind([=]
|
||||
addBtn->clicked().connect([=]
|
||||
{
|
||||
tracksAdd.emit(getTracks());
|
||||
}));
|
||||
});
|
||||
|
||||
_tracksContainer = bindNew<Wt::WContainerWidget>("tracks");
|
||||
|
||||
_showMore = bindNew<Wt::WPushButton>("show-more", Wt::WString::tr("Lms.Explore.show-more"));
|
||||
_showMore->clicked().connect(std::bind([=]
|
||||
_showMore->clicked().connect([=]
|
||||
{
|
||||
addSome();
|
||||
}));
|
||||
});
|
||||
|
||||
refresh();
|
||||
|
||||
@@ -75,7 +75,7 @@ _filters(filters)
|
||||
}
|
||||
|
||||
std::vector<Database::IdType>
|
||||
Tracks::getTracks(boost::optional<std::size_t> offset, boost::optional<std::size_t> size, bool& moreResults)
|
||||
Tracks::getTracks(std::optional<std::size_t> offset, std::optional<std::size_t> size, bool& moreResults)
|
||||
{
|
||||
const auto searchKeywords {splitString(_search->text().toUTF8(), " ")};
|
||||
const auto clusterIds {_filters->getClusterIds()};
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <boost/optional.hpp>
|
||||
#include <optional>
|
||||
|
||||
#include <Wt/WContainerWidget.h>
|
||||
#include <Wt/WLineEdit.h>
|
||||
@@ -43,7 +43,7 @@ class Tracks : public Wt::WTemplate
|
||||
void refresh();
|
||||
void addSome();
|
||||
|
||||
std::vector<Database::IdType> getTracks(boost::optional<std::size_t> offset, boost::optional<std::size_t> size, bool& moreResults);
|
||||
std::vector<Database::IdType> getTracks(std::optional<std::size_t> offset, std::optional<std::size_t> size, bool& moreResults);
|
||||
std::vector<Database::IdType> getTracks();
|
||||
|
||||
Wt::WContainerWidget* _tracksContainer;
|
||||
|
||||
@@ -19,12 +19,10 @@
|
||||
|
||||
#include "Config.hpp"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include "utils/Logger.hpp"
|
||||
|
||||
|
||||
Config::Config(const boost::filesystem::path& p)
|
||||
Config::Config(const std::filesystem::path& p)
|
||||
{
|
||||
_config.readFile(p.string().c_str());
|
||||
}
|
||||
@@ -35,7 +33,7 @@ Config::getString(const std::string& setting, const std::string& def, const std:
|
||||
try {
|
||||
std::string res {(const char*)_config.lookup(setting)};
|
||||
|
||||
if (!allowedValues.empty() && allowedValues.find(res) == allowedValues.end())
|
||||
if (!allowedValues.empty() && allowedValues.find(res) == std::cend(allowedValues))
|
||||
{
|
||||
LMS_LOG(MAIN, ERROR) << "Invalid setting for '" << setting << "', using default value '" << def << "'";
|
||||
return def;
|
||||
@@ -49,12 +47,12 @@ Config::getString(const std::string& setting, const std::string& def, const std:
|
||||
}
|
||||
}
|
||||
|
||||
boost::filesystem::path
|
||||
Config::getPath(const std::string& setting, const boost::filesystem::path& path)
|
||||
std::filesystem::path
|
||||
Config::getPath(const std::string& setting, const std::filesystem::path& path)
|
||||
{
|
||||
try {
|
||||
const char* res = _config.lookup(setting);
|
||||
return boost::filesystem::path(std::string(res));
|
||||
return std::filesystem::path {std::string(res)};
|
||||
}
|
||||
catch (std::exception &e)
|
||||
{
|
||||
|
||||
@@ -18,16 +18,16 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <filesystem>
|
||||
#include <set>
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <libconfig.h++>
|
||||
|
||||
// Used to get config values from configuration files
|
||||
class Config final
|
||||
{
|
||||
public:
|
||||
Config(const boost::filesystem::path& p);
|
||||
Config(const std::filesystem::path& p);
|
||||
~Config() = default;
|
||||
|
||||
Config(const Config&) = delete;
|
||||
@@ -37,7 +37,7 @@ class Config final
|
||||
|
||||
// Default values are returned in case of setting not found
|
||||
std::string getString(const std::string& setting, const std::string& def = "", const std::set<std::string>& allowedValues = {});
|
||||
boost::filesystem::path getPath(const std::string& setting, const boost::filesystem::path& def = boost::filesystem::path());
|
||||
std::filesystem::path getPath(const std::string& setting, const std::filesystem::path& def = std::filesystem::path());
|
||||
unsigned long getULong(const std::string& setting, unsigned long def = 0);
|
||||
long getLong(const std::string& setting, long def = 0);
|
||||
bool getBool(const std::string& setting, bool def = false);
|
||||
|
||||
+7
-7
@@ -28,7 +28,7 @@
|
||||
#include "utils/Exception.hpp"
|
||||
#include "utils/Logger.hpp"
|
||||
|
||||
boost::filesystem::path searchExecPath(std::string filename)
|
||||
std::filesystem::path searchExecPath(std::string filename)
|
||||
{
|
||||
std::string path;
|
||||
|
||||
@@ -42,7 +42,7 @@ boost::filesystem::path searchExecPath(std::string filename)
|
||||
tokenizer tok(path, sep);
|
||||
for (tokenizer::iterator it = tok.begin(); it != tok.end(); ++it)
|
||||
{
|
||||
boost::filesystem::path p = *it;
|
||||
std::filesystem::path p = *it;
|
||||
p /= filename;
|
||||
if (!::access(p.c_str(), X_OK))
|
||||
{
|
||||
@@ -53,7 +53,7 @@ boost::filesystem::path searchExecPath(std::string filename)
|
||||
return result;
|
||||
}
|
||||
|
||||
void computeCrc(const boost::filesystem::path& p, std::vector<unsigned char>& crc)
|
||||
void computeCrc(const std::filesystem::path& p, std::vector<unsigned char>& crc)
|
||||
{
|
||||
using crc_type = boost::crc_32_type;
|
||||
crc_type result;
|
||||
@@ -87,11 +87,11 @@ void computeCrc(const boost::filesystem::path& p, std::vector<unsigned char>& cr
|
||||
}
|
||||
}
|
||||
|
||||
bool ensureDirectory(boost::filesystem::path dir)
|
||||
bool ensureDirectory(const std::filesystem::path& dir)
|
||||
{
|
||||
if (boost::filesystem::exists(dir))
|
||||
return boost::filesystem::is_directory(dir);
|
||||
if (std::filesystem::exists(dir))
|
||||
return std::filesystem::is_directory(dir);
|
||||
else
|
||||
return boost::filesystem::create_directory(dir);
|
||||
return std::filesystem::create_directory(dir);
|
||||
}
|
||||
|
||||
|
||||
+4
-4
@@ -19,15 +19,15 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <filesystem>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
boost::filesystem::path searchExecPath(std::string filename);
|
||||
std::filesystem::path searchExecPath(std::string filename);
|
||||
|
||||
void computeCrc(const boost::filesystem::path& p, std::vector<unsigned char>& checksum);
|
||||
void computeCrc(const std::filesystem::path& p, std::vector<unsigned char>& checksum);
|
||||
|
||||
// Make sure the given path is a directory
|
||||
// Create it if needed
|
||||
bool ensureDirectory(boost::filesystem::path dir);
|
||||
bool ensureDirectory(const std::filesystem::path& dir);
|
||||
|
||||
|
||||
+3
-3
@@ -55,7 +55,7 @@ bool readList(const std::string& str, const std::string& separators, std::list<s
|
||||
}
|
||||
|
||||
template<>
|
||||
boost::optional<std::string>
|
||||
std::optional<std::string>
|
||||
readAs(const std::string& str)
|
||||
{
|
||||
return str;
|
||||
@@ -137,13 +137,13 @@ stringEndsWith(const std::string& str, const std::string& ending)
|
||||
return boost::algorithm::ends_with(str, ending);
|
||||
}
|
||||
|
||||
boost::optional<std::string>
|
||||
std::optional<std::string>
|
||||
stringFromHex(const std::string& str)
|
||||
{
|
||||
static const char lut[] {"0123456789ABCDEF"};
|
||||
|
||||
if (str.length() % 2 != 0)
|
||||
return boost::none;
|
||||
return std::nullopt;
|
||||
|
||||
std::string res;
|
||||
res.reserve(str.length() / 2);
|
||||
|
||||
+5
-6
@@ -22,13 +22,12 @@
|
||||
#include <chrono>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <optional>
|
||||
#include <random>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
#include <Wt/WDate.h>
|
||||
|
||||
bool
|
||||
@@ -53,14 +52,14 @@ std::string
|
||||
bufferToString(const std::vector<unsigned char>& data);
|
||||
|
||||
template<typename T>
|
||||
boost::optional<T> readAs(const std::string& str)
|
||||
std::optional<T> readAs(const std::string& str)
|
||||
{
|
||||
T res;
|
||||
|
||||
std::istringstream iss ( str );
|
||||
iss >> res;
|
||||
if (iss.fail())
|
||||
return boost::none;
|
||||
return std::nullopt;
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -71,7 +70,7 @@ replaceInString(const std::string& str, const std::string& from, const std::stri
|
||||
bool
|
||||
stringEndsWith(const std::string& str, const std::string& ending);
|
||||
|
||||
boost::optional<std::string>
|
||||
std::optional<std::string>
|
||||
stringFromHex(const std::string& str);
|
||||
|
||||
// warning: not efficient
|
||||
@@ -105,7 +104,7 @@ void uniqueAndSortedByOccurence(In first, In last, Out out)
|
||||
}
|
||||
|
||||
template<class T, class Compare = std::less<>>
|
||||
constexpr const T& clamp( T v, T lo, T hi, Compare comp = {})
|
||||
constexpr T clamp(T v, T lo, T hi, Compare comp = {})
|
||||
{
|
||||
assert(!comp(hi, lo));
|
||||
return comp(v, lo) ? lo : comp(hi, v) ? hi : v;
|
||||
|
||||
+3
-3
@@ -8,14 +8,14 @@ som_SOURCES = \
|
||||
$(top_srcdir)/src/similarity/features/som/DataNormalizer.cpp \
|
||||
$(top_srcdir)/src/similarity/features/som/Network.cpp
|
||||
|
||||
som_CXXFLAGS=-std=c++14 -Wall -I${top_srcdir}/src/ -I${top_srcdir}/src/similarity/features/som/
|
||||
som_CXXFLAGS=-std=c++17 -I${top_srcdir}/src/ -I${top_srcdir}/src/similarity/features/som/
|
||||
|
||||
|
||||
database_SOURCES = \
|
||||
$(srcdir)/database/DatabaseTest.cpp \
|
||||
$(top_srcdir)/src/database/Artist.cpp \
|
||||
$(top_srcdir)/src/database/Cluster.cpp \
|
||||
$(top_srcdir)/src/database/Database.cpp \
|
||||
$(top_srcdir)/src/database/Db.cpp \
|
||||
$(top_srcdir)/src/database/TrackArtistLink.cpp \
|
||||
$(top_srcdir)/src/database/TrackFeatures.cpp \
|
||||
$(top_srcdir)/src/database/TrackList.cpp \
|
||||
@@ -29,5 +29,5 @@ database_SOURCES = \
|
||||
$(top_srcdir)/src/utils/Logger.cpp \
|
||||
$(top_srcdir)/src/utils/Utils.cpp
|
||||
|
||||
database_CXXFLAGS=-std=c++14 -Wall -I${top_srcdir}/src/
|
||||
database_CXXFLAGS=-std=c++17 -I${top_srcdir}/src/
|
||||
|
||||
|
||||
@@ -19,11 +19,11 @@
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <filesystem>
|
||||
|
||||
#include "database/Artist.hpp"
|
||||
#include "database/Cluster.hpp"
|
||||
#include "database/Database.hpp"
|
||||
#include "database/Db.hpp"
|
||||
#include "database/TrackList.hpp"
|
||||
#include "database/Release.hpp"
|
||||
#include "database/Track.hpp"
|
||||
@@ -34,10 +34,10 @@ using namespace Database;
|
||||
class ScopedFileDeleter final
|
||||
{
|
||||
public:
|
||||
ScopedFileDeleter(const boost::filesystem::path& path) : _path {path} {}
|
||||
~ScopedFileDeleter() { boost::filesystem::remove(_path); }
|
||||
ScopedFileDeleter(const std::filesystem::path& path) : _path {path} {}
|
||||
~ScopedFileDeleter() { std::filesystem::remove(_path); }
|
||||
private:
|
||||
boost::filesystem::path _path;
|
||||
std::filesystem::path _path;
|
||||
};
|
||||
|
||||
#define CHECK(PRED) \
|
||||
@@ -1247,19 +1247,19 @@ testDatabaseEmpty(Session& session)
|
||||
CHECK(Track::getAll(session).empty());
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
int main()
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
const boost::filesystem::path tmpFile {boost::filesystem::temp_directory_path() / boost::filesystem::unique_path()};
|
||||
const std::filesystem::path tmpFile {std::tmpnam(nullptr)};
|
||||
ScopedFileDeleter tmpFileDeleter {tmpFile};
|
||||
|
||||
std::cout << "Database test file: '" << tmpFile.string() << "'" << std::endl;
|
||||
|
||||
for (std::size_t i = 0; i < 2; ++i)
|
||||
{
|
||||
Database::Database db {tmpFile};
|
||||
Database::Db db {tmpFile};
|
||||
std::unique_ptr<Session> session {db.createSession()};
|
||||
|
||||
auto runTest = [&session](const std::string& name, std::function<void(Session&)> testFunc)
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
using namespace SOM;
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
int main()
|
||||
{
|
||||
static const InputVector::value_type EPSILON = 0.01;
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <chrono>
|
||||
#include <optional>
|
||||
#include <stdexcept>
|
||||
#include <stdlib.h>
|
||||
#include <iostream>
|
||||
@@ -31,13 +32,13 @@ std::ostream& operator<<(std::ostream& os, const MetaData::Album& album)
|
||||
|
||||
|
||||
|
||||
void parse(MetaData::Parser& parser, const boost::filesystem::path& file)
|
||||
void parse(MetaData::Parser& parser, const std::filesystem::path& file)
|
||||
{
|
||||
using namespace MetaData;
|
||||
|
||||
parser.setClusterTypeNames( {"MOOD", "GENRE"} );
|
||||
|
||||
boost::optional<Track> track {parser.parse(file, true)};
|
||||
std::optional<Track> track {parser.parse(file, true)};
|
||||
if (!track)
|
||||
{
|
||||
std::cerr << "Parsing failed" << std::endl;
|
||||
@@ -119,11 +120,9 @@ int main(int argc, char *argv[])
|
||||
|
||||
try
|
||||
{
|
||||
Av::AvInit();
|
||||
|
||||
for (std::size_t i {}; i < static_cast<std::size_t>(argc - 1); ++i)
|
||||
{
|
||||
boost::filesystem::path file {argv[i + 1]};
|
||||
std::filesystem::path file {argv[i + 1]};
|
||||
|
||||
std::cout << "Parsing file '" << file << "'" << std::endl;
|
||||
|
||||
|
||||
@@ -8,5 +8,5 @@ lms_metadata_SOURCES = \
|
||||
$(top_srcdir)/src/utils/Logger.cpp \
|
||||
$(top_srcdir)/src/utils/Utils.cpp
|
||||
|
||||
lms_metadata_CXXFLAGS=-std=c++14 -Wall -I$(top_srcdir)/src -D_REENTRANT
|
||||
lms_metadata_CXXFLAGS=-std=c++17 -I$(top_srcdir)/src -D_REENTRANT
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdexcept>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <chrono>
|
||||
#include <random>
|
||||
#include <filesystem>
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
#include <stdlib.h>
|
||||
#include <string>
|
||||
|
||||
#include "database/Database.hpp"
|
||||
#include "database/Db.hpp"
|
||||
#include "database/Session.hpp"
|
||||
#include "database/Track.hpp"
|
||||
#include "database/Artist.hpp"
|
||||
@@ -32,7 +32,7 @@ std::ostream& operator<<(std::ostream& os, const Database::Track::pointer& track
|
||||
|
||||
static
|
||||
bool
|
||||
getTrackFeatures(Database::Session &session, const Database::Track::pointer& track, const std::map<std::string, std::size_t>& featuresSettings, SOM::InputVector& res)
|
||||
getTrackFeatures(Database::Session&, const Database::Track::pointer& track, const std::map<std::string, std::size_t>& featuresSettings, SOM::InputVector& res)
|
||||
{
|
||||
std::map<std::string, std::vector<double>> features;
|
||||
for (const auto& featureSettings : featuresSettings)
|
||||
@@ -84,13 +84,13 @@ int main(int argc, char *argv[])
|
||||
for (const auto& featureSettings : featuresSettings)
|
||||
nbDims += featureSettings.second;
|
||||
|
||||
boost::filesystem::path configFilePath = "/etc/lms.conf";
|
||||
std::filesystem::path configFilePath {"/etc/lms.conf"};
|
||||
if (argc >= 2)
|
||||
configFilePath = std::string(argv[1], 0, 256);
|
||||
|
||||
ServiceProvider<Config>::create(configFilePath);
|
||||
|
||||
Database::Database db {getService<Config>()->getPath("working-dir") / "lms.db"};
|
||||
Database::Db db {getService<Config>()->getPath("working-dir") / "lms.db"};
|
||||
auto session {db.createSession()};
|
||||
|
||||
std::cout << "Getting all features..." << std::endl;
|
||||
|
||||
@@ -4,7 +4,7 @@ lms_similarity_SOURCES = \
|
||||
$(srcdir)/LmsSimilarity.cpp \
|
||||
$(top_srcdir)/src/database/Artist.cpp \
|
||||
$(top_srcdir)/src/database/Cluster.cpp \
|
||||
$(top_srcdir)/src/database/Database.cpp \
|
||||
$(top_srcdir)/src/database/Db.cpp \
|
||||
$(top_srcdir)/src/database/TrackFeatures.cpp \
|
||||
$(top_srcdir)/src/database/TrackList.cpp \
|
||||
$(top_srcdir)/src/database/Release.cpp \
|
||||
@@ -20,5 +20,5 @@ lms_similarity_SOURCES = \
|
||||
$(top_srcdir)/src/utils/Logger.cpp \
|
||||
$(top_srcdir)/src/utils/Utils.cpp
|
||||
|
||||
lms_similarity_CXXFLAGS=-std=c++14 -Wall -I$(top_srcdir)/src -D_REENTRANT
|
||||
lms_similarity_CXXFLAGS=-std=c++17 -I$(top_srcdir)/src -D_REENTRANT
|
||||
|
||||
|
||||
Reference in New Issue
Block a user