forked from openkylin/phonon-backend-vlc
Import Upstream version 0.11.3
This commit is contained in:
commit
36f66f4b7c
|
@ -0,0 +1,12 @@
|
|||
.svn
|
||||
Makefile
|
||||
CMakeTmp
|
||||
CMakeCache.txt
|
||||
CMakeFiles/
|
||||
cmake_install.cmake
|
||||
cmake_uninstall.cmake
|
||||
lib/
|
||||
*.o
|
||||
*.so
|
||||
*.user
|
||||
build
|
|
@ -0,0 +1,34 @@
|
|||
The phonon-VLC authors are:
|
||||
---------------------------
|
||||
|
||||
Harald Sitter
|
||||
Casian Andrei
|
||||
Ben Cooksley
|
||||
Jean-Baptiste Kempf
|
||||
Mark Kretschmann
|
||||
Martin T. H. Sandsmark
|
||||
Patrick von Reth
|
||||
Andreas Hartmetz
|
||||
Rémi Duraffort
|
||||
Colin Guthrie
|
||||
Fathi Boudra
|
||||
Patrick Spendrin
|
||||
Rémi Denis-Courmont
|
||||
Arno Rehn
|
||||
Kamil Klimek
|
||||
Michael Forney
|
||||
Raphael Kubo da Costa
|
||||
Alex Neundorf
|
||||
Benoit Calvez
|
||||
Myriam Schweingruber
|
||||
Romain Perier
|
||||
Valentin Rusu
|
||||
Albert Astals Cid
|
||||
Alejandro Wainzinger
|
||||
Alexander Potashev
|
||||
Andrius da Costa Ribas
|
||||
Arnaud Le Roy
|
||||
Locke Shinseiko
|
||||
Pino Toscano
|
||||
Ralf Habacker
|
||||
Thiago Macieira
|
|
@ -0,0 +1,56 @@
|
|||
cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
|
||||
project(PhononVLC VERSION 0.11.3)
|
||||
|
||||
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||
|
||||
include(FeatureSummary)
|
||||
|
||||
# ECM
|
||||
find_package(ECM 5.60 NO_MODULE)
|
||||
set_package_properties(ECM PROPERTIES
|
||||
TYPE REQUIRED
|
||||
DESCRIPTION "Extra CMake Modules"
|
||||
URL "https://api.kde.org/frameworks/extra-cmake-modules/html/index.html")
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR})
|
||||
|
||||
include(KDEInstallDirs)
|
||||
include(ECMPoQmTools)
|
||||
include(KDECMakeSettings)
|
||||
include(KDECompilerSettings)
|
||||
include(ECMSetupVersion)
|
||||
|
||||
# Phonon
|
||||
find_package(Phonon4Qt5 4.10.60 NO_MODULE)
|
||||
set_package_properties(Phonon4Qt5 PROPERTIES
|
||||
TYPE REQUIRED
|
||||
DESCRIPTION "Phonon core library"
|
||||
URL "https://api.kde.org/phonon/html/index.html")
|
||||
|
||||
find_package(Phonon4Qt5Experimental 4.10.60 NO_MODULE)
|
||||
set_package_properties(Phonon4Qt5Experimental PROPERTIES
|
||||
TYPE OPTIONAL
|
||||
DESCRIPTION "Phonon experimental library"
|
||||
URL "https://api.kde.org/phonon/html/index.html")
|
||||
if(Phonon4Qt5Experimental_FOUND)
|
||||
set(PHONON_EXPERIMENTAL TRUE)
|
||||
endif()
|
||||
|
||||
# LibVLC
|
||||
find_package(LIBVLC 2.1.0)
|
||||
set_package_properties(LIBVLC PROPERTIES
|
||||
TYPE REQUIRED
|
||||
DESCRIPTION "VLC C library"
|
||||
URL "http://git.videolan.org")
|
||||
|
||||
ecm_setup_version(PROJECT VARIABLE_PREFIX PHONON_VLC)
|
||||
|
||||
# PVLC only uses static mimetype lists, they are created by cmake, hooray.
|
||||
include(MimeTypes.cmake)
|
||||
|
||||
add_subdirectory(src)
|
||||
|
||||
if(IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/po")
|
||||
ecm_install_po_files_as_qm(po)
|
||||
endif()
|
||||
|
||||
feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES)
|
|
@ -0,0 +1,462 @@
|
|||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 2.1, February 1999
|
||||
|
||||
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
[This is the first released version of the Lesser GPL. It also counts
|
||||
as the successor of the GNU Library Public License, version 2, hence
|
||||
the version number 2.1.]
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
Licenses are intended to guarantee your freedom to share and change
|
||||
free software--to make sure the software is free for all its users.
|
||||
|
||||
This license, the Lesser General Public License, applies to some
|
||||
specially designated software packages--typically libraries--of the
|
||||
Free Software Foundation and other authors who decide to use it. You
|
||||
can use it too, but we suggest you first think carefully about whether
|
||||
this license or the ordinary General Public License is the better
|
||||
strategy to use in any particular case, based on the explanations
|
||||
below.
|
||||
|
||||
When we speak of free software, we are referring to freedom of use,
|
||||
not price. Our General Public Licenses are designed to make sure that
|
||||
you have the freedom to distribute copies of free software (and charge
|
||||
for this service if you wish); that you receive source code or can get
|
||||
it if you want it; that you can change the software and use pieces of
|
||||
it in new free programs; and that you are informed that you can do
|
||||
these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
distributors to deny you these rights or to ask you to surrender these
|
||||
rights. These restrictions translate to certain responsibilities for
|
||||
you if you distribute copies of the library or if you modify it.
|
||||
|
||||
For example, if you distribute copies of the library, whether gratis
|
||||
or for a fee, you must give the recipients all the rights that we gave
|
||||
you. You must make sure that they, too, receive or can get the source
|
||||
code. If you link other code with the library, you must provide
|
||||
complete object files to the recipients, so that they can relink them
|
||||
with the library after making changes to the library and recompiling
|
||||
it. And you must show them these terms so they know their rights.
|
||||
|
||||
We protect your rights with a two-step method: (1) we copyright the
|
||||
library, and (2) we offer you this license, which gives you legal
|
||||
permission to copy, distribute and/or modify the library.
|
||||
|
||||
To protect each distributor, we want to make it very clear that
|
||||
there is no warranty for the free library. Also, if the library is
|
||||
modified by someone else and passed on, the recipients should know
|
||||
that what they have is not the original version, so that the original
|
||||
author's reputation will not be affected by problems that might be
|
||||
introduced by others.
|
||||
|
||||
Finally, software patents pose a constant threat to the existence of
|
||||
any free program. We wish to make sure that a company cannot
|
||||
effectively restrict the users of a free program by obtaining a
|
||||
restrictive license from a patent holder. Therefore, we insist that
|
||||
any patent license obtained for a version of the library must be
|
||||
consistent with the full freedom of use specified in this license.
|
||||
|
||||
Most GNU software, including some libraries, is covered by the
|
||||
ordinary GNU General Public License. This license, the GNU Lesser
|
||||
General Public License, applies to certain designated libraries, and
|
||||
is quite different from the ordinary General Public License. We use
|
||||
this license for certain libraries in order to permit linking those
|
||||
libraries into non-free programs.
|
||||
|
||||
When a program is linked with a library, whether statically or using
|
||||
a shared library, the combination of the two is legally speaking a
|
||||
combined work, a derivative of the original library. The ordinary
|
||||
General Public License therefore permits such linking only if the
|
||||
entire combination fits its criteria of freedom. The Lesser General
|
||||
Public License permits more lax criteria for linking other code with
|
||||
the library.
|
||||
|
||||
We call this license the "Lesser" General Public License because it
|
||||
does Less to protect the user's freedom than the ordinary General
|
||||
Public License. It also provides other free software developers Less
|
||||
of an advantage over competing non-free programs. These disadvantages
|
||||
are the reason we use the ordinary General Public License for many
|
||||
libraries. However, the Lesser license provides advantages in certain
|
||||
special circumstances.
|
||||
|
||||
For example, on rare occasions, there may be a special need to
|
||||
encourage the widest possible use of a certain library, so that it
|
||||
becomes a de-facto standard. To achieve this, non-free programs must
|
||||
be allowed to use the library. A more frequent case is that a free
|
||||
library does the same job as widely used non-free libraries. In this
|
||||
case, there is little to gain by limiting the free library to free
|
||||
software only, so we use the Lesser General Public License.
|
||||
|
||||
In other cases, permission to use a particular library in non-free
|
||||
programs enables a greater number of people to use a large body of
|
||||
free software. For example, permission to use the GNU C Library in
|
||||
non-free programs enables many more people to use the whole GNU
|
||||
operating system, as well as its variant, the GNU/Linux operating
|
||||
system.
|
||||
|
||||
Although the Lesser General Public License is Less protective of the
|
||||
users' freedom, it does ensure that the user of a program that is
|
||||
linked with the Library has the freedom and the wherewithal to run
|
||||
that program using a modified version of the Library.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow. Pay close attention to the difference between a
|
||||
"work based on the library" and a "work that uses the library". The
|
||||
former contains code derived from the library, whereas the latter must
|
||||
be combined with the library in order to run.
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any software library or other
|
||||
program which contains a notice placed by the copyright holder or
|
||||
other authorized party saying it may be distributed under the terms of
|
||||
this Lesser General Public License (also called "this License").
|
||||
Each licensee is addressed as "you".
|
||||
|
||||
A "library" means a collection of software functions and/or data
|
||||
prepared so as to be conveniently linked with application programs
|
||||
(which use some of those functions and data) to form executables.
|
||||
|
||||
The "Library", below, refers to any such software library or work
|
||||
which has been distributed under these terms. A "work based on the
|
||||
Library" means either the Library or any derivative work under
|
||||
copyright law: that is to say, a work containing the Library or a
|
||||
portion of it, either verbatim or with modifications and/or translated
|
||||
straightforwardly into another language. (Hereinafter, translation is
|
||||
included without limitation in the term "modification".)
|
||||
|
||||
"Source code" for a work means the preferred form of the work for
|
||||
making modifications to it. For a library, complete source code means
|
||||
all the source code for all modules it contains, plus any associated
|
||||
interface definition files, plus the scripts used to control
|
||||
compilation and installation of the library.
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running a program using the Library is not restricted, and output from
|
||||
such a program is covered only if its contents constitute a work based
|
||||
on the Library (independent of the use of the Library in a tool for
|
||||
writing it). Whether that is true depends on what the Library does
|
||||
and what the program that uses the Library does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Library's
|
||||
complete source code as you receive it, in any medium, provided that
|
||||
you conspicuously and appropriately publish on each copy an
|
||||
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||
all the notices that refer to this License and to the absence of any
|
||||
warranty; and distribute a copy of this License along with the
|
||||
Library.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy,
|
||||
and you may at your option offer warranty protection in exchange for a
|
||||
fee.
|
||||
|
||||
2. You may modify your copy or copies of the Library or any portion
|
||||
of it, thus forming a work based on the Library, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) The modified work must itself be a software library.
|
||||
|
||||
b) You must cause the files modified to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
c) You must cause the whole of the work to be licensed at no
|
||||
charge to all third parties under the terms of this License.
|
||||
|
||||
d) If a facility in the modified Library refers to a function or a
|
||||
table of data to be supplied by an application program that uses
|
||||
the facility, other than as an argument passed when the facility
|
||||
is invoked, then you must make a good faith effort to ensure that,
|
||||
in the event an application does not supply such function or
|
||||
table, the facility still operates, and performs whatever part of
|
||||
its purpose remains meaningful.
|
||||
|
||||
(For example, a function in a library to compute square roots has
|
||||
a purpose that is entirely well-defined independent of the
|
||||
application. Therefore, Subsection 2d requires that any
|
||||
application-supplied function or table used by this function must
|
||||
be optional: if the application does not supply it, the square
|
||||
root function must still compute square roots.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Library,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Library, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote
|
||||
it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Library.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Library
|
||||
with the Library (or with a work based on the Library) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||
License instead of this License to a given copy of the Library. To do
|
||||
this, you must alter all the notices that refer to this License, so
|
||||
that they refer to the ordinary GNU General Public License, version 2,
|
||||
instead of to this License. (If a newer version than version 2 of the
|
||||
ordinary GNU General Public License has appeared, then you can specify
|
||||
that version instead if you wish.) Do not make any other change in
|
||||
these notices.
|
||||
|
||||
Once this change is made in a given copy, it is irreversible for
|
||||
that copy, so the ordinary GNU General Public License applies to all
|
||||
subsequent copies and derivative works made from that copy.
|
||||
|
||||
This option is useful when you wish to copy part of the code of
|
||||
the Library into a program that is not a library.
|
||||
|
||||
4. You may copy and distribute the Library (or a portion or
|
||||
derivative of it, under Section 2) in object code or executable form
|
||||
under the terms of Sections 1 and 2 above provided that you accompany
|
||||
it with the complete corresponding machine-readable source code, which
|
||||
must be distributed under the terms of Sections 1 and 2 above on a
|
||||
medium customarily used for software interchange.
|
||||
|
||||
If distribution of object code is made by offering access to copy
|
||||
from a designated place, then offering equivalent access to copy the
|
||||
source code from the same place satisfies the requirement to
|
||||
distribute the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
5. A program that contains no derivative of any portion of the
|
||||
Library, but is designed to work with the Library by being compiled or
|
||||
linked with it, is called a "work that uses the Library". Such a
|
||||
work, in isolation, is not a derivative work of the Library, and
|
||||
therefore falls outside the scope of this License.
|
||||
|
||||
However, linking a "work that uses the Library" with the Library
|
||||
creates an executable that is a derivative of the Library (because it
|
||||
contains portions of the Library), rather than a "work that uses the
|
||||
library". The executable is therefore covered by this License.
|
||||
Section 6 states terms for distribution of such executables.
|
||||
|
||||
When a "work that uses the Library" uses material from a header file
|
||||
that is part of the Library, the object code for the work may be a
|
||||
derivative work of the Library even though the source code is not.
|
||||
Whether this is true is especially significant if the work can be
|
||||
linked without the Library, or if the work is itself a library. The
|
||||
threshold for this to be true is not precisely defined by law.
|
||||
|
||||
If such an object file uses only numerical parameters, data
|
||||
structure layouts and accessors, and small macros and small inline
|
||||
functions (ten lines or less in length), then the use of the object
|
||||
file is unrestricted, regardless of whether it is legally a derivative
|
||||
work. (Executables containing this object code plus portions of the
|
||||
Library will still fall under Section 6.)
|
||||
|
||||
Otherwise, if the work is a derivative of the Library, you may
|
||||
distribute the object code for the work under the terms of Section 6.
|
||||
Any executables containing that work also fall under Section 6,
|
||||
whether or not they are linked directly with the Library itself.
|
||||
|
||||
6. As an exception to the Sections above, you may also combine or
|
||||
link a "work that uses the Library" with the Library to produce a
|
||||
work containing portions of the Library, and distribute that work
|
||||
under terms of your choice, provided that the terms permit
|
||||
modification of the work for the customer's own use and reverse
|
||||
engineering for debugging such modifications.
|
||||
|
||||
You must give prominent notice with each copy of the work that the
|
||||
Library is used in it and that the Library and its use are covered by
|
||||
this License. You must supply a copy of this License. If the work
|
||||
during execution displays copyright notices, you must include the
|
||||
copyright notice for the Library among them, as well as a reference
|
||||
directing the user to the copy of this License. Also, you must do one
|
||||
of these things:
|
||||
|
||||
a) Accompany the work with the complete corresponding
|
||||
machine-readable source code for the Library including whatever
|
||||
changes were used in the work (which must be distributed under
|
||||
Sections 1 and 2 above); and, if the work is an executable linked
|
||||
with the Library, with the complete machine-readable "work that
|
||||
uses the Library", as object code and/or source code, so that the
|
||||
user can modify the Library and then relink to produce a modified
|
||||
executable containing the modified Library. (It is understood
|
||||
that the user who changes the contents of definitions files in the
|
||||
Library will not necessarily be able to recompile the application
|
||||
to use the modified definitions.)
|
||||
|
||||
b) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (1) uses at run time a
|
||||
copy of the library already present on the user's computer system,
|
||||
rather than copying library functions into the executable, and (2)
|
||||
will operate properly with a modified version of the library, if
|
||||
the user installs one, as long as the modified version is
|
||||
interface-compatible with the version that the work was made with.
|
||||
|
||||
c) Accompany the work with a written offer, valid for at least
|
||||
three years, to give the same user the materials specified in
|
||||
Subsection 6a, above, for a charge no more than the cost of
|
||||
performing this distribution.
|
||||
|
||||
d) If distribution of the work is made by offering access to copy
|
||||
from a designated place, offer equivalent access to copy the above
|
||||
specified materials from the same place.
|
||||
|
||||
e) Verify that the user has already received a copy of these
|
||||
materials or that you have already sent this user a copy.
|
||||
|
||||
For an executable, the required form of the "work that uses the
|
||||
Library" must include any data and utility programs needed for
|
||||
reproducing the executable from it. However, as a special exception,
|
||||
the materials to be distributed need not include anything that is
|
||||
normally distributed (in either source or binary form) with the major
|
||||
components (compiler, kernel, and so on) of the operating system on
|
||||
which the executable runs, unless that component itself accompanies
|
||||
the executable.
|
||||
|
||||
It may happen that this requirement contradicts the license
|
||||
restrictions of other proprietary libraries that do not normally
|
||||
accompany the operating system. Such a contradiction means you cannot
|
||||
use both them and the Library together in an executable that you
|
||||
distribute.
|
||||
|
||||
7. You may place library facilities that are a work based on the
|
||||
Library side-by-side in a single library together with other library
|
||||
facilities not covered by this License, and distribute such a combined
|
||||
library, provided that the separate distribution of the work based on
|
||||
the Library and of the other library facilities is otherwise
|
||||
permitted, and provided that you do these two things:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work
|
||||
based on the Library, uncombined with any other library
|
||||
facilities. This must be distributed under the terms of the
|
||||
Sections above.
|
||||
|
||||
b) Give prominent notice with the combined library of the fact
|
||||
that part of it is a work based on the Library, and explaining
|
||||
where to find the accompanying uncombined form of the same work.
|
||||
|
||||
8. You may not copy, modify, sublicense, link with, or distribute
|
||||
the Library except as expressly provided under this License. Any
|
||||
attempt otherwise to copy, modify, sublicense, link with, or
|
||||
distribute the Library is void, and will automatically terminate your
|
||||
rights under this License. However, parties who have received copies,
|
||||
or rights, from you under this License will not have their licenses
|
||||
terminated so long as such parties remain in full compliance.
|
||||
|
||||
9. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Library or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Library (or any work based on the
|
||||
Library), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Library or works based on it.
|
||||
|
||||
10. Each time you redistribute the Library (or any work based on the
|
||||
Library), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute, link with or modify the Library
|
||||
subject to these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties with
|
||||
this License.
|
||||
|
||||
11. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Library at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Library by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Library.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply, and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
12. If the distribution and/or use of the Library is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Library under this License
|
||||
may add an explicit geographical distribution limitation excluding those
|
||||
countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
13. The Free Software Foundation may publish revised and/or new
|
||||
versions of the Lesser General Public License from time to time.
|
||||
Such new versions will be similar in spirit to the present version,
|
||||
but may differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Library
|
||||
specifies a version number of this License which applies to it and
|
||||
"any later version", you have the option of following the terms and
|
||||
conditions either of that version or of any later version published by
|
||||
the Free Software Foundation. If the Library does not specify a
|
||||
license version number, you may choose any version ever published by
|
||||
the Free Software Foundation.
|
||||
|
||||
14. If you wish to incorporate parts of the Library into other free
|
||||
programs whose distribution conditions are incompatible with these,
|
||||
write to the author to ask for permission. For software which is
|
||||
copyrighted by the Free Software Foundation, write to the Free
|
||||
Software Foundation; we sometimes make exceptions for this. Our
|
||||
decision will be guided by the two goals of preserving the free status
|
||||
of all derivatives of our free software and of promoting the sharing
|
||||
and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
||||
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
#! /usr/bin/env bash
|
||||
$EXTRACT_TR_STRINGS $(find . -name "*.cpp" -o -name "*.h") -o $podir/phonon_vlc_qt.pot
|
|
@ -0,0 +1,165 @@
|
|||
# Copyright (C) 2012, Harald Sitter <sitter@kde.org>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
|
||||
set(PHONON_VLC_MIME_TYPES
|
||||
application/mpeg4-iod
|
||||
application/mpeg4-muxcodetable
|
||||
application/mxf
|
||||
application/ogg
|
||||
application/ram
|
||||
application/sdp
|
||||
application/vnd.apple.mpegurl
|
||||
application/vnd.ms-asf
|
||||
application/vnd.ms-wpl
|
||||
application/vnd.rn-realmedia
|
||||
application/vnd.rn-realmedia-vbr
|
||||
application/x-cd-image
|
||||
application/x-extension-m4a
|
||||
application/x-extension-mp4
|
||||
application/x-flac
|
||||
application/x-flash-video
|
||||
application/x-matroska
|
||||
application/x-ogg
|
||||
application/x-quicktime-media-link
|
||||
application/x-quicktimeplayer
|
||||
application/x-shockwave-flash
|
||||
application/xspf+xml
|
||||
audio/3gpp
|
||||
audio/3gpp2
|
||||
audio/AMR
|
||||
audio/AMR-WB
|
||||
audio/aac
|
||||
audio/ac3
|
||||
audio/basic
|
||||
audio/dv
|
||||
audio/eac3
|
||||
audio/flac
|
||||
audio/m4a
|
||||
audio/midi
|
||||
audio/mp1
|
||||
audio/mp2
|
||||
audio/mp3
|
||||
audio/mp4
|
||||
audio/mpeg
|
||||
audio/mpegurl
|
||||
audio/mpg
|
||||
audio/ogg
|
||||
audio/opus
|
||||
audio/scpls
|
||||
audio/vnd.dolby.heaac.1
|
||||
audio/vnd.dolby.heaac.2
|
||||
audio/vnd.dolby.mlp
|
||||
audio/vnd.dts
|
||||
audio/vnd.dts.hd
|
||||
audio/vnd.rn-realaudio
|
||||
audio/vorbis
|
||||
audio/wav
|
||||
audio/webm
|
||||
audio/x-aac
|
||||
audio/x-adpcm
|
||||
audio/x-aiff
|
||||
audio/x-ape
|
||||
audio/x-flac
|
||||
audio/x-gsm
|
||||
audio/x-it
|
||||
audio/x-m4a
|
||||
audio/x-matroska
|
||||
audio/x-mod
|
||||
audio/x-mp1
|
||||
audio/x-mp2
|
||||
audio/x-mp3
|
||||
audio/x-mpeg
|
||||
audio/x-mpegurl
|
||||
audio/x-mpg
|
||||
audio/x-ms-asf
|
||||
audio/x-ms-asx
|
||||
audio/x-ms-wax
|
||||
audio/x-ms-wma
|
||||
audio/x-musepack
|
||||
audio/x-pn-aiff
|
||||
audio/x-pn-au
|
||||
audio/x-pn-realaudio
|
||||
audio/x-pn-realaudio-plugin
|
||||
audio/x-pn-wav
|
||||
audio/x-pn-windows-acm
|
||||
audio/x-real-audio
|
||||
audio/x-realaudio
|
||||
audio/x-s3m
|
||||
audio/x-scpls
|
||||
audio/x-shorten
|
||||
audio/x-speex
|
||||
audio/x-tta
|
||||
audio/x-vorbis
|
||||
audio/x-vorbis+ogg
|
||||
audio/x-wav
|
||||
audio/x-wavpack
|
||||
audio/x-xm
|
||||
image/vnd.rn-realpix
|
||||
misc/ultravox
|
||||
text/google-video-pointer
|
||||
text/x-google-video-pointer
|
||||
video/3gp
|
||||
video/3gpp
|
||||
video/3gpp2
|
||||
video/avi
|
||||
video/divx
|
||||
video/dv
|
||||
video/fli
|
||||
video/flv
|
||||
video/mp2t
|
||||
video/mp4
|
||||
video/mp4v-es
|
||||
video/mpeg
|
||||
video/mpeg-system
|
||||
video/msvideo
|
||||
video/ogg
|
||||
video/quicktime
|
||||
video/vnd.divx
|
||||
video/vnd.mpegurl
|
||||
video/vnd.rn-realvideo
|
||||
video/webm
|
||||
video/x-anim
|
||||
video/x-avi
|
||||
video/x-flc
|
||||
video/x-fli
|
||||
video/x-flv
|
||||
video/x-m4v
|
||||
video/x-matroska
|
||||
video/x-mpeg
|
||||
video/x-mpeg-system
|
||||
video/x-mpeg2
|
||||
video/x-ms-asf
|
||||
video/x-ms-asf-plugin
|
||||
video/x-ms-asx
|
||||
video/x-ms-wm
|
||||
video/x-ms-wmv
|
||||
video/x-ms-wmx
|
||||
video/x-ms-wvx
|
||||
video/x-msvideo
|
||||
video/x-nsv
|
||||
video/x-ogm
|
||||
video/x-ogm+ogg
|
||||
video/x-theora
|
||||
video/x-theora+ogg
|
||||
x-content/audio-cdda
|
||||
x-content/audio-player
|
||||
x-content/video-dvd
|
||||
x-content/video-svcd
|
||||
x-content/video-vcd
|
||||
)
|
||||
|
||||
macro(CREATE_C_ARRAY var list)
|
||||
set(ret "")
|
||||
foreach(str ${PHONON_VLC_MIME_TYPES})
|
||||
if(NOT ret)
|
||||
set(ret "\"${str}\"")
|
||||
else(NOT ret)
|
||||
set(ret "${ret}, \"${str}\"")
|
||||
endif(NOT ret)
|
||||
endforeach(str)
|
||||
set(${var} "{${ret}, 0}")
|
||||
endmacro(CREATE_C_ARRAY var list)
|
||||
|
||||
CREATE_C_ARRAY(PHONON_VLC_MIME_TYPES_C_ARRAY ${PHONON_VLC_MIME_TYPES})
|
|
@ -0,0 +1,22 @@
|
|||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@ -0,0 +1,89 @@
|
|||
# - Try to find the KDEWIN library
|
||||
#
|
||||
# Once done this will define
|
||||
#
|
||||
# KDEWIN_FOUND - system has KDEWIN
|
||||
# KDEWIN_INCLUDES - the KDEWIN include directories
|
||||
# KDEWIN_LIBRARIES - The libraries needed to use KDEWIN
|
||||
|
||||
# Copyright (c) 2006, Alexander Neundorf, <neundorf@kde.org>
|
||||
# Copyright (c) 2007-2009, Ralf Habacker, <ralf.habacker@freenet.de>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
|
||||
|
||||
if (WIN32)
|
||||
|
||||
if(WINCE)
|
||||
FIND_PACKAGE(WCECOMPAT REQUIRED)
|
||||
endif(WINCE)
|
||||
|
||||
if (NOT KDEWIN_LIBRARY)
|
||||
|
||||
|
||||
find_path(KDEWIN_INCLUDE_DIR kdewin_export.h
|
||||
${KDE4_INCLUDE_DIR}
|
||||
${CMAKE_INCLUDE_PATH}
|
||||
${CMAKE_INSTALL_PREFIX}/include
|
||||
)
|
||||
|
||||
# search for kdewin in the default install directory for applications (default of (n)make install)
|
||||
FILE(TO_CMAKE_PATH "${CMAKE_LIBRARY_PATH}" _cmakeLibraryPathCmakeStyle)
|
||||
|
||||
string(TOLOWER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE_TOLOWER)
|
||||
if (CMAKE_BUILD_TYPE_TOLOWER MATCHES debug)
|
||||
set (LIBRARY_NAME kdewind)
|
||||
else(CMAKE_BUILD_TYPE_TOLOWER MATCHES debug)
|
||||
set (LIBRARY_NAME kdewin)
|
||||
endif (CMAKE_BUILD_TYPE_TOLOWER MATCHES debug)
|
||||
|
||||
find_library(KDEWIN_LIBRARY
|
||||
NAMES ${LIBRARY_NAME}
|
||||
PATHS
|
||||
${KDE4_LIB_DIR}
|
||||
${_cmakeLibraryPathCmakeStyle}
|
||||
${CMAKE_INSTALL_PREFIX}/lib
|
||||
NO_SYSTEM_ENVIRONMENT_PATH
|
||||
)
|
||||
endif (NOT KDEWIN_LIBRARY)
|
||||
|
||||
if (KDEWIN_LIBRARY AND KDEWIN_INCLUDE_DIR)
|
||||
set(KDEWIN_FOUND TRUE)
|
||||
# add needed system libs
|
||||
if(NOT WINCE)
|
||||
set(KDEWIN_LIBRARIES ${KDEWIN_LIBRARY} user32 shell32 ws2_32 netapi32 userenv)
|
||||
else(NOT WINCE)
|
||||
set(KDEWIN_LIBRARIES ${KDEWIN_LIBRARY} ws2 ${WCECOMPAT_LIBRARIES})
|
||||
endif(NOT WINCE)
|
||||
|
||||
if (MINGW)
|
||||
#mingw compiler
|
||||
set(KDEWIN_INCLUDES ${KDEWIN_INCLUDE_DIR} ${KDEWIN_INCLUDE_DIR}/mingw ${QT_INCLUDES})
|
||||
else (MINGW)
|
||||
# msvc compiler
|
||||
# add the MS SDK include directory if available
|
||||
file(TO_CMAKE_PATH "$ENV{MSSDK}" MSSDK_DIR)
|
||||
if (WINCE)
|
||||
set(KDEWIN_INCLUDES ${KDEWIN_INCLUDE_DIR} ${KDEWIN_INCLUDE_DIR}/msvc ${WCECOMPAT_INCLUDE_DIR} ${QT_INCLUDES} ${MSSDK_DIR})
|
||||
else(WINCE)
|
||||
set(KDEWIN_INCLUDES ${KDEWIN_INCLUDE_DIR} ${KDEWIN_INCLUDE_DIR}/msvc ${QT_INCLUDES} ${MSSDK_DIR})
|
||||
endif(WINCE)
|
||||
endif (MINGW)
|
||||
|
||||
endif (KDEWIN_LIBRARY AND KDEWIN_INCLUDE_DIR)
|
||||
# required for configure
|
||||
set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES} ${KDEWIN_INCLUDES})
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} ${KDEWIN_LIBRARIES})
|
||||
|
||||
if (KDEWIN_FOUND)
|
||||
if (NOT KDEWin_FIND_QUIETLY)
|
||||
message(STATUS "Found KDEWin library: ${KDEWIN_LIBRARY}")
|
||||
endif (NOT KDEWin_FIND_QUIETLY)
|
||||
|
||||
else (KDEWIN_FOUND)
|
||||
if (KDEWin_FIND_REQUIRED)
|
||||
message(FATAL_ERROR "Could NOT find KDEWin library\nPlease install it first")
|
||||
endif (KDEWin_FIND_REQUIRED)
|
||||
endif (KDEWIN_FOUND)
|
||||
endif (WIN32)
|
|
@ -0,0 +1,118 @@
|
|||
# CMake module to search for LIBVLC (VLC library)
|
||||
#
|
||||
# Copyright (C) 2011-2018, Harald Sitter <sitter@kde.org>
|
||||
# Copyright (C) 2010, Rohit Yadav <rohityadav89@gmail.com>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
#
|
||||
# If it's found it sets LIBVLC_FOUND to TRUE
|
||||
# and following variables are set:
|
||||
# LIBVLC_INCLUDE_DIR
|
||||
# LIBVLC_LIBRARY
|
||||
# LIBVLC_VERSION
|
||||
|
||||
if(NOT LIBVLC_MIN_VERSION)
|
||||
set(LIBVLC_MIN_VERSION "0.0")
|
||||
endif(NOT LIBVLC_MIN_VERSION)
|
||||
|
||||
# find_path and find_library normally search standard locations
|
||||
# before the specified paths. To search non-standard paths first,
|
||||
# FIND_* is invoked first with specified paths and NO_DEFAULT_PATH
|
||||
# and then again with no specified paths to search the default
|
||||
# locations. When an earlier FIND_* succeeds, subsequent FIND_*s
|
||||
# searching for the same item do nothing.
|
||||
|
||||
if (NOT WIN32)
|
||||
find_package(PkgConfig)
|
||||
pkg_check_modules(PC_LIBVLC libvlc)
|
||||
set(LIBVLC_DEFINITIONS ${PC_LIBVLC_CFLAGS_OTHER})
|
||||
endif (NOT WIN32)
|
||||
|
||||
#Put here path to custom location
|
||||
#example: /home/user/vlc/include etc..
|
||||
find_path(LIBVLC_INCLUDE_DIR vlc/vlc.h
|
||||
HINTS "$ENV{LIBVLC_INCLUDE_PATH}" ${PC_LIBVLC_INCLUDEDIR} ${PC_LIBVLC_INCLUDE_DIRS}
|
||||
PATHS
|
||||
"$ENV{LIB_DIR}/include"
|
||||
"$ENV{LIB_DIR}/include/vlc"
|
||||
"/usr/include"
|
||||
"/usr/include/vlc"
|
||||
"/usr/local/include"
|
||||
"/usr/local/include/vlc"
|
||||
#mingw
|
||||
c:/msys/local/include
|
||||
)
|
||||
find_path(LIBVLC_INCLUDE_DIR PATHS "${CMAKE_INCLUDE_PATH}/vlc" NAMES vlc.h
|
||||
HINTS ${PC_LIBVLC_INCLUDEDIR} ${PC_LIBVLC_INCLUDE_DIRS})
|
||||
|
||||
#Put here path to custom location
|
||||
#example: /home/user/vlc/lib etc..
|
||||
find_library(LIBVLC_LIBRARY NAMES vlc libvlc
|
||||
HINTS "$ENV{LIBVLC_LIBRARY_PATH}" ${PC_LIBVLC_LIBDIR} ${PC_LIBVLC_LIBRARY_DIRS}
|
||||
PATHS
|
||||
"$ENV{LIB_DIR}/lib"
|
||||
#mingw
|
||||
c:/msys/local/lib
|
||||
)
|
||||
find_library(LIBVLC_LIBRARY NAMES vlc libvlc)
|
||||
find_library(LIBVLCCORE_LIBRARY NAMES vlccore libvlccore
|
||||
HINTS "$ENV{LIBVLC_LIBRARY_PATH}" ${PC_LIBVLC_LIBDIR} ${PC_LIBVLC_LIBRARY_DIRS}
|
||||
PATHS
|
||||
"$ENV{LIB_DIR}/lib"
|
||||
#mingw
|
||||
c:/msys/local/lib
|
||||
)
|
||||
find_library(LIBVLCCORE_LIBRARY NAMES vlccore libvlccore)
|
||||
|
||||
set(LIBVLC_VERSION ${PC_LIBVLC_VERSION})
|
||||
if (NOT LIBVLC_VERSION)
|
||||
file(READ "${LIBVLC_INCLUDE_DIR}/vlc/libvlc_version.h" _libvlc_version_h)
|
||||
|
||||
string(REGEX MATCH "# define LIBVLC_VERSION_MAJOR +\\(([0-9])\\)" _dummy "${_libvlc_version_h}")
|
||||
set(_version_major "${CMAKE_MATCH_1}")
|
||||
|
||||
string(REGEX MATCH "# define LIBVLC_VERSION_MINOR +\\(([0-9])\\)" _dummy "${_libvlc_version_h}")
|
||||
set(_version_minor "${CMAKE_MATCH_1}")
|
||||
|
||||
string(REGEX MATCH "# define LIBVLC_VERSION_REVISION +\\(([0-9])\\)" _dummy "${_libvlc_version_h}")
|
||||
set(_version_revision "${CMAKE_MATCH_1}")
|
||||
|
||||
# Optionally, one could also parse LIBVLC_VERSION_EXTRA, but it does not
|
||||
# seem to be used by libvlc.pc.
|
||||
|
||||
set(LIBVLC_VERSION "${_version_major}.${_version_minor}.${_version_revision}")
|
||||
endif (NOT LIBVLC_VERSION)
|
||||
|
||||
if (LIBVLC_INCLUDE_DIR AND LIBVLC_LIBRARY AND LIBVLCCORE_LIBRARY)
|
||||
set(LIBVLC_FOUND TRUE)
|
||||
endif (LIBVLC_INCLUDE_DIR AND LIBVLC_LIBRARY AND LIBVLCCORE_LIBRARY)
|
||||
|
||||
if (LIBVLC_VERSION STRLESS "${LIBVLC_MIN_VERSION}")
|
||||
message(WARNING "LibVLC version not found: version searched: ${LIBVLC_MIN_VERSION}, found ${LIBVLC_VERSION}\nUnless you are on Windows this is bound to fail.")
|
||||
# TODO: only activate once version detection can be garunteed (which is currently not the case on windows)
|
||||
# set(LIBVLC_FOUND FALSE)
|
||||
endif (LIBVLC_VERSION STRLESS "${LIBVLC_MIN_VERSION}")
|
||||
|
||||
if (NOT LIBVLC_FIND_QUIETLY)
|
||||
message(STATUS "Found LibVLC include-dir path: ${LIBVLC_INCLUDE_DIR}")
|
||||
message(STATUS "Found LibVLC library path:${LIBVLC_LIBRARY}")
|
||||
message(STATUS "Found LibVLCcore library path:${LIBVLCCORE_LIBRARY}")
|
||||
message(STATUS "Found LibVLC version: ${LIBVLC_VERSION} (searched for: ${LIBVLC_MIN_VERSION})")
|
||||
endif (NOT LIBVLC_FIND_QUIETLY)
|
||||
|
||||
if(LIBVLC_FOUND AND NOT TARGET LibVLC::LibVLC)
|
||||
add_library(LibVLC::LibVLC UNKNOWN IMPORTED)
|
||||
set_target_properties(LibVLC::LibVLC PROPERTIES
|
||||
IMPORTED_LOCATION "${LIBVLC_LIBRARY}"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${LIBVLC_INCLUDE_DIR}"
|
||||
)
|
||||
endif()
|
||||
|
||||
if(LIBVLC_FOUND AND NOT TARGET LibVLC::Core)
|
||||
add_library(LibVLC::Core UNKNOWN IMPORTED)
|
||||
set_target_properties(LibVLC::Core PROPERTIES
|
||||
IMPORTED_LOCATION "${LIBVLCCORE_LIBRARY}"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${LIBVLC_INCLUDE_DIR}"
|
||||
)
|
||||
endif()
|
|
@ -0,0 +1,46 @@
|
|||
# Translation of phonon_vlc_qt.po to Catalan
|
||||
# Copyright (C) 2011-2019 This_file_is_part_of_KDE
|
||||
# This file is distributed under the license LGPL version 2.1 or
|
||||
# version 3 or later versions approved by the membership of KDE e.V.
|
||||
#
|
||||
# Josep Ma. Ferrer <txemaq@gmail.com>, 2011, 2012, 2019.
|
||||
# Antoni Bella Pérez <antonibella5@yahoo.com>, 2019.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: phonon-vlc\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2019-07-01 01:43+0200\n"
|
||||
"PO-Revision-Date: 2019-08-07 10:31+0200\n"
|
||||
"Last-Translator: Antoni Bella Pérez <antonibella5@yahoo.com>\n"
|
||||
"Language-Team: Catalan <kde-i18n-ca@kde.org>\n"
|
||||
"Language: ca\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: Lokalize 19.07.70\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Accelerator-Marker: &\n"
|
||||
"X-Qt-Contexts: true\n"
|
||||
|
||||
#: src/backend.cpp:132
|
||||
msgctxt "Phonon::VLC::Backend|"
|
||||
msgid "LibVLC Failed to Initialize"
|
||||
msgstr "Ha fallat en inicialitzar la «libVLC»"
|
||||
|
||||
#: src/backend.cpp:133
|
||||
msgctxt "Phonon::VLC::Backend|"
|
||||
msgid ""
|
||||
"Phonon's VLC backend failed to start.\n"
|
||||
"\n"
|
||||
"This usually means a problem with your VLC installation, please report a bug "
|
||||
"with your distributor."
|
||||
msgstr ""
|
||||
"Ha fallat en iniciar el dorsal VLC de Phonon.\n"
|
||||
"\n"
|
||||
"Això normalment vol dir que hi ha un problema amb la instal·lació del VLC. "
|
||||
"Si us plau, informeu de l'error al distribuïdor."
|
||||
|
||||
#: src/devicemanager.cpp:214
|
||||
msgctxt "Phonon::VLC::DeviceManager|"
|
||||
msgid "Default"
|
||||
msgstr "Predeterminat"
|
|
@ -0,0 +1,46 @@
|
|||
# Translation of phonon_vlc_qt.po to Catalan (Valencian)
|
||||
# Copyright (C) 2011-2019 This_file_is_part_of_KDE
|
||||
# This file is distributed under the license LGPL version 2.1 or
|
||||
# version 3 or later versions approved by the membership of KDE e.V.
|
||||
#
|
||||
# Josep Ma. Ferrer <txemaq@gmail.com>, 2011, 2012, 2019.
|
||||
# Antoni Bella Pérez <antonibella5@yahoo.com>, 2019.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: phonon-vlc\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2019-07-01 01:43+0200\n"
|
||||
"PO-Revision-Date: 2019-08-07 10:31+0200\n"
|
||||
"Last-Translator: Antoni Bella Pérez <antonibella5@yahoo.com>\n"
|
||||
"Language-Team: Catalan <kde-i18n-ca@kde.org>\n"
|
||||
"Language: ca@valencia\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: Lokalize 19.07.70\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Accelerator-Marker: &\n"
|
||||
"X-Qt-Contexts: true\n"
|
||||
|
||||
#: src/backend.cpp:132
|
||||
msgctxt "Phonon::VLC::Backend|"
|
||||
msgid "LibVLC Failed to Initialize"
|
||||
msgstr "Ha fallat en inicialitzar la «libVLC»"
|
||||
|
||||
#: src/backend.cpp:133
|
||||
msgctxt "Phonon::VLC::Backend|"
|
||||
msgid ""
|
||||
"Phonon's VLC backend failed to start.\n"
|
||||
"\n"
|
||||
"This usually means a problem with your VLC installation, please report a bug "
|
||||
"with your distributor."
|
||||
msgstr ""
|
||||
"Ha fallat en iniciar el dorsal VLC de Phonon.\n"
|
||||
"\n"
|
||||
"Això normalment vol dir que hi ha un problema amb la instal·lació del VLC. "
|
||||
"Per favor, informeu de l'error al distribuïdor."
|
||||
|
||||
#: src/devicemanager.cpp:214
|
||||
msgctxt "Phonon::VLC::DeviceManager|"
|
||||
msgid "Default"
|
||||
msgstr "Predeterminat"
|
|
@ -0,0 +1,44 @@
|
|||
# Copyright (C) YEAR This_file_is_part_of_KDE
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# Vít Pelčák <vit@pelcak.org>, 2011, 2012, 2019.
|
||||
# Lukáš Tinkl <lukas@kde.org>, 2012.
|
||||
# Tomáš Chvátal <tomas.chvatal@gmail.com>, 2013.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2019-07-01 01:50+0200\n"
|
||||
"PO-Revision-Date: 2019-07-18 15:19+0200\n"
|
||||
"Last-Translator: Vit Pelcak <vit@pelcak.org>\n"
|
||||
"Language-Team: Czech <kde-i18n-doc@kde.org>\n"
|
||||
"Language: cs\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: Lokalize 19.04.2\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
|
||||
"X-Qt-Contexts: true\n"
|
||||
|
||||
#: src/backend.cpp:132
|
||||
msgctxt "Phonon::VLC::Backend|"
|
||||
msgid "LibVLC Failed to Initialize"
|
||||
msgstr "Inicializace libVLC selhala"
|
||||
|
||||
#: src/backend.cpp:133
|
||||
msgctxt "Phonon::VLC::Backend|"
|
||||
msgid ""
|
||||
"Phonon's VLC backend failed to start.\n"
|
||||
"\n"
|
||||
"This usually means a problem with your VLC installation, please report a bug "
|
||||
"with your distributor."
|
||||
msgstr ""
|
||||
"Podpůrná vrstva Phononu VLC nemohla být spuštěna.\n"
|
||||
"\n"
|
||||
"To obvykle znamená problém s instalací VLC. Prosím, nahlaste chybu tvůrci "
|
||||
"vaší distribuce."
|
||||
|
||||
#: src/devicemanager.cpp:214
|
||||
msgctxt "Phonon::VLC::DeviceManager|"
|
||||
msgid "Default"
|
||||
msgstr "Výchozí"
|
|
@ -0,0 +1,37 @@
|
|||
# Martin Schlander <mschlander@opensuse.org>, 2020.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"PO-Revision-Date: 2020-04-08 21:14+0200\n"
|
||||
"Last-Translator: Martin Schlander <mschlander@opensuse.org>\n"
|
||||
"Language-Team: Danish <kde-i18n-doc@kde.org>\n"
|
||||
"Language: da\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Qt-Contexts: true\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Lokalize 18.12.3\n"
|
||||
|
||||
#: src/backend.cpp:132
|
||||
msgctxt "Phonon::VLC::Backend|"
|
||||
msgid "LibVLC Failed to Initialize"
|
||||
msgstr "LibVLC kunne ikke initialisere"
|
||||
|
||||
#: src/backend.cpp:133
|
||||
msgctxt "Phonon::VLC::Backend|"
|
||||
msgid ""
|
||||
"Phonon's VLC backend failed to start.\n"
|
||||
"\n"
|
||||
"This usually means a problem with your VLC installation, please report a bug "
|
||||
"with your distributor."
|
||||
msgstr ""
|
||||
"Phonons VLC-motor kunne ikke starte.\n"
|
||||
"\n"
|
||||
"Dette skyldes normalt et problem med din VLC-installation. Rapportér "
|
||||
"venligst fejlen til din distributør."
|
||||
|
||||
#: src/devicemanager.cpp:214
|
||||
msgctxt "Phonon::VLC::DeviceManager|"
|
||||
msgid "Default"
|
||||
msgstr "Standard"
|
|
@ -0,0 +1,42 @@
|
|||
# Copyright (C) YEAR This_file_is_part_of_KDE
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Burkhard Lück <lueck@hube-lueck.de>, 2018, 2019.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2019-07-01 01:50+0200\n"
|
||||
"PO-Revision-Date: 2019-07-05 15:28+0200\n"
|
||||
"Last-Translator: Burkhard Lück <lueck@hube-lueck.de>\n"
|
||||
"Language-Team: German <kde-i18n-de@kde.org>\n"
|
||||
"Language: de\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Lokalize 18.12.3\n"
|
||||
"X-Qt-Contexts: true\n"
|
||||
|
||||
#: src/backend.cpp:132
|
||||
msgctxt "Phonon::VLC::Backend|"
|
||||
msgid "LibVLC Failed to Initialize"
|
||||
msgstr "LibVLC kann nicht initialisiert werden"
|
||||
|
||||
#: src/backend.cpp:133
|
||||
msgctxt "Phonon::VLC::Backend|"
|
||||
msgid ""
|
||||
"Phonon's VLC backend failed to start.\n"
|
||||
"\n"
|
||||
"This usually means a problem with your VLC installation, please report a bug "
|
||||
"with your distributor."
|
||||
msgstr ""
|
||||
"Das VLC-Backend von Phonon kann nicht gestartet werden.\n"
|
||||
"\n"
|
||||
"Das weist meisten auf ein Problem mit Ihrer VLC-Installation hin. Berichten "
|
||||
"Sie diesen Fehler bitte bei Ihrem Distributor."
|
||||
|
||||
#: src/devicemanager.cpp:214
|
||||
msgctxt "Phonon::VLC::DeviceManager|"
|
||||
msgid "Default"
|
||||
msgstr "Standard"
|
|
@ -0,0 +1,42 @@
|
|||
# Copyright (C) YEAR This_file_is_part_of_KDE
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Steve Allewell <steve.allewell@gmail.com>, 2017, 2019.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2019-07-01 01:50+0200\n"
|
||||
"PO-Revision-Date: 2019-08-03 17:00+0100\n"
|
||||
"Last-Translator: Steve Allewell <steve.allewell@gmail.com>\n"
|
||||
"Language-Team: British English <kde-l10n-en_gb@kde.org>\n"
|
||||
"Language: en_GB\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Lokalize 19.07.70\n"
|
||||
"X-Qt-Contexts: true\n"
|
||||
|
||||
#: src/backend.cpp:132
|
||||
msgctxt "Phonon::VLC::Backend|"
|
||||
msgid "LibVLC Failed to Initialize"
|
||||
msgstr "LibVLC Failed to Initialise"
|
||||
|
||||
#: src/backend.cpp:133
|
||||
msgctxt "Phonon::VLC::Backend|"
|
||||
msgid ""
|
||||
"Phonon's VLC backend failed to start.\n"
|
||||
"\n"
|
||||
"This usually means a problem with your VLC installation, please report a bug "
|
||||
"with your distributor."
|
||||
msgstr ""
|
||||
"Phonon's VLC backend failed to start.\n"
|
||||
"\n"
|
||||
"This usually means a problem with your VLC installation, please report a bug "
|
||||
"with your distributor."
|
||||
|
||||
#: src/devicemanager.cpp:214
|
||||
msgctxt "Phonon::VLC::DeviceManager|"
|
||||
msgid "Default"
|
||||
msgstr "Default"
|
|
@ -0,0 +1,44 @@
|
|||
# Spanish translations for phonon_vlc.po package.
|
||||
# Copyright (C) 2017 This_file_is_part_of_KDE
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Automatically generated, 2017.
|
||||
# Eloy Cuadra <ecuadra@eloihr.net>, 2017, 2019.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: phonon_vlc\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2019-07-01 01:50+0200\n"
|
||||
"PO-Revision-Date: 2019-07-09 19:06+0200\n"
|
||||
"Last-Translator: Eloy Cuadra <ecuadra@eloihr.net>\n"
|
||||
"Language-Team: Spanish <kde-l10n-es@kde.org>\n"
|
||||
"Language: es\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Lokalize 19.04.2\n"
|
||||
"X-Qt-Contexts: true\n"
|
||||
|
||||
#: src/backend.cpp:132
|
||||
msgctxt "Phonon::VLC::Backend|"
|
||||
msgid "LibVLC Failed to Initialize"
|
||||
msgstr "Ha fallado la inicialización de LibVLC"
|
||||
|
||||
#: src/backend.cpp:133
|
||||
msgctxt "Phonon::VLC::Backend|"
|
||||
msgid ""
|
||||
"Phonon's VLC backend failed to start.\n"
|
||||
"\n"
|
||||
"This usually means a problem with your VLC installation, please report a bug "
|
||||
"with your distributor."
|
||||
msgstr ""
|
||||
"Ha fallado el inicio del motor VLC de Phonon.\n"
|
||||
"\n"
|
||||
"Esto suele significar que hay un problema en su instalación de VLC. Por "
|
||||
"favor, informe del error a su distribuidor."
|
||||
|
||||
#: src/devicemanager.cpp:214
|
||||
msgctxt "Phonon::VLC::DeviceManager|"
|
||||
msgid "Default"
|
||||
msgstr "Por omisión"
|
|
@ -0,0 +1,42 @@
|
|||
# Copyright (C) YEAR This_file_is_part_of_KDE
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Marek Laane <bald@smail.ee>, 2011, 2012, 2019.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2019-07-01 01:43+0200\n"
|
||||
"PO-Revision-Date: 2019-11-08 00:18+0200\n"
|
||||
"Last-Translator: Marek Laane <qiilaq69@gmail.com>\n"
|
||||
"Language-Team: Estonian <kde-et@lists.linux.ee>\n"
|
||||
"Language: et\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: Lokalize 19.08.1\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Qt-Contexts: true\n"
|
||||
|
||||
#: src/backend.cpp:132
|
||||
msgctxt "Phonon::VLC::Backend|"
|
||||
msgid "LibVLC Failed to Initialize"
|
||||
msgstr "LibVLC initsialiseerimine nurjus"
|
||||
|
||||
#: src/backend.cpp:133
|
||||
msgctxt "Phonon::VLC::Backend|"
|
||||
msgid ""
|
||||
"Phonon's VLC backend failed to start.\n"
|
||||
"\n"
|
||||
"This usually means a problem with your VLC installation, please report a bug "
|
||||
"with your distributor."
|
||||
msgstr ""
|
||||
"Phononi VLC taustaprogrammi käivitamine nurjus.\n"
|
||||
"\n"
|
||||
"Tavaliselt tähendab see probleemi sinu VLC paigaldusega, palun anna veast "
|
||||
"teada oma distributsiooni pakkujale."
|
||||
|
||||
#: src/devicemanager.cpp:214
|
||||
msgctxt "Phonon::VLC::DeviceManager|"
|
||||
msgid "Default"
|
||||
msgstr "Vaikimisi"
|
|
@ -0,0 +1,41 @@
|
|||
# Translation of phonon_vlc_qt.po to Euskara/Basque (eu).
|
||||
# KDE euskaratzeko proiektuaren arduraduna <xalba@euskalnet.net>.
|
||||
#
|
||||
# Translators:
|
||||
# Iñigo Salvador Azurmendi <xalba@euskalnet.net>, 2019.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"PO-Revision-Date: 2019-07-07 22:18+0200\n"
|
||||
"Last-Translator: Iñigo Salvador Azurmendi <xalba@euskalnet.net>\n"
|
||||
"Language-Team: Basque <kde-i18n-eu@kde.org>\n"
|
||||
"Language: eu\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Qt-Contexts: true\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Generator: Lokalize 19.04.2\n"
|
||||
|
||||
#: src/backend.cpp:132
|
||||
msgctxt "Phonon::VLC::Backend|"
|
||||
msgid "LibVLC Failed to Initialize"
|
||||
msgstr "LibVLC hasieratzea huts egin du"
|
||||
|
||||
#: src/backend.cpp:133
|
||||
msgctxt "Phonon::VLC::Backend|"
|
||||
msgid ""
|
||||
"Phonon's VLC backend failed to start.\n"
|
||||
"\n"
|
||||
"This usually means a problem with your VLC installation, please report a bug "
|
||||
"with your distributor."
|
||||
msgstr ""
|
||||
"Phonon-en VLC bizkarraldekoa abiatzea huts egin du.\n"
|
||||
"\n"
|
||||
"Honek adierazi ohi du zure instalaziorekin arazo bat dagoela, bidali akats "
|
||||
"txosten bat zure banatzaileari."
|
||||
|
||||
#: src/devicemanager.cpp:214
|
||||
msgctxt "Phonon::VLC::DeviceManager|"
|
||||
msgid "Default"
|
||||
msgstr "Lehenetsia"
|
|
@ -0,0 +1,47 @@
|
|||
# Copyright (C) YEAR This_file_is_part_of_KDE
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# Lasse Liehu <lasse.liehu@gmail.com>, 2011, 2013.
|
||||
# Tommi Nieminen <translator@legisign.org>, 2019.
|
||||
#
|
||||
# KDE Finnish translation sprint participants:
|
||||
# Author: Artnay
|
||||
# Author: Rytilahti
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: phonon_vlc\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2019-07-01 01:50+0200\n"
|
||||
"PO-Revision-Date: 2019-07-30 23:06+0200\n"
|
||||
"Last-Translator: Tommi Nieminen <translator@legisign.org>\n"
|
||||
"Language-Team: Finnish <kde-i18n-doc@kde.org>\n"
|
||||
"Language: fi\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-POT-Import-Date: 2012-12-01 22:27:40+0000\n"
|
||||
"X-Generator: Lokalize 2.0\n"
|
||||
"X-Qt-Contexts: true\n"
|
||||
|
||||
#: src/backend.cpp:132
|
||||
msgctxt "Phonon::VLC::Backend|"
|
||||
msgid "LibVLC Failed to Initialize"
|
||||
msgstr "LibVLC:n alustus epäonnistui"
|
||||
|
||||
#: src/backend.cpp:133
|
||||
msgctxt "Phonon::VLC::Backend|"
|
||||
msgid ""
|
||||
"Phonon's VLC backend failed to start.\n"
|
||||
"\n"
|
||||
"This usually means a problem with your VLC installation, please report a bug "
|
||||
"with your distributor."
|
||||
msgstr ""
|
||||
"Phononin VLC-taustajärjestelmän käynnistys epäonnistui.\n"
|
||||
"\n"
|
||||
"Tämä tarkoittaa yleensä, että VLC-asennus on virheellinen. Ilmoita viasta "
|
||||
"jakelullesi."
|
||||
|
||||
#: src/devicemanager.cpp:214
|
||||
msgctxt "Phonon::VLC::DeviceManager|"
|
||||
msgid "Default"
|
||||
msgstr "Oletus"
|
|
@ -0,0 +1,48 @@
|
|||
# Copyright (C) YEAR This_file_is_part_of_KDE
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# Geoffray Levasseur <geoffray.levasseurbrandin@numericable.fr>, 2011, 2012, 2013.
|
||||
# xavier <ktranslator31@yahoo.fr>, 2013.
|
||||
# Simon Depiets <sdepiets@gmail.com>, 2019.
|
||||
# Xavier Besnard <xavier.besnard@neuf.fr>, 2021.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2019-07-01 01:50+0200\n"
|
||||
"PO-Revision-Date: 2021-01-13 17:49+0100\n"
|
||||
"Last-Translator: Xavier Besnard <xavier.besnard@neuf.fr>\n"
|
||||
"Language-Team: French <kde-francophone@kde.org>\n"
|
||||
"Language: fr\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
"X-Generator: Lokalize 20.12.0\n"
|
||||
"X-Environment: kde\n"
|
||||
"X-Accelerator-Marker: &\n"
|
||||
"X-Text-Markup: qtrich\n"
|
||||
"X-Qt-Contexts: true\n"
|
||||
|
||||
#: src/backend.cpp:132
|
||||
msgctxt "Phonon::VLC::Backend|"
|
||||
msgid "LibVLC Failed to Initialize"
|
||||
msgstr "L'initialisation de « LibVLC » a échoué."
|
||||
|
||||
#: src/backend.cpp:133
|
||||
msgctxt "Phonon::VLC::Backend|"
|
||||
msgid ""
|
||||
"Phonon's VLC backend failed to start.\n"
|
||||
"\n"
|
||||
"This usually means a problem with your VLC installation, please report a bug "
|
||||
"with your distributor."
|
||||
msgstr ""
|
||||
"Le démarrage du moteur « VLC » de Phonon a échoué.\n"
|
||||
"\n"
|
||||
"Ceci signifie généralement qu'il y a un problème avec votre installation de "
|
||||
"VLC. Veuillez donc rapporter un bogue à votre distributeur."
|
||||
|
||||
#: src/devicemanager.cpp:214
|
||||
msgctxt "Phonon::VLC::DeviceManager|"
|
||||
msgid "Default"
|
||||
msgstr "Par défaut"
|
|
@ -0,0 +1,42 @@
|
|||
# Copyright (C) YEAR This_file_is_part_of_KDE
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# Marce Villarino <mvillarino@kde-espana.es>, 2011, 2012, 2014.
|
||||
# Adrián Chaves (Gallaecio) <adrian@chaves.io>, 2017, 2019.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2019-07-01 01:50+0200\n"
|
||||
"PO-Revision-Date: 2019-07-06 20:23+0200\n"
|
||||
"Last-Translator: Adrián Chaves (Gallaecio) <adrian@chaves.io>\n"
|
||||
"Language-Team: Galician <kde-i18n-doc@kde.org>\n"
|
||||
"Language: gl\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Qt-Contexts: true\n"
|
||||
|
||||
#: src/backend.cpp:132
|
||||
msgctxt "Phonon::VLC::Backend|"
|
||||
msgid "LibVLC Failed to Initialize"
|
||||
msgstr "Non se puido inicializar LibVLC"
|
||||
|
||||
#: src/backend.cpp:133
|
||||
msgctxt "Phonon::VLC::Backend|"
|
||||
msgid ""
|
||||
"Phonon's VLC backend failed to start.\n"
|
||||
"\n"
|
||||
"This usually means a problem with your VLC installation, please report a bug "
|
||||
"with your distributor."
|
||||
msgstr ""
|
||||
"Non se puido iniciar a infraestrutura de VLC para Phonon.\n"
|
||||
"\n"
|
||||
"Xeralmente isto indica que hai algún problema coa instalación do VLC. Envíe "
|
||||
"un informe do fallo ao distribuidor."
|
||||
|
||||
#: src/devicemanager.cpp:214
|
||||
msgctxt "Phonon::VLC::DeviceManager|"
|
||||
msgid "Default"
|
||||
msgstr "Predeterminado"
|
|
@ -0,0 +1,37 @@
|
|||
# Kristóf Kiszel <kiszel.kristof@gmail.com>, 2021.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"PO-Revision-Date: 2021-01-02 10:00+0100\n"
|
||||
"Last-Translator: Kristóf Kiszel <kiszel.kristof@gmail.com>\n"
|
||||
"Language-Team: Hungarian <kde-l10n-hu@kde.org>\n"
|
||||
"Language: hu\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Qt-Contexts: true\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Generator: Lokalize 21.03.70\n"
|
||||
|
||||
#: src/backend.cpp:132
|
||||
msgctxt "Phonon::VLC::Backend|"
|
||||
msgid "LibVLC Failed to Initialize"
|
||||
msgstr "A LibVLC inicializálása meghiúsult"
|
||||
|
||||
#: src/backend.cpp:133
|
||||
msgctxt "Phonon::VLC::Backend|"
|
||||
msgid ""
|
||||
"Phonon's VLC backend failed to start.\n"
|
||||
"\n"
|
||||
"This usually means a problem with your VLC installation, please report a bug "
|
||||
"with your distributor."
|
||||
msgstr ""
|
||||
"Nem sikerült elindítani a Phono VLC modulját.\n"
|
||||
"\n"
|
||||
"Ez általában azt jelenti, hogy hiba van a VLC telepítésével. Jelentse a "
|
||||
"hibát a disztribúció fejlesztőinek."
|
||||
|
||||
#: src/devicemanager.cpp:214
|
||||
msgctxt "Phonon::VLC::DeviceManager|"
|
||||
msgid "Default"
|
||||
msgstr "Alapértelmezett"
|
|
@ -0,0 +1,41 @@
|
|||
# Copyright (C) YEAR This_file_is_part_of_KDE
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# Wantoyo <wantoyek@gmail.com>, 2018, 2019.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2019-07-01 01:50+0200\n"
|
||||
"PO-Revision-Date: 2019-07-04 21:10+0700\n"
|
||||
"Last-Translator: Wantoyo <wantoyek@gmail.com>\n"
|
||||
"Language-Team: Indonesian <kde-i18n-doc@kde.org>\n"
|
||||
"Language: id\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Qt-Contexts: true\n"
|
||||
|
||||
#: src/backend.cpp:132
|
||||
msgctxt "Phonon::VLC::Backend|"
|
||||
msgid "LibVLC Failed to Initialize"
|
||||
msgstr "LibVLC Gagal Mengnisialisasi"
|
||||
|
||||
#: src/backend.cpp:133
|
||||
msgctxt "Phonon::VLC::Backend|"
|
||||
msgid ""
|
||||
"Phonon's VLC backend failed to start.\n"
|
||||
"\n"
|
||||
"This usually means a problem with your VLC installation, please report a bug "
|
||||
"with your distributor."
|
||||
msgstr ""
|
||||
"Backend phonon VLC gagal dimulaikan.\n"
|
||||
"\n"
|
||||
"Ini mungkin biasanya bermasalah dengan penginstalan VLC-mu, silakan laporkan "
|
||||
"bug kepada distributormu."
|
||||
|
||||
#: src/devicemanager.cpp:214
|
||||
msgctxt "Phonon::VLC::DeviceManager|"
|
||||
msgid "Default"
|
||||
msgstr "Baku"
|
|
@ -0,0 +1,41 @@
|
|||
# translation of phonon_vlc.po to Italian
|
||||
# Copyright (C) YEAR This_file_is_part_of_KDE
|
||||
# This file is distributed under the same license as the phonon_vlc package.
|
||||
# Luigi Toscano <luigi.toscano@tiscali.it>, 2011, 2012, 2019.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: phonon_vlc\n"
|
||||
"PO-Revision-Date: 2019-07-04 12:51+0200\n"
|
||||
"Last-Translator: Luigi Toscano <luigi.toscano@tiscali.it>\n"
|
||||
"Language-Team: Italian <kde-i18n-it@kde.org>\n"
|
||||
"Language: it\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Generator: Lokalize 18.12.2\n"
|
||||
"X-Qt-Contexts: true\n"
|
||||
|
||||
#: src/backend.cpp:132
|
||||
msgctxt "Phonon::VLC::Backend|"
|
||||
msgid "LibVLC Failed to Initialize"
|
||||
msgstr "Inizializzazione di LibVLC non riuscita"
|
||||
|
||||
#: src/backend.cpp:133
|
||||
msgctxt "Phonon::VLC::Backend|"
|
||||
msgid ""
|
||||
"Phonon's VLC backend failed to start.\n"
|
||||
"\n"
|
||||
"This usually means a problem with your VLC installation, please report a bug "
|
||||
"with your distributor."
|
||||
msgstr ""
|
||||
"Si è verificato un errore durante l'esecuzione del motore VLC di Phonon.\n"
|
||||
"\n"
|
||||
"Questo di solito indica un problema nell'installazione di VLC, segnala il "
|
||||
"bug presso il tuo distributore."
|
||||
|
||||
#: src/devicemanager.cpp:214
|
||||
msgctxt "Phonon::VLC::DeviceManager|"
|
||||
msgid "Default"
|
||||
msgstr "Predefinito"
|
|
@ -0,0 +1,41 @@
|
|||
# Copyright (C) YEAR This_file_is_part_of_KDE
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# Shinjo Park <kde@peremen.name>, 2011, 2013, 2019.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2019-07-01 01:50+0200\n"
|
||||
"PO-Revision-Date: 2019-07-18 23:25+0200\n"
|
||||
"Last-Translator: Shinjo Park <kde@peremen.name>\n"
|
||||
"Language-Team: Korean <kde-kr@kde.org>\n"
|
||||
"Language: ko\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
"X-Qt-Contexts: true\n"
|
||||
"X-Generator: Lokalize 18.12.3\n"
|
||||
|
||||
#: src/backend.cpp:132
|
||||
msgctxt "Phonon::VLC::Backend|"
|
||||
msgid "LibVLC Failed to Initialize"
|
||||
msgstr "LibVLC를 초기화할 수 없음"
|
||||
|
||||
#: src/backend.cpp:133
|
||||
msgctxt "Phonon::VLC::Backend|"
|
||||
msgid ""
|
||||
"Phonon's VLC backend failed to start.\n"
|
||||
"\n"
|
||||
"This usually means a problem with your VLC installation, please report a bug "
|
||||
"with your distributor."
|
||||
msgstr ""
|
||||
"Phonon VLC 백엔드를 시작할 수 없습니다.\n"
|
||||
"\n"
|
||||
"VLC 설치에 문제가 있는 것 같으므로 배포자에게 문의하십시오."
|
||||
|
||||
#: src/devicemanager.cpp:214
|
||||
msgctxt "Phonon::VLC::DeviceManager|"
|
||||
msgid "Default"
|
||||
msgstr "기본값"
|
|
@ -0,0 +1,42 @@
|
|||
# Copyright (C) YEAR This_file_is_part_of_KDE
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Freek de Kruijf <freekdekruijf@kde.nl>, 2011, 2012, 2019.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2019-07-01 01:50+0200\n"
|
||||
"PO-Revision-Date: 2019-07-04 21:28+0200\n"
|
||||
"Last-Translator: Freek de Kruijf <freekdekruijf@kde.nl>\n"
|
||||
"Language-Team: Dutch <kde-i18n-nl@kde.org>\n"
|
||||
"Language: nl\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: Lokalize 19.04.2\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Qt-Contexts: true\n"
|
||||
|
||||
#: src/backend.cpp:132
|
||||
msgctxt "Phonon::VLC::Backend|"
|
||||
msgid "LibVLC Failed to Initialize"
|
||||
msgstr "Initialisatie van LibVLC is mislukt"
|
||||
|
||||
#: src/backend.cpp:133
|
||||
msgctxt "Phonon::VLC::Backend|"
|
||||
msgid ""
|
||||
"Phonon's VLC backend failed to start.\n"
|
||||
"\n"
|
||||
"This usually means a problem with your VLC installation, please report a bug "
|
||||
"with your distributor."
|
||||
msgstr ""
|
||||
"Het opstarten van de VLC-backend van Phonon is mislukt.\n"
|
||||
"\n"
|
||||
"Dit betekent meestal een probleem met uw VLC-installatie, aub. een "
|
||||
"bugrapport indienen bij uw leverancier."
|
||||
|
||||
#: src/devicemanager.cpp:214
|
||||
msgctxt "Phonon::VLC::DeviceManager|"
|
||||
msgid "Default"
|
||||
msgstr "Standaard"
|
|
@ -0,0 +1,44 @@
|
|||
# Translation of phonon_vlc_qt to Norwegian Nynorsk
|
||||
#
|
||||
# Karl Ove Hufthammer <karl@huftis.org>, 2015, 2019.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2019-07-01 01:50+0200\n"
|
||||
"PO-Revision-Date: 2019-07-17 20:51+0200\n"
|
||||
"Last-Translator: Karl Ove Hufthammer <karl@huftis.org>\n"
|
||||
"Language-Team: Norwegian Nynorsk <l10n-no@lister.huftis.org>\n"
|
||||
"Language: nn\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Lokalize 19.04.2\n"
|
||||
"X-Environment: kde\n"
|
||||
"X-Accelerator-Marker: &\n"
|
||||
"X-Text-Markup: qtrich\n"
|
||||
"X-Qt-Contexts: true\n"
|
||||
|
||||
#: src/backend.cpp:132
|
||||
msgctxt "Phonon::VLC::Backend|"
|
||||
msgid "LibVLC Failed to Initialize"
|
||||
msgstr "Klarte ikkje starta LibVLC"
|
||||
|
||||
#: src/backend.cpp:133
|
||||
msgctxt "Phonon::VLC::Backend|"
|
||||
msgid ""
|
||||
"Phonon's VLC backend failed to start.\n"
|
||||
"\n"
|
||||
"This usually means a problem with your VLC installation, please report a bug "
|
||||
"with your distributor."
|
||||
msgstr ""
|
||||
"Klarte ikkje starta VLC-motoren til Phonon.\n"
|
||||
"\n"
|
||||
"Ein vanleg grunn er at VLC ikkje er rett installert. Meld eventuelt frå som "
|
||||
"ein feil i distroen din."
|
||||
|
||||
#: src/devicemanager.cpp:214
|
||||
msgctxt "Phonon::VLC::DeviceManager|"
|
||||
msgid "Default"
|
||||
msgstr "Standard"
|
|
@ -0,0 +1,38 @@
|
|||
# Łukasz Wojniłowicz <lukasz.wojnilowicz@gmail.com>, 2019.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"PO-Revision-Date: 2019-07-13 06:38+0200\n"
|
||||
"Last-Translator: Łukasz Wojniłowicz <lukasz.wojnilowicz@gmail.com>\n"
|
||||
"Language-Team: Polish <kde-i18n-doc@kde.org>\n"
|
||||
"Language: pl\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Qt-Contexts: true\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 "
|
||||
"|| n%100>=20) ? 1 : 2);\n"
|
||||
"X-Generator: Lokalize 19.07.70\n"
|
||||
|
||||
#: src/backend.cpp:132
|
||||
msgctxt "Phonon::VLC::Backend|"
|
||||
msgid "LibVLC Failed to Initialize"
|
||||
msgstr "Nie udało się zainicjować LibVLC"
|
||||
|
||||
#: src/backend.cpp:133
|
||||
msgctxt "Phonon::VLC::Backend|"
|
||||
msgid ""
|
||||
"Phonon's VLC backend failed to start.\n"
|
||||
"\n"
|
||||
"This usually means a problem with your VLC installation, please report a bug "
|
||||
"with your distributor."
|
||||
msgstr ""
|
||||
"Nie udało się uruchomić silnika VLC Phonona.\n"
|
||||
"\n"
|
||||
"Zazwyczaj oznacza to kłopot z wgranym VLC. Należy zgłosić to do dystrybutora "
|
||||
"tego pakietu."
|
||||
|
||||
#: src/devicemanager.cpp:214
|
||||
msgctxt "Phonon::VLC::DeviceManager|"
|
||||
msgid "Default"
|
||||
msgstr "Domyślne"
|
|
@ -0,0 +1,43 @@
|
|||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR This_file_is_part_of_KDE
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: phonon_vlc\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2019-07-01 01:43+0200\n"
|
||||
"PO-Revision-Date: 2019-07-04 11:08+0100\n"
|
||||
"Last-Translator: José Nuno Coelho Pires <zepires@gmail.com>\n"
|
||||
"Language-Team: Portuguese <kde-i18n-pt@kde.org>\n"
|
||||
"Language: pt\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-POFile-SpellExtra: LibVLC VLC\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Qt-Contexts: true\n"
|
||||
|
||||
#: src/backend.cpp:132
|
||||
msgctxt "Phonon::VLC::Backend|"
|
||||
msgid "LibVLC Failed to Initialize"
|
||||
msgstr "Não Foi Possível Inicializar a LibVLC"
|
||||
|
||||
#: src/backend.cpp:133
|
||||
msgctxt "Phonon::VLC::Backend|"
|
||||
msgid ""
|
||||
"Phonon's VLC backend failed to start.\n"
|
||||
"\n"
|
||||
"This usually means a problem with your VLC installation, please report a bug "
|
||||
"with your distributor."
|
||||
msgstr ""
|
||||
"Não foi possível iniciar a infra-estrutura de VLC para o Phonon.\n"
|
||||
"\n"
|
||||
"Isto normalmente significa que há um problema na sua instalação do VLC; "
|
||||
"comunique por favor um erro à sua distribuição."
|
||||
|
||||
#: src/devicemanager.cpp:214
|
||||
msgctxt "Phonon::VLC::DeviceManager|"
|
||||
msgid "Default"
|
||||
msgstr "Predefinição"
|
|
@ -0,0 +1,37 @@
|
|||
# Luiz Fernando Ranghetti <elchevive@opensuse.org>, 2019.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"PO-Revision-Date: 2019-07-04 12:19-0300\n"
|
||||
"Last-Translator: Luiz Fernando Ranghetti <elchevive@opensuse.org>\n"
|
||||
"Language-Team: Portuguese <kde-i18n-pt_BR@kde.org>\n"
|
||||
"Language: pt_BR\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Qt-Contexts: true\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
"X-Generator: Lokalize 19.04.2\n"
|
||||
|
||||
#: src/backend.cpp:132
|
||||
msgctxt "Phonon::VLC::Backend|"
|
||||
msgid "LibVLC Failed to Initialize"
|
||||
msgstr "Falha ao inicializar a LibVLC"
|
||||
|
||||
#: src/backend.cpp:133
|
||||
msgctxt "Phonon::VLC::Backend|"
|
||||
msgid ""
|
||||
"Phonon's VLC backend failed to start.\n"
|
||||
"\n"
|
||||
"This usually means a problem with your VLC installation, please report a bug "
|
||||
"with your distributor."
|
||||
msgstr ""
|
||||
"Não foi possível iniciar a infraestrutura VLC do Phonon.\n"
|
||||
"\n"
|
||||
"Isto normalmente significa que há um problema na sua instalação do VLC. "
|
||||
"Comunique este erro à sua distribuição."
|
||||
|
||||
#: src/devicemanager.cpp:214
|
||||
msgctxt "Phonon::VLC::DeviceManager|"
|
||||
msgid "Default"
|
||||
msgstr "Padrão"
|
|
@ -0,0 +1,42 @@
|
|||
# Copyright (C) YEAR This_file_is_part_of_KDE
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# Sergiu Bivol <sergiu@cip.md>, 2011, 2020.
|
||||
# Cristian Oneț <onet.cristian@gmail.com>, 2013.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"PO-Revision-Date: 2020-09-13 13:16+0100\n"
|
||||
"Last-Translator: Sergiu Bivol <sergiu@cip.md>\n"
|
||||
"Language-Team: Romanian\n"
|
||||
"Language: ro\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=3; plural=n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < "
|
||||
"20)) ? 1 : 2;\n"
|
||||
"X-Generator: Lokalize 19.12.3\n"
|
||||
"X-Qt-Contexts: true\n"
|
||||
|
||||
#: src/backend.cpp:132
|
||||
msgctxt "Phonon::VLC::Backend|"
|
||||
msgid "LibVLC Failed to Initialize"
|
||||
msgstr "Inițializarea LibVLC a eșuat"
|
||||
|
||||
#: src/backend.cpp:133
|
||||
msgctxt "Phonon::VLC::Backend|"
|
||||
msgid ""
|
||||
"Phonon's VLC backend failed to start.\n"
|
||||
"\n"
|
||||
"This usually means a problem with your VLC installation, please report a bug "
|
||||
"with your distributor."
|
||||
msgstr ""
|
||||
"Pornirea platformei VLC pentru Phonon a eșuat.\n"
|
||||
"\n"
|
||||
"De obicei, aceasta indică o problemă cu instalarea VLC. Raportați o eroare "
|
||||
"la distribuitorul dumneavoastră."
|
||||
|
||||
#: src/devicemanager.cpp:214
|
||||
msgctxt "Phonon::VLC::DeviceManager|"
|
||||
msgid "Default"
|
||||
msgstr "Implicit"
|
|
@ -0,0 +1,38 @@
|
|||
# Alexander Yavorsky <kekcuha@gmail.com>, 2020.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"PO-Revision-Date: 2020-05-05 18:06+0300\n"
|
||||
"Last-Translator: Alexander Yavorsky <kekcuha@gmail.com>\n"
|
||||
"Language-Team: Russian <kde-russian@lists.kde.ru>\n"
|
||||
"Language: ru\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Qt-Contexts: true\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
|
||||
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
|
||||
"X-Generator: Lokalize 20.04.0\n"
|
||||
|
||||
#: src/backend.cpp:132
|
||||
msgctxt "Phonon::VLC::Backend|"
|
||||
msgid "LibVLC Failed to Initialize"
|
||||
msgstr "Не удалось инициализировать LibVLC"
|
||||
|
||||
#: src/backend.cpp:133
|
||||
msgctxt "Phonon::VLC::Backend|"
|
||||
msgid ""
|
||||
"Phonon's VLC backend failed to start.\n"
|
||||
"\n"
|
||||
"This usually means a problem with your VLC installation, please report a bug "
|
||||
"with your distributor."
|
||||
msgstr ""
|
||||
"Не удалось запустить модуль поддержки VLC для Phonon.\n"
|
||||
"\n"
|
||||
"Обычно это связано с неправильной установкой VLC. Пожалуйста, сообщите об "
|
||||
"ошибке разработчикам вашего дистрибутива."
|
||||
|
||||
#: src/devicemanager.cpp:214
|
||||
msgctxt "Phonon::VLC::DeviceManager|"
|
||||
msgid "Default"
|
||||
msgstr "По умолчанию"
|
|
@ -0,0 +1,42 @@
|
|||
# translation of phonon_vlc.po to Slovak
|
||||
# Roman Paholik <wizzardsk@gmail.com>, 2012.
|
||||
# Roman Paholík <wizzardsk@gmail.com>, 2012.
|
||||
# Matej Mrenica <matejm98mthw@gmail.com>, 2019.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: phonon_vlc\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2019-07-01 01:50+0200\n"
|
||||
"PO-Revision-Date: 2019-08-08 12:07+0200\n"
|
||||
"Last-Translator: Matej Mrenica <matejm98mthw@gmail.com>\n"
|
||||
"Language-Team: Slovak <kde-i18n-doc@kde.org>\n"
|
||||
"Language: sk\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: Lokalize 19.07.90\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
|
||||
"X-Qt-Contexts: true\n"
|
||||
|
||||
#: src/backend.cpp:132
|
||||
msgctxt "Phonon::VLC::Backend|"
|
||||
msgid "LibVLC Failed to Initialize"
|
||||
msgstr "Zlyhala inicializácia LibVLC"
|
||||
|
||||
#: src/backend.cpp:133
|
||||
msgctxt "Phonon::VLC::Backend|"
|
||||
msgid ""
|
||||
"Phonon's VLC backend failed to start.\n"
|
||||
"\n"
|
||||
"This usually means a problem with your VLC installation, please report a bug "
|
||||
"with your distributor."
|
||||
msgstr ""
|
||||
"Zlyhalo spustenie Phonon VLC backendu.\n"
|
||||
"\n"
|
||||
"Toto obyčajne znamená problém s vašou inštaláciou VLC, prosím zadajte chybu "
|
||||
"s vašim poskytovateľom."
|
||||
|
||||
#: src/devicemanager.cpp:214
|
||||
msgctxt "Phonon::VLC::DeviceManager|"
|
||||
msgid "Default"
|
||||
msgstr "Predvolené"
|
|
@ -0,0 +1,48 @@
|
|||
# Slovenian translation of phonon_vlc.
|
||||
# Copyright (C) 2011 Free Software Foundation, Inc.
|
||||
#
|
||||
#
|
||||
# Klemen Košir <klemen.kosir@gmx.com>, 2011.
|
||||
# Andrej Vernekar <andrej.vernekar@gmail.com>, 2012.
|
||||
# Andrej Mernik <andrejm@ubuntu.si>, 2013.
|
||||
# Matjaž Jeran <matjaz.jeran@amis.net>, 2019.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: phonon_vlc\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: \n"
|
||||
"PO-Revision-Date: 2021-03-19 15:54+0100\n"
|
||||
"Last-Translator: Matjaž Jeran <matjaz.jeran@amis.net>\n"
|
||||
"Language-Team: Slovenian <lugos-slo@lugos.si>\n"
|
||||
"Language: sl\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Translator: Andrej Mernik <andrejm@ubuntu.si>\n"
|
||||
"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100>=3 && n"
|
||||
"%100<=4 ? 2 : 3);\n"
|
||||
"X-Generator: Poedit 2.4.2\n"
|
||||
"X-Qt-Contexts: true\n"
|
||||
|
||||
#: src/backend.cpp:132
|
||||
msgctxt "Phonon::VLC::Backend|"
|
||||
msgid "LibVLC Failed to Initialize"
|
||||
msgstr "Začetnih vrednosti knjižnice libVLC ni bilo mogoče nastaviti"
|
||||
|
||||
#: src/backend.cpp:133
|
||||
msgctxt "Phonon::VLC::Backend|"
|
||||
msgid ""
|
||||
"Phonon's VLC backend failed to start.\n"
|
||||
"\n"
|
||||
"This usually means a problem with your VLC installation, please report a bug "
|
||||
"with your distributor."
|
||||
msgstr ""
|
||||
"Zaledja VLC za Phonon ni bilo mogoče zagnati.\n"
|
||||
"\n"
|
||||
"Razlog za to napako je ponavadi težava z namestitvijo programa VLC. Prosimo "
|
||||
"sporočite napako vašemu distributerju."
|
||||
|
||||
#: src/devicemanager.cpp:214
|
||||
msgctxt "Phonon::VLC::DeviceManager|"
|
||||
msgid "Default"
|
||||
msgstr "Privzeto"
|
|
@ -0,0 +1,42 @@
|
|||
# Copyright (C) YEAR This_file_is_part_of_KDE
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Stefan Asserhäll <stefan.asserhall@bredband.net>, 2017, 2019.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2019-07-01 01:50+0200\n"
|
||||
"PO-Revision-Date: 2019-07-04 17:31+0100\n"
|
||||
"Last-Translator: Stefan Asserhäll <stefan.asserhall@bredband.net>\n"
|
||||
"Language-Team: Swedish <kde-i18n-doc@kde.org>\n"
|
||||
"Language: sv\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Lokalize 2.0\n"
|
||||
"X-Qt-Contexts: true\n"
|
||||
|
||||
#: src/backend.cpp:132
|
||||
msgctxt "Phonon::VLC::Backend|"
|
||||
msgid "LibVLC Failed to Initialize"
|
||||
msgstr "Initiering av libVLC misslyckades"
|
||||
|
||||
#: src/backend.cpp:133
|
||||
msgctxt "Phonon::VLC::Backend|"
|
||||
msgid ""
|
||||
"Phonon's VLC backend failed to start.\n"
|
||||
"\n"
|
||||
"This usually means a problem with your VLC installation, please report a bug "
|
||||
"with your distributor."
|
||||
msgstr ""
|
||||
"Phonons VLC-gränssnitt misslyckades starta.\n"
|
||||
"\n"
|
||||
"Det betyder oftast ett problem med installationen av VLC. Rapportera gärna "
|
||||
"felet till din distributör."
|
||||
|
||||
#: src/devicemanager.cpp:214
|
||||
msgctxt "Phonon::VLC::DeviceManager|"
|
||||
msgid "Default"
|
||||
msgstr "Förval"
|
|
@ -0,0 +1,45 @@
|
|||
# Translation of phonon_vlc_qt.po to Ukrainian
|
||||
# Copyright (C) 2011-2019 This_file_is_part_of_KDE
|
||||
# This file is distributed under the license LGPL version 2.1 or
|
||||
# version 3 or later versions approved by the membership of KDE e.V.
|
||||
#
|
||||
# Yuri Chornoivan <yurchor@ukr.net>, 2011, 2012, 2013, 2019.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: phonon_vlc_qt\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
|
||||
"POT-Creation-Date: 2019-07-01 01:50+0200\n"
|
||||
"PO-Revision-Date: 2019-07-04 19:57+0300\n"
|
||||
"Last-Translator: Yuri Chornoivan <yurchor@ukr.net>\n"
|
||||
"Language-Team: Ukrainian <kde-i18n-uk@kde.org>\n"
|
||||
"Language: uk\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=4; plural=n==1 ? 3 : n%10==1 && n%100!=11 ? 0 : n"
|
||||
"%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
|
||||
"X-Generator: Lokalize 19.07.70\n"
|
||||
"X-Qt-Contexts: true\n"
|
||||
|
||||
#: src/backend.cpp:132
|
||||
msgctxt "Phonon::VLC::Backend|"
|
||||
msgid "LibVLC Failed to Initialize"
|
||||
msgstr "Не вдалося ініціалізувати LibVLC"
|
||||
|
||||
#: src/backend.cpp:133
|
||||
msgctxt "Phonon::VLC::Backend|"
|
||||
msgid ""
|
||||
"Phonon's VLC backend failed to start.\n"
|
||||
"\n"
|
||||
"This usually means a problem with your VLC installation, please report a bug "
|
||||
"with your distributor."
|
||||
msgstr ""
|
||||
"Не вдалося запустити модуль VLC Phonon.\n"
|
||||
"\n"
|
||||
"Зазвичай, такі проблеми пов’язано з працездатністю встановленого вами VLC, "
|
||||
"будь ласка, повідомте про цю ваду розробникам вашого дистрибутива."
|
||||
|
||||
#: src/devicemanager.cpp:214
|
||||
msgctxt "Phonon::VLC::DeviceManager|"
|
||||
msgid "Default"
|
||||
msgstr "Типовий"
|
|
@ -0,0 +1,38 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: kdeorg\n"
|
||||
"PO-Revision-Date: 2021-03-14 15:44\n"
|
||||
"Language-Team: Chinese Simplified\n"
|
||||
"Language: zh_CN\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Qt-Contexts: true\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
"X-Crowdin-Project: kdeorg\n"
|
||||
"X-Crowdin-Project-ID: 269464\n"
|
||||
"X-Crowdin-Language: zh-CN\n"
|
||||
"X-Crowdin-File: /kf5-stable/messages/phonon-vlc/phonon_vlc_qt.pot\n"
|
||||
"X-Crowdin-File-ID: 24358\n"
|
||||
|
||||
#: src/backend.cpp:132
|
||||
msgctxt "Phonon::VLC::Backend|"
|
||||
msgid "LibVLC Failed to Initialize"
|
||||
msgstr "LibVLC 初始化失败"
|
||||
|
||||
#: src/backend.cpp:133
|
||||
msgctxt "Phonon::VLC::Backend|"
|
||||
msgid ""
|
||||
"Phonon's VLC backend failed to start.\n"
|
||||
"\n"
|
||||
"This usually means a problem with your VLC installation, please report a bug "
|
||||
"with your distributor."
|
||||
msgstr ""
|
||||
"无法启动 Phonon 的 VLC 后端。\n"
|
||||
"\n"
|
||||
"这通常表示 VLC 安装有问题,请向软件包发行者报告问题。"
|
||||
|
||||
#: src/devicemanager.cpp:214
|
||||
msgctxt "Phonon::VLC::DeviceManager|"
|
||||
msgid "Default"
|
||||
msgstr "默认"
|
|
@ -0,0 +1,36 @@
|
|||
# pan93412 <pan93412@gmail.com>, 2019.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: pan 93412\n"
|
||||
"PO-Revision-Date: 2019-10-19 15:18+0800\n"
|
||||
"Last-Translator: pan93412 <pan93412@gmail.com>\n"
|
||||
"Language-Team: Chinese <zh-l10n@lists.linux.org.tw>\n"
|
||||
"Language: zh_TW\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Qt-Contexts: true\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
"X-Generator: Lokalize 19.08.2\n"
|
||||
|
||||
#: src/backend.cpp:132
|
||||
msgctxt "Phonon::VLC::Backend|"
|
||||
msgid "LibVLC Failed to Initialize"
|
||||
msgstr "LibVLC 初始化失敗"
|
||||
|
||||
#: src/backend.cpp:133
|
||||
msgctxt "Phonon::VLC::Backend|"
|
||||
msgid ""
|
||||
"Phonon's VLC backend failed to start.\n"
|
||||
"\n"
|
||||
"This usually means a problem with your VLC installation, please report a bug "
|
||||
"with your distributor."
|
||||
msgstr ""
|
||||
"Phonon 的 VLC 後端介面啟動失敗。\n"
|
||||
"\n"
|
||||
"通常這表示您的 VLC 安裝有問題。請向您的套件維護者回報。"
|
||||
|
||||
#: src/devicemanager.cpp:214
|
||||
msgctxt "Phonon::VLC::DeviceManager|"
|
||||
msgid "Default"
|
||||
msgstr "預設"
|
|
@ -0,0 +1,4 @@
|
|||
.svn
|
||||
Makefile
|
||||
moc_*
|
||||
phonon_vlc_*
|
|
@ -0,0 +1,95 @@
|
|||
if (MSVC OR (WIN32 AND "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel"))
|
||||
set (CMAKE_MODULE_PATH ${CMAKE_INSTALL_PREFIX}/share/apps/cmake/modules)
|
||||
find_package(KDEWin)
|
||||
if (KDEWIN_FOUND)
|
||||
include_directories(${KDEWIN_INCLUDES}/msvc)
|
||||
link_libraries(${KDEWIN_LIBRARIES})
|
||||
else (KDEWIN_FOUND)
|
||||
include(CheckIncludeFileCXX)
|
||||
check_include_file_cxx(inttypes.h HAVE_INTTYPES)
|
||||
check_include_file_cxx(stdint.h HAVE_STDINT)
|
||||
if ( NOT HAVE_STDINT AND NOT HAVE_INTTYPES )
|
||||
message (FATAL_ERROR "You don't have stdint.h and inttypes.h\n\t get them from http://code.google.com/p/baseutils/source/browse/#svn/trunk/msvc,\n\t or get kdewin http://websvn.kde.org/trunk/kdesupport/kdewin/")
|
||||
endif ( NOT HAVE_STDINT AND NOT HAVE_INTTYPES )
|
||||
endif (KDEWIN_FOUND)
|
||||
endif (MSVC OR (WIN32 AND "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel"))
|
||||
|
||||
# NB: This is evaluated in the build system because the phonon headers
|
||||
# change behavior based on the defines, meaning the defines must already be set
|
||||
# by the time the headers are pre-processed!
|
||||
if(${PHONON_VERSION} VERSION_GREATER "4.9.50")
|
||||
message(STATUS "Building against Phonon 4.10 API")
|
||||
set(BACKEND_VERSION_DEFINE -DPHONON_BACKEND_VERSION_4_10)
|
||||
# Older not supported because backend doesn't build with older cmake rigging anwyay.
|
||||
endif()
|
||||
add_definitions(${BACKEND_VERSION_DEFINE}) # also automatically used for moc
|
||||
|
||||
set(phonon_vlc_SRCS
|
||||
audio/audiooutput.cpp
|
||||
audio/audiodataoutput.cpp
|
||||
audio/volumefadereffect.cpp
|
||||
backend.cpp
|
||||
devicemanager.cpp
|
||||
effect.cpp
|
||||
effectmanager.cpp
|
||||
media.cpp
|
||||
mediacontroller.cpp
|
||||
mediaobject.cpp
|
||||
mediaplayer.cpp
|
||||
sinknode.cpp
|
||||
streamreader.cpp
|
||||
# video/videodataoutput.cpp
|
||||
video/videowidget.cpp
|
||||
video/videomemorystream.cpp
|
||||
utils/debug.cpp
|
||||
utils/libvlc.cpp
|
||||
)
|
||||
|
||||
if(NOT ${LIBVLC_VERSION} VERSION_LESS "2.2.0")
|
||||
list(APPEND phonon_vlc_SRCS equalizereffect.cpp)
|
||||
endif()
|
||||
|
||||
if(PHONON_EXPERIMENTAL)
|
||||
list(APPEND phonon_vlc_SRCS video/videodataoutput.cpp)
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
list(APPEND phonon_vlc_SRCS
|
||||
video/mac/nsvideoview.mm
|
||||
video/mac/vlcmacwidget.mm)
|
||||
endif()
|
||||
|
||||
ecm_create_qm_loader(phonon_vlc_SRCS phonon_vlc_qt)
|
||||
add_library(phonon_vlc MODULE ${phonon_vlc_SRCS})
|
||||
|
||||
target_include_directories(phonon_vlc
|
||||
PRIVATE
|
||||
# Extra include. We use some internal stuff for easy chroma conversion.
|
||||
${LIBVLC_INCLUDE_DIR}/vlc/plugins
|
||||
)
|
||||
|
||||
target_link_libraries(phonon_vlc
|
||||
Phonon::phonon4qt5
|
||||
Qt5::Core
|
||||
Qt5::Widgets
|
||||
LibVLC::Core
|
||||
LibVLC::LibVLC
|
||||
)
|
||||
if(PHONON_EXPERIMENTAL)
|
||||
target_link_libraries(phonon_vlc Phonon::phonon4qt5experimental)
|
||||
endif()
|
||||
|
||||
install(TARGETS phonon_vlc DESTINATION ${PHONON_BACKEND_DIR})
|
||||
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.cmake
|
||||
${CMAKE_CURRENT_BINARY_DIR}/config.h @ONLY)
|
||||
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/utils/mime.h.cmake
|
||||
${CMAKE_CURRENT_BINARY_DIR}/utils/mime.h @ONLY)
|
||||
|
||||
# Instead of desktop files we are embedding the information into the plugin itself.
|
||||
# We have no KDE technology to help with finding the actual libraries anyway, so
|
||||
# we need to have the library path anyway.
|
||||
# Also see qtplugin/Q_PLUGIN_METADATA documentation.
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/phonon-vlc.json.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/phonon-vlc.json @ONLY)
|
|
@ -0,0 +1,164 @@
|
|||
/*
|
||||
Copyright (C) 2006 Matthias Kretz <kretz@kde.org>
|
||||
Copyright (C) 2009 Martin Sandsmark <sandsmark@samfundet.no>
|
||||
Copyright (C) 2010 Ben Cooksley <sourtooth@gmail.com>
|
||||
Copyright (C) 2011 Harald Sitter <sitter@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) version 3, or any
|
||||
later version accepted by the membership of KDE e.V. (or its
|
||||
successor approved by the membership of KDE e.V.), Nokia Corporation
|
||||
(or its successors, if any) and the KDE Free Qt Foundation, which shall
|
||||
act as a proxy defined in Section 6 of version 3 of the license.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "audiodataoutput.h"
|
||||
|
||||
#include "media.h"
|
||||
|
||||
namespace Phonon {
|
||||
namespace VLC {
|
||||
|
||||
AudioDataOutput::AudioDataOutput(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
m_sampleRate = 44100;
|
||||
connect(this, SIGNAL(sampleReadDone()), this, SLOT(sendData()));
|
||||
|
||||
// Register channels
|
||||
m_channels.append(Phonon::AudioDataOutput::LeftChannel);
|
||||
m_channels.append(Phonon::AudioDataOutput::RightChannel);
|
||||
m_channels.append(Phonon::AudioDataOutput::CenterChannel);
|
||||
m_channels.append(Phonon::AudioDataOutput::LeftSurroundChannel);
|
||||
m_channels.append(Phonon::AudioDataOutput::RightSurroundChannel);
|
||||
m_channels.append(Phonon::AudioDataOutput::SubwooferChannel);
|
||||
}
|
||||
|
||||
AudioDataOutput::~AudioDataOutput()
|
||||
{
|
||||
}
|
||||
|
||||
int AudioDataOutput::dataSize() const
|
||||
{
|
||||
return m_dataSize;
|
||||
}
|
||||
|
||||
int AudioDataOutput::sampleRate() const
|
||||
{
|
||||
return m_sampleRate;
|
||||
}
|
||||
|
||||
void AudioDataOutput::setDataSize(int size)
|
||||
{
|
||||
m_dataSize = size;
|
||||
}
|
||||
|
||||
void AudioDataOutput::handleAddToMedia(Media *media)
|
||||
{
|
||||
media->addOption(QString(":sout=#duplicate{dst=display,dst='transcode{vcodec=none,acodec=s16l,samplerate=%1}"
|
||||
":smem{audio-prerender-callback=%2,"
|
||||
"audio-postrender-callback=%3,"
|
||||
"audio-data=%4,"
|
||||
"time-sync=true}'}"
|
||||
).arg(QString::number(m_sampleRate),
|
||||
QString::number((long long int) INTPTR_FUNC(AudioDataOutput::lock)),
|
||||
QString::number((long long int) INTPTR_FUNC(AudioDataOutput::unlock)),
|
||||
QString::number((long long int) INTPTR_PTR(this))));
|
||||
}
|
||||
|
||||
void AudioDataOutput::lock(AudioDataOutput *cw, quint8 **pcm_buffer , quint32 size)
|
||||
{
|
||||
cw->m_locker.lock();
|
||||
*pcm_buffer = new quint8[size];
|
||||
}
|
||||
|
||||
void AudioDataOutput::unlock(AudioDataOutput *cw, quint8 *pcm_buffer,
|
||||
quint32 channelCount, quint32 rate,
|
||||
quint32 sampleCount, quint32 bits_per_sample,
|
||||
quint32 size, qint64 pts)
|
||||
{
|
||||
Q_UNUSED(size);
|
||||
Q_UNUSED(pts);
|
||||
|
||||
// (bytesPerChannelPerSample * channels * read_samples) + (bytesPerChannelPerSample * read_channels)
|
||||
int bytesPerChannelPerSample = bits_per_sample / 8;
|
||||
cw->m_sampleRate = rate;
|
||||
cw->m_channelCount = channelCount;
|
||||
|
||||
for (quint32 readSamples = 0; readSamples < sampleCount; ++readSamples) {
|
||||
// Prepare a sample buffer, and initialise it
|
||||
quint16 sampleBuffer[6];
|
||||
for (int initialised = 0; initialised < 6; ++initialised) {
|
||||
sampleBuffer[initialised] = 0;
|
||||
}
|
||||
|
||||
int bufferPosition = (bytesPerChannelPerSample * channelCount * readSamples);
|
||||
|
||||
for (quint32 readChannels = 0; readChannels < channelCount; ++readChannels) {
|
||||
quint32 complet = 0;
|
||||
for (int readBytes = 0; readBytes < bytesPerChannelPerSample; ++readBytes) {
|
||||
// Read from the pcm_buffer into the per channel internal buffer
|
||||
|
||||
quint32 complet_temp = 0;
|
||||
complet_temp = pcm_buffer[bufferPosition];
|
||||
complet_temp <<= (8 * readBytes);
|
||||
|
||||
complet += complet_temp;
|
||||
++bufferPosition;
|
||||
}
|
||||
|
||||
sampleBuffer[readChannels] = complet;
|
||||
}
|
||||
|
||||
if (channelCount == 1) {
|
||||
cw->m_channelSamples[1].append(qint16(sampleBuffer[0]));
|
||||
}
|
||||
|
||||
for (quint32 readChannels = 0; readChannels < channelCount; ++readChannels) {
|
||||
cw->m_channelSamples[readChannels].append(qint16(sampleBuffer[readChannels]));
|
||||
}
|
||||
// Finished reading one sample
|
||||
}
|
||||
|
||||
delete pcm_buffer;
|
||||
|
||||
cw->m_locker.unlock();
|
||||
emit cw->sampleReadDone();
|
||||
}
|
||||
|
||||
void AudioDataOutput::sendData()
|
||||
{
|
||||
m_locker.lock();
|
||||
|
||||
int chan_count = m_channelCount;
|
||||
if (m_channelCount == 1) {
|
||||
chan_count = 2;
|
||||
}
|
||||
|
||||
while (m_channelSamples[0].count() > m_dataSize) {
|
||||
QMap<Phonon::AudioDataOutput::Channel, QVector<qint16> > m_data;
|
||||
for (int position = 0; position < chan_count; position++) {
|
||||
Phonon::AudioDataOutput::Channel chan = m_channels.value(position);
|
||||
QVector<qint16> data = m_channelSamples[position].mid(0, m_dataSize);
|
||||
m_channelSamples[position].remove(0, data.count());
|
||||
m_data.insert(chan, data);
|
||||
}
|
||||
emit dataReady(m_data);
|
||||
}
|
||||
m_locker.unlock();
|
||||
}
|
||||
|
||||
} // namespace VLC
|
||||
} // namespace Phonon
|
||||
|
||||
#include "moc_audiodataoutput.cpp"
|
|
@ -0,0 +1,162 @@
|
|||
/*
|
||||
Copyright (C) 2006 Matthias Kretz <kretz@kde.org>
|
||||
Copyright (C) 2009 Martin Sandsmark <sandsmark@samfundet.no>
|
||||
Copyright (C) 2010 Ben Cooksley <sourtooth@gmail.com>
|
||||
Copyright (C) 2011 Harald Sitter <sitter@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) version 3, or any
|
||||
later version accepted by the membership of KDE e.V. (or its
|
||||
successor approved by the membership of KDE e.V.), Nokia Corporation
|
||||
(or its successors, if any) and the KDE Free Qt Foundation, which shall
|
||||
act as a proxy defined in Section 6 of version 3 of the license.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef Phonon_VLC_AUDIODATAOUTPUT_H
|
||||
#define Phonon_VLC_AUDIODATAOUTPUT_H
|
||||
|
||||
#include <QtCore/QMutex>
|
||||
#include <QtCore/QObject>
|
||||
|
||||
#include <phonon/audiodataoutput.h>
|
||||
#include <phonon/audiodataoutputinterface.h>
|
||||
|
||||
#include "sinknode.h"
|
||||
|
||||
namespace Phonon {
|
||||
namespace VLC {
|
||||
|
||||
/** \brief Implementation for AudioDataOutput using libVLC
|
||||
*
|
||||
* This class makes the capture of raw audio data possible. It sets special options
|
||||
* for the libVLC Media Object when connecting to it, and then captures libVLC events
|
||||
* to get the audio data and send it further with the dataReady() signal.
|
||||
*
|
||||
* As a sink node, it can be connected to media objects.
|
||||
*
|
||||
* The frontend Phonon::AudioDataOutput object is unused.
|
||||
*
|
||||
* See the Phonon documentation for details.
|
||||
*
|
||||
* \see AudioOutput
|
||||
* \see SinkNode
|
||||
*
|
||||
* \author Martin Sandsmark <sandsmark@samfundet.no>
|
||||
*/
|
||||
class AudioDataOutput : public QObject, public SinkNode, public AudioDataOutputInterface
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(Phonon::AudioDataOutputInterface)
|
||||
public:
|
||||
/**
|
||||
* Creates an audio data output. The sample rate is set to 44100 Hz.
|
||||
* The available audio channels are registered. These are:
|
||||
* \li Left \li Right \li Center \li LeftSurround \li RightSurround \li Subwoofer
|
||||
*/
|
||||
explicit AudioDataOutput(QObject *parent);
|
||||
~AudioDataOutput();
|
||||
|
||||
Phonon::AudioDataOutput *frontendObject() const
|
||||
{
|
||||
return m_frontend;
|
||||
}
|
||||
|
||||
void setFrontendObject(Phonon::AudioDataOutput *frontend)
|
||||
{
|
||||
m_frontend = frontend;
|
||||
}
|
||||
|
||||
public Q_SLOTS:
|
||||
/**
|
||||
* \return The currently used number of samples passed through the signal.
|
||||
*/
|
||||
int dataSize() const;
|
||||
|
||||
/**
|
||||
* \return The current sample rate in Hz.
|
||||
*/
|
||||
int sampleRate() const;
|
||||
|
||||
/**
|
||||
* Sets the number of samples to be passed in one signal emission.
|
||||
*/
|
||||
void setDataSize(int size);
|
||||
|
||||
/**
|
||||
* Adds special options to the libVLC Media Object to adapt it to give audio data
|
||||
* directly. There are two callbacks used: lock(), unlock().
|
||||
*
|
||||
* \see lock()
|
||||
* \see unlock()
|
||||
* \reimp
|
||||
*/
|
||||
void handleAddToMedia(Media *media);
|
||||
|
||||
signals:
|
||||
void dataReady(const QMap<Phonon::AudioDataOutput::Channel, QVector<qint16> > &data);
|
||||
void dataReady(const QMap<Phonon::AudioDataOutput::Channel, QVector<float> > &data);
|
||||
void endOfMedia(int remainingSamples);
|
||||
void sampleReadDone();
|
||||
|
||||
private Q_SLOTS:
|
||||
/**
|
||||
* Looks at the channel samples generated in lock() and creates the QMap required for
|
||||
* the dataReady() signal. Then the signal is emitted. This repeats as long as there is
|
||||
* data remaining.
|
||||
*
|
||||
* \see lock()
|
||||
*/
|
||||
void sendData();
|
||||
|
||||
private:
|
||||
/**
|
||||
* This is a VLC prerender callback. The m_locker mutex is locked, and a new buffer is prepared
|
||||
* for the incoming audio data.
|
||||
*
|
||||
* \param cw The AudioDataOutput for this callback
|
||||
* \param pcm_buffer The new data buffer
|
||||
* \param size Size for the incoming data
|
||||
*
|
||||
* \see unlock()
|
||||
*/
|
||||
static void lock(AudioDataOutput *cw, quint8 **pcm_buffer , quint32 size);
|
||||
|
||||
/**
|
||||
* This is a VLC postrender callback. Interprets the data received in m_buffer,
|
||||
* separating the samples and channels. Finally, the buffer is freed and m_locker
|
||||
* is unlocked. Now the audio data output is ready for sending data.
|
||||
*
|
||||
* \param cw The AudioDataOutput for this callback
|
||||
*
|
||||
* \see lock()
|
||||
* \see sendData()
|
||||
*/
|
||||
static void unlock(AudioDataOutput *cw, quint8 *pcm_buffer,
|
||||
quint32 channelCount, quint32 rate,
|
||||
quint32 sampleCount, quint32 bits_per_sample,
|
||||
quint32 size, qint64 pts);
|
||||
|
||||
int m_dataSize;
|
||||
int m_sampleRate;
|
||||
Phonon::AudioDataOutput *m_frontend;
|
||||
|
||||
QMutex m_locker;
|
||||
int m_channelCount;
|
||||
QVector<qint16> m_channelSamples[6];
|
||||
QList<Phonon::AudioDataOutput::Channel> m_channels;
|
||||
};
|
||||
|
||||
} // namespace VLC
|
||||
} // namespace Phonon
|
||||
|
||||
#endif // Phonon_VLC_AUDIODATAOUTPUT_H
|
|
@ -0,0 +1,250 @@
|
|||
/*
|
||||
Copyright (C) 2007-2008 Tanguy Krotoff <tkrotoff@gmail.com>
|
||||
Copyright (C) 2008 Lukas Durfina <lukas.durfina@gmail.com>
|
||||
Copyright (C) 2009 Fathi Boudra <fabo@kde.org>
|
||||
Copyright (C) 2013-2018 Harald Sitter <sitter@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "audiooutput.h"
|
||||
|
||||
#include <phonon/pulsesupport.h>
|
||||
|
||||
#include <vlc/vlc.h>
|
||||
|
||||
#include "backend.h"
|
||||
#include "utils/debug.h"
|
||||
#include "devicemanager.h"
|
||||
#include "mediaobject.h"
|
||||
#include "media.h"
|
||||
|
||||
namespace Phonon {
|
||||
namespace VLC {
|
||||
|
||||
AudioOutput::AudioOutput(QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_volume(0.75)
|
||||
, m_explicitVolume(false)
|
||||
, m_muted(false)
|
||||
, m_category(Phonon::NoCategory)
|
||||
{
|
||||
}
|
||||
|
||||
AudioOutput::~AudioOutput()
|
||||
{
|
||||
}
|
||||
|
||||
#if (LIBVLC_VERSION_INT >= LIBVLC_VERSION(3, 0, 0, 0))
|
||||
static libvlc_media_player_role categoryToRole(Category category)
|
||||
{
|
||||
switch(category) {
|
||||
case NoCategory:
|
||||
return libvlc_role_None;
|
||||
case NotificationCategory:
|
||||
return libvlc_role_Notification;
|
||||
case MusicCategory:
|
||||
return libvlc_role_Music;
|
||||
case VideoCategory:
|
||||
return libvlc_role_Video;
|
||||
case CommunicationCategory:
|
||||
return libvlc_role_Communication;
|
||||
case GameCategory:
|
||||
return libvlc_role_Game;
|
||||
case AccessibilityCategory:
|
||||
return libvlc_role_Accessibility;
|
||||
}
|
||||
return libvlc_role_None;
|
||||
}
|
||||
#endif
|
||||
|
||||
void AudioOutput::handleConnectToMediaObject(MediaObject *mediaObject)
|
||||
{
|
||||
Q_UNUSED(mediaObject);
|
||||
setOutputDeviceImplementation();
|
||||
if (!PulseSupport::getInstance()->isActive()) {
|
||||
// Rely on libvlc for updates if PASupport is not active
|
||||
connect(m_player, SIGNAL(mutedChanged(bool)),
|
||||
this, SLOT(onMutedChanged(bool)));
|
||||
connect(m_player, SIGNAL(volumeChanged(float)),
|
||||
this, SLOT(onVolumeChanged(float)));
|
||||
applyVolume();
|
||||
}
|
||||
#if (LIBVLC_VERSION_INT >= LIBVLC_VERSION(3, 0, 0, 0))
|
||||
libvlc_media_player_set_role(*m_player, categoryToRole(m_category));
|
||||
#endif
|
||||
}
|
||||
|
||||
void AudioOutput::handleAddToMedia(Media *media)
|
||||
{
|
||||
media->addOption(":audio");
|
||||
PulseSupport *pulse = PulseSupport::getInstance();
|
||||
if (pulse && pulse->isActive()) {
|
||||
pulse->setupStreamEnvironment(m_streamUuid);
|
||||
}
|
||||
}
|
||||
|
||||
qreal AudioOutput::volume() const
|
||||
{
|
||||
return m_volume;
|
||||
}
|
||||
|
||||
void AudioOutput::setVolume(qreal volume)
|
||||
{
|
||||
if (m_player) {
|
||||
debug() << "async setting of volume to" << volume;
|
||||
m_volume = volume;
|
||||
m_explicitVolume = true;
|
||||
applyVolume();
|
||||
|
||||
#if (LIBVLC_VERSION_INT < LIBVLC_VERSION(2, 2, 2, 0))
|
||||
emit volumeChanged(m_volume);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void AudioOutput::setMuted(bool mute)
|
||||
{
|
||||
if (mute == m_player->mute()) {
|
||||
// Make sure we actually have propagated the mutness into the frontend.
|
||||
onMutedChanged(mute);
|
||||
return;
|
||||
}
|
||||
m_player->setMute(mute);
|
||||
}
|
||||
|
||||
void AudioOutput::setCategory(Category category)
|
||||
{
|
||||
m_category = category;
|
||||
}
|
||||
|
||||
int AudioOutput::outputDevice() const
|
||||
{
|
||||
return m_device.index();
|
||||
}
|
||||
|
||||
bool AudioOutput::setOutputDevice(int deviceIndex)
|
||||
{
|
||||
const AudioOutputDevice device = AudioOutputDevice::fromIndex(deviceIndex);
|
||||
if (!device.isValid()) {
|
||||
error() << Q_FUNC_INFO << "Unable to find the output device with index" << deviceIndex;
|
||||
return false;
|
||||
}
|
||||
return setOutputDevice(device);
|
||||
}
|
||||
|
||||
bool AudioOutput::setOutputDevice(const AudioOutputDevice &newDevice)
|
||||
{
|
||||
debug() << Q_FUNC_INFO;
|
||||
|
||||
if (!newDevice.isValid()) {
|
||||
error() << "Invalid audio output device";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (newDevice == m_device)
|
||||
return true;
|
||||
|
||||
m_device = newDevice;
|
||||
if (m_player) {
|
||||
setOutputDeviceImplementation();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void AudioOutput::setStreamUuid(QString uuid)
|
||||
{
|
||||
DEBUG_BLOCK;
|
||||
debug() << uuid;
|
||||
m_streamUuid = uuid;
|
||||
}
|
||||
|
||||
void AudioOutput::setOutputDeviceImplementation()
|
||||
{
|
||||
Q_ASSERT(m_player);
|
||||
#if (LIBVLC_VERSION_INT >= LIBVLC_VERSION(2, 2, 0, 0))
|
||||
// VLC 2.2 has the PulseSupport overrides always disabled because of
|
||||
// incompatibility. Also see backend.cpp for more detals.
|
||||
// To get access to the correct activity state we need to temporarily
|
||||
// enable pulse and then disable it again. This is necessary because isActive
|
||||
// is in fact isActive&isEnabled.............
|
||||
PulseSupport::getInstance()->enable(true);
|
||||
const bool pulseActive = PulseSupport::getInstance()->isActive();
|
||||
PulseSupport::getInstance()->enable(false);
|
||||
#else
|
||||
const bool pulseActive = PulseSupport::getInstance()->isActive();
|
||||
#endif
|
||||
if (pulseActive) {
|
||||
m_player->setAudioOutput("pulse");
|
||||
debug() << "Setting aout to pulse";
|
||||
return;
|
||||
}
|
||||
|
||||
const QVariant dalProperty = m_device.property("deviceAccessList");
|
||||
if (!dalProperty.isValid()) {
|
||||
error() << "Device" << m_device.property("name") << "has no access list";
|
||||
return;
|
||||
}
|
||||
const DeviceAccessList deviceAccessList = dalProperty.value<DeviceAccessList>();
|
||||
if (deviceAccessList.isEmpty()) {
|
||||
error() << "Device" << m_device.property("name") << "has an empty access list";
|
||||
return;
|
||||
}
|
||||
|
||||
// ### we're not trying the whole access list (could mean same device on different soundsystems)
|
||||
const DeviceAccess &firstDeviceAccess = deviceAccessList.first();
|
||||
|
||||
QByteArray soundSystem = firstDeviceAccess.first;
|
||||
debug() << "Setting output soundsystem to" << soundSystem;
|
||||
m_player->setAudioOutput(soundSystem);
|
||||
|
||||
QByteArray deviceName = firstDeviceAccess.second.toLatin1();
|
||||
if (!deviceName.isEmpty()) {
|
||||
// print the name as possibly messed up by toLatin1() to see conversion problems
|
||||
debug() << "Setting output device to" << deviceName << '(' << m_device.property("name") << ')';
|
||||
m_player->setAudioOutputDevice(soundSystem, deviceName);
|
||||
}
|
||||
}
|
||||
|
||||
void AudioOutput::applyVolume()
|
||||
{
|
||||
if (m_player && m_explicitVolume) {
|
||||
const int preVolume = m_player->audioVolume();
|
||||
const int newVolume = m_volume * 100;
|
||||
m_player->setAudioVolume(newVolume);
|
||||
|
||||
#if (LIBVLC_VERSION_INT < LIBVLC_VERSION(2, 2, 2, 0))
|
||||
onMutedChanged(m_volume == 0.0);
|
||||
onVolumeChanged(newVolume);
|
||||
#endif
|
||||
|
||||
debug() << "Volume changed from" << preVolume << "to" << newVolume;
|
||||
}
|
||||
}
|
||||
|
||||
void AudioOutput::onMutedChanged(bool mute)
|
||||
{
|
||||
m_muted = mute;
|
||||
emit mutedChanged(mute);
|
||||
}
|
||||
|
||||
void AudioOutput::onVolumeChanged(float volume)
|
||||
{
|
||||
m_volume = volume;
|
||||
emit volumeChanged(volume);
|
||||
}
|
||||
|
||||
}
|
||||
} // Namespace Phonon::VLC
|
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
Copyright (C) 2007-2008 Tanguy Krotoff <tkrotoff@gmail.com>
|
||||
Copyright (C) 2008 Lukas Durfina <lukas.durfina@gmail.com>
|
||||
Copyright (C) 2009 Fathi Boudra <fabo@kde.org>
|
||||
Copyright (C) 2013 Harald Sitter <sitter@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef PHONON_VLC_AUDIOOUTPUT_H
|
||||
#define PHONON_VLC_AUDIOOUTPUT_H
|
||||
|
||||
#include <QtCore/QObject>
|
||||
|
||||
#include <phonon/audiooutputinterface.h>
|
||||
|
||||
#include "sinknode.h"
|
||||
|
||||
namespace Phonon {
|
||||
namespace VLC {
|
||||
|
||||
/** \brief AudioOutput implementation for Phonon-VLC
|
||||
*
|
||||
* This class is a SinkNode that implements the AudioOutputInterface from Phonon. It
|
||||
* supports setting the volume and the audio output device.
|
||||
*
|
||||
* There are signals for the change of the volume or for when an audio device failed.
|
||||
*
|
||||
* See the Phonon::AudioOutputInterface documentation for details.
|
||||
*
|
||||
* \see AudioDataOutput
|
||||
*/
|
||||
class AudioOutput : public QObject, public SinkNode, public AudioOutputInterface
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(Phonon::AudioOutputInterface)
|
||||
|
||||
public:
|
||||
/**
|
||||
* Creates an AudioOutput with the given backend object. The volume is set to 1.0
|
||||
*
|
||||
* \param p_back Parent backend
|
||||
* \param p_parent A parent object
|
||||
*/
|
||||
explicit AudioOutput(QObject *parent);
|
||||
~AudioOutput();
|
||||
|
||||
/** \reimp */
|
||||
void handleConnectToMediaObject(MediaObject *mediaObject);
|
||||
/** \reimp */
|
||||
void handleAddToMedia(Media *media);
|
||||
|
||||
/**
|
||||
* \return The current volume for this audio output.
|
||||
*/
|
||||
qreal volume() const;
|
||||
|
||||
/**
|
||||
* Sets the volume of the audio output. See the Phonon::AudioOutputInterface::setVolume() documentation
|
||||
* for details.
|
||||
*/
|
||||
void setVolume(qreal volume);
|
||||
|
||||
/**
|
||||
* \return The index of the current audio output device from the list obtained from the backend object.
|
||||
*/
|
||||
int outputDevice() const;
|
||||
|
||||
/**
|
||||
* Sets the current output device for this audio output. The validity of the device index
|
||||
* is verified before attempting to change the device.
|
||||
*
|
||||
* \param device The index of the device, obtained from the backend's audio device list
|
||||
* \return \c true if succeeded, or no change was made
|
||||
* \return \c false if failed
|
||||
*/
|
||||
bool setOutputDevice(int);
|
||||
|
||||
/**
|
||||
* Sets the current output device for this audio output.
|
||||
*
|
||||
* \param device The device to set; it should be valid and contain an usable deviceAccessList property
|
||||
* \return \c true if succeeded, or no change was made
|
||||
* \return \c false if failed
|
||||
*/
|
||||
bool setOutputDevice(const AudioOutputDevice &newDevice);
|
||||
void setStreamUuid(QString uuid);
|
||||
void setMuted(bool mute);
|
||||
|
||||
virtual void setCategory(Phonon::Category category);
|
||||
|
||||
signals:
|
||||
void volumeChanged(qreal volume);
|
||||
void audioDeviceFailed();
|
||||
void mutedChanged(bool mute);
|
||||
|
||||
private slots:
|
||||
/**
|
||||
* Sets the volume to m_volume.
|
||||
*/
|
||||
void applyVolume();
|
||||
|
||||
void onMutedChanged(bool mute);
|
||||
void onVolumeChanged(float volume);
|
||||
|
||||
private:
|
||||
/**
|
||||
* We can only really set the output device once we have a libvlc_media_player, which comes
|
||||
* from our SinkNode.
|
||||
*/
|
||||
void setOutputDeviceImplementation();
|
||||
|
||||
qreal m_volume;
|
||||
// Set after first setVolume to indicate volume was set manually.
|
||||
bool m_explicitVolume;
|
||||
bool m_muted;
|
||||
AudioOutputDevice m_device;
|
||||
QString m_streamUuid;
|
||||
Category m_category;
|
||||
};
|
||||
|
||||
} // namespace VLC
|
||||
} // namespace Phonon
|
||||
|
||||
#endif // PHONON_VLC_AUDIOOUTPUT_H
|
|
@ -0,0 +1,127 @@
|
|||
/* This file is part of the KDE project.
|
||||
*
|
||||
* Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
|
||||
* Copyright (C) 2013 Martin Sandsmark <martin.sandsmark@kde.org>
|
||||
*
|
||||
* This library is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 2.1 or 3 of the License.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "volumefadereffect.h"
|
||||
#include <mediaplayer.h>
|
||||
|
||||
#include "utils/debug.h"
|
||||
|
||||
#include <QtCore/QTimeLine>
|
||||
|
||||
#ifndef QT_NO_PHONON_VOLUMEFADEREFFECT
|
||||
namespace Phonon
|
||||
{
|
||||
namespace VLC
|
||||
{
|
||||
VolumeFaderEffect::VolumeFaderEffect(QObject *parent)
|
||||
: QObject(parent)
|
||||
, SinkNode()
|
||||
, m_fadeCurve(Phonon::VolumeFaderEffect::Fade3Decibel)
|
||||
, m_fadeFromVolume(0)
|
||||
, m_fadeToVolume(0)
|
||||
{
|
||||
m_fadeTimeline = new QTimeLine(1000, this);
|
||||
connect(m_fadeTimeline, SIGNAL(valueChanged(qreal)), this, SLOT(slotSetVolume(qreal)));
|
||||
}
|
||||
|
||||
VolumeFaderEffect::~VolumeFaderEffect()
|
||||
{
|
||||
}
|
||||
|
||||
float VolumeFaderEffect::volume() const
|
||||
{
|
||||
Q_ASSERT(m_player);
|
||||
return m_player->audioVolume() / 100.0f;
|
||||
}
|
||||
|
||||
void VolumeFaderEffect::slotSetVolume(qreal volume)
|
||||
{
|
||||
float gstVolume = m_fadeFromVolume + (volume * (m_fadeToVolume - m_fadeFromVolume));
|
||||
setVolumeInternal(gstVolume);
|
||||
}
|
||||
|
||||
Phonon::VolumeFaderEffect::FadeCurve VolumeFaderEffect::fadeCurve() const
|
||||
{
|
||||
return m_fadeCurve;
|
||||
}
|
||||
|
||||
void VolumeFaderEffect::setFadeCurve(Phonon::VolumeFaderEffect::FadeCurve pFadeCurve)
|
||||
{
|
||||
m_fadeCurve = pFadeCurve;
|
||||
QEasingCurve fadeCurve;
|
||||
switch(pFadeCurve) {
|
||||
case Phonon::VolumeFaderEffect::Fade3Decibel:
|
||||
fadeCurve = QEasingCurve::InQuad;
|
||||
break;
|
||||
case Phonon::VolumeFaderEffect::Fade6Decibel:
|
||||
fadeCurve = QEasingCurve::Linear;
|
||||
break;
|
||||
case Phonon::VolumeFaderEffect::Fade9Decibel:
|
||||
fadeCurve = QEasingCurve::OutCubic;
|
||||
break;
|
||||
case Phonon::VolumeFaderEffect::Fade12Decibel:
|
||||
fadeCurve = QEasingCurve::OutQuart;
|
||||
break;
|
||||
}
|
||||
m_fadeTimeline->setEasingCurve(fadeCurve);
|
||||
}
|
||||
|
||||
void VolumeFaderEffect::fadeTo(float targetVolume, int fadeTime)
|
||||
{
|
||||
Q_ASSERT(m_player);
|
||||
abortFade();
|
||||
m_fadeToVolume = targetVolume;
|
||||
m_fadeFromVolume = m_player->audioVolume() / 100.0f;
|
||||
|
||||
// Don't call QTimeLine::setDuration() with zero.
|
||||
// It is not supported and breaks fading.
|
||||
if (fadeTime <= 0) {
|
||||
debug() << "Called with retarded fade time " << fadeTime;
|
||||
setVolumeInternal(targetVolume);
|
||||
return;
|
||||
}
|
||||
|
||||
m_fadeTimeline->setDuration(fadeTime);
|
||||
m_fadeTimeline->start();
|
||||
}
|
||||
|
||||
void VolumeFaderEffect::setVolume(float v)
|
||||
{
|
||||
abortFade();
|
||||
setVolumeInternal(v);
|
||||
}
|
||||
|
||||
void VolumeFaderEffect::abortFade()
|
||||
{
|
||||
m_fadeTimeline->stop();
|
||||
}
|
||||
|
||||
void VolumeFaderEffect::setVolumeInternal(float v)
|
||||
{
|
||||
if (m_player)
|
||||
m_player->setAudioFade(v);
|
||||
else
|
||||
warning() << Q_FUNC_INFO << this << "no m_player set";
|
||||
}
|
||||
|
||||
}
|
||||
} //namespace Phonon::VLC
|
||||
|
||||
#endif //QT_NO_PHONON_VOLUMEFADEREFFECT
|
||||
#include "moc_volumefadereffect.cpp"
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
/* This file is part of the KDE project.
|
||||
*
|
||||
* Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
|
||||
* Copyright (C) 2013 Martin Sandsmark <martin.sandsmark@kde.org>
|
||||
*
|
||||
* This library is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 2.1 or 3 of the License.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef PHONON_VLC_VOLUMEFADEREFFECT_H
|
||||
#define PHONON_VLC_VOLUMEFADEREFFECT_H
|
||||
|
||||
#include <phonon/volumefaderinterface.h>
|
||||
|
||||
#include <QtCore/QTime>
|
||||
#include <QtCore/QPointer>
|
||||
|
||||
#include "sinknode.h"
|
||||
|
||||
class QTimeLine;
|
||||
|
||||
namespace Phonon {
|
||||
|
||||
class MediaObject;
|
||||
|
||||
namespace VLC {
|
||||
|
||||
class VolumeFaderEffect : public QObject, public SinkNode, public VolumeFaderInterface
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(Phonon::VolumeFaderInterface)
|
||||
|
||||
public:
|
||||
explicit VolumeFaderEffect(QObject *parent = 0);
|
||||
~VolumeFaderEffect();
|
||||
|
||||
// VolumeFaderInterface:
|
||||
float volume() const;
|
||||
Phonon::VolumeFaderEffect::FadeCurve fadeCurve() const;
|
||||
void setFadeCurve(Phonon::VolumeFaderEffect::FadeCurve fadeCurve);
|
||||
void fadeTo(float volume, int fadeTime);
|
||||
void setVolume(float v);
|
||||
QPointer<MediaObject> mediaObject() { return m_mediaObject; }
|
||||
|
||||
private slots:
|
||||
void slotSetVolume(qreal v);
|
||||
|
||||
private:
|
||||
void abortFade();
|
||||
inline void setVolumeInternal(float v);
|
||||
|
||||
Phonon::VolumeFaderEffect::FadeCurve m_fadeCurve;
|
||||
float m_fadeFromVolume;
|
||||
float m_fadeToVolume;
|
||||
QTimeLine *m_fadeTimeline;
|
||||
|
||||
};
|
||||
|
||||
} // namespace VLC
|
||||
} // namespace Phonon
|
||||
|
||||
#endif // PHONON_VLC_VOLUMEFADEREFFECT_H
|
|
@ -0,0 +1,365 @@
|
|||
/*
|
||||
Copyright (C) 2007-2008 Tanguy Krotoff <tkrotoff@gmail.com>
|
||||
Copyright (C) 2008 Lukas Durfina <lukas.durfina@gmail.com>
|
||||
Copyright (C) 2009 Fathi Boudra <fabo@kde.org>
|
||||
Copyright (C) 2009-2011 vlc-phonon AUTHORS <kde-multimedia@kde.org>
|
||||
Copyright (C) 2011-2013 Harald Sitter <sitter@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "backend.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QIcon>
|
||||
#include <QLatin1Literal>
|
||||
#include <QMessageBox>
|
||||
#include <QtPlugin>
|
||||
#include <QVariant>
|
||||
|
||||
#include <phonon/GlobalDescriptionContainer>
|
||||
#include <phonon/pulsesupport.h>
|
||||
|
||||
#include <vlc/libvlc_version.h>
|
||||
|
||||
#include "audio/audiooutput.h"
|
||||
#include "audio/audiodataoutput.h"
|
||||
#include "audio/volumefadereffect.h"
|
||||
#include "config.h"
|
||||
#include "devicemanager.h"
|
||||
#include "effect.h"
|
||||
#include "effectmanager.h"
|
||||
#include "mediaobject.h"
|
||||
#include "sinknode.h"
|
||||
#include "utils/debug.h"
|
||||
#include "utils/libvlc.h"
|
||||
#include "utils/mime.h"
|
||||
#ifdef PHONON_EXPERIMENTAL
|
||||
#include "video/videodataoutput.h"
|
||||
#endif
|
||||
#include "video/videowidget.h"
|
||||
|
||||
namespace Phonon
|
||||
{
|
||||
namespace VLC
|
||||
{
|
||||
|
||||
Backend *Backend::self;
|
||||
|
||||
Backend::Backend(QObject *parent, const QVariantList &)
|
||||
: QObject(parent)
|
||||
, m_deviceManager(0)
|
||||
, m_effectManager(0)
|
||||
{
|
||||
self = this;
|
||||
|
||||
// Backend information properties
|
||||
setProperty("identifier", QLatin1String("phonon_vlc"));
|
||||
setProperty("backendName", QLatin1String("VLC"));
|
||||
setProperty("backendComment", QLatin1String("VLC backend for Phonon"));
|
||||
setProperty("backendVersion", QLatin1String(PHONON_VLC_VERSION));
|
||||
setProperty("backendIcon", QLatin1String("vlc"));
|
||||
setProperty("backendWebsite", QLatin1String("https://commits.kde.org/phonon-vlc"));
|
||||
|
||||
// Check if we should enable debug output
|
||||
int debugLevel = qgetenv("PHONON_BACKEND_DEBUG").toInt();
|
||||
if (debugLevel > 3) // 3 is maximum
|
||||
debugLevel = 3;
|
||||
Debug::setMinimumDebugLevel((Debug::DebugLevel)((int) Debug::DEBUG_NONE - 1 - debugLevel));
|
||||
|
||||
debug() << "Constructing Phonon-VLC Version" << PHONON_VLC_VERSION;
|
||||
|
||||
// Actual libVLC initialisation
|
||||
if (LibVLC::init()) {
|
||||
debug() << "Using VLC version" << libvlc_get_version();
|
||||
if (!qApp->applicationName().isEmpty()) {
|
||||
QString userAgent =
|
||||
QString("%0/%1 (Phonon/%2; Phonon-VLC/%3)").arg(
|
||||
qApp->applicationName(),
|
||||
qApp->applicationVersion(),
|
||||
PHONON_VERSION_STR,
|
||||
PHONON_VLC_VERSION);
|
||||
libvlc_set_user_agent(pvlc_libvlc,
|
||||
qApp->applicationName().toUtf8().constData(),
|
||||
userAgent.toUtf8().constData());
|
||||
} else {
|
||||
qWarning("WARNING: Setting the user agent for streaming and"
|
||||
" PulseAudio requires you to set QCoreApplication::applicationName()");
|
||||
}
|
||||
|
||||
PulseSupport::getInstance()->enable(true);
|
||||
const bool pulseActive = PulseSupport::getInstance()->isActive();
|
||||
PulseSupport::getInstance()->enable(false);
|
||||
if (!qApp->applicationName().isEmpty()) {
|
||||
const QString id = QString("org.kde.phonon.%1").arg(qApp->applicationName());
|
||||
const QString version = qApp->applicationVersion();
|
||||
QString icon;
|
||||
if (!qApp->windowIcon().isNull()){
|
||||
// Try to get the fromTheme() name of the QIcon.
|
||||
icon = qApp->windowIcon().name();
|
||||
}
|
||||
if (icon.isEmpty()) {
|
||||
// If we failed to get a proper icon name, use the appname instead.
|
||||
icon = qApp->applicationName().toLower();
|
||||
}
|
||||
libvlc_set_app_id(pvlc_libvlc,
|
||||
id.toUtf8().constData(),
|
||||
version.toUtf8().constData(),
|
||||
icon.toUtf8().constData());
|
||||
} else if (pulseActive) {
|
||||
qWarning("WARNING: Setting PulseAudio context information requires you"
|
||||
" to set QCoreApplication::applicationName(),"
|
||||
" QCoreApplication::applicationVersion() and"
|
||||
" QGuiApplication::windowIcon().");
|
||||
}
|
||||
} else {
|
||||
#ifdef __GNUC__
|
||||
#warning TODO - this error message is as useful as a knife at a gun fight
|
||||
#endif
|
||||
QMessageBox msg;
|
||||
msg.setIcon(QMessageBox::Critical);
|
||||
msg.setWindowTitle(tr("LibVLC Failed to Initialize"));
|
||||
msg.setText(tr("Phonon's VLC backend failed to start."
|
||||
"\n\n"
|
||||
"This usually means a problem with your VLC installation,"
|
||||
" please report a bug with your distributor."));
|
||||
msg.setDetailedText(LibVLC::errorMessage());
|
||||
msg.exec();
|
||||
fatal() << "Phonon::VLC::vlcInit: Failed to initialize VLC";
|
||||
}
|
||||
|
||||
#if (LIBVLC_VERSION_INT < LIBVLC_VERSION(2, 2, 2, 0))
|
||||
// VLC 2.2 changed the stream creation order around internally which breaks
|
||||
// the Pulseaudio hijacking. Since VLC upstream doesn't feel like giving us
|
||||
// any more property control we now consider this feature unsupported. As
|
||||
// such whatever properties VLC sets will be what pulse knows about us.
|
||||
|
||||
// Initialise PulseAudio support
|
||||
PulseSupport *pulse = PulseSupport::getInstance();
|
||||
pulse->enable(true);
|
||||
connect(pulse, SIGNAL(objectDescriptionChanged(ObjectDescriptionType)),
|
||||
SIGNAL(objectDescriptionChanged(ObjectDescriptionType)));
|
||||
#endif
|
||||
|
||||
m_deviceManager = new DeviceManager(this);
|
||||
m_effectManager = new EffectManager(this);
|
||||
}
|
||||
|
||||
Backend::~Backend()
|
||||
{
|
||||
if (LibVLC::self)
|
||||
delete LibVLC::self;
|
||||
if (GlobalAudioChannels::self)
|
||||
delete GlobalAudioChannels::self;
|
||||
if (GlobalSubtitles::self)
|
||||
delete GlobalSubtitles::self;
|
||||
PulseSupport::shutdown();
|
||||
}
|
||||
|
||||
QObject *Backend::createObject(BackendInterface::Class c, QObject *parent, const QList<QVariant> &args)
|
||||
{
|
||||
if (!LibVLC::self || !pvlc_libvlc)
|
||||
return 0;
|
||||
|
||||
switch (c) {
|
||||
case MediaObjectClass:
|
||||
return new MediaObject(parent);
|
||||
case AudioOutputClass:
|
||||
return new AudioOutput(parent);
|
||||
#if (LIBVLC_VERSION_INT < LIBVLC_VERSION(2, 0, 0, 0))
|
||||
// Broken >= 2.0
|
||||
// https://trac.videolan.org/vlc/ticket/6992
|
||||
case AudioDataOutputClass:
|
||||
return new AudioDataOutput(parent);
|
||||
#endif
|
||||
#ifdef PHONON_EXPERIMENTAL
|
||||
case VideoDataOutputClass:
|
||||
return new VideoDataOutput(parent);
|
||||
#endif
|
||||
case VideoGraphicsObjectClass:
|
||||
return nullptr; // No longer supported
|
||||
case EffectClass:
|
||||
return effectManager()->createEffect(args[0].toInt(), parent);
|
||||
case VideoWidgetClass:
|
||||
return new VideoWidget(qobject_cast<QWidget *>(parent));
|
||||
// case VolumeFaderEffectClass:
|
||||
#ifdef __GNUC__
|
||||
#warning VFE crashes and has volume bugs ... deactivated
|
||||
// return new VolumeFaderEffect(parent);
|
||||
#endif
|
||||
}
|
||||
|
||||
warning() << "Backend class" << c << "is not supported by Phonon VLC :(";
|
||||
return 0;
|
||||
}
|
||||
|
||||
QStringList Backend::availableMimeTypes() const
|
||||
{
|
||||
if (m_supportedMimeTypes.isEmpty())
|
||||
const_cast<Backend *>(this)->m_supportedMimeTypes = mimeTypeList();
|
||||
return m_supportedMimeTypes;
|
||||
}
|
||||
|
||||
QList<int> Backend::objectDescriptionIndexes(ObjectDescriptionType type) const
|
||||
{
|
||||
QList<int> list;
|
||||
|
||||
switch (type) {
|
||||
case Phonon::AudioChannelType: {
|
||||
list << GlobalAudioChannels::instance()->globalIndexes();
|
||||
}
|
||||
break;
|
||||
case Phonon::AudioOutputDeviceType:
|
||||
case Phonon::AudioCaptureDeviceType:
|
||||
case Phonon::VideoCaptureDeviceType: {
|
||||
return deviceManager()->deviceIds(type);
|
||||
}
|
||||
break;
|
||||
case Phonon::EffectType: {
|
||||
QList<EffectInfo> effectList = effectManager()->effects();
|
||||
for (int eff = 0; eff < effectList.size(); ++eff) {
|
||||
list.append(eff);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Phonon::SubtitleType: {
|
||||
list << GlobalSubtitles::instance()->globalIndexes();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
QHash<QByteArray, QVariant> Backend::objectDescriptionProperties(ObjectDescriptionType type, int index) const
|
||||
{
|
||||
QHash<QByteArray, QVariant> ret;
|
||||
|
||||
switch (type) {
|
||||
case Phonon::AudioChannelType: {
|
||||
const AudioChannelDescription description = GlobalAudioChannels::instance()->fromIndex(index);
|
||||
ret.insert("name", description.name());
|
||||
ret.insert("description", description.description());
|
||||
}
|
||||
break;
|
||||
case Phonon::AudioOutputDeviceType:
|
||||
case Phonon::AudioCaptureDeviceType:
|
||||
case Phonon::VideoCaptureDeviceType: {
|
||||
// Index should be unique, even for different categories
|
||||
return deviceManager()->deviceProperties(index);
|
||||
}
|
||||
break;
|
||||
case Phonon::EffectType: {
|
||||
const QList<EffectInfo> effectList = effectManager()->effects();
|
||||
if (index >= 0 && index <= effectList.size()) {
|
||||
const EffectInfo &effect = effectList.at(index);
|
||||
ret.insert("name", effect.name());
|
||||
ret.insert("description", effect.description());
|
||||
ret.insert("author", effect.author());
|
||||
} else {
|
||||
Q_ASSERT(1); // Since we use list position as ID, this should not happen
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Phonon::SubtitleType: {
|
||||
const SubtitleDescription description = GlobalSubtitles::instance()->fromIndex(index);
|
||||
ret.insert("name", description.name());
|
||||
ret.insert("description", description.description());
|
||||
ret.insert("type", description.property("type"));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool Backend::startConnectionChange(QSet<QObject *> objects)
|
||||
{
|
||||
//FIXME
|
||||
foreach(QObject * object, objects) {
|
||||
debug() << "Object:" << object->metaObject()->className();
|
||||
}
|
||||
|
||||
// There is nothing we can do but hope the connection changes will not take too long
|
||||
// so that buffers would underrun
|
||||
// But we should be pretty safe the way xine works by not doing anything here.
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Backend::connectNodes(QObject *source, QObject *sink)
|
||||
{
|
||||
debug() << "Backend connected" << source->metaObject()->className() << "to" << sink->metaObject()->className();
|
||||
|
||||
SinkNode *sinkNode = dynamic_cast<SinkNode *>(sink);
|
||||
if (sinkNode) {
|
||||
MediaObject *mediaObject = qobject_cast<MediaObject *>(source);
|
||||
if (mediaObject) {
|
||||
// Connect the SinkNode to a MediaObject
|
||||
sinkNode->connectToMediaObject(mediaObject);
|
||||
return true;
|
||||
}
|
||||
|
||||
VolumeFaderEffect *effect = qobject_cast<VolumeFaderEffect *>(source);
|
||||
if (effect) {
|
||||
sinkNode->connectToMediaObject(effect->mediaObject());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
warning() << "Linking" << source->metaObject()->className() << "to" << sink->metaObject()->className() << "failed";
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Backend::disconnectNodes(QObject *source, QObject *sink)
|
||||
{
|
||||
SinkNode *sinkNode = dynamic_cast<SinkNode *>(sink);
|
||||
if (sinkNode) {
|
||||
MediaObject *const mediaObject = qobject_cast<MediaObject *>(source);
|
||||
if (mediaObject) {
|
||||
// Disconnect the SinkNode from a MediaObject
|
||||
sinkNode->disconnectFromMediaObject(mediaObject);
|
||||
return true;
|
||||
}
|
||||
|
||||
VolumeFaderEffect *const effect = qobject_cast<VolumeFaderEffect *>(source);
|
||||
if (effect) {
|
||||
sinkNode->disconnectFromMediaObject(effect->mediaObject());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Backend::endConnectionChange(QSet<QObject *> objects)
|
||||
{
|
||||
foreach(QObject *object, objects) {
|
||||
debug() << "Object:" << object->metaObject()->className();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
DeviceManager *Backend::deviceManager() const
|
||||
{
|
||||
return m_deviceManager;
|
||||
}
|
||||
|
||||
EffectManager *Backend::effectManager() const
|
||||
{
|
||||
return m_effectManager;
|
||||
}
|
||||
|
||||
} // namespace VLC
|
||||
} // namespace Phonon
|
|
@ -0,0 +1,158 @@
|
|||
/*
|
||||
Copyright (C) 2007-2008 Tanguy Krotoff <tkrotoff@gmail.com>
|
||||
Copyright (C) 2008 Lukas Durfina <lukas.durfina@gmail.com>
|
||||
Copyright (C) 2009 Fathi Boudra <fabo@kde.org>
|
||||
Copyright (C) 2009-2011 vlc-phonon AUTHORS <kde-multimedia@kde.org>
|
||||
Copyright (C) 2011 Harald Sitter <sitter@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef Phonon_VLC_BACKEND_H
|
||||
#define Phonon_VLC_BACKEND_H
|
||||
|
||||
#include <QtCore/QStringList>
|
||||
|
||||
#include <phonon/objectdescription.h>
|
||||
#include <phonon/backendinterface.h>
|
||||
|
||||
class LibVLC;
|
||||
|
||||
namespace Phonon
|
||||
{
|
||||
namespace VLC
|
||||
{
|
||||
class DeviceManager;
|
||||
class EffectManager;
|
||||
|
||||
/** \brief Backend class for Phonon-VLC.
|
||||
*
|
||||
* This class provides the special objects created by the backend and information about
|
||||
* various things that the backend supports. An object of this class is the root for
|
||||
* the backend plugin.
|
||||
*
|
||||
* Phonon will request the backend to create objects of various classes, like MediaObject,
|
||||
* AudioOutput, VideoWidget, Effect. There are also methods to handle the connections between
|
||||
* these objects.
|
||||
*
|
||||
* This class also provides information about the devices and effects that the backend supports.
|
||||
* These are audio output devices, audio capture devices, video capture devices, effects.
|
||||
*/
|
||||
|
||||
class Backend : public QObject, public BackendInterface
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PLUGIN_METADATA(IID "org.kde.phonon.vlc" FILE "phonon-vlc.json")
|
||||
Q_INTERFACES(Phonon::BackendInterface)
|
||||
|
||||
public:
|
||||
/**
|
||||
* Instance. Since there is no backend instance without actual Backend object
|
||||
* this class behaves likes a singleton.
|
||||
*/
|
||||
static Backend *self;
|
||||
|
||||
/**
|
||||
* Constructs the backend. Sets the backend properties, fetches the debug level from the
|
||||
* environment, initializes libVLC, constructs the device and effect managers, initializes
|
||||
* PulseAudio support.
|
||||
*
|
||||
* \param parent A parent object for the backend (passed to the QObject constructor)
|
||||
*/
|
||||
explicit Backend(QObject *parent = 0, const QVariantList & = QVariantList());
|
||||
virtual ~Backend();
|
||||
|
||||
/// \return The device manager that is associated with this backend object
|
||||
DeviceManager *deviceManager() const;
|
||||
|
||||
/// \return The effect manager that is associated with this backend object.
|
||||
EffectManager *effectManager() const;
|
||||
|
||||
/**
|
||||
* Creates a backend object of the desired class and with the desired parent. Extra arguments can be provided.
|
||||
*
|
||||
* \param c The class of object that is to be created
|
||||
* \param parent The object that will be the parent of the new object
|
||||
* \param args Optional arguments for the object creation
|
||||
* \return The desired object or NULL if the class is not implemented.
|
||||
*/
|
||||
QObject *createObject(BackendInterface::Class, QObject *parent, const QList<QVariant> &args);
|
||||
|
||||
/// \returns a list of all available mimetypes (hardcoded)
|
||||
QStringList availableMimeTypes() const;
|
||||
|
||||
/**
|
||||
* Returns a list of indexes for the desired object types. It specifies a list of objects
|
||||
* of a particular category that the backend knows about. These indexes can be used with
|
||||
* objectDescriptionProperties() to get the properties of a particular object.
|
||||
*
|
||||
* \param type The type of objects for the list
|
||||
*/
|
||||
QList<int> objectDescriptionIndexes(ObjectDescriptionType type) const;
|
||||
|
||||
/**
|
||||
* Returns a list of properties for a particular object of the desired category.
|
||||
*
|
||||
* \param type The type of object for the index
|
||||
* \param index The index for the object of the desired type
|
||||
* \return The property list. If the object is inexistent, an empty list is returned.
|
||||
*/
|
||||
QHash<QByteArray, QVariant> objectDescriptionProperties(ObjectDescriptionType type, int index) const;
|
||||
|
||||
/**
|
||||
* Called when a connection between nodes is about to be changed
|
||||
*
|
||||
* \param objects A set of objects that will be involved in the change
|
||||
*/
|
||||
bool startConnectionChange(QSet<QObject *>);
|
||||
|
||||
/**
|
||||
* Connects two media nodes. The sink is informed that it should connect itself to the source.
|
||||
*
|
||||
* \param source The source media node for the connection
|
||||
* \param sink The sink media node for the connection
|
||||
* \return True if the connection was successful
|
||||
*/
|
||||
bool connectNodes(QObject *, QObject *);
|
||||
|
||||
/**
|
||||
* Disconnects two previously connected media nodes. It disconnects the sink node from the source node.
|
||||
*
|
||||
* \param source The source node for the disconnection
|
||||
* \param sink The sink node for the disconnection
|
||||
* \return True if the disconnection was successful
|
||||
*/
|
||||
bool disconnectNodes(QObject *, QObject *);
|
||||
|
||||
/**
|
||||
* Called after a connection between nodes has been changed
|
||||
*
|
||||
* \param objects Nodes involved in the disconnection
|
||||
*/
|
||||
bool endConnectionChange(QSet<QObject *>);
|
||||
|
||||
Q_SIGNALS:
|
||||
void objectDescriptionChanged(ObjectDescriptionType);
|
||||
|
||||
private:
|
||||
mutable QStringList m_supportedMimeTypes;
|
||||
|
||||
DeviceManager *m_deviceManager;
|
||||
EffectManager *m_effectManager;
|
||||
};
|
||||
|
||||
} // namespace VLC
|
||||
} // namespace Phonon
|
||||
|
||||
#endif // Phonon_VLC_BACKEND_H
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
Copyright (C) 2019 Harald Sitter <sitter@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef PHONON_VLC_CONFIG_H
|
||||
#define PHONON_VLC_CONFIG_H
|
||||
|
||||
// I'd really love to have inline constexpr QStringViews here, I'm unsure what
|
||||
// that requires vis-a-vis compiler support though :(
|
||||
|
||||
#cmakedefine PHONON_VLC_VERSION "@PHONON_VLC_VERSION@"
|
||||
#cmakedefine PHONON_EXPERIMENTAL
|
||||
|
||||
#endif // PHONON_VLC_CONFIG_H
|
|
@ -0,0 +1,340 @@
|
|||
/*
|
||||
Copyright (C) 2007-2008 Tanguy Krotoff <tkrotoff@gmail.com>
|
||||
Copyright (C) 2008 Lukas Durfina <lukas.durfina@gmail.com>
|
||||
Copyright (C) 2009 Fathi Boudra <fabo@kde.org>
|
||||
Copyright (C) 2009-2010 vlc-phonon AUTHORS <kde-multimedia@kde.org>
|
||||
Copyright (C) 2011 Harald Sitter <sitter@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "devicemanager.h"
|
||||
|
||||
#include <phonon/pulsesupport.h>
|
||||
|
||||
#include <vlc/vlc.h>
|
||||
|
||||
#include "backend.h"
|
||||
#include "utils/debug.h"
|
||||
#include "utils/libvlc.h"
|
||||
#include "utils/vstring.h"
|
||||
|
||||
namespace Phonon
|
||||
{
|
||||
namespace VLC
|
||||
{
|
||||
|
||||
/*
|
||||
* Device Info
|
||||
*/
|
||||
|
||||
DeviceInfo::DeviceInfo(const QString &name, bool isAdvanced)
|
||||
{
|
||||
// Get an id
|
||||
static int counter = 0;
|
||||
m_id = counter++;
|
||||
|
||||
// Get name and description for the device
|
||||
m_name = name;
|
||||
m_isAdvanced = isAdvanced;
|
||||
m_capabilities = None;
|
||||
|
||||
// A default device should never be advanced
|
||||
if (name.startsWith(QLatin1String("default"), Qt::CaseInsensitive))
|
||||
m_isAdvanced = false;
|
||||
}
|
||||
|
||||
int DeviceInfo::id() const
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
const QString& DeviceInfo::name() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
const QString& DeviceInfo::description() const
|
||||
{
|
||||
return m_description;
|
||||
}
|
||||
|
||||
bool DeviceInfo::isAdvanced() const
|
||||
{
|
||||
return m_isAdvanced;
|
||||
}
|
||||
|
||||
void DeviceInfo::setAdvanced(bool advanced)
|
||||
{
|
||||
m_isAdvanced = advanced;
|
||||
}
|
||||
|
||||
const DeviceAccessList& DeviceInfo::accessList() const
|
||||
{
|
||||
return m_accessList;
|
||||
}
|
||||
|
||||
void DeviceInfo::addAccess(const DeviceAccess& access)
|
||||
{
|
||||
if (m_accessList.isEmpty())
|
||||
m_description = access.first + ": " + access.second;
|
||||
m_accessList.append(access);
|
||||
}
|
||||
|
||||
quint16 DeviceInfo::capabilities() const
|
||||
{
|
||||
return m_capabilities;
|
||||
}
|
||||
|
||||
void DeviceInfo::setCapabilities(quint16 cap)
|
||||
{
|
||||
m_capabilities = cap;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Device Manager
|
||||
*/
|
||||
|
||||
DeviceManager::DeviceManager(Backend *parent)
|
||||
: QObject(parent)
|
||||
, m_backend(parent)
|
||||
{
|
||||
Q_ASSERT(parent);
|
||||
updateDeviceList();
|
||||
}
|
||||
|
||||
DeviceManager::~DeviceManager()
|
||||
{
|
||||
}
|
||||
|
||||
QList<int> DeviceManager::deviceIds(ObjectDescriptionType type)
|
||||
{
|
||||
DeviceInfo::Capability capability = DeviceInfo::None;
|
||||
switch (type) {
|
||||
case Phonon::AudioOutputDeviceType:
|
||||
capability = DeviceInfo::AudioOutput;
|
||||
break;
|
||||
case Phonon::AudioCaptureDeviceType:
|
||||
capability = DeviceInfo::AudioCapture;
|
||||
break;
|
||||
case Phonon::VideoCaptureDeviceType:
|
||||
capability = DeviceInfo::VideoCapture;
|
||||
break;
|
||||
default: ;
|
||||
}
|
||||
|
||||
QList<int> ids;
|
||||
foreach (const DeviceInfo &device, m_devices) {
|
||||
if (device.capabilities() & capability)
|
||||
ids.append(device.id());
|
||||
}
|
||||
|
||||
return ids;
|
||||
}
|
||||
|
||||
QHash<QByteArray, QVariant> DeviceManager::deviceProperties(int id)
|
||||
{
|
||||
QHash<QByteArray, QVariant> properties;
|
||||
|
||||
foreach (const DeviceInfo &device, m_devices) {
|
||||
if (device.id() == id) {
|
||||
properties.insert("name", device.name());
|
||||
properties.insert("description", device.description());
|
||||
properties.insert("isAdvanced", device.isAdvanced());
|
||||
properties.insert("deviceAccessList", QVariant::fromValue<Phonon::DeviceAccessList>(device.accessList()));
|
||||
properties.insert("discovererIcon", "vlc");
|
||||
|
||||
if (device.capabilities() & DeviceInfo::AudioOutput) {
|
||||
properties.insert("icon", QLatin1String("audio-card"));
|
||||
}
|
||||
|
||||
if (device.capabilities() & DeviceInfo::AudioCapture) {
|
||||
properties.insert("hasaudio", true);
|
||||
properties.insert("icon", QLatin1String("audio-input-microphone"));
|
||||
}
|
||||
|
||||
if (device.capabilities() & DeviceInfo::VideoCapture) {
|
||||
properties.insert("hasvideo", true);
|
||||
properties.insert("icon", QLatin1String("camera-web"));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
||||
const DeviceInfo *DeviceManager::device(int id) const
|
||||
{
|
||||
for (int i = 0; i < m_devices.size(); i ++) {
|
||||
if (m_devices[i].id() == id)
|
||||
return &m_devices[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static QList<QByteArray> vlcAudioOutBackends()
|
||||
{
|
||||
QList<QByteArray> ret;
|
||||
|
||||
VLC_FOREACH_LIST(audio_output, aout) {
|
||||
QByteArray name(aout->psz_name);
|
||||
if (!ret.contains(name))
|
||||
ret.append(name);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void DeviceManager::updateDeviceList()
|
||||
{
|
||||
QList<DeviceInfo> newDeviceList;
|
||||
|
||||
if (!LibVLC::self || !pvlc_libvlc)
|
||||
return;
|
||||
|
||||
QList<QByteArray> audioOutBackends = vlcAudioOutBackends();
|
||||
|
||||
PulseSupport *pulse = PulseSupport::getInstance();
|
||||
if (pulse && pulse->isUsable()) {
|
||||
if (audioOutBackends.contains("pulse")) {
|
||||
DeviceInfo defaultAudioOutputDevice(tr("Default"), false);
|
||||
defaultAudioOutputDevice.setCapabilities(DeviceInfo::AudioOutput);
|
||||
defaultAudioOutputDevice.addAccess(DeviceAccess("pulse", "default"));
|
||||
newDeviceList.append(defaultAudioOutputDevice);
|
||||
pulse->request(true);
|
||||
return;
|
||||
} else {
|
||||
pulse->enable(false);
|
||||
}
|
||||
}
|
||||
|
||||
QList<QByteArray> knownSoundSystems;
|
||||
// Whitelist - Order has no particular impact.
|
||||
// NOTE: if listing was not intercepted by the PA code above we also need
|
||||
// to try injecting the pulse aout as otherwise the user would have to
|
||||
// use the fake PA device in ALSA to output through PA (kind of silly).
|
||||
knownSoundSystems << QByteArray("pulse")
|
||||
<< QByteArray("alsa")
|
||||
<< QByteArray("oss")
|
||||
<< QByteArray("jack")
|
||||
<< QByteArray("aout_directx") // Windows up to VLC 2.0
|
||||
<< QByteArray("directsound") // Windows from VLC 2.1 upwards
|
||||
<< QByteArray("auhal"); // Mac
|
||||
foreach (const QByteArray &soundSystem, knownSoundSystems) {
|
||||
if (!audioOutBackends.contains(soundSystem)) {
|
||||
debug() << "Sound system" << soundSystem << "not supported by libvlc";
|
||||
continue;
|
||||
}
|
||||
|
||||
// FIXME: there is a rather ungodly amount of code duplication going
|
||||
// on here.
|
||||
#if (LIBVLC_VERSION_INT >= LIBVLC_VERSION(2, 2, 0, 0))
|
||||
bool hasDevices = false;
|
||||
VLC_FOREACH(audio_output_device,
|
||||
device,
|
||||
libvlc_audio_output_device_list_get(pvlc_libvlc, soundSystem),
|
||||
libvlc_audio_output_device_list_release) {
|
||||
QString idName = QString::fromUtf8(device->psz_device);
|
||||
QString longName = QString::fromUtf8(device->psz_description);
|
||||
|
||||
debug() << "found device" << soundSystem << idName << longName;
|
||||
|
||||
DeviceInfo info(longName, true);
|
||||
info.addAccess(DeviceAccess(soundSystem, idName));
|
||||
info.setCapabilities(DeviceInfo::AudioOutput);
|
||||
newDeviceList.append(info);
|
||||
|
||||
hasDevices = true;
|
||||
}
|
||||
|
||||
if (!hasDevices) {
|
||||
debug() << "manually injecting sound system" << soundSystem;
|
||||
DeviceInfo info(QString::fromUtf8(soundSystem), false);
|
||||
info.addAccess(DeviceAccess(soundSystem, ""));
|
||||
info.setCapabilities(DeviceInfo::AudioOutput);
|
||||
newDeviceList.append(info);
|
||||
}
|
||||
#else
|
||||
const int deviceCount = libvlc_audio_output_device_count(pvlc_libvlc, soundSystem);
|
||||
|
||||
for (int i = 0; i < deviceCount; i++) {
|
||||
VString idName(libvlc_audio_output_device_id(libvlc, soundSystem, i));
|
||||
VString longName(libvlc_audio_output_device_longname(pvlc_libvlc, soundSystem, i));
|
||||
|
||||
debug() << "found device" << soundSystem << idName << longName;
|
||||
|
||||
DeviceInfo info(longName, true);
|
||||
info.addAccess(DeviceAccess(soundSystem, idName));
|
||||
info.setCapabilities(DeviceInfo::AudioOutput);
|
||||
newDeviceList.append(info);
|
||||
}
|
||||
|
||||
// libVLC gives no devices for some sound systems, like OSS
|
||||
if (deviceCount == 0) {
|
||||
debug() << "manually injecting sound system" << soundSystem;
|
||||
// NOTE: Do not mark manually injected devices as advanced.
|
||||
// libphonon filters advanced devices from the default
|
||||
// selection which on systems such as OSX or Windows can
|
||||
// lead to an empty device list as the injected device is
|
||||
// the only available one.
|
||||
DeviceInfo info(QString::fromUtf8(soundSystem), false);
|
||||
info.addAccess(DeviceAccess(soundSystem, ""));
|
||||
info.setCapabilities(DeviceInfo::AudioOutput);
|
||||
newDeviceList.append(info);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Compares the list with the devices available at the moment with the last list. If
|
||||
* a new device is seen, a signal is emitted. If a device disappeared, another signal
|
||||
* is emitted.
|
||||
*/
|
||||
|
||||
// Search for added devices
|
||||
for (int i = 0; i < newDeviceList.count(); ++i) {
|
||||
int id = newDeviceList[i].id();
|
||||
if (!listContainsDevice(m_devices, id)) {
|
||||
// This is a new device, add it
|
||||
m_devices.append(newDeviceList[i]);
|
||||
emit deviceAdded(id);
|
||||
|
||||
debug() << "Added backend device" << newDeviceList[i].name();
|
||||
}
|
||||
}
|
||||
|
||||
// Search for removed devices
|
||||
for (int i = m_devices.count() - 1; i >= 0; --i) {
|
||||
int id = m_devices[i].id();
|
||||
if (!listContainsDevice(newDeviceList, id)) {
|
||||
emit deviceRemoved(id);
|
||||
m_devices.removeAt(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool DeviceManager::listContainsDevice(const QList<DeviceInfo> &list, int id)
|
||||
{
|
||||
foreach (const DeviceInfo &d, list) {
|
||||
if (d.id() == id)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,146 @@
|
|||
/*
|
||||
Copyright (C) 2009-2010 vlc-phonon AUTHORS <kde-multimedia@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef Phonon_VLC_DEVICEMANAGER_H
|
||||
#define Phonon_VLC_DEVICEMANAGER_H
|
||||
|
||||
#include <QtCore/QObject>
|
||||
|
||||
#include <phonon/ObjectDescription>
|
||||
|
||||
namespace Phonon
|
||||
{
|
||||
namespace VLC
|
||||
{
|
||||
|
||||
class Backend;
|
||||
|
||||
/** \brief Container for information about devices supported by libVLC
|
||||
*
|
||||
* It includes a (hopefully unique) device identifier, a name identifier, a
|
||||
* description, a hardware identifier (may be a platform dependent device name),
|
||||
* and other relevant info.
|
||||
*/
|
||||
class DeviceInfo
|
||||
{
|
||||
public:
|
||||
enum Capability {
|
||||
None = 0x0000,
|
||||
AudioOutput = 0x0001,
|
||||
AudioCapture = 0x0002,
|
||||
VideoCapture = 0x0004
|
||||
};
|
||||
public:
|
||||
/**
|
||||
* Constructs a device info object and sets it's device identifiers.
|
||||
*/
|
||||
explicit DeviceInfo(const QString &name, bool isAdvanced = true);
|
||||
|
||||
int id() const;
|
||||
const QString& name() const;
|
||||
const QString& description() const;
|
||||
bool isAdvanced() const;
|
||||
void setAdvanced(bool advanced);
|
||||
const DeviceAccessList& accessList() const;
|
||||
void addAccess(const DeviceAccess &access);
|
||||
quint16 capabilities() const;
|
||||
void setCapabilities(quint16 cap);
|
||||
|
||||
private:
|
||||
int m_id;
|
||||
QString m_name;
|
||||
QString m_description;
|
||||
bool m_isAdvanced;
|
||||
DeviceAccessList m_accessList;
|
||||
quint16 m_capabilities;
|
||||
};
|
||||
|
||||
/** \brief Keeps track of audio/video devices that libVLC supports
|
||||
*
|
||||
* This class maintains a device list. Types of devices:
|
||||
* \li audio output devices
|
||||
* \li audio capture devices
|
||||
* \li video capture devices
|
||||
*
|
||||
* Methods are provided to retrieve information about these devices.
|
||||
*
|
||||
* \see EffectManager
|
||||
*/
|
||||
class DeviceManager : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
/**
|
||||
* Constructs a device manager and immediately updates the devices.
|
||||
*/
|
||||
explicit DeviceManager(Backend *parent);
|
||||
|
||||
/**
|
||||
* Clears all the devices before destroying.
|
||||
*/
|
||||
virtual ~DeviceManager();
|
||||
|
||||
/**
|
||||
* \param type Only devices with a capability of this type are returned
|
||||
* The following are supported:
|
||||
* \li AudioOutputDeviceType
|
||||
* \li AudioCaptureDeviceType
|
||||
* \li VideoCaptureDeviceType
|
||||
*
|
||||
* \return A list of device identifiers that have capabilities that
|
||||
* match the desired type
|
||||
*
|
||||
* \note The capture devices are temporarily not implemented / removed
|
||||
*/
|
||||
QList<int> deviceIds(ObjectDescriptionType type);
|
||||
|
||||
/**
|
||||
* \param id The identifier for the device
|
||||
* \return Object description properties for a device
|
||||
*/
|
||||
QHash<QByteArray, QVariant> deviceProperties(int id);
|
||||
|
||||
/**
|
||||
* \param id The identifier for the device
|
||||
* \return Pointer to DeviceInfo, or NULL if the id is invalid
|
||||
*/
|
||||
const DeviceInfo *device(int id) const;
|
||||
|
||||
signals:
|
||||
void deviceAdded(int);
|
||||
void deviceRemoved(int);
|
||||
|
||||
public slots:
|
||||
/**
|
||||
* Update the current list of active devices. It probes for audio output devices,
|
||||
* audio capture devices, video capture devices. The methods depend on the
|
||||
* device types.
|
||||
*/
|
||||
void updateDeviceList();
|
||||
|
||||
private:
|
||||
static bool listContainsDevice(const QList<DeviceInfo> &list, int id);
|
||||
|
||||
private:
|
||||
Backend *m_backend;
|
||||
QList<DeviceInfo> m_devices;
|
||||
};
|
||||
}
|
||||
} // namespace Phonon::VLC
|
||||
|
||||
#endif // Phonon_VLC_DEVICEMANAGER_H
|
|
@ -0,0 +1,225 @@
|
|||
/*
|
||||
Copyright (C) 2007-2008 Tanguy Krotoff <tkrotoff@gmail.com>
|
||||
Copyright (C) 2008 Lukas Durfina <lukas.durfina@gmail.com>
|
||||
Copyright (C) 2009 Fathi Boudra <fabo@kde.org>
|
||||
Copyright (C) 2009-2011 vlc-phonon AUTHORS <kde-multimedia@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "effect.h"
|
||||
|
||||
#include "effectmanager.h"
|
||||
|
||||
#include "mediaobject.h"
|
||||
|
||||
namespace Phonon
|
||||
{
|
||||
namespace VLC
|
||||
{
|
||||
|
||||
Effect::Effect(EffectManager *p_em, int i_effectId, QObject *p_parent)
|
||||
: QObject(p_parent)
|
||||
, SinkNode()
|
||||
{
|
||||
Q_UNUSED(p_em);
|
||||
Q_UNUSED(i_effectId);
|
||||
// p_effectManager = p_em;
|
||||
// const QList<EffectInfo> effects = p_effectManager->effects();
|
||||
|
||||
// if (i_effectId >= 0 && i_effectId < effects.size()) {
|
||||
// i_effect_filter = effects[ i_effectId ]->filter();
|
||||
// effect_type = effects[ i_effectId ]->type();
|
||||
// setupEffectParams();
|
||||
// } else {
|
||||
// // effect ID out of range
|
||||
// Q_ASSERT(0);
|
||||
// }
|
||||
}
|
||||
|
||||
Effect::~Effect()
|
||||
{
|
||||
parameterList.clear();
|
||||
}
|
||||
|
||||
void Effect::handleConnectToMediaObject(MediaObject *)
|
||||
{
|
||||
switch (effect_type) {
|
||||
case EffectInfo::AudioEffect:
|
||||
// libvlc_audio_filter_add(p_vlc_instance, (libvlc_audio_filter_names_t)i_effect_filter, vlc_exception);
|
||||
// vlcExceptionRaised();
|
||||
break;
|
||||
case EffectInfo::VideoEffect:
|
||||
// libvlc_video_filter_add(p_vlc_current_media_player, (libvlc_video_filter_names_t)i_effect_filter, vlc_exception);
|
||||
// vlcExceptionRaised();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Effect::handleDisconnectFromMediaObject(MediaObject *)
|
||||
{
|
||||
switch (effect_type) {
|
||||
case EffectInfo::AudioEffect:
|
||||
// libvlc_audio_filter_remove(p_vlc_instance, (libvlc_audio_filter_names_t)i_effect_filter, vlc_exception);
|
||||
// vlcExceptionRaised();
|
||||
break;
|
||||
case EffectInfo::VideoEffect:
|
||||
// libvlc_video_filter_remove(p_vlc_current_media_player, (libvlc_video_filter_names_t)i_effect_filter, vlc_exception);
|
||||
// vlcExceptionRaised();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Effect::setupEffectParams()
|
||||
{
|
||||
// libvlc_filter_parameter_list_t *p_list;
|
||||
switch (effect_type) {
|
||||
case EffectInfo::AudioEffect:
|
||||
// p_list = libvlc_audio_filter_get_parameters(p_vlc_instance, (libvlc_audio_filter_names_t)i_effect_filter, vlc_exception );
|
||||
// vlcExceptionRaised();
|
||||
break;
|
||||
case EffectInfo::VideoEffect:
|
||||
// p_list = libvlc_video_filter_get_parameters(p_vlc_instance, (libvlc_video_filter_names_t)i_effect_filter, vlc_exception );
|
||||
// vlcExceptionRaised();
|
||||
break;
|
||||
}
|
||||
// if( !p_list )
|
||||
// return;
|
||||
|
||||
// int i_index = 0;
|
||||
// libvlc_filter_parameter_list_t *p_parameter_list = p_list;
|
||||
// while (p_parameter_list) {
|
||||
// switch (p_parameter_list->var_type) {
|
||||
// case LIBVLC_BOOL: {
|
||||
// const QString description = p_parameter_list->psz_description;
|
||||
// parameterList.append(Phonon::EffectParameter(
|
||||
// i_index,
|
||||
// QString(p_parameter_list->psz_parameter_name),
|
||||
// Phonon::EffectParameter::ToggledHint, // hints
|
||||
// QVariant((bool) p_parameter_list->default_value.b_bool),
|
||||
// QVariant((bool) false),
|
||||
// QVariant((bool) true),
|
||||
// QVariantList(),
|
||||
// description));
|
||||
// break;
|
||||
// }
|
||||
// case LIBVLC_INT: {
|
||||
// const QString description = p_parameter_list->psz_description;
|
||||
// parameterList.append(Phonon::EffectParameter(
|
||||
// i_index,
|
||||
// QString(p_parameter_list->psz_parameter_name),
|
||||
// EffectParameter::IntegerHint, // hints
|
||||
// QVariant((int) p_parameter_list->default_value.i_int),
|
||||
// QVariant((int) p_parameter_list->min_value.i_int),
|
||||
// QVariant((int) p_parameter_list->max_value.i_int),
|
||||
// QVariantList(),
|
||||
// description));
|
||||
// break;
|
||||
// }
|
||||
// case LIBVLC_FLOAT: {
|
||||
// const QString description = p_parameter_list->psz_description;
|
||||
// parameterList.append(Phonon::EffectParameter(
|
||||
// i_index,
|
||||
// QString(p_parameter_list->psz_parameter_name),
|
||||
// 0, // hints
|
||||
// QVariant((double) p_parameter_list->default_value.f_float),
|
||||
// QVariant((double) p_parameter_list->min_value.f_float),
|
||||
// QVariant((double) p_parameter_list->max_value.f_float),
|
||||
// QVariantList(),
|
||||
// description));
|
||||
// break;
|
||||
// }
|
||||
// case LIBVLC_STRING: {
|
||||
// const QString description = p_parameter_list->psz_description;
|
||||
// parameterList.append(Phonon::EffectParameter(
|
||||
// i_index,
|
||||
// QString(p_parameter_list->psz_parameter_name),
|
||||
// 0, // hints
|
||||
// QVariant((const char *) p_parameter_list->default_value.psz_string),
|
||||
// NULL,
|
||||
// NULL,
|
||||
// QVariantList(),
|
||||
// description));
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// i_index++;
|
||||
// p_parameter_list = p_parameter_list->p_next;
|
||||
// }
|
||||
// libvlc_filter_parameters_release(p_list);
|
||||
}
|
||||
|
||||
QList<EffectParameter> Effect::parameters() const
|
||||
{
|
||||
return parameterList;
|
||||
}
|
||||
|
||||
QVariant Effect::parameterValue(const EffectParameter ¶m) const
|
||||
{
|
||||
Q_UNUSED(param);
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
void Effect::setParameterValue(const EffectParameter ¶m, const QVariant &newValue)
|
||||
{
|
||||
Q_UNUSED(param);
|
||||
Q_UNUSED(newValue);
|
||||
// libvlc_value_t value;
|
||||
// libvlc_var_type_t type;
|
||||
// switch (param.type()) {
|
||||
// case QVariant::Bool:
|
||||
// value.b_bool = newValue.toBool();
|
||||
// type = LIBVLC_BOOL;
|
||||
// break;
|
||||
// case QVariant::Int:
|
||||
// value.i_int = newValue.toInt();
|
||||
// type = LIBVLC_INT;
|
||||
// break;
|
||||
// case QVariant::Double:
|
||||
// value.f_float = (float) newValue.toDouble();
|
||||
// type = LIBVLC_FLOAT;
|
||||
// break;
|
||||
// case QVariant::String:
|
||||
// value.psz_string = newValue.toString().toAscii().data();
|
||||
// type = LIBVLC_STRING;
|
||||
// break;
|
||||
// default:
|
||||
// break;
|
||||
// }
|
||||
// switch (effect_type) {
|
||||
// case EffectInfo::AudioEffect:
|
||||
// libvlc_audio_filter_set_parameter(
|
||||
// p_vlc_instance,
|
||||
// // (libvlc_audio_filter_names_t) i_effect_filter,
|
||||
// param.name().toAscii().data(),
|
||||
// type,
|
||||
// value,
|
||||
// vlc_exception);
|
||||
// vlcExceptionRaised();
|
||||
// break;
|
||||
// case EffectInfo::VideoEffect:
|
||||
// libvlc_video_filter_set_parameter(
|
||||
// p_vlc_current_media_player,
|
||||
// (libvlc_video_filter_names_t) i_effect_filter,
|
||||
// param.name().toAscii().data(),
|
||||
// type,
|
||||
// value,
|
||||
// vlc_exception);
|
||||
// vlcExceptionRaised();
|
||||
// break;
|
||||
// }
|
||||
}
|
||||
|
||||
}
|
||||
} // Namespace Phonon::VLC
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
Copyright (C) 2007-2008 Tanguy Krotoff <tkrotoff@gmail.com>
|
||||
Copyright (C) 2008 Lukas Durfina <lukas.durfina@gmail.com>
|
||||
Copyright (C) 2009 Fathi Boudra <fabo@kde.org>
|
||||
Copyright (C) 2009-2011 vlc-phonon AUTHORS <kde-multimedia@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef PHONON_VLC_EFFECT_H
|
||||
#define PHONON_VLC_EFFECT_H
|
||||
|
||||
#include "sinknode.h"
|
||||
#include "effectmanager.h"
|
||||
|
||||
#include <phonon/effectinterface.h>
|
||||
#include <phonon/effectparameter.h>
|
||||
|
||||
namespace Phonon
|
||||
{
|
||||
namespace VLC
|
||||
{
|
||||
|
||||
class EffectManager;
|
||||
|
||||
/** \brief Effect implementation for Phonon-VLC
|
||||
*
|
||||
* There are methods to get or set the effect parameters, implemented for
|
||||
* the EffectInterface. See the Phonon documentation for details.
|
||||
*
|
||||
* As a sink node, it provides methods to handle the connection to a media object.
|
||||
*
|
||||
* An effect manager is the parent of each effect.
|
||||
*
|
||||
* \see EffectManager
|
||||
* \see VolumeFaderEffect
|
||||
*/
|
||||
class Effect : public QObject, public SinkNode, public EffectInterface
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(Phonon::EffectInterface)
|
||||
|
||||
public:
|
||||
|
||||
Effect(EffectManager *p_em, int i_effectId, QObject *p_parent);
|
||||
~Effect();
|
||||
|
||||
void setupEffectParams();
|
||||
QList<EffectParameter> parameters() const;
|
||||
QVariant parameterValue(const EffectParameter ¶m) const;
|
||||
void setParameterValue(const EffectParameter ¶m, const QVariant &newValue);
|
||||
|
||||
/** \reimp */
|
||||
void handleConnectToMediaObject(MediaObject *p_media_object);
|
||||
/** \reimp */
|
||||
void handleDisconnectFromMediaObject(MediaObject *p_media_object);
|
||||
|
||||
private:
|
||||
|
||||
EffectManager *p_effectManager;
|
||||
int i_effect_filter;
|
||||
EffectInfo::Type effect_type;
|
||||
QList<Phonon::EffectParameter> parameterList;
|
||||
};
|
||||
|
||||
}
|
||||
} // Namespace Phonon::VLC
|
||||
|
||||
#endif // PHONON_VLC_EFFECT_H
|
|
@ -0,0 +1,135 @@
|
|||
/*
|
||||
Copyright (C) 2007-2008 Tanguy Krotoff <tkrotoff@gmail.com>
|
||||
Copyright (C) 2008 Lukas Durfina <lukas.durfina@gmail.com>
|
||||
Copyright (C) 2009 Fathi Boudra <fabo@kde.org>
|
||||
Copyright (C) 2009-2011 vlc-phonon AUTHORS <kde-multimedia@kde.org>
|
||||
Copyright (C) 2011 Harald Sitter <sitter@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "effectmanager.h"
|
||||
|
||||
#include <vlc/vlc.h>
|
||||
#include <vlc/libvlc_version.h>
|
||||
|
||||
#if (LIBVLC_VERSION_INT >= LIBVLC_VERSION(2, 2, 0, 0))
|
||||
#include "equalizereffect.h"
|
||||
#endif
|
||||
|
||||
#include "utils/debug.h"
|
||||
#include "utils/libvlc.h"
|
||||
|
||||
namespace Phonon {
|
||||
namespace VLC {
|
||||
|
||||
EffectInfo::EffectInfo(const QString &name, const QString &description,
|
||||
const QString &author, int filter, Type type)
|
||||
: m_name(name)
|
||||
, m_description(description)
|
||||
, m_author(author)
|
||||
, m_filter(filter)
|
||||
, m_type(type)
|
||||
{}
|
||||
|
||||
EffectManager::EffectManager(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
if (!pvlc_libvlc)
|
||||
return;
|
||||
|
||||
updateEffects();
|
||||
}
|
||||
|
||||
EffectManager::~EffectManager()
|
||||
{
|
||||
m_audioEffectList.clear();
|
||||
m_videoEffectList.clear();
|
||||
|
||||
// EffectsList holds the same pointers as audio and video, so qDeleteAll on
|
||||
// this container would cause a double freeing.
|
||||
m_effectList.clear();
|
||||
}
|
||||
|
||||
const QList<EffectInfo> EffectManager::audioEffects() const
|
||||
{
|
||||
return m_audioEffectList;
|
||||
}
|
||||
|
||||
const QList<EffectInfo> EffectManager::videoEffects() const
|
||||
{
|
||||
return m_videoEffectList;
|
||||
}
|
||||
|
||||
const QList<EffectInfo> EffectManager::effects() const
|
||||
{
|
||||
return m_effectList;
|
||||
}
|
||||
|
||||
QObject *EffectManager::createEffect(int id, QObject *parent)
|
||||
{
|
||||
Q_UNUSED(id);
|
||||
#if (LIBVLC_VERSION_INT >= LIBVLC_VERSION(2, 2, 0, 0))
|
||||
return new EqualizerEffect(parent);
|
||||
#else
|
||||
Q_UNUSED(parent);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
void EffectManager::updateEffects()
|
||||
{
|
||||
DEBUG_BLOCK;
|
||||
|
||||
m_effectList.clear();
|
||||
m_audioEffectList.clear();
|
||||
m_videoEffectList.clear();
|
||||
|
||||
// Generic effect activation etc is entirely kaput and equalizer has specific
|
||||
// API anyway, so we simply manually insert it \o/
|
||||
|
||||
#if (LIBVLC_VERSION_INT >= LIBVLC_VERSION(2, 2, 0, 0))
|
||||
const QString eqName = QString("equalizer-%1bands").arg(QString::number(libvlc_audio_equalizer_get_band_count()));
|
||||
m_audioEffectList.append(EffectInfo(
|
||||
eqName,
|
||||
QString(""),
|
||||
QString(""),
|
||||
0,
|
||||
EffectInfo::AudioEffect));
|
||||
#endif
|
||||
|
||||
// int moduleCount = -1;
|
||||
// VLC_FOREACH_MODULE(module, libvlc_audio_filter_list_get(libvlc)) {
|
||||
// m_audioEffectList.append(new EffectInfo(module->psz_longname,
|
||||
// module->psz_help,
|
||||
// QString(),
|
||||
// ++moduleCount,
|
||||
// EffectInfo::AudioEffect));
|
||||
// }
|
||||
|
||||
// moduleCount = -1;
|
||||
// VLC_FOREACH_MODULE(module, libvlc_video_filter_list_get(libvlc)) {
|
||||
// m_videoEffectList.append(new EffectInfo(module->psz_longname,
|
||||
// module->psz_help,
|
||||
// QString(),
|
||||
// ++moduleCount,
|
||||
// EffectInfo::VideoEffect));
|
||||
// }
|
||||
|
||||
m_effectList.append(m_audioEffectList);
|
||||
m_effectList.append(m_videoEffectList);
|
||||
}
|
||||
|
||||
} // namespace VLC
|
||||
} // namespace Phonon
|
|
@ -0,0 +1,119 @@
|
|||
/*
|
||||
Copyright (C) 2007-2008 Tanguy Krotoff <tkrotoff@gmail.com>
|
||||
Copyright (C) 2008 Lukas Durfina <lukas.durfina@gmail.com>
|
||||
Copyright (C) 2009 Fathi Boudra <fabo@kde.org>
|
||||
Copyright (C) 2009-2011 vlc-phonon AUTHORS <kde-multimedia@kde.org>
|
||||
Copyright (C) 2011 Harald Sitter <sitter@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef Phonon_VLC_EFFECTMANAGER_H
|
||||
#define Phonon_VLC_EFFECTMANAGER_H
|
||||
|
||||
#include <QtCore/QObject>
|
||||
|
||||
namespace Phonon {
|
||||
namespace VLC {
|
||||
|
||||
class Backend;
|
||||
class EffectManager;
|
||||
|
||||
/// Holds information about an effect
|
||||
class EffectInfo
|
||||
{
|
||||
public:
|
||||
|
||||
enum Type {AudioEffect, VideoEffect};
|
||||
|
||||
EffectInfo(const QString &name,
|
||||
const QString &description,
|
||||
const QString &author,
|
||||
int filter,
|
||||
Type type);
|
||||
|
||||
QString name() const {
|
||||
return m_name;
|
||||
}
|
||||
|
||||
QString description() const {
|
||||
return m_description;
|
||||
}
|
||||
|
||||
QString author() const {
|
||||
return m_author;
|
||||
}
|
||||
|
||||
int filter() const {
|
||||
return m_filter;
|
||||
}
|
||||
|
||||
Type type() const {
|
||||
return m_type;
|
||||
}
|
||||
|
||||
private:
|
||||
QString m_name;
|
||||
QString m_description;
|
||||
QString m_author;
|
||||
int m_filter;
|
||||
Type m_type;
|
||||
};
|
||||
|
||||
/** \brief Manages a list of effects.
|
||||
*
|
||||
* \see EffectInfo
|
||||
*/
|
||||
class EffectManager : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
/**
|
||||
* Creates a new effect manager. It creates the lists of effects.
|
||||
*
|
||||
* \param backend A parent backend object for the effect manager
|
||||
*
|
||||
* \warning Currently it doesn't add any effects, everything is disabled.
|
||||
* \see EffectInfo
|
||||
*/
|
||||
explicit EffectManager(QObject *parent = 0);
|
||||
|
||||
/// Deletes all the effects from the lists and destroys the effect manager.
|
||||
~EffectManager();
|
||||
|
||||
/// Returns a list of available audio effects
|
||||
const QList<EffectInfo> audioEffects() const;
|
||||
|
||||
/// Returns a list of available video effects
|
||||
const QList<EffectInfo> videoEffects() const;
|
||||
|
||||
/// Returns a list of available effects
|
||||
const QList<EffectInfo> effects() const;
|
||||
|
||||
QObject *createEffect(int id, QObject *parent);
|
||||
|
||||
private:
|
||||
/// Generates the aggegated list of effects from both video and audio
|
||||
void updateEffects();
|
||||
|
||||
QList<EffectInfo> m_effectList;
|
||||
QList<EffectInfo> m_audioEffectList;
|
||||
QList<EffectInfo> m_videoEffectList;
|
||||
bool m_equalizerEnabled;
|
||||
};
|
||||
|
||||
} // namespace VLC
|
||||
} // namespace Phonon
|
||||
|
||||
#endif // Phonon_VLC_EFFECTMANAGER_H
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
Copyright (C) 2013 Harald Sitter <sitter@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "equalizereffect.h"
|
||||
|
||||
#include "mediaplayer.h"
|
||||
#include "utils/debug.h"
|
||||
|
||||
namespace Phonon {
|
||||
namespace VLC {
|
||||
|
||||
EqualizerEffect::EqualizerEffect(QObject *parent)
|
||||
: QObject(parent)
|
||||
, SinkNode()
|
||||
, EffectInterface()
|
||||
, m_equalizer(libvlc_audio_equalizer_new())
|
||||
{
|
||||
// Amarok decided to make up rules because phonon didn't manage to
|
||||
// pre-amp string needs to be pre-amp
|
||||
// bands need to be xxHz
|
||||
// That way they can be consistently mapped to localized/formatted strings.
|
||||
|
||||
EffectParameter preamp(-1, "pre-amp", 0 /* hint */, 0.0f, -20.0f, 20.0f);
|
||||
m_bands.append(preamp);
|
||||
|
||||
const unsigned int bandCount = libvlc_audio_equalizer_get_band_count();
|
||||
for (unsigned int i = 0; i < bandCount; ++i) {
|
||||
const float frequency = libvlc_audio_equalizer_get_band_frequency(i);
|
||||
const QString name = QString("%1Hz").arg(QString::number(frequency));
|
||||
EffectParameter parameter(i, name, 0 /* hint */, 0.0f, -20.0f, 20.0f);
|
||||
m_bands.append(parameter);
|
||||
}
|
||||
}
|
||||
|
||||
EqualizerEffect::~EqualizerEffect()
|
||||
{
|
||||
libvlc_audio_equalizer_release(m_equalizer);
|
||||
}
|
||||
|
||||
QList<EffectParameter> EqualizerEffect::parameters() const
|
||||
{
|
||||
return m_bands;
|
||||
}
|
||||
|
||||
QVariant EqualizerEffect::parameterValue(const EffectParameter ¶meter) const
|
||||
{
|
||||
return libvlc_audio_equalizer_get_amp_at_index(m_equalizer, parameter.id());
|
||||
}
|
||||
|
||||
void EqualizerEffect::setParameterValue(const EffectParameter ¶meter,
|
||||
const QVariant &newValue)
|
||||
{
|
||||
if (parameter.id() == -1)
|
||||
libvlc_audio_equalizer_set_preamp(m_equalizer, newValue.toFloat());
|
||||
else
|
||||
libvlc_audio_equalizer_set_amp_at_index(m_equalizer, newValue.toFloat(), parameter.id());
|
||||
}
|
||||
|
||||
void EqualizerEffect::handleConnectToMediaObject(MediaObject *mediaObject)
|
||||
{
|
||||
Q_UNUSED(mediaObject);
|
||||
m_player->setEqualizer(m_equalizer);
|
||||
}
|
||||
|
||||
} // namespace VLC
|
||||
} // namespace Phonon
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
Copyright (C) 2013 Harald Sitter <sitter@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef PHONON_VLC_EQUALIZEREFFECT_H
|
||||
#define PHONON_VLC_EQUALIZEREFFECT_H
|
||||
|
||||
#include <QtCore/QObject>
|
||||
|
||||
#include <phonon/effectinterface.h>
|
||||
#include <phonon/effectparameter.h>
|
||||
|
||||
#include <vlc/vlc.h>
|
||||
|
||||
#include "sinknode.h"
|
||||
|
||||
namespace Phonon {
|
||||
namespace VLC {
|
||||
|
||||
class EqualizerEffect : public QObject, public SinkNode, public EffectInterface
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(Phonon::EffectInterface)
|
||||
public:
|
||||
explicit EqualizerEffect(QObject *parent = 0);
|
||||
~EqualizerEffect();
|
||||
|
||||
QList<EffectParameter> parameters() const;
|
||||
QVariant parameterValue(const EffectParameter ¶meter) const;
|
||||
void setParameterValue(const EffectParameter ¶meter, const QVariant &newValue);
|
||||
|
||||
void handleConnectToMediaObject(MediaObject *mediaObject);
|
||||
|
||||
private:
|
||||
libvlc_equalizer_t *m_equalizer;
|
||||
QList <EffectParameter> m_bands;
|
||||
};
|
||||
|
||||
} // namespace VLC
|
||||
} // namespace Phonon
|
||||
|
||||
#endif // PHONON_VLC_EQUALIZEREFFECT_H
|
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
Copyright (C) 2011 Harald Sitter <sitter@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "media.h"
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
|
||||
#include <vlc/vlc.h>
|
||||
|
||||
#include "utils/debug.h"
|
||||
#include "utils/libvlc.h"
|
||||
#include "utils/vstring.h"
|
||||
|
||||
namespace Phonon {
|
||||
namespace VLC {
|
||||
|
||||
Media::Media(const QByteArray &mrl, QObject *parent) :
|
||||
QObject(parent),
|
||||
m_media(libvlc_media_new_location(pvlc_libvlc, mrl.constData())),
|
||||
m_mrl(mrl)
|
||||
{
|
||||
Q_ASSERT(m_media);
|
||||
|
||||
libvlc_event_manager_t *manager = libvlc_media_event_manager(m_media);
|
||||
libvlc_event_type_t events[] = {
|
||||
libvlc_MediaMetaChanged,
|
||||
libvlc_MediaSubItemAdded,
|
||||
libvlc_MediaDurationChanged,
|
||||
libvlc_MediaParsedChanged,
|
||||
libvlc_MediaFreed,
|
||||
libvlc_MediaStateChanged
|
||||
};
|
||||
const int eventCount = sizeof(events) / sizeof(*events);
|
||||
for (int i = 0; i < eventCount; ++i) {
|
||||
libvlc_event_attach(manager, events[i], event_cb, this);
|
||||
}
|
||||
}
|
||||
|
||||
Media::~Media()
|
||||
{
|
||||
if (m_media) {
|
||||
libvlc_media_release(m_media);
|
||||
m_media = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Media::addOption(const QString &option)
|
||||
{
|
||||
libvlc_media_add_option_flag(m_media,
|
||||
option.toUtf8().data(),
|
||||
libvlc_media_option_trusted);
|
||||
}
|
||||
|
||||
QString Media::meta(libvlc_meta_t meta)
|
||||
{
|
||||
return VString(libvlc_media_get_meta(m_media, meta)).toQString();
|
||||
}
|
||||
|
||||
void Media::event_cb(const libvlc_event_t *event, void *opaque)
|
||||
{
|
||||
Media *that = reinterpret_cast<Media *>(opaque);
|
||||
Q_ASSERT(that);
|
||||
|
||||
switch (event->type) {
|
||||
case libvlc_MediaDurationChanged:
|
||||
QMetaObject::invokeMethod(
|
||||
that, "durationChanged",
|
||||
Qt::QueuedConnection,
|
||||
Q_ARG(qint64, event->u.media_duration_changed.new_duration));
|
||||
break;
|
||||
case libvlc_MediaMetaChanged:
|
||||
QMetaObject::invokeMethod(
|
||||
that, "metaDataChanged",
|
||||
Qt::QueuedConnection);
|
||||
break;
|
||||
case libvlc_MediaSubItemAdded:
|
||||
case libvlc_MediaParsedChanged:
|
||||
case libvlc_MediaFreed:
|
||||
case libvlc_MediaStateChanged:
|
||||
default:
|
||||
break;
|
||||
QString msg = QString("Unknown event: ") + QString(libvlc_event_type_name(event->type));
|
||||
Q_ASSERT_X(false, "event_cb", qPrintable(msg));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Media::setCdTrack(int track)
|
||||
{
|
||||
debug() << "setting CDDA track" << track;
|
||||
addOption(QLatin1String(":cdda-track="), QVariant(track));
|
||||
}
|
||||
|
||||
} // namespace VLC
|
||||
} // namespace Phonon
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
Copyright (C) 2011 Harald Sitter <sitter@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef PHONON_VLC_MEDIA_H
|
||||
#define PHONON_VLC_MEDIA_H
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QStringBuilder>
|
||||
#include <QtCore/QVariant>
|
||||
|
||||
#include <vlc/libvlc.h>
|
||||
#include <vlc/libvlc_media.h>
|
||||
|
||||
#define INTPTR_PTR(x) reinterpret_cast<intptr_t>(x)
|
||||
#define INTPTR_FUNC(x) reinterpret_cast<intptr_t>(&x)
|
||||
|
||||
namespace Phonon {
|
||||
namespace VLC {
|
||||
|
||||
class Media : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit Media(const QByteArray &mrl, QObject *parent = 0);
|
||||
~Media();
|
||||
|
||||
inline libvlc_media_t *libvlc_media() const { return m_media; }
|
||||
inline operator libvlc_media_t *() const { return m_media; }
|
||||
|
||||
inline void addOption(const QString &option, const QVariant &argument)
|
||||
{
|
||||
addOption(option % argument.toString());
|
||||
}
|
||||
|
||||
inline void addOption(const QString &option, intptr_t functionPtr)
|
||||
{
|
||||
QString optionWithPtr = option;
|
||||
optionWithPtr.append(QString::number(static_cast<qint64>(functionPtr)));
|
||||
addOption(optionWithPtr);
|
||||
}
|
||||
|
||||
void addOption(const QString &option);
|
||||
|
||||
QString meta(libvlc_meta_t meta);
|
||||
|
||||
void setCdTrack(int track);
|
||||
|
||||
signals:
|
||||
void durationChanged(qint64 duration);
|
||||
void metaDataChanged();
|
||||
|
||||
private:
|
||||
static void event_cb(const libvlc_event_t *event, void *opaque);
|
||||
|
||||
libvlc_media_t *m_media;
|
||||
libvlc_state_t m_state;
|
||||
QByteArray m_mrl;
|
||||
};
|
||||
|
||||
} // namespace VLC
|
||||
} // namespace Phonon
|
||||
|
||||
#endif // PHONON_VLC_MEDIA_H
|
|
@ -0,0 +1,497 @@
|
|||
/*
|
||||
Copyright (C) 2007-2008 Tanguy Krotoff <tkrotoff@gmail.com>
|
||||
Copyright (C) 2008 Lukas Durfina <lukas.durfina@gmail.com>
|
||||
Copyright (C) 2009 Fathi Boudra <fabo@kde.org>
|
||||
Copyright (C) 2009-2011 vlc-phonon AUTHORS <kde-multimedia@kde.org>
|
||||
Copyright (C) 2011-2018 Harald Sitter <sitter@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "mediacontroller.h"
|
||||
|
||||
#include <phonon/GlobalDescriptionContainer>
|
||||
|
||||
#include <QTimer>
|
||||
|
||||
#include "utils/debug.h"
|
||||
#include "utils/libvlc.h"
|
||||
#include "mediaplayer.h"
|
||||
|
||||
namespace Phonon {
|
||||
namespace VLC {
|
||||
|
||||
#ifdef __GNUC__
|
||||
#warning titles and chapters not covered by globaldescriptioncontainer!!
|
||||
#endif
|
||||
|
||||
MediaController::MediaController()
|
||||
: m_subtitleAutodetect(true)
|
||||
, m_subtitleEncoding("UTF-8")
|
||||
, m_subtitleFontChanged(false)
|
||||
, m_player(0)
|
||||
, m_refreshTimer(new QTimer(dynamic_cast<QObject *>(this)))
|
||||
, m_attemptingAutoplay(false)
|
||||
{
|
||||
GlobalSubtitles::instance()->register_(this);
|
||||
GlobalAudioChannels::instance()->register_(this);
|
||||
resetMembers();
|
||||
}
|
||||
|
||||
MediaController::~MediaController()
|
||||
{
|
||||
GlobalSubtitles::instance()->unregister_(this);
|
||||
GlobalAudioChannels::instance()->unregister_(this);
|
||||
}
|
||||
|
||||
bool MediaController::hasInterface(Interface iface) const
|
||||
{
|
||||
switch (iface) {
|
||||
case AddonInterface::NavigationInterface:
|
||||
return true;
|
||||
break;
|
||||
case AddonInterface::ChapterInterface:
|
||||
return true;
|
||||
break;
|
||||
case AddonInterface::AngleInterface:
|
||||
return false;
|
||||
break;
|
||||
case AddonInterface::TitleInterface:
|
||||
return true;
|
||||
break;
|
||||
case AddonInterface::SubtitleInterface:
|
||||
return true;
|
||||
break;
|
||||
case AddonInterface::AudioChannelInterface:
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
|
||||
warning() << "Interface" << iface << "is not supported by Phonon VLC :(";
|
||||
return false;
|
||||
}
|
||||
|
||||
QVariant MediaController::interfaceCall(Interface iface, int i_command, const QList<QVariant> & arguments)
|
||||
{
|
||||
DEBUG_BLOCK;
|
||||
switch (iface) {
|
||||
case AddonInterface::ChapterInterface:
|
||||
switch (static_cast<AddonInterface::ChapterCommand>(i_command)) {
|
||||
case AddonInterface::availableChapters:
|
||||
return availableChapters();
|
||||
case AddonInterface::chapter:
|
||||
return currentChapter();
|
||||
case AddonInterface::setChapter:
|
||||
if (arguments.isEmpty() || !arguments.first().canConvert(QVariant::Int)) {
|
||||
error() << Q_FUNC_INFO << "arguments invalid";
|
||||
return false;
|
||||
}
|
||||
setCurrentChapter(arguments.first().toInt());
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case AddonInterface::TitleInterface:
|
||||
switch (static_cast<AddonInterface::TitleCommand>(i_command)) {
|
||||
case AddonInterface::availableTitles:
|
||||
return availableTitles();
|
||||
case AddonInterface::title:
|
||||
return currentTitle();
|
||||
case AddonInterface::setTitle:
|
||||
if (arguments.isEmpty() || !arguments.first().canConvert(QVariant::Int)) {
|
||||
error() << Q_FUNC_INFO << "arguments invalid";
|
||||
return false;
|
||||
}
|
||||
setCurrentTitle(arguments.first().toInt());
|
||||
return true;
|
||||
case AddonInterface::autoplayTitles:
|
||||
return autoplayTitles();
|
||||
case AddonInterface::setAutoplayTitles:
|
||||
if (arguments.isEmpty() || !arguments.first().canConvert(QVariant::Bool)) {
|
||||
error() << Q_FUNC_INFO << " arguments invalid";
|
||||
return false;
|
||||
}
|
||||
setAutoplayTitles(arguments.first().toBool());
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case AddonInterface::AngleInterface:
|
||||
warning() << "AddonInterface::AngleInterface not supported!";
|
||||
break;
|
||||
case AddonInterface::SubtitleInterface:
|
||||
switch (static_cast<AddonInterface::SubtitleCommand>(i_command)) {
|
||||
case AddonInterface::availableSubtitles:
|
||||
return QVariant::fromValue(availableSubtitles());
|
||||
case AddonInterface::currentSubtitle:
|
||||
return QVariant::fromValue(currentSubtitle());
|
||||
case AddonInterface::setCurrentSubtitle:
|
||||
if (arguments.isEmpty() || !arguments.first().canConvert<SubtitleDescription>()) {
|
||||
error() << Q_FUNC_INFO << "arguments invalid";
|
||||
return false;
|
||||
}
|
||||
setCurrentSubtitle(arguments.first().value<SubtitleDescription>());
|
||||
return true;
|
||||
case AddonInterface::setCurrentSubtitleFile:
|
||||
if (arguments.isEmpty() || !arguments.first().canConvert<QUrl>()) {
|
||||
error() << Q_FUNC_INFO << " arguments invalid";
|
||||
return false;
|
||||
}
|
||||
setCurrentSubtitleFile(arguments.first().value<QUrl>());
|
||||
case AddonInterface::subtitleAutodetect:
|
||||
return QVariant::fromValue(subtitleAutodetect());
|
||||
case AddonInterface::setSubtitleAutodetect:
|
||||
if (arguments.isEmpty() || !arguments.first().canConvert<bool>()) {
|
||||
error() << Q_FUNC_INFO << " arguments invalid";
|
||||
return false;
|
||||
}
|
||||
setSubtitleAutodetect(arguments.first().value<bool>());
|
||||
return true;
|
||||
case AddonInterface::subtitleEncoding:
|
||||
return subtitleEncoding();
|
||||
case AddonInterface::setSubtitleEncoding:
|
||||
if (arguments.isEmpty() || !arguments.first().canConvert<QString>()) {
|
||||
error() << Q_FUNC_INFO << " arguments invalid";
|
||||
return false;
|
||||
}
|
||||
setSubtitleEncoding(arguments.first().value<QString>());
|
||||
return true;
|
||||
case AddonInterface::subtitleFont:
|
||||
return subtitleFont();
|
||||
case AddonInterface::setSubtitleFont:
|
||||
if (arguments.isEmpty() || !arguments.first().canConvert<QFont>()) {
|
||||
error() << Q_FUNC_INFO << " arguments invalid";
|
||||
return false;
|
||||
}
|
||||
setSubtitleFont(arguments.first().value<QFont>());
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case AddonInterface::AudioChannelInterface:
|
||||
switch (static_cast<AddonInterface::AudioChannelCommand>(i_command)) {
|
||||
case AddonInterface::availableAudioChannels:
|
||||
return QVariant::fromValue(availableAudioChannels());
|
||||
case AddonInterface::currentAudioChannel:
|
||||
return QVariant::fromValue(currentAudioChannel());
|
||||
case AddonInterface::setCurrentAudioChannel:
|
||||
if (arguments.isEmpty() || !arguments.first().canConvert<AudioChannelDescription>()) {
|
||||
error() << Q_FUNC_INFO << "arguments invalid";
|
||||
return false;
|
||||
}
|
||||
setCurrentAudioChannel(arguments.first().value<AudioChannelDescription>());
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
error() << Q_FUNC_INFO << "unsupported AddonInterface::Interface:" << iface;
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
void MediaController::resetMediaController()
|
||||
{
|
||||
resetMembers();
|
||||
emit availableAudioChannelsChanged();
|
||||
emit availableSubtitlesChanged();
|
||||
emit availableTitlesChanged(0);
|
||||
emit availableChaptersChanged(0);
|
||||
}
|
||||
|
||||
void MediaController::resetMembers()
|
||||
{
|
||||
m_currentAudioChannel = Phonon::AudioChannelDescription();
|
||||
GlobalAudioChannels::self->clearListFor(this);
|
||||
|
||||
m_currentSubtitle = Phonon::SubtitleDescription();
|
||||
GlobalSubtitles::instance()->clearListFor(this);
|
||||
|
||||
m_currentChapter = 0;
|
||||
m_availableChapters = 0;
|
||||
|
||||
m_currentTitle = 1;
|
||||
m_availableTitles = 0;
|
||||
|
||||
m_attemptingAutoplay = false;
|
||||
}
|
||||
|
||||
// ----------------------------- Audio Channel ------------------------------ //
|
||||
void MediaController::setCurrentAudioChannel(const Phonon::AudioChannelDescription &audioChannel)
|
||||
{
|
||||
const int localIndex = GlobalAudioChannels::instance()->localIdFor(this, audioChannel.index());
|
||||
if (!m_player->setAudioTrack(localIndex))
|
||||
error() << "libVLC:" << LibVLC::errorMessage();
|
||||
else
|
||||
m_currentAudioChannel = audioChannel;
|
||||
}
|
||||
|
||||
QList<Phonon::AudioChannelDescription> MediaController::availableAudioChannels() const
|
||||
{
|
||||
return GlobalAudioChannels::instance()->listFor(this);
|
||||
}
|
||||
|
||||
Phonon::AudioChannelDescription MediaController::currentAudioChannel() const
|
||||
{
|
||||
return m_currentAudioChannel;
|
||||
}
|
||||
|
||||
void MediaController::refreshAudioChannels()
|
||||
{
|
||||
GlobalAudioChannels::instance()->clearListFor(this);
|
||||
|
||||
const int currentChannelId = m_player->audioTrack();
|
||||
|
||||
int idCount = 0;
|
||||
VLC_FOREACH_TRACK(it, m_player->audioTrackDescription()) {
|
||||
#if (LIBVLC_VERSION_INT >= LIBVLC_VERSION(3, 0, 0, 0))
|
||||
idCount= it->i_id;
|
||||
#else
|
||||
// LibVLC's internal ID is broken, so we simply count up as internally
|
||||
// the setter will simply go by position in list anyway.
|
||||
#endif
|
||||
GlobalAudioChannels::instance()->add(this, idCount, QString::fromUtf8(it->psz_name), "");
|
||||
if (idCount == currentChannelId) {
|
||||
#ifdef __GNUC__
|
||||
#warning GlobalDescriptionContainer does not allow reverse resolution from local to descriptor!
|
||||
#endif
|
||||
const QList<AudioChannelDescription> list = GlobalAudioChannels::instance()->listFor(this);
|
||||
foreach (const AudioChannelDescription &descriptor, list) {
|
||||
if (descriptor.name() == QString::fromUtf8(it->psz_name)) {
|
||||
m_currentAudioChannel = descriptor;
|
||||
}
|
||||
}
|
||||
}
|
||||
++idCount;
|
||||
}
|
||||
|
||||
emit availableAudioChannelsChanged();
|
||||
}
|
||||
|
||||
// -------------------------------- Subtitle -------------------------------- //
|
||||
void MediaController::setCurrentSubtitle(const Phonon::SubtitleDescription &subtitle)
|
||||
{
|
||||
DEBUG_BLOCK;
|
||||
QString type = subtitle.property("type").toString();
|
||||
|
||||
debug() << subtitle;
|
||||
|
||||
if (type == "file") {
|
||||
QString filename = subtitle.property("name").toString();
|
||||
if (!filename.isEmpty()) {
|
||||
if (!m_player->setSubtitle(filename))
|
||||
error() << "libVLC:" << LibVLC::errorMessage();
|
||||
else
|
||||
m_currentSubtitle = subtitle;
|
||||
|
||||
// There is no subtitle event inside libvlc so let's send our own event...
|
||||
GlobalSubtitles::instance()->add(this, m_currentSubtitle);
|
||||
emit availableSubtitlesChanged();
|
||||
}
|
||||
} else {
|
||||
const int localIndex = GlobalSubtitles::instance()->localIdFor(this, subtitle.index());
|
||||
debug () << "localid" << localIndex;
|
||||
if (!m_player->setSubtitle(localIndex))
|
||||
error() << "libVLC:" << LibVLC::errorMessage();
|
||||
else
|
||||
m_currentSubtitle = subtitle;
|
||||
}
|
||||
}
|
||||
|
||||
void MediaController::setCurrentSubtitleFile(const QUrl &url)
|
||||
{
|
||||
const QString file = url.toLocalFile();
|
||||
if (!m_player->setSubtitle(file))
|
||||
error() << "libVLC failed to set subtitle file:" << LibVLC::errorMessage();
|
||||
// Unfortunately the addition of SPUs does not trigger an event in the
|
||||
// VLC mediaplayer, yet the actual addition to the descriptor is async.
|
||||
// So for the time being our best shot at getting an up-to-date list of SPUs
|
||||
// is shooting in the dark and hoping we hit something.
|
||||
// Refresha after 1, 2 and 5 seconds. If we have no updated list after 5
|
||||
// seconds we are out of luck.
|
||||
// https://trac.videolan.org/vlc/ticket/9796
|
||||
QObject *mediaObject = dynamic_cast<QObject *>(this); // MediaObject : QObject, MediaController
|
||||
m_refreshTimer->singleShot(1 * 1000, mediaObject, SLOT(refreshDescriptors()));
|
||||
m_refreshTimer->singleShot(2 * 1000, mediaObject, SLOT(refreshDescriptors()));
|
||||
m_refreshTimer->singleShot(5 * 1000, mediaObject, SLOT(refreshDescriptors()));
|
||||
}
|
||||
|
||||
QList<Phonon::SubtitleDescription> MediaController::availableSubtitles() const
|
||||
{
|
||||
return GlobalSubtitles::instance()->listFor(this);
|
||||
}
|
||||
|
||||
Phonon::SubtitleDescription MediaController::currentSubtitle() const
|
||||
{
|
||||
return m_currentSubtitle;
|
||||
}
|
||||
|
||||
void MediaController::refreshSubtitles()
|
||||
{
|
||||
DEBUG_BLOCK;
|
||||
GlobalSubtitles::instance()->clearListFor(this);
|
||||
|
||||
const int currentSubtitleId = m_player->subtitle();
|
||||
|
||||
VLC_FOREACH_TRACK(it, m_player->videoSubtitleDescription()) {
|
||||
debug() << "found subtitle" << it->psz_name << "[" << it->i_id << "]";
|
||||
GlobalSubtitles::instance()->add(this, it->i_id, QString::fromUtf8(it->psz_name), "");
|
||||
if (it->i_id == currentSubtitleId) {
|
||||
#ifdef __GNUC__
|
||||
#warning GlobalDescriptionContainer does not allow reverse resolution from local to descriptor!
|
||||
#endif
|
||||
const QList<SubtitleDescription> list = GlobalSubtitles::instance()->listFor(this);
|
||||
foreach (const SubtitleDescription &descriptor, list) {
|
||||
if (descriptor.name() == QString::fromUtf8(it->psz_name)) {
|
||||
m_currentSubtitle = descriptor;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
emit availableSubtitlesChanged();
|
||||
}
|
||||
|
||||
bool MediaController::subtitleAutodetect() const
|
||||
{
|
||||
return m_subtitleAutodetect;
|
||||
}
|
||||
|
||||
void MediaController::setSubtitleAutodetect(bool enabled)
|
||||
{
|
||||
m_subtitleAutodetect = enabled;
|
||||
}
|
||||
|
||||
QString MediaController::subtitleEncoding() const
|
||||
{
|
||||
return m_subtitleEncoding;
|
||||
}
|
||||
|
||||
void MediaController::setSubtitleEncoding(const QString &encoding)
|
||||
{
|
||||
m_subtitleEncoding = encoding;
|
||||
}
|
||||
|
||||
QFont MediaController::subtitleFont() const
|
||||
{
|
||||
return m_subtitleFont;
|
||||
}
|
||||
|
||||
void MediaController::setSubtitleFont(const QFont &font)
|
||||
{
|
||||
m_subtitleFontChanged = true;
|
||||
m_subtitleFont = font;
|
||||
}
|
||||
|
||||
// --------------------------------- Title ---------------------------------- //
|
||||
void MediaController::setCurrentTitle(int title)
|
||||
{
|
||||
DEBUG_BLOCK;
|
||||
m_currentTitle = title;
|
||||
|
||||
switch (source().discType()) {
|
||||
case Cd:
|
||||
m_player->setCdTrack(title);
|
||||
return;
|
||||
case Dvd:
|
||||
case Vcd:
|
||||
case BluRay:
|
||||
m_player->setTitle(title);
|
||||
return;
|
||||
case NoDisc:
|
||||
warning() << "Current media source is not a CD, DVD or VCD!";
|
||||
return;
|
||||
}
|
||||
|
||||
warning() << "MediaSource does not support setting of tile in this version of Phonon VLC!"
|
||||
<< "Type is" << source().discType();
|
||||
}
|
||||
|
||||
int MediaController::availableTitles() const
|
||||
{
|
||||
return m_availableTitles;
|
||||
}
|
||||
|
||||
int MediaController::currentTitle() const
|
||||
{
|
||||
return m_currentTitle;
|
||||
}
|
||||
|
||||
void MediaController::setAutoplayTitles(bool autoplay)
|
||||
{
|
||||
m_autoPlayTitles = autoplay;
|
||||
}
|
||||
|
||||
bool MediaController::autoplayTitles() const
|
||||
{
|
||||
return m_autoPlayTitles;
|
||||
}
|
||||
|
||||
void MediaController::refreshTitles()
|
||||
{
|
||||
m_availableTitles = 0;
|
||||
|
||||
#if (LIBVLC_VERSION_INT >= LIBVLC_VERSION(3, 0, 0, 0))
|
||||
SharedTitleDescriptions list = m_player->titleDescription();
|
||||
for (unsigned int i = 0; i < list->size(); ++i) {
|
||||
++m_availableTitles;
|
||||
emit availableTitlesChanged(m_availableTitles);
|
||||
}
|
||||
#else
|
||||
VLC_FOREACH_TRACK(it, m_player->titleDescription()) {
|
||||
++m_availableTitles;
|
||||
emit availableTitlesChanged(m_availableTitles);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// -------------------------------- Chapter --------------------------------- //
|
||||
void MediaController::setCurrentChapter(int chapter)
|
||||
{
|
||||
m_currentChapter = chapter;
|
||||
m_player->setChapter(chapter);
|
||||
}
|
||||
|
||||
int MediaController::availableChapters() const
|
||||
{
|
||||
return m_availableChapters;
|
||||
}
|
||||
|
||||
int MediaController::currentChapter() const
|
||||
{
|
||||
return m_currentChapter;
|
||||
}
|
||||
|
||||
// We need to rebuild available chapters when title is changed
|
||||
void MediaController::refreshChapters(int title)
|
||||
{
|
||||
m_availableChapters = 0;
|
||||
|
||||
// Get the description of available chapters for specific title
|
||||
#if (LIBVLC_VERSION_INT >= LIBVLC_VERSION(3, 0, 0, 0))
|
||||
SharedChapterDescriptions list = m_player->videoChapterDescription(title);
|
||||
for (unsigned int i = 0; i < list->size(); ++i) {
|
||||
++m_availableChapters;
|
||||
emit availableChaptersChanged(m_availableChapters);
|
||||
}
|
||||
#else
|
||||
VLC_FOREACH_TRACK(it, m_player->videoChapterDescription(title)) {
|
||||
++m_availableChapters;
|
||||
emit availableChaptersChanged(m_availableChapters);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// --------------------------------- Angle ---------------------------------- //
|
||||
// NOT SUPPORTED IN LIBVLC //
|
||||
|
||||
} // namespace VLC
|
||||
} // namespace Phonon
|
|
@ -0,0 +1,156 @@
|
|||
/*
|
||||
Copyright (C) 2007-2008 Tanguy Krotoff <tkrotoff@gmail.com>
|
||||
Copyright (C) 2008 Lukas Durfina <lukas.durfina@gmail.com>
|
||||
Copyright (C) 2009 Fathi Boudra <fabo@kde.org>
|
||||
Copyright (C) 2009-2011 vlc-phonon AUTHORS <kde-multimedia@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef PHONON_VLC_MEDIACONTROLLER_H
|
||||
#define PHONON_VLC_MEDIACONTROLLER_H
|
||||
|
||||
#include <phonon/AddonInterface>
|
||||
#include <phonon/MediaSource>
|
||||
#include <phonon/ObjectDescription>
|
||||
|
||||
#include <QtGui/QFont>
|
||||
|
||||
class QTimer;
|
||||
|
||||
namespace Phonon {
|
||||
namespace VLC {
|
||||
|
||||
class MediaPlayer;
|
||||
|
||||
/**
|
||||
* \brief Interface for AddonInterface.
|
||||
*
|
||||
* Provides a bridge between Phonon's AddonInterface and MediaController.
|
||||
*
|
||||
* This class cannot inherit from QObject has MediaObject already inherit from QObject.
|
||||
* This is a Qt limitation: there is no possibility to inherit virtual Qobject :/
|
||||
* See http://doc.trolltech.com/qq/qq15-academic.html
|
||||
* Phonon implementation got the same problem.
|
||||
*
|
||||
* \see MediaObject
|
||||
*/
|
||||
class MediaController : public AddonInterface
|
||||
{
|
||||
public:
|
||||
|
||||
MediaController();
|
||||
virtual ~MediaController();
|
||||
|
||||
bool hasInterface(Interface iface) const;
|
||||
|
||||
QVariant interfaceCall(Interface iface, int i_command, const QList<QVariant> & arguments = QList<QVariant>());
|
||||
|
||||
/**
|
||||
* Overloaded by MediaObject through MediaObjectInterface.
|
||||
* Access to the media source is necessary to identify the type of the source
|
||||
* and behave accordingly.
|
||||
*
|
||||
* For example setTitle calls need to work on both DVDs and CDs, however
|
||||
* in libvlc titles and tracks are two different concepts.
|
||||
*/
|
||||
virtual MediaSource source() const = 0;
|
||||
|
||||
// MediaController signals
|
||||
virtual void availableSubtitlesChanged() = 0;
|
||||
virtual void availableAudioChannelsChanged() = 0;
|
||||
|
||||
virtual void availableChaptersChanged(int) = 0;
|
||||
virtual void availableTitlesChanged(int) = 0;
|
||||
|
||||
void titleAdded(int id, const QString &name);
|
||||
void chapterAdded(int titleId, const QString &name);
|
||||
|
||||
protected:
|
||||
// AudioChannel
|
||||
void setCurrentAudioChannel(const Phonon::AudioChannelDescription &audioChannel);
|
||||
QList<Phonon::AudioChannelDescription> availableAudioChannels() const;
|
||||
Phonon::AudioChannelDescription currentAudioChannel() const;
|
||||
void refreshAudioChannels();
|
||||
|
||||
// Subtitle
|
||||
void setCurrentSubtitle(const Phonon::SubtitleDescription &subtitle);
|
||||
void setCurrentSubtitleFile(const QUrl &url);
|
||||
QList<Phonon::SubtitleDescription> availableSubtitles() const;
|
||||
Phonon::SubtitleDescription currentSubtitle() const;
|
||||
void refreshSubtitles();
|
||||
bool subtitleAutodetect() const;
|
||||
void setSubtitleAutodetect(bool enabled);
|
||||
QString subtitleEncoding() const;
|
||||
void setSubtitleEncoding(const QString &encoding);
|
||||
QFont subtitleFont() const;
|
||||
void setSubtitleFont(const QFont &font);
|
||||
|
||||
// Chapter
|
||||
void setCurrentChapter(int chapterNumber);
|
||||
int availableChapters() const;
|
||||
int currentChapter() const;
|
||||
void refreshChapters(int title);
|
||||
|
||||
// Title
|
||||
void setCurrentTitle(int titleNumber);
|
||||
int availableTitles() const;
|
||||
int currentTitle() const;
|
||||
void setAutoplayTitles(bool autoplay);
|
||||
bool autoplayTitles() const;
|
||||
void refreshTitles();
|
||||
|
||||
/**
|
||||
* Clear all member variables and emit appropriate signals.
|
||||
* This is used each time we restart the video.
|
||||
*
|
||||
* \see resetMembers
|
||||
*/
|
||||
void resetMediaController();
|
||||
|
||||
/**
|
||||
* Reset all member variables.
|
||||
*
|
||||
* \see resetMediaController
|
||||
*/
|
||||
void resetMembers();
|
||||
|
||||
Phonon::AudioChannelDescription m_currentAudioChannel;
|
||||
Phonon::SubtitleDescription m_currentSubtitle;
|
||||
|
||||
int m_currentChapter;
|
||||
int m_availableChapters;
|
||||
|
||||
int m_currentTitle;
|
||||
int m_availableTitles;
|
||||
|
||||
bool m_autoPlayTitles;
|
||||
|
||||
bool m_subtitleAutodetect;
|
||||
QString m_subtitleEncoding;
|
||||
bool m_subtitleFontChanged;
|
||||
QFont m_subtitleFont;
|
||||
|
||||
// MediaPlayer
|
||||
MediaPlayer *m_player;
|
||||
|
||||
QTimer *m_refreshTimer;
|
||||
|
||||
bool m_attemptingAutoplay;
|
||||
};
|
||||
|
||||
} // namespace VLC
|
||||
} // namespace Phonon
|
||||
|
||||
#endif // PHONON_VLC_MEDIACONTROLLER_H
|
|
@ -0,0 +1,844 @@
|
|||
/*
|
||||
Copyright (C) 2007-2008 Tanguy Krotoff <tkrotoff@gmail.com>
|
||||
Copyright (C) 2008 Lukas Durfina <lukas.durfina@gmail.com>
|
||||
Copyright (C) 2009 Fathi Boudra <fabo@kde.org>
|
||||
Copyright (C) 2010 Ben Cooksley <sourtooth@gmail.com>
|
||||
Copyright (C) 2009-2011 vlc-phonon AUTHORS <kde-multimedia@kde.org>
|
||||
Copyright (C) 2010-2021 Harald Sitter <sitter@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "mediaobject.h"
|
||||
|
||||
#include <QtCore/QDir>
|
||||
#include <QtCore/QStringBuilder>
|
||||
#include <QtCore/QUrl>
|
||||
|
||||
#include <phonon/pulsesupport.h>
|
||||
|
||||
#include <vlc/libvlc_version.h>
|
||||
#include <vlc/vlc.h>
|
||||
|
||||
#include "utils/debug.h"
|
||||
#include "utils/libvlc.h"
|
||||
#include "media.h"
|
||||
#include "sinknode.h"
|
||||
#include "streamreader.h"
|
||||
|
||||
//Time in milliseconds before sending aboutToFinish() signal
|
||||
//2 seconds
|
||||
static const int ABOUT_TO_FINISH_TIME = 2000;
|
||||
|
||||
namespace Phonon {
|
||||
namespace VLC {
|
||||
|
||||
MediaObject::MediaObject(QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_nextSource(MediaSource(QUrl()))
|
||||
, m_streamReader(0)
|
||||
, m_state(Phonon::StoppedState)
|
||||
, m_tickInterval(0)
|
||||
, m_transitionTime(0)
|
||||
, m_media(0)
|
||||
{
|
||||
qRegisterMetaType<QMultiMap<QString, QString> >("QMultiMap<QString, QString>");
|
||||
|
||||
m_player = new MediaPlayer(this);
|
||||
Q_ASSERT(m_player);
|
||||
if (!m_player->libvlc_media_player())
|
||||
error() << "libVLC:" << LibVLC::errorMessage();
|
||||
|
||||
// Player signals.
|
||||
connect(m_player, SIGNAL(seekableChanged(bool)), this, SIGNAL(seekableChanged(bool)));
|
||||
connect(m_player, SIGNAL(timeChanged(qint64)), this, SLOT(timeChanged(qint64)));
|
||||
connect(m_player, SIGNAL(stateChanged(MediaPlayer::State)), this, SLOT(updateState(MediaPlayer::State)));
|
||||
connect(m_player, SIGNAL(hasVideoChanged(bool)), this, SLOT(onHasVideoChanged(bool)));
|
||||
connect(m_player, SIGNAL(bufferChanged(int)), this, SLOT(setBufferStatus(int)));
|
||||
connect(m_player, SIGNAL(timeChanged(qint64)), this, SLOT(timeChanged(qint64)));
|
||||
|
||||
// Internal Signals.
|
||||
connect(this, SIGNAL(moveToNext()), SLOT(moveToNextSource()));
|
||||
connect(m_refreshTimer, SIGNAL(timeout()), this, SLOT(refreshDescriptors()));
|
||||
|
||||
resetMembers();
|
||||
}
|
||||
|
||||
MediaObject::~MediaObject()
|
||||
{
|
||||
unloadMedia();
|
||||
// Shutdown the pulseaudio mainloop before the MediaPlayer gets destroyed
|
||||
// (it is a child of the MO). There appears to be a peculiar race condition
|
||||
// between the pa_thread_mainloop used by VLC and the pa_glib_mainloop used
|
||||
// by Phonon's PulseSupport where for a very short time frame after the
|
||||
// former was stopped and freed the latter can run and fall over
|
||||
// Invalid read from eventfd: Bad file descriptor
|
||||
// Code should not be reached at pulsecore/fdsem.c:157, function flush(). Aborting.
|
||||
// Since we don't use PulseSupport since VLC 2.2 we can simply force a
|
||||
// loop shutdown even when the application isn't about to terminate.
|
||||
// The instance gets created again anyway.
|
||||
PulseSupport::shutdown();
|
||||
}
|
||||
|
||||
void MediaObject::resetMembers()
|
||||
{
|
||||
// default to -1, so that streams won't break and to comply with the docs (-1 if unknown)
|
||||
m_totalTime = -1;
|
||||
m_hasVideo = false;
|
||||
m_seekpoint = 0;
|
||||
|
||||
m_prefinishEmitted = false;
|
||||
m_aboutToFinishEmitted = false;
|
||||
|
||||
m_lastTick = 0;
|
||||
|
||||
m_timesVideoChecked = 0;
|
||||
|
||||
m_buffering = false;
|
||||
m_stateAfterBuffering = ErrorState;
|
||||
|
||||
resetMediaController();
|
||||
|
||||
// Forcefully shutdown plusesupport to prevent crashing between the PS PA glib mainloop
|
||||
// and the VLC PA threaded mainloop. See destructor.
|
||||
PulseSupport::shutdown();
|
||||
}
|
||||
|
||||
void MediaObject::play()
|
||||
{
|
||||
DEBUG_BLOCK;
|
||||
|
||||
switch (m_state) {
|
||||
case PlayingState:
|
||||
// Do not do anything if we are already playing (as per documentation).
|
||||
return;
|
||||
case PausedState:
|
||||
m_player->resume();
|
||||
break;
|
||||
default:
|
||||
setupMedia();
|
||||
if (m_player->play())
|
||||
error() << "libVLC:" << LibVLC::errorMessage();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void MediaObject::pause()
|
||||
{
|
||||
DEBUG_BLOCK;
|
||||
switch (m_state) {
|
||||
case BufferingState:
|
||||
case PlayingState:
|
||||
m_player->pause();
|
||||
break;
|
||||
case PausedState:
|
||||
return;
|
||||
default:
|
||||
debug() << "doing paused play";
|
||||
setupMedia();
|
||||
m_player->pausedPlay();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void MediaObject::stop()
|
||||
{
|
||||
DEBUG_BLOCK;
|
||||
if (m_streamReader)
|
||||
m_streamReader->unlock();
|
||||
m_nextSource = MediaSource(QUrl());
|
||||
m_player->stop();
|
||||
}
|
||||
|
||||
void MediaObject::seek(qint64 milliseconds)
|
||||
{
|
||||
DEBUG_BLOCK;
|
||||
|
||||
switch (m_state) {
|
||||
case PlayingState:
|
||||
case PausedState:
|
||||
case BufferingState:
|
||||
break;
|
||||
default:
|
||||
// Seeking while not being in a playingish state is cached for later.
|
||||
m_seekpoint = milliseconds;
|
||||
return;
|
||||
}
|
||||
|
||||
debug() << "seeking" << milliseconds << "msec";
|
||||
|
||||
m_player->setTime(milliseconds);
|
||||
|
||||
const qint64 time = currentTime();
|
||||
const qint64 total = totalTime();
|
||||
|
||||
// Reset last tick marker so we emit time even after seeking
|
||||
if (time < m_lastTick)
|
||||
m_lastTick = time;
|
||||
if (time < total - m_prefinishMark)
|
||||
m_prefinishEmitted = false;
|
||||
if (time < total - ABOUT_TO_FINISH_TIME)
|
||||
m_aboutToFinishEmitted = false;
|
||||
}
|
||||
|
||||
void MediaObject::timeChanged(qint64 time)
|
||||
{
|
||||
const qint64 totalTime = m_totalTime;
|
||||
|
||||
switch (m_state) {
|
||||
case PlayingState:
|
||||
case BufferingState:
|
||||
case PausedState:
|
||||
emitTick(time);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (m_state == PlayingState || m_state == BufferingState) { // Buffering is concurrent
|
||||
if (time >= totalTime - m_prefinishMark) {
|
||||
if (!m_prefinishEmitted) {
|
||||
m_prefinishEmitted = true;
|
||||
emit prefinishMarkReached(totalTime - time);
|
||||
}
|
||||
}
|
||||
// Note that when the totalTime is <= 0 we cannot calculate any sane delta.
|
||||
if (totalTime > 0 && time >= totalTime - ABOUT_TO_FINISH_TIME)
|
||||
emitAboutToFinish();
|
||||
}
|
||||
}
|
||||
|
||||
void MediaObject::emitTick(qint64 time)
|
||||
{
|
||||
if (m_tickInterval == 0) // Make sure we do not ever emit ticks when deactivated.\]
|
||||
return;
|
||||
if (time + m_tickInterval >= m_lastTick) {
|
||||
m_lastTick = time;
|
||||
emit tick(time);
|
||||
}
|
||||
}
|
||||
|
||||
void MediaObject::loadMedia(const QByteArray &mrl)
|
||||
{
|
||||
DEBUG_BLOCK;
|
||||
|
||||
// Initial state is loading, from which we quickly progress to stopped because
|
||||
// libvlc does not provide feedback on loading and the media does not get loaded
|
||||
// until we play it.
|
||||
// FIXME: libvlc should really allow for this as it can cause unexpected delay
|
||||
// even though the GUI might indicate that playback should start right away.
|
||||
changeState(Phonon::LoadingState);
|
||||
|
||||
m_mrl = mrl;
|
||||
debug() << "loading encoded:" << m_mrl;
|
||||
|
||||
// We do not have a loading state generally speaking, usually the backend
|
||||
// is exepected to go to loading state and then at some point reach stopped,
|
||||
// at which point playback can be started.
|
||||
// See state enum documentation for more information.
|
||||
changeState(Phonon::StoppedState);
|
||||
}
|
||||
|
||||
void MediaObject::loadMedia(const QString &mrl)
|
||||
{
|
||||
loadMedia(mrl.toUtf8());
|
||||
}
|
||||
|
||||
qint32 MediaObject::tickInterval() const
|
||||
{
|
||||
return m_tickInterval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Supports runtime changes.
|
||||
* If the user goes to tick(0) we stop the timer, otherwise we fire it up.
|
||||
*/
|
||||
void MediaObject::setTickInterval(qint32 interval)
|
||||
{
|
||||
m_tickInterval = interval;
|
||||
}
|
||||
|
||||
qint64 MediaObject::currentTime() const
|
||||
{
|
||||
qint64 time = -1;
|
||||
|
||||
switch (state()) {
|
||||
case Phonon::PausedState:
|
||||
case Phonon::BufferingState:
|
||||
case Phonon::PlayingState:
|
||||
time = m_player->time();
|
||||
break;
|
||||
case Phonon::StoppedState:
|
||||
case Phonon::LoadingState:
|
||||
time = 0;
|
||||
break;
|
||||
case Phonon::ErrorState:
|
||||
time = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
return time;
|
||||
}
|
||||
|
||||
Phonon::State MediaObject::state() const
|
||||
{
|
||||
return m_state;
|
||||
}
|
||||
|
||||
Phonon::ErrorType MediaObject::errorType() const
|
||||
{
|
||||
return Phonon::NormalError;
|
||||
}
|
||||
|
||||
MediaSource MediaObject::source() const
|
||||
{
|
||||
return m_mediaSource;
|
||||
}
|
||||
|
||||
void MediaObject::setSource(const MediaSource &source)
|
||||
{
|
||||
DEBUG_BLOCK;
|
||||
|
||||
// Reset previous streamereaders
|
||||
if (m_streamReader) {
|
||||
m_streamReader->unlock();
|
||||
delete m_streamReader;
|
||||
m_streamReader = 0;
|
||||
// For streamreaders we exchanage the player's seekability with the
|
||||
// reader's so here we change it back.
|
||||
// Note: the reader auto-disconnects due to destruction.
|
||||
connect(m_player, SIGNAL(seekableChanged(bool)), this, SIGNAL(seekableChanged(bool)));
|
||||
}
|
||||
|
||||
// Reset previous isScreen flag
|
||||
m_isScreen = false;
|
||||
|
||||
m_mediaSource = source;
|
||||
|
||||
QByteArray url;
|
||||
switch (source.type()) {
|
||||
case MediaSource::Invalid:
|
||||
error() << Q_FUNC_INFO << "MediaSource Type is Invalid:" << source.type();
|
||||
break;
|
||||
case MediaSource::Empty:
|
||||
error() << Q_FUNC_INFO << "MediaSource is empty.";
|
||||
break;
|
||||
case MediaSource::LocalFile:
|
||||
case MediaSource::Url:
|
||||
debug() << "MediaSource::Url:" << source.url();
|
||||
if (source.url().scheme().isEmpty()) {
|
||||
url = "file://";
|
||||
// QUrl considers url.scheme.isEmpty() == url.isRelative(),
|
||||
// so to be sure the url is not actually absolute we just
|
||||
// check the first character
|
||||
if (!source.url().toString().startsWith('/'))
|
||||
url.append(QFile::encodeName(QDir::currentPath()) + '/');
|
||||
}
|
||||
url += source.url().toEncoded();
|
||||
loadMedia(url);
|
||||
break;
|
||||
case MediaSource::Disc:
|
||||
switch (source.discType()) {
|
||||
case Phonon::NoDisc:
|
||||
error() << Q_FUNC_INFO << "the MediaSource::Disc doesn't specify which one (Phonon::NoDisc)";
|
||||
return;
|
||||
case Phonon::Cd:
|
||||
loadMedia(QLatin1Literal("cdda://") % m_mediaSource.deviceName());
|
||||
break;
|
||||
case Phonon::Dvd:
|
||||
loadMedia(QLatin1Literal("dvd://") % m_mediaSource.deviceName());
|
||||
break;
|
||||
case Phonon::Vcd:
|
||||
loadMedia(QLatin1Literal("vcd://") % m_mediaSource.deviceName());
|
||||
break;
|
||||
case Phonon::BluRay:
|
||||
loadMedia(QLatin1Literal("bluray://") % m_mediaSource.deviceName());
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case MediaSource::CaptureDevice: {
|
||||
QByteArray driverName;
|
||||
QString deviceName;
|
||||
|
||||
if (source.deviceAccessList().isEmpty()) {
|
||||
error() << Q_FUNC_INFO << "No device access list for this capture device";
|
||||
break;
|
||||
}
|
||||
|
||||
// TODO try every device in the access list until it works, not just the first one
|
||||
driverName = source.deviceAccessList().first().first;
|
||||
deviceName = source.deviceAccessList().first().second;
|
||||
|
||||
if (driverName == QByteArray("v4l2")) {
|
||||
loadMedia(QLatin1Literal("v4l2://") % deviceName);
|
||||
} else if (driverName == QByteArray("alsa")) {
|
||||
/*
|
||||
* Replace "default" and "plughw" and "x-phonon" with "hw" for capture device names, because
|
||||
* VLC does not want to open them when using default instead of hw.
|
||||
* plughw also does not work.
|
||||
*
|
||||
* TODO investigate what happens
|
||||
*/
|
||||
if (deviceName.startsWith(QLatin1String("default"))) {
|
||||
deviceName.replace(0, 7, "hw");
|
||||
}
|
||||
if (deviceName.startsWith(QLatin1String("plughw"))) {
|
||||
deviceName.replace(0, 6, "hw");
|
||||
}
|
||||
if (deviceName.startsWith(QLatin1String("x-phonon"))) {
|
||||
deviceName.replace(0, 8, "hw");
|
||||
}
|
||||
|
||||
loadMedia(QLatin1Literal("alsa://") % deviceName);
|
||||
} else if (driverName == "screen") {
|
||||
loadMedia(QLatin1Literal("screen://") % deviceName);
|
||||
|
||||
// Set the isScreen flag needed to add extra options in playInternal
|
||||
m_isScreen = true;
|
||||
} else {
|
||||
error() << Q_FUNC_INFO << "Unsupported MediaSource::CaptureDevice:" << driverName;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MediaSource::Stream:
|
||||
m_streamReader = new StreamReader(this);
|
||||
// LibVLC refuses to emit seekability as it does a try-and-seek approach
|
||||
// to work around this we exchange the player's seekability signal
|
||||
// for the readers
|
||||
// https://bugs.kde.org/show_bug.cgi?id=293012
|
||||
connect(m_streamReader, SIGNAL(streamSeekableChanged(bool)), this, SIGNAL(seekableChanged(bool)));
|
||||
disconnect(m_player, SIGNAL(seekableChanged(bool)), this, SIGNAL(seekableChanged(bool)));
|
||||
// Only connect now to avoid seekability detection before we are connected.
|
||||
m_streamReader->connectToSource(source);
|
||||
loadMedia(QByteArray("imem://"));
|
||||
break;
|
||||
}
|
||||
|
||||
debug() << "Sending currentSourceChanged";
|
||||
emit currentSourceChanged(m_mediaSource);
|
||||
}
|
||||
|
||||
void MediaObject::setNextSource(const MediaSource &source)
|
||||
{
|
||||
DEBUG_BLOCK;
|
||||
debug() << source.url();
|
||||
m_nextSource = source;
|
||||
// This function is not ever called by the consumer but only libphonon.
|
||||
// Furthermore libphonon only calls this function in its aboutToFinish slot,
|
||||
// iff sources are already in the queue. In case our aboutToFinish was too
|
||||
// late we may already be stopped when the slot gets activated.
|
||||
// Therefore we need to make sure that we move to the next source iff
|
||||
// this function is called when we are in stoppedstate.
|
||||
if (m_state == StoppedState)
|
||||
moveToNext();
|
||||
}
|
||||
|
||||
qint32 MediaObject::prefinishMark() const
|
||||
{
|
||||
return m_prefinishMark;
|
||||
}
|
||||
|
||||
void MediaObject::setPrefinishMark(qint32 msecToEnd)
|
||||
{
|
||||
m_prefinishMark = msecToEnd;
|
||||
if (currentTime() < totalTime() - m_prefinishMark) {
|
||||
// Not about to finish
|
||||
m_prefinishEmitted = false;
|
||||
}
|
||||
}
|
||||
|
||||
qint32 MediaObject::transitionTime() const
|
||||
{
|
||||
return m_transitionTime;
|
||||
}
|
||||
|
||||
void MediaObject::setTransitionTime(qint32 time)
|
||||
{
|
||||
m_transitionTime = time;
|
||||
}
|
||||
|
||||
void MediaObject::emitAboutToFinish()
|
||||
{
|
||||
if (!m_aboutToFinishEmitted) {
|
||||
// Track is about to finish
|
||||
m_aboutToFinishEmitted = true;
|
||||
emit aboutToFinish();
|
||||
}
|
||||
}
|
||||
|
||||
// State changes are force queued by libphonon.
|
||||
void MediaObject::changeState(Phonon::State newState)
|
||||
{
|
||||
DEBUG_BLOCK;
|
||||
|
||||
// State not changed
|
||||
if (newState == m_state)
|
||||
return;
|
||||
|
||||
debug() << m_state << "-->" << newState;
|
||||
|
||||
#ifdef __GNUC__
|
||||
#warning do we actually need m_seekpoint? if a consumer seeks before playing state that is their problem?!
|
||||
#endif
|
||||
// Workaround that seeking needs to work before the file is being played...
|
||||
// We store seeks and apply them when going to seek (or discard them on reset).
|
||||
if (newState == PlayingState) {
|
||||
if (m_seekpoint != 0) {
|
||||
seek(m_seekpoint);
|
||||
m_seekpoint = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// State changed
|
||||
Phonon::State previousState = m_state;
|
||||
m_state = newState;
|
||||
emit stateChanged(m_state, previousState);
|
||||
}
|
||||
|
||||
void MediaObject::moveToNextSource()
|
||||
{
|
||||
DEBUG_BLOCK;
|
||||
|
||||
setSource(m_nextSource);
|
||||
|
||||
// The consumer may set an invalid source as final source to force a
|
||||
// queued stop, regardless of how fast the consumer is at actually calling
|
||||
// stop. Such a source must not cause an actual move (moving ~= state
|
||||
// changes towards playing) but instead we only set the source to reflect
|
||||
// that we got the setNextSource call.
|
||||
if (hasNextTrack())
|
||||
play();
|
||||
|
||||
m_nextSource = MediaSource(QUrl());
|
||||
}
|
||||
|
||||
inline bool MediaObject::hasNextTrack()
|
||||
{
|
||||
return m_nextSource.type() != MediaSource::Invalid && m_nextSource.type() != MediaSource::Empty;
|
||||
}
|
||||
|
||||
inline void MediaObject::unloadMedia()
|
||||
{
|
||||
if (m_media) {
|
||||
m_media->disconnect(this);
|
||||
m_media->deleteLater();
|
||||
m_media = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void MediaObject::setupMedia()
|
||||
{
|
||||
DEBUG_BLOCK;
|
||||
|
||||
unloadMedia();
|
||||
resetMembers();
|
||||
|
||||
// Create a media with the given MRL
|
||||
m_media = new Media(m_mrl, this);
|
||||
if (!m_media)
|
||||
error() << "libVLC:" << LibVLC::errorMessage();
|
||||
|
||||
if (m_isScreen) {
|
||||
m_media->addOption(QLatin1String("screen-fps=24.0"));
|
||||
m_media->addOption(QLatin1String("screen-caching=300"));
|
||||
}
|
||||
|
||||
if (source().discType() == Cd && m_currentTitle > 0)
|
||||
m_media->setCdTrack(m_currentTitle);
|
||||
|
||||
if (m_streamReader)
|
||||
// StreamReader is no sink but a source, for this we have no concept right now
|
||||
// also we do not need one since the reader is the only source we have.
|
||||
// Consequently we need to manually tell the StreamReader to attach to the Media.
|
||||
m_streamReader->addToMedia(m_media);
|
||||
|
||||
if (!m_subtitleAutodetect)
|
||||
m_media->addOption(QLatin1String(":no-sub-autodetect-file"));
|
||||
|
||||
if (m_subtitleEncoding != QLatin1String("UTF-8")) // utf8 is phonon default, so let vlc handle it
|
||||
m_media->addOption(QLatin1String(":subsdec-encoding="), m_subtitleEncoding);
|
||||
|
||||
if (!m_subtitleFontChanged) // Update font settings
|
||||
m_subtitleFont = QFont();
|
||||
|
||||
#ifdef __GNUC__
|
||||
#warning freetype module is not working as expected - font api not working
|
||||
#endif
|
||||
// BUG: VLC's freetype module doesn't pick up per-media options
|
||||
// vlc -vvvv --freetype-font="Comic Sans MS" multiple_sub_sample.mkv :freetype-font=Arial
|
||||
// https://trac.videolan.org/vlc/ticket/9797
|
||||
m_media->addOption(QLatin1String(":freetype-font="), m_subtitleFont.family());
|
||||
m_media->addOption(QLatin1String(":freetype-fontsize="), m_subtitleFont.pointSize());
|
||||
if (m_subtitleFont.bold())
|
||||
m_media->addOption(QLatin1String(":freetype-bold"));
|
||||
else
|
||||
m_media->addOption(QLatin1String(":no-freetype-bold"));
|
||||
|
||||
foreach (SinkNode *sink, m_sinks) {
|
||||
sink->addToMedia(m_media);
|
||||
}
|
||||
|
||||
// Connect to Media signals. Disconnection is done at unloading.
|
||||
connect(m_media, SIGNAL(durationChanged(qint64)),
|
||||
this, SLOT(updateDuration(qint64)));
|
||||
connect(m_media, SIGNAL(metaDataChanged()),
|
||||
this, SLOT(updateMetaData()));
|
||||
|
||||
// Update available audio channels/subtitles/angles/chapters/etc...
|
||||
// i.e everything from MediaController
|
||||
// There is no audio channel/subtitle/angle/chapter events inside libvlc
|
||||
// so let's send our own events...
|
||||
// This will reset the GUI
|
||||
resetMediaController();
|
||||
|
||||
// Play
|
||||
m_player->setMedia(m_media);
|
||||
}
|
||||
|
||||
QString MediaObject::errorString() const
|
||||
{
|
||||
return libvlc_errmsg();
|
||||
}
|
||||
|
||||
bool MediaObject::hasVideo() const
|
||||
{
|
||||
// Cached: sometimes 4.0.0-dev sends the vout event but then
|
||||
// has_vout is still false. Guard against this by simply always reporting
|
||||
// the last hasVideoChanged value. If that is off we can still drop into
|
||||
// libvlc in case it changed meanwhile.
|
||||
return m_hasVideo || m_player->hasVideoOutput();
|
||||
}
|
||||
|
||||
bool MediaObject::isSeekable() const
|
||||
{
|
||||
if (m_streamReader)
|
||||
return m_streamReader->streamSeekable();
|
||||
return m_player->isSeekable();
|
||||
}
|
||||
|
||||
void MediaObject::updateDuration(qint64 newDuration)
|
||||
{
|
||||
// This here cache is needed because we need to provide -1 as totalTime()
|
||||
// for as long as we do not get a proper update through this slot.
|
||||
// VLC reports -1 with no media but 0 if it does not know the duration, so
|
||||
// apps that assume 0 = unknown get screwed if they query too early.
|
||||
// http://bugs.tomahawk-player.org/browse/TWK-1029
|
||||
m_totalTime = newDuration;
|
||||
emit totalTimeChanged(m_totalTime);
|
||||
}
|
||||
|
||||
void MediaObject::updateMetaData()
|
||||
{
|
||||
QMultiMap<QString, QString> metaDataMap;
|
||||
|
||||
const QString artist = m_media->meta(libvlc_meta_Artist);
|
||||
const QString title = m_media->meta(libvlc_meta_Title);
|
||||
const QString nowPlaying = m_media->meta(libvlc_meta_NowPlaying);
|
||||
|
||||
// Streams sometimes have the artist and title munged in nowplaying.
|
||||
// With ALBUM = Title and TITLE = NowPlaying it will still show up nicely in Amarok.
|
||||
if (artist.isEmpty() && !nowPlaying.isEmpty()) {
|
||||
metaDataMap.insert(QLatin1String("ALBUM"), title);
|
||||
metaDataMap.insert(QLatin1String("TITLE"), nowPlaying);
|
||||
} else {
|
||||
metaDataMap.insert(QLatin1String("ALBUM"), m_media->meta(libvlc_meta_Album));
|
||||
metaDataMap.insert(QLatin1String("TITLE"), title);
|
||||
}
|
||||
|
||||
metaDataMap.insert(QLatin1String("ARTIST"), artist);
|
||||
metaDataMap.insert(QLatin1String("DATE"), m_media->meta(libvlc_meta_Date));
|
||||
metaDataMap.insert(QLatin1String("GENRE"), m_media->meta(libvlc_meta_Genre));
|
||||
metaDataMap.insert(QLatin1String("TRACKNUMBER"), m_media->meta(libvlc_meta_TrackNumber));
|
||||
metaDataMap.insert(QLatin1String("DESCRIPTION"), m_media->meta(libvlc_meta_Description));
|
||||
metaDataMap.insert(QLatin1String("COPYRIGHT"), m_media->meta(libvlc_meta_Copyright));
|
||||
metaDataMap.insert(QLatin1String("URL"), m_media->meta(libvlc_meta_URL));
|
||||
metaDataMap.insert(QLatin1String("ENCODEDBY"), m_media->meta(libvlc_meta_EncodedBy));
|
||||
|
||||
if (metaDataMap == m_vlcMetaData) {
|
||||
// No need to issue any change, the data is the same
|
||||
return;
|
||||
}
|
||||
m_vlcMetaData = metaDataMap;
|
||||
|
||||
emit metaDataChanged(metaDataMap);
|
||||
}
|
||||
|
||||
void MediaObject::updateState(MediaPlayer::State state)
|
||||
{
|
||||
DEBUG_BLOCK;
|
||||
debug() << state;
|
||||
debug() << "attempted autoplay?" << m_attemptingAutoplay;
|
||||
|
||||
if (m_attemptingAutoplay) {
|
||||
switch (state) {
|
||||
case MediaPlayer::PlayingState:
|
||||
case MediaPlayer::PausedState:
|
||||
m_attemptingAutoplay = false;
|
||||
break;
|
||||
case MediaPlayer::ErrorState:
|
||||
debug() << "autoplay failed, must be end of media.";
|
||||
// The error should not be reflected to the consumer. So we swap it
|
||||
// for finished() which is actually what is happening here.
|
||||
// Or so we think ;)
|
||||
state = MediaPlayer::EndedState;
|
||||
--m_currentTitle;
|
||||
break;
|
||||
default:
|
||||
debug() << "not handling as part of autplay:" << state;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (state) {
|
||||
case MediaPlayer::NoState:
|
||||
changeState(LoadingState);
|
||||
break;
|
||||
case MediaPlayer::OpeningState:
|
||||
changeState(LoadingState);
|
||||
break;
|
||||
case MediaPlayer::BufferingState:
|
||||
changeState(BufferingState);
|
||||
break;
|
||||
case MediaPlayer::PlayingState:
|
||||
changeState(PlayingState);
|
||||
break;
|
||||
case MediaPlayer::PausedState:
|
||||
changeState(PausedState);
|
||||
break;
|
||||
case MediaPlayer::StoppedState:
|
||||
changeState(StoppedState);
|
||||
break;
|
||||
case MediaPlayer::EndedState:
|
||||
if (hasNextTrack()) {
|
||||
moveToNextSource();
|
||||
} else if (source().discType() == Cd && m_autoPlayTitles && !m_attemptingAutoplay) {
|
||||
debug() << "trying to simulate autoplay";
|
||||
m_attemptingAutoplay = true;
|
||||
m_player->setCdTrack(++m_currentTitle);
|
||||
} else {
|
||||
m_attemptingAutoplay = false;
|
||||
emitAboutToFinish();
|
||||
emit finished();
|
||||
changeState(StoppedState);
|
||||
}
|
||||
break;
|
||||
case MediaPlayer::ErrorState:
|
||||
debug() << errorString();
|
||||
emitAboutToFinish();
|
||||
emit finished();
|
||||
changeState(ErrorState);
|
||||
break;
|
||||
}
|
||||
|
||||
if (m_buffering) {
|
||||
switch (state) {
|
||||
case MediaPlayer::BufferingState:
|
||||
break;
|
||||
case MediaPlayer::PlayingState:
|
||||
debug() << "Restoring buffering state after state change to Playing";
|
||||
changeState(BufferingState);
|
||||
m_stateAfterBuffering = PlayingState;
|
||||
break;
|
||||
case MediaPlayer::PausedState:
|
||||
debug() << "Restoring buffering state after state change to Paused";
|
||||
changeState(BufferingState);
|
||||
m_stateAfterBuffering = PausedState;
|
||||
break;
|
||||
default:
|
||||
debug() << "Buffering aborted!";
|
||||
m_buffering = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void MediaObject::onHasVideoChanged(bool hasVideo)
|
||||
{
|
||||
DEBUG_BLOCK;
|
||||
if (m_hasVideo != hasVideo) {
|
||||
m_hasVideo = hasVideo;
|
||||
emit hasVideoChanged(m_hasVideo);
|
||||
} else {
|
||||
// We can simply return if we are have the appropriate caching already.
|
||||
// Otherwise we'd do pointless rescans of mediacontroller stuff.
|
||||
// MC and MO are force-reset on media changes anyway.
|
||||
return;
|
||||
}
|
||||
|
||||
refreshDescriptors();
|
||||
}
|
||||
|
||||
void MediaObject::setBufferStatus(int percent)
|
||||
{
|
||||
// VLC does not have a buffering state (surprise!) but instead only sends the
|
||||
// event (surprise!). Hence we need to simulate the state change.
|
||||
// Problem with BufferingState is that it is actually concurrent to Playing or Paused
|
||||
// meaning that while you are buffering you can also pause, thus triggering
|
||||
// a state change to paused. To handle this we let updateState change the
|
||||
// state accordingly (as we need to allow the UI to update itself, and
|
||||
// immediately after that we change back to buffering again.
|
||||
// This loop can only be interrupted by a state change to !Playing & !Paused
|
||||
// or by reaching a 100 % buffer caching (i.e. full cache).
|
||||
|
||||
m_buffering = true;
|
||||
if (m_state != BufferingState) {
|
||||
m_stateAfterBuffering = m_state;
|
||||
changeState(BufferingState);
|
||||
}
|
||||
|
||||
emit bufferStatus(percent);
|
||||
|
||||
// Transit to actual state only after emission so the signal is still
|
||||
// delivered while in BufferingState.
|
||||
if (percent >= 100) { // http://trac.videolan.org/vlc/ticket/5277
|
||||
m_buffering = false;
|
||||
changeState(m_stateAfterBuffering);
|
||||
}
|
||||
}
|
||||
|
||||
void MediaObject::refreshDescriptors()
|
||||
{
|
||||
if (m_player->titleCount() > 0)
|
||||
refreshTitles();
|
||||
|
||||
if (hasVideo()) {
|
||||
refreshAudioChannels();
|
||||
refreshSubtitles();
|
||||
|
||||
if (m_player->videoChapterCount() > 0)
|
||||
refreshChapters(m_player->title());
|
||||
}
|
||||
}
|
||||
|
||||
qint64 MediaObject::totalTime() const
|
||||
{
|
||||
return m_totalTime;
|
||||
}
|
||||
|
||||
void MediaObject::addSink(SinkNode *node)
|
||||
{
|
||||
Q_ASSERT(!m_sinks.contains(node));
|
||||
m_sinks.append(node);
|
||||
}
|
||||
|
||||
void MediaObject::removeSink(SinkNode *node)
|
||||
{
|
||||
Q_ASSERT(node);
|
||||
m_sinks.removeAll(node);
|
||||
}
|
||||
|
||||
} // namespace VLC
|
||||
} // namespace Phonon
|
|
@ -0,0 +1,347 @@
|
|||
/*
|
||||
Copyright (C) 2007-2008 Tanguy Krotoff <tkrotoff@gmail.com>
|
||||
Copyright (C) 2008 Lukas Durfina <lukas.durfina@gmail.com>
|
||||
Copyright (C) 2009 Fathi Boudra <fabo@kde.org>
|
||||
Copyright (C) 2009-2011 vlc-phonon AUTHORS <kde-multimedia@kde.org>
|
||||
Copyright (C) 2010-2011 Harald Sitter <sitter@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef PHONON_VLC_MEDIAOBJECT_H
|
||||
#define PHONON_VLC_MEDIAOBJECT_H
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QTimer>
|
||||
|
||||
#include <phonon/mediaobjectinterface.h>
|
||||
#include <phonon/addoninterface.h>
|
||||
|
||||
#include "mediacontroller.h"
|
||||
#include "mediaplayer.h"
|
||||
|
||||
namespace Phonon
|
||||
{
|
||||
namespace VLC
|
||||
{
|
||||
|
||||
class Media;
|
||||
class SinkNode;
|
||||
class StreamReader;
|
||||
|
||||
/** \brief Implementation for the most important class in Phonon
|
||||
*
|
||||
* The MediaObject class is the workhorse for Phonon. It handles what is needed
|
||||
* to play media. It has a media source object used to configure what media to
|
||||
* play.
|
||||
*
|
||||
* It provides the essential methods setSource(), play(), seek() and additional
|
||||
* methods to configure the next media source, the transition between sources,
|
||||
* transition times, ticks, other.
|
||||
*
|
||||
* There are numerous signals that provide information about the state of the media
|
||||
* and of the playing process. The aboutToFinish() and finished() signals are used
|
||||
* to see when the current media is finished.
|
||||
*
|
||||
* This class does not contain methods directly involved with libVLC. This part is
|
||||
* handled by the VLCMediaObject class. There are protected methods and slots
|
||||
* inherited by that class, like playInternal(), seekInternal().
|
||||
* These methods have no implementation here.
|
||||
*
|
||||
* For documentation regarding the methods implemented for MediaObjectInterface, see
|
||||
* the Phonon documentation.
|
||||
*
|
||||
* \see Phonon::MediaObjectInterface
|
||||
* \see VLCMediaObject
|
||||
*/
|
||||
class MediaObject : public QObject, public MediaObjectInterface, public MediaController
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(Phonon::MediaObjectInterface Phonon::AddonInterface)
|
||||
friend class SinkNode;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Initializes the members, connects the private slots to their corresponding signals,
|
||||
* sets the next media source to an empty media source.
|
||||
*
|
||||
* \param parent A parent for the QObject
|
||||
*/
|
||||
explicit MediaObject(QObject *parent);
|
||||
~MediaObject();
|
||||
|
||||
/**
|
||||
* Reset members (those that need resetting anyway).
|
||||
* Should always be called before going to a new source.
|
||||
*/
|
||||
void resetMembers();
|
||||
|
||||
/**
|
||||
* If the current state is paused, it resumes playing. Else, the playback
|
||||
* is commenced.
|
||||
*/
|
||||
void play();
|
||||
|
||||
/// Pauses the playback for the media player.
|
||||
void pause();
|
||||
|
||||
/// Sets the next media source to an empty one and stops playback.
|
||||
void stop();
|
||||
|
||||
/// \returns \c true when there is a video available, \c false otherwise
|
||||
bool hasVideo() const;
|
||||
|
||||
/// \returns \c true when the MediaObject is seekable, \c false otherwise
|
||||
bool isSeekable() const;
|
||||
|
||||
/// \returns total time (length, duration) of the current MediaSource (-1 if unknown)
|
||||
qint64 totalTime() const;
|
||||
|
||||
/// \returns An error message with the last libVLC error.
|
||||
QString errorString() const;
|
||||
|
||||
/**
|
||||
* Adds a sink for this media object. During playInternal(), all the sinks
|
||||
* will have their addToMedia() called.
|
||||
*
|
||||
* \see playInternal()
|
||||
* \see SinkNode::addToMedia()
|
||||
*/
|
||||
void addSink(SinkNode *node);
|
||||
|
||||
/// Removes a sink from this media object.
|
||||
void removeSink(SinkNode *node);
|
||||
|
||||
/**
|
||||
* Pushes a seek command to the SeekStack for this media object. The SeekStack then
|
||||
* calls seekInternal() when it's popped.
|
||||
*/
|
||||
void seek(qint64 milliseconds);
|
||||
|
||||
/**
|
||||
* \return The interval between successive tick() signals. If set to 0, the emission
|
||||
* of these signals is disabled.
|
||||
*/
|
||||
qint32 tickInterval() const;
|
||||
|
||||
/**
|
||||
* Sets the interval between successive tick() signals. If set to 0, it disables the
|
||||
* emission of these signals.
|
||||
*/
|
||||
void setTickInterval(qint32 tickInterval);
|
||||
|
||||
/**
|
||||
* \return The current time of the media, depending on the current state.
|
||||
* If the current state is stopped or loading, 0 is returned.
|
||||
* If the current state is error or unknown, -1 is returned.
|
||||
*/
|
||||
qint64 currentTime() const;
|
||||
|
||||
/// \return The current state for this media object.
|
||||
Phonon::State state() const;
|
||||
|
||||
/// All errors are categorized as normal errors.
|
||||
Phonon::ErrorType errorType() const;
|
||||
|
||||
/// \return The current media source for this media object.
|
||||
MediaSource source() const;
|
||||
|
||||
/**
|
||||
* Sets the current media source for this media object. Depending on the source type,
|
||||
* the media object loads the specified media. The MRL is passed to loadMedia(), if the media
|
||||
* is not a stream. The currentSourceChanged() signal
|
||||
* is emitted.
|
||||
*
|
||||
* Supported media source types:
|
||||
* \li local files
|
||||
* \li URL
|
||||
* \li discs (CD, DVD, VCD)
|
||||
* \li capture devices (V4L)
|
||||
* \li streams
|
||||
*
|
||||
* \param source The media source that will become the current source.
|
||||
*
|
||||
* \see loadMedia()
|
||||
*/
|
||||
void setSource(const MediaSource &source);
|
||||
|
||||
/// Sets the media source that will replace the current one, after the playback for it finishes.
|
||||
void setNextSource(const MediaSource &source);
|
||||
|
||||
qint32 prefinishMark() const;
|
||||
void setPrefinishMark(qint32 msecToEnd);
|
||||
|
||||
qint32 transitionTime() const;
|
||||
void setTransitionTime(qint32);
|
||||
|
||||
void emitAboutToFinish();
|
||||
|
||||
signals:
|
||||
// MediaController signals
|
||||
void availableSubtitlesChanged();
|
||||
void availableAudioChannelsChanged();
|
||||
|
||||
void availableChaptersChanged(int);
|
||||
void availableTitlesChanged(int);
|
||||
|
||||
void chapterChanged(int chapterNumber);
|
||||
void titleChanged(int titleNumber);
|
||||
void durationChanged(qint64 newDuration);
|
||||
|
||||
/**
|
||||
* New widget size computed by VLC.
|
||||
*
|
||||
* It should be applied to the widget that contains the VLC video.
|
||||
*/
|
||||
void videoWidgetSizeChanged(int i_width, int i_height);
|
||||
|
||||
void aboutToFinish();
|
||||
void bufferStatus(int percentFilled);
|
||||
void currentSourceChanged(const MediaSource &newSource);
|
||||
void finished();
|
||||
void hasVideoChanged(bool b_has_video);
|
||||
void metaDataChanged(const QMultiMap<QString, QString> & metaData);
|
||||
void prefinishMarkReached(qint32 msecToEnd);
|
||||
void seekableChanged(bool seekable);
|
||||
void stateChanged(Phonon::State newState, Phonon::State oldState);
|
||||
void tick(qint64 time);
|
||||
void totalTimeChanged(qint64 newTotalTime);
|
||||
|
||||
void moveToNext();
|
||||
|
||||
private slots:
|
||||
/**
|
||||
* If the new state is different from the current state, the current state is
|
||||
* changed and the corresponding signal is emitted.
|
||||
*/
|
||||
void changeState(Phonon::State newState);
|
||||
|
||||
/**
|
||||
* Checks when the tick(), prefinishMarkReached(), aboutToFinish() signals need to
|
||||
* be emitted and emits them if necessary.
|
||||
*
|
||||
* \param currentTime The current play time for the media, in miliseconds.
|
||||
*/
|
||||
void timeChanged(qint64 time);
|
||||
void emitTick(qint64 time);
|
||||
|
||||
/**
|
||||
* If the next media source is valid, the current source is replaced and playback is commenced.
|
||||
* The next source is set to an empty source.
|
||||
*
|
||||
* \see setNextSource()
|
||||
*/
|
||||
void moveToNextSource();
|
||||
|
||||
/*** Update media duration time - see comment in CPP */
|
||||
void updateDuration(qint64 newDuration);
|
||||
|
||||
/** Retrieve meta data of a file (i.e ARTIST, TITLE, ALBUM, etc...). */
|
||||
void updateMetaData();
|
||||
void updateState(MediaPlayer::State state);
|
||||
|
||||
/** Called when the availability of video output changed */
|
||||
void onHasVideoChanged(bool hasVideo);
|
||||
|
||||
void setBufferStatus(int percent);
|
||||
|
||||
/** Refreshes all MediaController descriptors if Video is present. */
|
||||
void refreshDescriptors();
|
||||
|
||||
private:
|
||||
/**
|
||||
* This method actually calls the functions needed to begin playing the media.
|
||||
* If another media is already playing, it is discarded. The new media filename is set
|
||||
* with loadMediaInternal(). A new VLC Media is created and set into the VLC Media Player.
|
||||
* All the connected sink nodes are connected to the new media. It connects the media object
|
||||
* to the events for the VLC Media, updates the meta-data, sets up the video widget id, and
|
||||
* starts playing.
|
||||
*
|
||||
* \see loadMediaInternal()
|
||||
* \see connectToMediaVLCEvents()
|
||||
* \see updateMetaData()
|
||||
* \see setVLCWidgetId()
|
||||
*/
|
||||
void setupMedia();
|
||||
|
||||
/**
|
||||
* Seeks to the required position. If the state is not playing, the seek position is remembered.
|
||||
*/
|
||||
void seekInternal(qint64 milliseconds);
|
||||
|
||||
bool hasNextTrack();
|
||||
|
||||
/**
|
||||
* Changes the current state to buffering and sets the new current file.
|
||||
*
|
||||
* \param filename The MRL of the media source
|
||||
*/
|
||||
void loadMedia(const QByteArray &mrl);
|
||||
|
||||
/**
|
||||
* Overload for loadMedia, converting a QString to a QByteArray.
|
||||
*
|
||||
* \param filename The MRL of the media source
|
||||
*
|
||||
* \see loadMedia
|
||||
*/
|
||||
void loadMedia(const QString &mrl);
|
||||
|
||||
/**
|
||||
* Uninitializes the media
|
||||
*/
|
||||
void unloadMedia();
|
||||
|
||||
MediaSource m_nextSource;
|
||||
|
||||
MediaSource m_mediaSource;
|
||||
StreamReader *m_streamReader;
|
||||
Phonon::State m_state;
|
||||
|
||||
qint32 m_prefinishMark;
|
||||
bool m_prefinishEmitted;
|
||||
|
||||
bool m_aboutToFinishEmitted;
|
||||
|
||||
qint32 m_tickInterval;
|
||||
qint64 m_lastTick;
|
||||
qint32 m_transitionTime;
|
||||
|
||||
Media *m_media;
|
||||
|
||||
qint64 m_totalTime;
|
||||
QByteArray m_mrl;
|
||||
QMultiMap<QString, QString> m_vlcMetaData;
|
||||
QList<SinkNode *> m_sinks;
|
||||
|
||||
bool m_hasVideo;
|
||||
bool m_isScreen;
|
||||
|
||||
/**
|
||||
* Workaround for being able to seek before VLC goes to playing state.
|
||||
* Seeks before playing are stored in this var, and processed on state change
|
||||
* to Playing.
|
||||
*/
|
||||
qint64 m_seekpoint;
|
||||
|
||||
int m_timesVideoChecked;
|
||||
|
||||
bool m_buffering;
|
||||
Phonon::State m_stateAfterBuffering;
|
||||
};
|
||||
|
||||
} // namespace VLC
|
||||
} // namespace Phonon
|
||||
|
||||
#endif // PHONON_VLC_MEDIAOBJECT_H
|
|
@ -0,0 +1,413 @@
|
|||
/*
|
||||
Copyright (C) 2011-2018 Harald Sitter <sitter@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "mediaplayer.h"
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtCore/QDir>
|
||||
#include <QtCore/QMetaType>
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/QTemporaryFile>
|
||||
#include <QtGui/QImage>
|
||||
|
||||
#include <vlc/libvlc_version.h>
|
||||
|
||||
#include "utils/libvlc.h"
|
||||
#include "media.h"
|
||||
|
||||
// Callbacks come from a VLC thread. In some cases Qt fails to detect this and
|
||||
// tries to invoke directly (i.e. from same thread). This can lead to thread
|
||||
// pollution throughout Phonon, which is very much not desired.
|
||||
#define P_EMIT_HAS_VIDEO(hasVideo) \
|
||||
QMetaObject::invokeMethod(\
|
||||
that, "hasVideoChanged", \
|
||||
Qt::QueuedConnection, \
|
||||
Q_ARG(bool, hasVideo))
|
||||
|
||||
#define P_EMIT_STATE(__state) \
|
||||
QMetaObject::invokeMethod(\
|
||||
that, "stateChanged", \
|
||||
Qt::QueuedConnection, \
|
||||
Q_ARG(MediaPlayer::State, __state))
|
||||
|
||||
namespace Phonon {
|
||||
namespace VLC {
|
||||
|
||||
MediaPlayer::MediaPlayer(QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_media(0)
|
||||
, m_player(libvlc_media_player_new(pvlc_libvlc))
|
||||
, m_doingPausedPlay(false)
|
||||
, m_volume(75)
|
||||
, m_fadeAmount(1.0f)
|
||||
{
|
||||
Q_ASSERT(m_player);
|
||||
|
||||
qRegisterMetaType<MediaPlayer::State>("MediaPlayer::State");
|
||||
|
||||
libvlc_event_manager_t *manager = libvlc_media_player_event_manager(m_player);
|
||||
libvlc_event_type_t events[] = {
|
||||
libvlc_MediaPlayerMediaChanged,
|
||||
libvlc_MediaPlayerNothingSpecial,
|
||||
libvlc_MediaPlayerOpening,
|
||||
libvlc_MediaPlayerBuffering,
|
||||
libvlc_MediaPlayerPlaying,
|
||||
libvlc_MediaPlayerPaused,
|
||||
libvlc_MediaPlayerStopped,
|
||||
libvlc_MediaPlayerForward,
|
||||
libvlc_MediaPlayerBackward,
|
||||
libvlc_MediaPlayerEndReached,
|
||||
libvlc_MediaPlayerEncounteredError,
|
||||
libvlc_MediaPlayerTimeChanged,
|
||||
libvlc_MediaPlayerPositionChanged,
|
||||
libvlc_MediaPlayerSeekableChanged,
|
||||
libvlc_MediaPlayerPausableChanged,
|
||||
libvlc_MediaPlayerTitleChanged,
|
||||
libvlc_MediaPlayerSnapshotTaken,
|
||||
libvlc_MediaPlayerLengthChanged,
|
||||
libvlc_MediaPlayerVout
|
||||
#if (LIBVLC_VERSION_INT >= LIBVLC_VERSION(2, 2, 2, 0))
|
||||
, libvlc_MediaPlayerCorked,
|
||||
libvlc_MediaPlayerUncorked,
|
||||
libvlc_MediaPlayerMuted,
|
||||
libvlc_MediaPlayerUnmuted,
|
||||
libvlc_MediaPlayerAudioVolume
|
||||
#endif
|
||||
};
|
||||
const int eventCount = sizeof(events) / sizeof(*events);
|
||||
for (int i = 0; i < eventCount; ++i) {
|
||||
libvlc_event_attach(manager, events[i], event_cb, this);
|
||||
}
|
||||
|
||||
// Deactivate video title overlay (i.e. name of the video displaying
|
||||
// at start. Since 2.1 that is handled via the API which in general is more
|
||||
// reliable than setting it via libvlc_new (or so I have been told....)
|
||||
libvlc_media_player_set_video_title_display(m_player, libvlc_position_disable, 0);
|
||||
}
|
||||
|
||||
MediaPlayer::~MediaPlayer()
|
||||
{
|
||||
libvlc_media_player_release(m_player);
|
||||
}
|
||||
|
||||
void MediaPlayer::setMedia(Media *media)
|
||||
{
|
||||
m_media = media;
|
||||
libvlc_media_player_set_media(m_player, *m_media);
|
||||
}
|
||||
|
||||
bool MediaPlayer::play()
|
||||
{
|
||||
m_doingPausedPlay = false;
|
||||
return libvlc_media_player_play(m_player) == 0;
|
||||
}
|
||||
|
||||
void MediaPlayer::pause()
|
||||
{
|
||||
m_doingPausedPlay = false;
|
||||
libvlc_media_player_set_pause(m_player, 1);
|
||||
}
|
||||
|
||||
void MediaPlayer::pausedPlay()
|
||||
{
|
||||
m_doingPausedPlay = true;
|
||||
libvlc_media_player_play(m_player);
|
||||
}
|
||||
|
||||
void MediaPlayer::resume()
|
||||
{
|
||||
m_doingPausedPlay = false;
|
||||
libvlc_media_player_set_pause(m_player, 0);
|
||||
}
|
||||
|
||||
void MediaPlayer::togglePause()
|
||||
{
|
||||
libvlc_media_player_pause(m_player);
|
||||
}
|
||||
|
||||
void MediaPlayer::stop()
|
||||
{
|
||||
m_doingPausedPlay = false;
|
||||
libvlc_media_player_stop(m_player);
|
||||
}
|
||||
|
||||
qint64 MediaPlayer::length() const
|
||||
{
|
||||
return libvlc_media_player_get_length(m_player);
|
||||
}
|
||||
|
||||
qint64 MediaPlayer::time() const
|
||||
{
|
||||
return libvlc_media_player_get_time(m_player);
|
||||
}
|
||||
|
||||
void MediaPlayer::setTime(qint64 newTime)
|
||||
{
|
||||
libvlc_media_player_set_time(m_player, newTime);
|
||||
}
|
||||
|
||||
bool MediaPlayer::isSeekable() const
|
||||
{
|
||||
return libvlc_media_player_is_seekable(m_player);
|
||||
}
|
||||
|
||||
bool MediaPlayer::hasVideoOutput() const
|
||||
{
|
||||
return libvlc_media_player_has_vout(m_player) > 0;
|
||||
}
|
||||
|
||||
bool MediaPlayer::setSubtitle(int subtitle)
|
||||
{
|
||||
return libvlc_video_set_spu(m_player, subtitle) == 0;
|
||||
}
|
||||
|
||||
bool MediaPlayer::setSubtitle(const QString &file)
|
||||
{
|
||||
#if (LIBVLC_VERSION_INT >= LIBVLC_VERSION(3, 0, 0, 0))
|
||||
return libvlc_media_player_add_slave(m_player,
|
||||
libvlc_media_slave_type_subtitle,
|
||||
file.toUtf8().data(),
|
||||
true) == 0;
|
||||
#else
|
||||
return libvlc_video_set_subtitle_file(m_player, file.toUtf8().data()) == 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
void MediaPlayer::setTitle(int title)
|
||||
{
|
||||
libvlc_media_player_set_title(m_player, title);
|
||||
}
|
||||
|
||||
void MediaPlayer::setChapter(int chapter)
|
||||
{
|
||||
libvlc_media_player_set_chapter(m_player, chapter);
|
||||
}
|
||||
|
||||
QImage MediaPlayer::snapshot() const
|
||||
{
|
||||
QTemporaryFile tempFile(QDir::tempPath() % QDir::separator() % QLatin1Literal("phonon-vlc-snapshot"));
|
||||
tempFile.open();
|
||||
|
||||
// This function is sync.
|
||||
if (libvlc_video_take_snapshot(m_player, 0, tempFile.fileName().toLocal8Bit().data(), 0, 0) != 0)
|
||||
return QImage();
|
||||
|
||||
return QImage(tempFile.fileName());
|
||||
}
|
||||
|
||||
bool MediaPlayer::setAudioTrack(int track)
|
||||
{
|
||||
return libvlc_audio_set_track(m_player, track) == 0;
|
||||
}
|
||||
|
||||
void MediaPlayer::event_cb(const libvlc_event_t *event, void *opaque)
|
||||
{
|
||||
MediaPlayer *that = reinterpret_cast<MediaPlayer *>(opaque);
|
||||
Q_ASSERT(that);
|
||||
|
||||
// Do not forget to register for the events you want to handle here!
|
||||
switch (event->type) {
|
||||
case libvlc_MediaPlayerTimeChanged:
|
||||
QMetaObject::invokeMethod(
|
||||
that, "timeChanged",
|
||||
Qt::QueuedConnection,
|
||||
Q_ARG(qint64, event->u.media_player_time_changed.new_time));
|
||||
break;
|
||||
case libvlc_MediaPlayerSeekableChanged:
|
||||
QMetaObject::invokeMethod(
|
||||
that, "seekableChanged",
|
||||
Qt::QueuedConnection,
|
||||
Q_ARG(bool, event->u.media_player_seekable_changed.new_seekable));
|
||||
break;
|
||||
case libvlc_MediaPlayerLengthChanged:
|
||||
QMetaObject::invokeMethod(
|
||||
that, "lengthChanged",
|
||||
Qt::QueuedConnection,
|
||||
Q_ARG(qint64, event->u.media_player_length_changed.new_length));
|
||||
break;
|
||||
case libvlc_MediaPlayerNothingSpecial:
|
||||
P_EMIT_STATE(NoState);
|
||||
break;
|
||||
case libvlc_MediaPlayerOpening:
|
||||
P_EMIT_STATE(OpeningState);
|
||||
break;
|
||||
case libvlc_MediaPlayerBuffering:
|
||||
QMetaObject::invokeMethod(
|
||||
that, "bufferChanged",
|
||||
Qt::QueuedConnection,
|
||||
Q_ARG(int, event->u.media_player_buffering.new_cache));
|
||||
break;
|
||||
case libvlc_MediaPlayerPlaying:
|
||||
// Intercept state change and apply pausing once playing.
|
||||
if (that->m_doingPausedPlay) {
|
||||
that->m_doingPausedPlay = false;
|
||||
// VLC internally will call stop if a player can not be paused, this
|
||||
// can lead to deadlocks as stop is partially blocking, to avoid this
|
||||
// we explicitly do a queued stop whenever a player can not be paused.
|
||||
// In those situations pausedplay capability can not be provided, so
|
||||
// applications wanting to do pausedplay will need to handle it anyway
|
||||
// as faking a paused state when there is none would be a very code
|
||||
// intense workaround asking for weird abstraction leakage.
|
||||
// See kde bug 337604.
|
||||
if (libvlc_media_player_can_pause(that->m_player)) {
|
||||
that->pause();
|
||||
} else {
|
||||
QMetaObject::invokeMethod(that, "stop", Qt::QueuedConnection);
|
||||
}
|
||||
} else
|
||||
P_EMIT_STATE(PlayingState);
|
||||
break;
|
||||
case libvlc_MediaPlayerPaused:
|
||||
P_EMIT_STATE(PausedState);
|
||||
break;
|
||||
case libvlc_MediaPlayerStopped:
|
||||
P_EMIT_STATE(StoppedState);
|
||||
break;
|
||||
case libvlc_MediaPlayerEndReached:
|
||||
P_EMIT_STATE(EndedState);
|
||||
break;
|
||||
case libvlc_MediaPlayerEncounteredError:
|
||||
P_EMIT_STATE(ErrorState);
|
||||
break;
|
||||
case libvlc_MediaPlayerVout:
|
||||
if (event->u.media_player_vout.new_count > 0) {
|
||||
P_EMIT_HAS_VIDEO(true);
|
||||
} else {
|
||||
P_EMIT_HAS_VIDEO(false);
|
||||
}
|
||||
break;
|
||||
case libvlc_MediaPlayerMediaChanged:
|
||||
break;
|
||||
#if (LIBVLC_VERSION_INT >= LIBVLC_VERSION(2, 2, 2, 0))
|
||||
case libvlc_MediaPlayerCorked:
|
||||
that->pause();
|
||||
break;
|
||||
case libvlc_MediaPlayerUncorked:
|
||||
that->play();
|
||||
break;
|
||||
case libvlc_MediaPlayerMuted:
|
||||
QMetaObject::invokeMethod(
|
||||
that, "mutedChanged",
|
||||
Qt::QueuedConnection,
|
||||
Q_ARG(bool, true));
|
||||
break;
|
||||
case libvlc_MediaPlayerUnmuted:
|
||||
QMetaObject::invokeMethod(
|
||||
that, "mutedChanged",
|
||||
Qt::QueuedConnection,
|
||||
Q_ARG(bool, false));
|
||||
break;
|
||||
case libvlc_MediaPlayerAudioVolume:
|
||||
QMetaObject::invokeMethod(
|
||||
that, "volumeChanged",
|
||||
Qt::QueuedConnection,
|
||||
Q_ARG(float, event->u.media_player_audio_volume.volume));
|
||||
break;
|
||||
#endif
|
||||
case libvlc_MediaPlayerForward:
|
||||
case libvlc_MediaPlayerBackward:
|
||||
case libvlc_MediaPlayerPositionChanged:
|
||||
case libvlc_MediaPlayerPausableChanged:
|
||||
case libvlc_MediaPlayerTitleChanged:
|
||||
case libvlc_MediaPlayerSnapshotTaken: // Snapshot call is sync, so this is useless.
|
||||
default:
|
||||
break;
|
||||
QString msg = QString("Unknown event: ") + QString(libvlc_event_type_name(event->type));
|
||||
Q_ASSERT_X(false, "event_cb", qPrintable(msg));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
QDebug operator<<(QDebug dbg, const MediaPlayer::State &s)
|
||||
{
|
||||
QString name;
|
||||
switch (s) {
|
||||
case MediaPlayer::NoState:
|
||||
name = QLatin1String("MediaPlayer::NoState");
|
||||
break;
|
||||
case MediaPlayer::OpeningState:
|
||||
name = QLatin1String("MediaPlayer::OpeningState");
|
||||
break;
|
||||
case MediaPlayer::BufferingState:
|
||||
name = QLatin1String("MediaPlayer::BufferingState");
|
||||
break;
|
||||
case MediaPlayer::PlayingState:
|
||||
name = QLatin1String("MediaPlayer::PlayingState");
|
||||
break;
|
||||
case MediaPlayer::PausedState:
|
||||
name = QLatin1String("MediaPlayer::PausedState");
|
||||
break;
|
||||
case MediaPlayer::StoppedState:
|
||||
name = QLatin1String("MediaPlayer::StoppedState");
|
||||
break;
|
||||
case MediaPlayer::EndedState:
|
||||
name = QLatin1String("MediaPlayer::EndedState");
|
||||
break;
|
||||
case MediaPlayer::ErrorState:
|
||||
name = QLatin1String("MediaPlayer::ErrorState");
|
||||
break;
|
||||
}
|
||||
dbg.nospace() << "State(" << qPrintable(name) << ")";
|
||||
return dbg.space();
|
||||
}
|
||||
|
||||
void MediaPlayer::setAudioFade(qreal fade)
|
||||
{
|
||||
m_fadeAmount = fade;
|
||||
setVolumeInternal();
|
||||
}
|
||||
|
||||
void MediaPlayer::setAudioVolume(int volume)
|
||||
{
|
||||
m_volume = volume;
|
||||
setVolumeInternal();
|
||||
}
|
||||
|
||||
bool MediaPlayer::mute() const
|
||||
{
|
||||
return libvlc_audio_get_mute(m_player);
|
||||
}
|
||||
|
||||
void MediaPlayer::setMute(bool mute)
|
||||
{
|
||||
libvlc_audio_set_mute(m_player, mute);
|
||||
}
|
||||
|
||||
void MediaPlayer::setVolumeInternal()
|
||||
{
|
||||
libvlc_audio_set_volume(m_player, m_volume * m_fadeAmount);
|
||||
}
|
||||
|
||||
void MediaPlayer::setCdTrack(int track)
|
||||
{
|
||||
if (!m_media)
|
||||
return;
|
||||
libvlc_media_player_stop(m_player);
|
||||
m_media->setCdTrack(track);
|
||||
libvlc_media_player_set_media(m_player, *m_media);
|
||||
libvlc_media_player_play(m_player);
|
||||
}
|
||||
|
||||
#if (LIBVLC_VERSION_INT >= LIBVLC_VERSION(2, 2, 0, 0))
|
||||
void MediaPlayer::setEqualizer(libvlc_equalizer_t *equalizer)
|
||||
{
|
||||
libvlc_media_player_set_equalizer(m_player, equalizer);
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace VLC
|
||||
} // namespace Phonon
|
|
@ -0,0 +1,277 @@
|
|||
/*
|
||||
Copyright (C) 2011-2018 Harald Sitter <sitter@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef PHONON_VLC_MEDIAPLAYER_H
|
||||
#define PHONON_VLC_MEDIAPLAYER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QSharedPointer>
|
||||
#include <QSize>
|
||||
|
||||
#include <vlc/libvlc_version.h>
|
||||
#include <vlc/vlc.h>
|
||||
|
||||
class QImage;
|
||||
class QString;
|
||||
|
||||
namespace Phonon {
|
||||
namespace VLC {
|
||||
|
||||
class Media;
|
||||
|
||||
template<class VLCArray>
|
||||
class Descriptions
|
||||
{
|
||||
public:
|
||||
typedef void (*ReleaseFunction) (VLCArray**, unsigned int) ;
|
||||
|
||||
Descriptions(VLCArray **data,
|
||||
unsigned int size,
|
||||
ReleaseFunction release)
|
||||
: m_release(release)
|
||||
, m_data(data)
|
||||
, m_size(size)
|
||||
{
|
||||
}
|
||||
|
||||
~Descriptions()
|
||||
{
|
||||
m_release(m_data, m_size);
|
||||
}
|
||||
|
||||
unsigned int size() const { return m_size; }
|
||||
|
||||
private:
|
||||
ReleaseFunction m_release;
|
||||
|
||||
VLCArray **m_data;
|
||||
unsigned int m_size;
|
||||
};
|
||||
|
||||
#if (LIBVLC_VERSION_INT >= LIBVLC_VERSION(3, 0, 0, 0))
|
||||
typedef Descriptions<libvlc_title_description_t> TitleDescriptions;
|
||||
typedef QSharedPointer<const TitleDescriptions> SharedTitleDescriptions;
|
||||
|
||||
typedef Descriptions<libvlc_chapter_description_t> ChapterDescriptions;
|
||||
typedef QSharedPointer<ChapterDescriptions> SharedChapterDescriptions;
|
||||
#endif
|
||||
|
||||
class MediaPlayer : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum State {
|
||||
NoState = 0,
|
||||
OpeningState,
|
||||
BufferingState,
|
||||
PlayingState,
|
||||
PausedState,
|
||||
StoppedState,
|
||||
EndedState,
|
||||
ErrorState
|
||||
};
|
||||
|
||||
explicit MediaPlayer(QObject *parent = 0);
|
||||
~MediaPlayer();
|
||||
|
||||
inline libvlc_media_player_t *libvlc_media_player() const { return m_player; }
|
||||
inline operator libvlc_media_player_t *() const { return m_player; }
|
||||
|
||||
void setMedia(Media *media);
|
||||
|
||||
void setVideoCallbacks();
|
||||
void setVideoFormatCallbacks();
|
||||
|
||||
void setNsObject(void *drawable) { libvlc_media_player_set_nsobject(m_player, drawable); }
|
||||
void setXWindow(quint32 drawable) { libvlc_media_player_set_xwindow(m_player, drawable); }
|
||||
void setHwnd(void *drawable) { libvlc_media_player_set_hwnd(m_player, drawable); }
|
||||
|
||||
// Playback
|
||||
bool play();
|
||||
void pause();
|
||||
void pausedPlay();
|
||||
void resume();
|
||||
void togglePause();
|
||||
Q_INVOKABLE void stop();
|
||||
|
||||
qint64 length() const;
|
||||
qint64 time() const;
|
||||
void setTime(qint64 newTime);
|
||||
|
||||
bool isSeekable() const;
|
||||
|
||||
// Video
|
||||
QSize videoSize() const
|
||||
{
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
libvlc_video_get_size(m_player, 0, &width, &height);
|
||||
return QSize(width, height);
|
||||
}
|
||||
|
||||
bool hasVideoOutput() const;
|
||||
|
||||
/// Set new video aspect ratio.
|
||||
/// \param aspect new video aspect-ratio or empty to reset to default
|
||||
void setVideoAspectRatio(const QByteArray &aspect)
|
||||
{ libvlc_video_set_aspect_ratio(m_player, aspect.isEmpty() ? 0 : aspect.data()); }
|
||||
|
||||
void setVideoAdjust(libvlc_video_adjust_option_t adjust, int value)
|
||||
{ libvlc_video_set_adjust_int(m_player, adjust, value); }
|
||||
|
||||
void setVideoAdjust(libvlc_video_adjust_option_t adjust, float value)
|
||||
{ libvlc_video_set_adjust_float(m_player, adjust, value); }
|
||||
|
||||
int subtitle() const
|
||||
{ return libvlc_video_get_spu(m_player); }
|
||||
|
||||
libvlc_track_description_t *videoSubtitleDescription() const
|
||||
{ return libvlc_video_get_spu_description(m_player); }
|
||||
|
||||
bool setSubtitle(int subtitle);
|
||||
bool setSubtitle(const QString &file);
|
||||
|
||||
int title() const
|
||||
{ return libvlc_media_player_get_title(m_player); }
|
||||
|
||||
int titleCount() const
|
||||
{ return libvlc_media_player_get_title_count(m_player); }
|
||||
|
||||
#if (LIBVLC_VERSION_INT >= LIBVLC_VERSION(3, 0, 0, 0))
|
||||
SharedTitleDescriptions titleDescription() const
|
||||
{
|
||||
libvlc_title_description_t **data;
|
||||
unsigned int size =
|
||||
libvlc_media_player_get_full_title_descriptions(m_player, &data);
|
||||
return SharedTitleDescriptions(
|
||||
new TitleDescriptions(
|
||||
data, size,
|
||||
&libvlc_title_descriptions_release)
|
||||
);
|
||||
}
|
||||
#else // deprecated
|
||||
libvlc_track_description_t *titleDescription() const
|
||||
{ return libvlc_video_get_title_description(m_player); }
|
||||
#endif
|
||||
|
||||
void setTitle(int title);
|
||||
|
||||
int videoChapterCount() const
|
||||
{ return libvlc_media_player_get_chapter_count(m_player); }
|
||||
|
||||
#if (LIBVLC_VERSION_INT >= LIBVLC_VERSION(3, 0, 0, 0))
|
||||
SharedChapterDescriptions videoChapterDescription(int title) const
|
||||
{
|
||||
libvlc_chapter_description_t **data;
|
||||
unsigned int size =
|
||||
libvlc_media_player_get_full_chapter_descriptions(m_player, title, &data);
|
||||
return SharedChapterDescriptions(
|
||||
new ChapterDescriptions(
|
||||
data, size,
|
||||
&libvlc_chapter_descriptions_release)
|
||||
);
|
||||
}
|
||||
#else // deprecated
|
||||
libvlc_track_description_t *videoChapterDescription(int title) const
|
||||
{ return libvlc_video_get_chapter_description(m_player, title); }
|
||||
#endif
|
||||
|
||||
void setChapter(int chapter);
|
||||
|
||||
/** Reentrant, through libvlc */
|
||||
QImage snapshot() const;
|
||||
|
||||
// Audio
|
||||
/// Get current audio volume.
|
||||
/// \return the software volume in percents (0 = mute, 100 = nominal / 0dB)
|
||||
int audioVolume() const { return m_volume; }
|
||||
|
||||
/// Set new audio volume.
|
||||
/// \param volume new volume
|
||||
void setAudioVolume(int volume);
|
||||
|
||||
/// \return mutness
|
||||
bool mute() const;
|
||||
|
||||
/**
|
||||
* Mutes
|
||||
* @param mute whether to mute or unmute
|
||||
*/
|
||||
void setMute(bool mute);
|
||||
|
||||
/// Set the fade percentage, between 0 (muted) and 1.0 (no fade)
|
||||
void setAudioFade(qreal fade);
|
||||
|
||||
/// \param name name of the output to set
|
||||
/// \returns \c true when setting was successful, \c false otherwise
|
||||
bool setAudioOutput(const QByteArray &name)
|
||||
{ return libvlc_audio_output_set(m_player, name.data()) == 0; }
|
||||
|
||||
/**
|
||||
* Set audio output device by name.
|
||||
* \param outputName the aout name (pulse, alsa, oss, etc.)
|
||||
* \param deviceName the output name (aout dependent)
|
||||
*/
|
||||
void setAudioOutputDevice(const QByteArray &outputName, const QByteArray &deviceName)
|
||||
{ libvlc_audio_output_device_set(m_player, outputName.data(), deviceName.data()); }
|
||||
|
||||
int audioTrack() const
|
||||
{ return libvlc_audio_get_track(m_player); }
|
||||
|
||||
libvlc_track_description_t * audioTrackDescription() const
|
||||
{ return libvlc_audio_get_track_description(m_player); }
|
||||
|
||||
bool setAudioTrack(int track);
|
||||
|
||||
void setCdTrack(int track);
|
||||
|
||||
#if (LIBVLC_VERSION_INT >= LIBVLC_VERSION(2, 2, 0, 0))
|
||||
void setEqualizer(libvlc_equalizer_t *equalizer);
|
||||
#endif
|
||||
|
||||
signals:
|
||||
void lengthChanged(qint64 length);
|
||||
void seekableChanged(bool seekable);
|
||||
void stateChanged(MediaPlayer::State state);
|
||||
void timeChanged(qint64 time);
|
||||
void bufferChanged(int percent);
|
||||
|
||||
/** Emitted when the vout availability has changed */
|
||||
void hasVideoChanged(bool hasVideo);
|
||||
|
||||
void mutedChanged(bool mute);
|
||||
void volumeChanged(float volume);
|
||||
|
||||
private:
|
||||
static void event_cb(const libvlc_event_t *event, void *opaque);
|
||||
void setVolumeInternal();
|
||||
|
||||
Media *m_media;
|
||||
|
||||
libvlc_media_player_t *m_player;
|
||||
|
||||
bool m_doingPausedPlay;
|
||||
int m_volume;
|
||||
qreal m_fadeAmount;
|
||||
};
|
||||
|
||||
QDebug operator<<(QDebug dbg, const MediaPlayer::State &s);
|
||||
|
||||
} // namespace VLC
|
||||
} // namespace Phonon
|
||||
|
||||
#endif // PHONON_VLC_MEDIAPLAYER_H
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"Name": "Phonon VLC",
|
||||
"Icon": "vlc",
|
||||
"Version": "@PHONON_VLC_VERSION@",
|
||||
"Website": "http://www.videolan.org",
|
||||
|
||||
"InterfaceVersion": 0,
|
||||
"InitialPreference": 20
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
Copyright (C) 2013 Harald Sitter <sitter@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "sinknode.h"
|
||||
|
||||
#include "utils/debug.h"
|
||||
#include "mediaobject.h"
|
||||
#include "mediaplayer.h"
|
||||
|
||||
namespace Phonon {
|
||||
namespace VLC {
|
||||
|
||||
SinkNode::SinkNode()
|
||||
: m_mediaObject(0)
|
||||
, m_player(0)
|
||||
{
|
||||
}
|
||||
|
||||
SinkNode::~SinkNode()
|
||||
{
|
||||
if (m_mediaObject) {
|
||||
disconnectFromMediaObject(m_mediaObject);
|
||||
}
|
||||
}
|
||||
|
||||
void SinkNode::connectToMediaObject(MediaObject *mediaObject)
|
||||
{
|
||||
if (m_mediaObject) {
|
||||
error() << Q_FUNC_INFO << "m_mediaObject already connected";
|
||||
}
|
||||
|
||||
m_mediaObject = mediaObject;
|
||||
m_player = mediaObject->m_player;
|
||||
m_mediaObject->addSink(this);
|
||||
|
||||
// ---> Global handling goes here! Above the derivee handle! <--- //
|
||||
|
||||
handleConnectToMediaObject(mediaObject);
|
||||
}
|
||||
|
||||
void SinkNode::disconnectFromMediaObject(MediaObject *mediaObject)
|
||||
{
|
||||
handleDisconnectFromMediaObject(mediaObject);
|
||||
|
||||
// ---> Global handling goes here! Below the derivee handle! <--- //
|
||||
|
||||
if (m_mediaObject != mediaObject) {
|
||||
error() << Q_FUNC_INFO << "SinkNode was not connected to mediaObject";
|
||||
}
|
||||
|
||||
if (m_mediaObject) {
|
||||
m_mediaObject->removeSink(this);
|
||||
}
|
||||
|
||||
m_mediaObject = 0;
|
||||
m_player = 0;
|
||||
}
|
||||
|
||||
void SinkNode::addToMedia(Media *media)
|
||||
{
|
||||
// ---> Global handling goes here! Above the derivee handle! <--- //
|
||||
|
||||
handleAddToMedia(media);
|
||||
}
|
||||
|
||||
} // namespace VLC
|
||||
} // namespace Phonon
|
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
Copyright (C) 2013 Harald Sitter <sitter@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef PHONON_VLC_SINKNODE_H
|
||||
#define PHONON_VLC_SINKNODE_H
|
||||
|
||||
#include <QPointer>
|
||||
|
||||
namespace Phonon {
|
||||
namespace VLC {
|
||||
|
||||
class Media;
|
||||
class MediaObject;
|
||||
class MediaPlayer;
|
||||
|
||||
/** \brief The sink node is essentialy an output for a media object
|
||||
*
|
||||
* This class handles connections for the sink to a media object. It remembers
|
||||
* the media object and the libVLC media player associated with it.
|
||||
*
|
||||
* \see MediaObject
|
||||
*/
|
||||
class SinkNode
|
||||
{
|
||||
public:
|
||||
SinkNode();
|
||||
virtual ~SinkNode();
|
||||
|
||||
/**
|
||||
* Associates the sink node to the provided media object. The m_mediaObject and m_vlcPlayer
|
||||
* attributes are set, and the sink is added to the media object's sinks.
|
||||
*
|
||||
* \param mediaObject The media object to connect to.
|
||||
*
|
||||
* \see disconnectFromMediaObject()
|
||||
*/
|
||||
void connectToMediaObject(MediaObject *mediaObject);
|
||||
|
||||
/**
|
||||
* Removes this sink from the specified media object's sinks.
|
||||
*
|
||||
* \param mediaObject The media object to disconnect from
|
||||
*
|
||||
* \see connectToMediaObject()
|
||||
*/
|
||||
void disconnectFromMediaObject(MediaObject *mediaObject);
|
||||
|
||||
/**
|
||||
* Does nothing. To be reimplemented in child classes.
|
||||
*/
|
||||
void addToMedia(Media *media);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Handling function for derived classes.
|
||||
* \note This handle is executed *after* the global handle.
|
||||
* Meaning the SinkNode base will be done handling the connect.
|
||||
* \see connectToMediaObject
|
||||
*/
|
||||
virtual void handleConnectToMediaObject(MediaObject *mediaObject) { Q_UNUSED(mediaObject); }
|
||||
|
||||
/**
|
||||
* Handling function for derived classes.
|
||||
* \note This handle is executed *before* the global handle.
|
||||
* Meaning the SinkNode base will continue handling the disconnect.
|
||||
* \see disconnectFromMediaObject
|
||||
*/
|
||||
virtual void handleDisconnectFromMediaObject(MediaObject *mediaObject) { Q_UNUSED(mediaObject); }
|
||||
|
||||
/**
|
||||
* Handling function for derived classes.
|
||||
* \note This handle is executed *after* the global handle.
|
||||
* Meaning the SinkNode base will be done handling the connect.
|
||||
* \see addToMedia
|
||||
*/
|
||||
virtual void handleAddToMedia(Media *media) { Q_UNUSED(media); }
|
||||
|
||||
/** Available while connected to a MediaObject (until disconnected) */
|
||||
QPointer<MediaObject> m_mediaObject;
|
||||
|
||||
/** Available while connected to a MediaObject (until disconnected) */
|
||||
MediaPlayer *m_player;
|
||||
};
|
||||
|
||||
} // namespace VLC
|
||||
} // namespace Phonon
|
||||
|
||||
#endif // PHONON_VLC_SINKNODE_H
|
|
@ -0,0 +1,242 @@
|
|||
/*
|
||||
Copyright (C) 2007-2008 Tanguy Krotoff <tkrotoff@gmail.com>
|
||||
Copyright (C) 2008 Lukas Durfina <lukas.durfina@gmail.com>
|
||||
Copyright (C) 2009 Fathi Boudra <fabo@kde.org>
|
||||
Copyright (C) 2009-2011 vlc-phonon AUTHORS <kde-multimedia@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "streamreader.h"
|
||||
|
||||
#include <QtCore/QMutexLocker>
|
||||
|
||||
#include <phonon/streaminterface.h>
|
||||
|
||||
#include "utils/debug.h"
|
||||
#include "media.h"
|
||||
#include "mediaobject.h"
|
||||
#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
|
||||
|
||||
namespace Phonon {
|
||||
namespace VLC {
|
||||
|
||||
#define BLOCKSIZE 32768
|
||||
|
||||
StreamReader::StreamReader(MediaObject *parent)
|
||||
: QObject(parent)
|
||||
, m_pos(0)
|
||||
, m_size(0)
|
||||
, m_eos(false)
|
||||
, m_seekable(false)
|
||||
, m_unlocked(false)
|
||||
, m_mediaObject(parent)
|
||||
{
|
||||
}
|
||||
|
||||
StreamReader::~StreamReader()
|
||||
{
|
||||
}
|
||||
|
||||
void StreamReader::addToMedia(Media *media)
|
||||
{
|
||||
lock(); // Make sure we can lock in read().
|
||||
|
||||
media->addOption(QLatin1String("imem-cat=4"));
|
||||
media->addOption(QLatin1String("imem-data="), INTPTR_PTR(this));
|
||||
media->addOption(QLatin1String("imem-get="), INTPTR_FUNC(readCallback));
|
||||
media->addOption(QLatin1String("imem-release="), INTPTR_FUNC(readDoneCallback));
|
||||
media->addOption(QLatin1String("imem-seek="), INTPTR_FUNC(seekCallback));
|
||||
|
||||
// if stream has known size, we may pass it
|
||||
// imem module will use it and pass it to demux
|
||||
if (streamSize() > 0) {
|
||||
media->addOption(QString("imem-size=%1").arg(streamSize()));
|
||||
}
|
||||
}
|
||||
|
||||
void StreamReader::lock()
|
||||
{
|
||||
QMutexLocker lock(&m_mutex);
|
||||
DEBUG_BLOCK;
|
||||
m_unlocked = false;
|
||||
}
|
||||
|
||||
void StreamReader::unlock()
|
||||
{
|
||||
QMutexLocker lock(&m_mutex);
|
||||
DEBUG_BLOCK;
|
||||
m_unlocked = true;
|
||||
m_waitingForData.wakeAll();
|
||||
}
|
||||
|
||||
int StreamReader::readCallback(void *data, const char *cookie,
|
||||
int64_t *dts, int64_t *pts, unsigned *flags, // krazy:exclude=typedefs
|
||||
size_t *bufferSize, void **buffer)
|
||||
{
|
||||
Q_UNUSED(cookie);
|
||||
Q_UNUSED(dts);
|
||||
Q_UNUSED(pts);
|
||||
Q_UNUSED(flags);
|
||||
|
||||
StreamReader *that = static_cast<StreamReader *>(data);
|
||||
size_t length = BLOCKSIZE;
|
||||
|
||||
*buffer = new char[length];
|
||||
|
||||
int size = length;
|
||||
bool ret = that->read(that->currentPos(), &size, static_cast<char*>(*buffer));
|
||||
|
||||
*bufferSize = static_cast<size_t>(size);
|
||||
|
||||
return ret ? 0 : -1;
|
||||
}
|
||||
|
||||
int StreamReader::readDoneCallback(void *data, const char *cookie,
|
||||
size_t bufferSize, void *buffer)
|
||||
{
|
||||
Q_UNUSED(data);
|
||||
Q_UNUSED(cookie);
|
||||
Q_UNUSED(bufferSize);
|
||||
delete[] static_cast<char *>(buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int StreamReader::seekCallback(void *data, const uint64_t pos)
|
||||
{
|
||||
StreamReader *that = static_cast<StreamReader *>(data);
|
||||
if (static_cast<int64_t>(pos) > that->streamSize()) { // krazy:exclude=typedefs
|
||||
// attempt to seek past the end of our data.
|
||||
return -1;
|
||||
}
|
||||
|
||||
that->setCurrentPos(pos);
|
||||
// this should return a true/false, but it doesn't, so assume success.
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
quint64 StreamReader::currentBufferSize() const
|
||||
{
|
||||
return m_buffer.size();
|
||||
}
|
||||
|
||||
bool StreamReader::read(quint64 pos, int *length, char *buffer)
|
||||
{
|
||||
QMutexLocker lock(&m_mutex);
|
||||
DEBUG_BLOCK;
|
||||
bool ret = true;
|
||||
|
||||
if (m_unlocked) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (currentPos() != pos) {
|
||||
if (!streamSeekable()) {
|
||||
return false;
|
||||
}
|
||||
setCurrentPos(pos);
|
||||
}
|
||||
|
||||
if (m_buffer.capacity() < *length) {
|
||||
m_buffer.reserve(*length);
|
||||
}
|
||||
|
||||
while (currentBufferSize() < static_cast<unsigned int>(*length)) {
|
||||
quint64 oldSize = currentBufferSize();
|
||||
needData();
|
||||
|
||||
m_waitingForData.wait(&m_mutex);
|
||||
|
||||
if (oldSize == currentBufferSize()) {
|
||||
if (m_eos && m_buffer.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
// We didn't get any more data
|
||||
*length = static_cast<int>(oldSize);
|
||||
// If we have some data to return, why tell to reader that we failed?
|
||||
// Remember that length argument is more like maxSize not requiredSize
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_mediaObject->state() != Phonon::BufferingState &&
|
||||
m_mediaObject->state() != Phonon::LoadingState) {
|
||||
enoughData();
|
||||
}
|
||||
|
||||
memcpy(buffer, m_buffer.data(), *length);
|
||||
m_pos += *length;
|
||||
// trim the buffer by the amount read
|
||||
m_buffer = m_buffer.mid(*length);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void StreamReader::endOfData()
|
||||
{
|
||||
m_eos = true;
|
||||
m_waitingForData.wakeAll();
|
||||
}
|
||||
|
||||
void StreamReader::writeData(const QByteArray &data)
|
||||
{
|
||||
QMutexLocker lock(&m_mutex);
|
||||
DEBUG_BLOCK;
|
||||
m_buffer.append(data);
|
||||
m_waitingForData.wakeAll();
|
||||
}
|
||||
|
||||
quint64 StreamReader::currentPos() const
|
||||
{
|
||||
return m_pos;
|
||||
}
|
||||
|
||||
void StreamReader::setCurrentPos(qint64 pos)
|
||||
{
|
||||
QMutexLocker lock(&m_mutex);
|
||||
m_pos = pos;
|
||||
m_buffer.clear(); // Not optimal, but meh
|
||||
|
||||
// Do not touch m_size here, it reflects the size of the stream not the size of the buffer,
|
||||
// and generally seeking does not change the size!
|
||||
|
||||
seekStream(pos);
|
||||
}
|
||||
|
||||
void StreamReader::setStreamSize(qint64 newSize)
|
||||
{
|
||||
m_size = newSize;
|
||||
}
|
||||
|
||||
qint64 StreamReader::streamSize() const
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
|
||||
void StreamReader::setStreamSeekable(bool seekable)
|
||||
{
|
||||
m_seekable = seekable;
|
||||
emit streamSeekableChanged(seekable);
|
||||
}
|
||||
|
||||
bool StreamReader::streamSeekable() const
|
||||
{
|
||||
return m_seekable;
|
||||
}
|
||||
|
||||
} // namespace VLC
|
||||
} // namespace Phonon
|
||||
|
||||
#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM
|
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
Copyright (C) 2007-2008 Tanguy Krotoff <tkrotoff@gmail.com>
|
||||
Copyright (C) 2008 Lukas Durfina <lukas.durfina@gmail.com>
|
||||
Copyright (C) 2009 Fathi Boudra <fabo@kde.org>
|
||||
Copyright (C) 2009-2011 vlc-phonon AUTHORS <kde-multimedia@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef PHONON_STREAMREADER_H
|
||||
#define PHONON_STREAMREADER_H
|
||||
|
||||
#include <phonon/mediasource.h>
|
||||
#include <phonon/streaminterface.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <QtCore/QMutex>
|
||||
#include <QtCore/QWaitCondition>
|
||||
|
||||
#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
|
||||
|
||||
namespace Phonon
|
||||
{
|
||||
|
||||
class MediaSource;
|
||||
|
||||
namespace VLC
|
||||
{
|
||||
|
||||
class Media;
|
||||
class MediaObject;
|
||||
|
||||
/** \brief Class for supporting custom data streams to the backend
|
||||
*
|
||||
* This class receives data from a Phonon MediaSource that is a stream.
|
||||
* When data is requested, it fetches it from the media source and passes it further.
|
||||
* MediaObject uses this class to pass stream data to libVLC.
|
||||
*
|
||||
* It implements Phonon::StreamInterface, necessary for the connection with an
|
||||
* Phonon::AbstractMediaStream owned by the Phonon::MediaSource. See the Phonon
|
||||
* documentation for details.
|
||||
*
|
||||
* There are callbacks implemented in streamhooks.cpp, for libVLC.
|
||||
*/
|
||||
class StreamReader : public QObject, public Phonon::StreamInterface
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(Phonon::StreamInterface)
|
||||
public:
|
||||
explicit StreamReader(MediaObject *parent);
|
||||
~StreamReader();
|
||||
|
||||
void addToMedia(Media *media);
|
||||
|
||||
void lock();
|
||||
void unlock();
|
||||
|
||||
static int readCallback(void *data, const char *cookie,
|
||||
int64_t *dts, int64_t *pts, unsigned *flags, // krazy:exclude=typedefs
|
||||
size_t *bufferSize, void **buffer);
|
||||
|
||||
static int readDoneCallback(void *data, const char *cookie,
|
||||
size_t bufferSize, void *buffer);
|
||||
|
||||
static int seekCallback(void *data, const uint64_t pos);
|
||||
|
||||
quint64 currentBufferSize() const;
|
||||
void writeData(const QByteArray &data);
|
||||
quint64 currentPos() const;
|
||||
void setCurrentPos(qint64 pos);
|
||||
|
||||
/**
|
||||
* Requests data from this stream. The stream requests data from the
|
||||
* Phonon::MediaSource's abstract media stream with the needData() signal.
|
||||
* If the requested data is available, it is copied into the buffer.
|
||||
*
|
||||
* \param pos Position in the stream
|
||||
* \param length Length of the data requested
|
||||
* \param buffer A buffer to put the data
|
||||
*/
|
||||
bool read(quint64 offset, int *length, char *buffer);
|
||||
|
||||
void endOfData();
|
||||
void setStreamSize(qint64 newSize);
|
||||
qint64 streamSize() const;
|
||||
void setStreamSeekable(bool seekable);
|
||||
bool streamSeekable() const;
|
||||
|
||||
signals:
|
||||
void streamSeekableChanged(bool seekable);
|
||||
|
||||
protected:
|
||||
QByteArray m_buffer;
|
||||
quint64 m_pos;
|
||||
quint64 m_size;
|
||||
bool m_eos;
|
||||
bool m_seekable;
|
||||
bool m_unlocked;
|
||||
QMutex m_mutex;
|
||||
QWaitCondition m_waitingForData;
|
||||
MediaObject *m_mediaObject;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM
|
||||
|
||||
#endif // PHONON_STREAMREADER_H
|
|
@ -0,0 +1,232 @@
|
|||
/*
|
||||
Copyright (c) 2003-2005 Max Howell <max.howell@methylblue.com>
|
||||
Copyright (c) 2007-2009 Mark Kretschmann <kretschmann@kde.org>
|
||||
Copyright (c) 2010 Kevin Funk <krf@electrostorm.net>
|
||||
Copyright (c) 2011 Harald Sitter <sitter@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "debug.h"
|
||||
#include "debug_p.h"
|
||||
|
||||
#include <QtCore/QMutex>
|
||||
#include <QtCore/QObject>
|
||||
#include <QApplication>
|
||||
|
||||
#ifdef Q_OS_UNIX
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
// Define Application wide prefix
|
||||
#ifndef APP_PREFIX
|
||||
#define APP_PREFIX QLatin1String( "PHONON-VLC" )
|
||||
#endif
|
||||
|
||||
#define DEBUG_INDENT_OBJECTNAME QLatin1String("Debug_Indent_object")
|
||||
|
||||
QMutex Debug::mutex( QMutex::Recursive );
|
||||
|
||||
using namespace Debug;
|
||||
|
||||
static bool s_debugColorsEnabled = true;
|
||||
static DebugLevel s_debugLevel = DEBUG_NONE;
|
||||
|
||||
IndentPrivate::IndentPrivate(QObject* parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
setObjectName( DEBUG_INDENT_OBJECTNAME );
|
||||
}
|
||||
|
||||
/**
|
||||
* We can't use a statically instantiated QString for the indent, because
|
||||
* static namespaces are unique to each dlopened library. So we piggy back
|
||||
* the QString on the KApplication instance
|
||||
*/
|
||||
IndentPrivate* IndentPrivate::instance()
|
||||
{
|
||||
QObject* qOApp = reinterpret_cast<QObject*>(qApp);
|
||||
QObject* obj = qOApp ? qOApp->findChild<QObject*>( DEBUG_INDENT_OBJECTNAME ) : 0;
|
||||
return (obj ? static_cast<IndentPrivate*>( obj ) : new IndentPrivate( qApp ));
|
||||
}
|
||||
|
||||
/*
|
||||
Text color codes (use last digit here)
|
||||
30=black 31=red 32=green 33=yellow 34=blue 35=magenta 36=cyan 37=white
|
||||
*/
|
||||
static int s_colors[] = { 1, 2, 4, 5, 6 }; // no yellow and white for sanity
|
||||
static int s_colorIndex = 0;
|
||||
|
||||
static QString toString( DebugLevel level )
|
||||
{
|
||||
switch( level )
|
||||
{
|
||||
case DEBUG_WARN:
|
||||
return "[WARNING]";
|
||||
case DEBUG_ERROR:
|
||||
return "[ERROR__]";
|
||||
case DEBUG_FATAL:
|
||||
return "[FATAL__]";
|
||||
default:
|
||||
return QString();
|
||||
}
|
||||
}
|
||||
|
||||
static int toColor( DebugLevel level )
|
||||
{
|
||||
switch( level ) {
|
||||
case DEBUG_WARN:
|
||||
return 3; // red
|
||||
case DEBUG_ERROR:
|
||||
case DEBUG_FATAL:
|
||||
return 1; // yellow
|
||||
default:
|
||||
return 0; // default: black
|
||||
}
|
||||
}
|
||||
|
||||
static QString colorize( const QString &text, int color = s_colorIndex )
|
||||
{
|
||||
if( !debugColorEnabled() )
|
||||
return text;
|
||||
|
||||
return QString( "\x1b[00;3%1m%2\x1b[00;39m" ).arg( QString::number(s_colors[color]), text );
|
||||
}
|
||||
|
||||
static QString reverseColorize( const QString &text, int color )
|
||||
{
|
||||
if( !debugColorEnabled() )
|
||||
return text;
|
||||
|
||||
return QString( "\x1b[07;3%1m%2\x1b[00;39m" ).arg( QString::number(color), text );
|
||||
}
|
||||
|
||||
QString Debug::indent()
|
||||
{
|
||||
return IndentPrivate::instance()->m_string;
|
||||
}
|
||||
|
||||
bool Debug::debugEnabled()
|
||||
{
|
||||
return s_debugLevel < DEBUG_NONE;
|
||||
}
|
||||
|
||||
bool Debug::debugColorEnabled()
|
||||
{
|
||||
return s_debugColorsEnabled;
|
||||
}
|
||||
|
||||
DebugLevel Debug::minimumDebugLevel()
|
||||
{
|
||||
return s_debugLevel;
|
||||
}
|
||||
|
||||
void Debug::setColoredDebug( bool enable )
|
||||
{
|
||||
s_debugColorsEnabled = enable;
|
||||
}
|
||||
|
||||
void Debug::setMinimumDebugLevel(DebugLevel level)
|
||||
{
|
||||
s_debugLevel = level;
|
||||
}
|
||||
|
||||
QDebug Debug::dbgstream( DebugLevel level )
|
||||
{
|
||||
if ( level < s_debugLevel )
|
||||
return nullDebug();
|
||||
|
||||
mutex.lock();
|
||||
const QString currentIndent = indent();
|
||||
mutex.unlock();
|
||||
|
||||
QString text = QString("%1%2").arg( APP_PREFIX ).arg( currentIndent );
|
||||
if ( level > DEBUG_INFO )
|
||||
text.append( ' ' + reverseColorize( toString(level), toColor( level ) ) );
|
||||
|
||||
return QDebug( QtDebugMsg ) << qPrintable( text );
|
||||
}
|
||||
|
||||
void Debug::perfLog( const QString &message, const QString &func )
|
||||
{
|
||||
#ifdef Q_OS_UNIX
|
||||
if( !debugEnabled() )
|
||||
return;
|
||||
|
||||
QString str = QString( "MARK: %1: %2 %3" ).arg( qApp->applicationName(), func, message );
|
||||
access( str.toLocal8Bit().data(), F_OK );
|
||||
#endif
|
||||
}
|
||||
|
||||
Block::Block( const char *label )
|
||||
: m_label( label )
|
||||
, m_color( s_colorIndex )
|
||||
{
|
||||
if( !debugEnabled() || DEBUG_INFO < s_debugLevel)
|
||||
return;
|
||||
|
||||
#if QT_VERSION >= 0x040700
|
||||
m_startTime.start();
|
||||
#else
|
||||
m_startTime = QTime::currentTime();
|
||||
#endif
|
||||
|
||||
mutex.lock();
|
||||
s_colorIndex = (s_colorIndex + 1) % 5;
|
||||
dbgstream()
|
||||
<< qPrintable( colorize( QLatin1String( "BEGIN:" ), m_color ) )
|
||||
<< m_label;
|
||||
IndentPrivate::instance()->m_string += QLatin1String(" ");
|
||||
mutex.unlock();
|
||||
}
|
||||
|
||||
Block::~Block()
|
||||
{
|
||||
if( !debugEnabled() || DEBUG_INFO < s_debugLevel)
|
||||
return;
|
||||
|
||||
#if QT_VERSION >= 0x040700
|
||||
const double duration = m_startTime.elapsed() / 1000.0;
|
||||
#else
|
||||
const double duration = (double)m_startTime.msecsTo( QTime::currentTime() ) / 1000.0;
|
||||
#endif
|
||||
|
||||
mutex.lock();
|
||||
IndentPrivate::instance()->m_string.truncate( Debug::indent().length() - 2 );
|
||||
mutex.unlock();
|
||||
|
||||
// Print timing information, and a special message (DELAY) if the method took longer than 5s
|
||||
if( duration < 5.0 )
|
||||
{
|
||||
dbgstream()
|
||||
<< qPrintable( colorize( QLatin1String( "END__:" ), m_color ) )
|
||||
<< m_label
|
||||
<< qPrintable( colorize( QString( "[Took: %3s]")
|
||||
.arg( QString::number(duration, 'g', 2) ), m_color ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
dbgstream()
|
||||
<< qPrintable( colorize( QString( "END__:" ), m_color ) )
|
||||
<< m_label
|
||||
<< qPrintable( reverseColorize( QString( "[DELAY Took (quite long) %3s]")
|
||||
.arg( QString::number(duration, 'g', 2) ), toColor( DEBUG_WARN ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
void Debug::stamp()
|
||||
{
|
||||
static int n = 0;
|
||||
debug() << "| Stamp: " << ++n << endl;
|
||||
}
|
|
@ -0,0 +1,200 @@
|
|||
/*
|
||||
Copyright (c) 2003-2005 Max Howell <max.howell@methylblue.com>
|
||||
Copyright (c) 2007-2009 Mark Kretschmann <kretschmann@kde.org>
|
||||
Copyright (c) 2010 Kevin Funk <krf@electrostorm.net>
|
||||
Copyright (c) 2011 Harald Sitter <sitter@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef PHONON_DEBUG_H
|
||||
#define PHONON_DEBUG_H
|
||||
|
||||
// We always want debug output available at runtime
|
||||
#undef QT_NO_DEBUG_OUTPUT
|
||||
#undef KDE_NO_DEBUG_OUTPUT
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtCore/QMutex>
|
||||
|
||||
#if QT_VERSION >= 0x040700
|
||||
# include <QtCore/QElapsedTimer>
|
||||
#else
|
||||
# include <QtCore/QTime>
|
||||
#endif
|
||||
|
||||
// Platform specific macros
|
||||
#ifdef _WIN32 // krazy:exclude=cpp we really want to check a compiler feature here :P
|
||||
#define __PRETTY_FUNCTION__ __FUNCTION__
|
||||
#endif
|
||||
#ifdef __SUNPRO_CC
|
||||
#define __PRETTY_FUNCTION__ __FILE__
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @namespace Debug
|
||||
* @short kdebug with indentation functionality and convenience macros
|
||||
* @author Max Howell <max.howell@methylblue.com>
|
||||
*
|
||||
* Usage:
|
||||
*
|
||||
* #define DEBUG_PREFIX "Blah"
|
||||
* #include "debug.h"
|
||||
*
|
||||
* void function()
|
||||
* {
|
||||
* Debug::Block myBlock( __PRETTY_FUNCTION__ );
|
||||
*
|
||||
* debug() << "output1" << endl;
|
||||
* debug() << "output2" << endl;
|
||||
* }
|
||||
*
|
||||
* Will output:
|
||||
*
|
||||
* app: BEGIN: void function()
|
||||
* app: [Blah] output1
|
||||
* app: [Blah] output2
|
||||
* app: END: void function(): Took 0.1s
|
||||
*
|
||||
* @see Block
|
||||
* @see CrashHelper
|
||||
* @see ListStream
|
||||
*/
|
||||
namespace Debug
|
||||
{
|
||||
extern QMutex mutex;
|
||||
|
||||
enum DebugLevel {
|
||||
DEBUG_INFO = 0,
|
||||
DEBUG_WARN = 1,
|
||||
DEBUG_ERROR = 2,
|
||||
DEBUG_FATAL = 3,
|
||||
DEBUG_NONE = 4
|
||||
};
|
||||
|
||||
QDebug dbgstream( DebugLevel level = DEBUG_INFO );
|
||||
bool debugEnabled();
|
||||
bool debugColorEnabled();
|
||||
DebugLevel minimumDebugLevel();
|
||||
void setColoredDebug( bool enable );
|
||||
void setMinimumDebugLevel( DebugLevel level );
|
||||
QString indent();
|
||||
|
||||
static inline QDebug dbgstreamwrapper( DebugLevel level ) { return dbgstream( level ); }
|
||||
|
||||
static inline QDebug debug() { return dbgstreamwrapper( DEBUG_INFO ); }
|
||||
static inline QDebug warning() { return dbgstreamwrapper( DEBUG_WARN ); }
|
||||
static inline QDebug error() { return dbgstreamwrapper( DEBUG_ERROR ); }
|
||||
static inline QDebug fatal() { return dbgstreamwrapper( DEBUG_FATAL ); }
|
||||
|
||||
void perfLog( const QString &message, const QString &func );
|
||||
}
|
||||
|
||||
using Debug::debug;
|
||||
using Debug::warning;
|
||||
using Debug::error;
|
||||
using Debug::fatal;
|
||||
|
||||
/// Standard function announcer
|
||||
#define DEBUG_FUNC_INFO { Debug::mutex.lock(); qDebug() << Debug::indent() ; Debug::mutex.unlock(); }
|
||||
|
||||
/// Announce a line
|
||||
#define DEBUG_LINE_INFO { Debug::mutex.lock(); qDebug() << Debug::indent() << "Line: " << __LINE__; Debug::mutex.unlock(); }
|
||||
|
||||
/// Convenience macro for making a standard Debug::Block
|
||||
#define DEBUG_BLOCK Debug::Block uniquelyNamedStackAllocatedStandardBlock( __PRETTY_FUNCTION__ );
|
||||
|
||||
/// Performance logging
|
||||
#define PERF_LOG( msg ) { Debug::perfLog( msg, __PRETTY_FUNCTION__ ); }
|
||||
|
||||
class BlockPrivate;
|
||||
|
||||
namespace Debug
|
||||
{
|
||||
/**
|
||||
* @class Debug::Block
|
||||
* @short Use this to label sections of your code
|
||||
*
|
||||
* Usage:
|
||||
*
|
||||
* void function()
|
||||
* {
|
||||
* Debug::Block myBlock( "section" );
|
||||
*
|
||||
* debug() << "output1" << endl;
|
||||
* debug() << "output2" << endl;
|
||||
* }
|
||||
*
|
||||
* Will output:
|
||||
*
|
||||
* app: BEGIN: section
|
||||
* app: [prefix] output1
|
||||
* app: [prefix] output2
|
||||
* app: END: section - Took 0.1s
|
||||
*
|
||||
*/
|
||||
class Block
|
||||
{
|
||||
public:
|
||||
explicit Block( const char *name );
|
||||
~Block();
|
||||
|
||||
private:
|
||||
#if QT_VERSION >= 0x040700
|
||||
QElapsedTimer m_startTime;
|
||||
#else
|
||||
QTime m_startTime;
|
||||
#endif
|
||||
const char *m_label;
|
||||
int m_color;
|
||||
};
|
||||
|
||||
/**
|
||||
* @name Debug::stamp()
|
||||
* @short To facilitate crash/freeze bugs, by making it easy to mark code that has been processed
|
||||
*
|
||||
* Usage:
|
||||
*
|
||||
* {
|
||||
* Debug::stamp();
|
||||
* function1();
|
||||
* Debug::stamp();
|
||||
* function2();
|
||||
* Debug::stamp();
|
||||
* }
|
||||
*
|
||||
* Will output (assuming the crash occurs in function2()
|
||||
*
|
||||
* app: Stamp: 1
|
||||
* app: Stamp: 2
|
||||
*
|
||||
*/
|
||||
void stamp();
|
||||
}
|
||||
|
||||
#include <QtCore/QVariant>
|
||||
|
||||
namespace Debug
|
||||
{
|
||||
/**
|
||||
* @class Debug::List
|
||||
* @short You can pass anything to this and it will output it as a list
|
||||
*
|
||||
* debug() << (Debug::List() << anInt << aString << aQStringList << aDouble) << endl;
|
||||
*/
|
||||
|
||||
typedef QList<QVariant> List;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
Copyright (c) 2010 Kevin Funk <krf@electrostorm.net>
|
||||
Copyright (c) 2011 Casian Andrei <skeletk13@gmail.com>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef DEBUGPRIVATE_H
|
||||
#define DEBUGPRIVATE_H
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
#include <QtCore/QString>
|
||||
|
||||
class IndentPrivate
|
||||
: public QObject
|
||||
{
|
||||
private:
|
||||
explicit IndentPrivate(QObject* parent = 0);
|
||||
|
||||
public:
|
||||
static IndentPrivate* instance();
|
||||
|
||||
QString m_string;
|
||||
};
|
||||
|
||||
/*
|
||||
* From kdelibs/kdecore/io
|
||||
*/
|
||||
class NoDebugStream: public QIODevice
|
||||
{
|
||||
// Q_OBJECT
|
||||
public:
|
||||
NoDebugStream() { open(WriteOnly); }
|
||||
bool isSequential() const { return true; }
|
||||
qint64 readData(char *, qint64) { return 0; /* eof */ }
|
||||
qint64 readLineData(char *, qint64) { return 0; /* eof */ }
|
||||
qint64 writeData(const char *, qint64 len) { return len; }
|
||||
} devnull;
|
||||
|
||||
QDebug nullDebug()
|
||||
{
|
||||
return QDebug(&devnull);
|
||||
}
|
||||
|
||||
#endif // DEBUGPRIVATE_H
|
|
@ -0,0 +1,128 @@
|
|||
/*
|
||||
Copyright (C) 2011-2012 vlc-phonon AUTHORS <kde-multimedia@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "libvlc.h"
|
||||
|
||||
#include <QtCore/QByteArray>
|
||||
#include <QtCore/QCoreApplication>
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtCore/QDir>
|
||||
#include <QtCore/QSettings>
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/QStringBuilder>
|
||||
#include <QtCore/QVarLengthArray>
|
||||
|
||||
#include <phonon/pulsesupport.h>
|
||||
|
||||
#include <vlc/libvlc.h>
|
||||
#include <vlc/libvlc_version.h>
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
LibVLC *LibVLC::self;
|
||||
|
||||
LibVLC::LibVLC()
|
||||
: m_vlcInstance(0)
|
||||
{
|
||||
}
|
||||
|
||||
LibVLC::~LibVLC()
|
||||
{
|
||||
if (m_vlcInstance)
|
||||
libvlc_release(m_vlcInstance);
|
||||
self = 0;
|
||||
}
|
||||
|
||||
bool LibVLC::init()
|
||||
{
|
||||
Q_ASSERT_X(!self, "LibVLC", "there should be only one LibVLC object");
|
||||
LibVLC::self = new LibVLC;
|
||||
|
||||
QList<QByteArray> args;
|
||||
|
||||
// Ends up as something like $HOME/.config/Phonon/vlc.conf
|
||||
const QString configFileName = QSettings("Phonon", "vlc").fileName();
|
||||
if (QFile::exists(configFileName)) {
|
||||
args << QByteArray("--config=").append(QFile::encodeName(configFileName));
|
||||
args << "--no-ignore-config";
|
||||
}
|
||||
|
||||
int debugLevel = qgetenv("PHONON_SUBSYSTEM_DEBUG").toInt();
|
||||
if (debugLevel > 0) {
|
||||
args << QByteArray("--verbose=").append(QByteArray::number(debugLevel));
|
||||
args << QByteArray("--extraintf=logger");
|
||||
#ifdef Q_WS_WIN
|
||||
QDir logFilePath(QString(qgetenv("APPDATA")).append("/vlc"));
|
||||
#else
|
||||
QDir logFilePath(QDir::homePath().append("/.vlc"));
|
||||
#endif //Q_WS_WIN
|
||||
logFilePath.mkdir("log");
|
||||
const QString logFile = logFilePath.path()
|
||||
.append("/log/vlc-log-")
|
||||
.append(QString::number(qApp->applicationPid()))
|
||||
.append(".txt");
|
||||
args << QByteArray("--logfile=").append(QFile::encodeName(QDir::toNativeSeparators(logFile)));
|
||||
}
|
||||
|
||||
args << "--no-media-library";
|
||||
args << "--no-osd";
|
||||
args << "--no-stats";
|
||||
// By default VLC will put a picture-in-picture when making a snapshot.
|
||||
// This is unexpected behaviour for us, so we force it off.
|
||||
args << "--no-snapshot-preview";
|
||||
// Do not load xlib dependent modules as we cannot ensure proper init
|
||||
// order as expected by xlib thus leading to crashes.
|
||||
// KDE BUG: 240001
|
||||
args << "--no-xlib";
|
||||
// Do not preload services discovery modules, we don't use them.
|
||||
args << "--services-discovery=''";
|
||||
// The application is meant to manage this. Also, using the builtin
|
||||
// inhibitor may cause problems on shutdown if VLC tries to uninhibit too
|
||||
// late in the application lifecycle.
|
||||
args << "--no-disable-screensaver";
|
||||
// Allow multiple starts (one gets to wonder whether that makes a difference).
|
||||
#if !defined(Q_OS_MAC) && (defined(Q_OS_WIN) || !defined(PHONON_NO_DBUS))
|
||||
args << "--no-one-instance";
|
||||
#endif
|
||||
args << "--no-audio";
|
||||
args << "--no-video";
|
||||
// 6 seconds disk read buffer (up from vlc 2.1 default of 300ms) when using alsa, prevents most buffer underruns
|
||||
// when the disk is very busy. We expect the pulse buffer after decoding to solve the same problem.
|
||||
Phonon::PulseSupport *pulse = Phonon::PulseSupport::getInstance();
|
||||
if (!pulse || !pulse->isActive()) {
|
||||
args << "--file-caching=6000";
|
||||
}
|
||||
|
||||
// Build const char* array
|
||||
QVarLengthArray<const char *, 64> vlcArgs(args.size());
|
||||
for (int i = 0; i < args.size(); ++i) {
|
||||
vlcArgs[i] = args.at(i).constData();
|
||||
}
|
||||
|
||||
// Create and initialize a libvlc instance (it should be done only once)
|
||||
self->m_vlcInstance = libvlc_new(vlcArgs.size(), vlcArgs.constData());
|
||||
if (!self->m_vlcInstance) {
|
||||
fatal() << "libVLC: could not initialize";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
const char *LibVLC::errorMessage()
|
||||
{
|
||||
return libvlc_errmsg();
|
||||
}
|
|
@ -0,0 +1,140 @@
|
|||
/*
|
||||
Copyright (C) 2011 vlc-phonon AUTHORS <kde-multimedia@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef LIBVLC_H
|
||||
#define LIBVLC_H
|
||||
|
||||
#include <QtCore/QtGlobal>
|
||||
#include <QtCore/QStringList>
|
||||
|
||||
#include <vlc/libvlc_version.h>
|
||||
|
||||
struct libvlc_instance_t;
|
||||
|
||||
/**
|
||||
* Convenience macro accessing the vlc_instance_t via LibVLC::self.
|
||||
* Please note that init() must have been called whenever using this, as no
|
||||
* checking of self is conducted (i.e. can be null).
|
||||
*/
|
||||
#define pvlc_libvlc LibVLC::self->vlc()
|
||||
|
||||
/**
|
||||
* Foreach loop macro for VLC descriptions.
|
||||
*
|
||||
* For this macro to work the type name must be of the form:
|
||||
* \verbatim libvlc_FOO_t \endverbatim
|
||||
* *
|
||||
* \param type the type identifier of VLC (without libvlc and _t)
|
||||
* \param variable the variable name you want to use
|
||||
* \param getter the getter from which to get the iterator
|
||||
* \param releaser, function name to release the list
|
||||
*/
|
||||
#define VLC_FOREACH(type, variable, getter, releaser) \
|
||||
for (libvlc_##type##_t *__libvlc_first_element = getter, *variable = __libvlc_first_element; \
|
||||
variable; \
|
||||
variable = variable->p_next, !variable ? releaser(__libvlc_first_element) : (void)0)
|
||||
|
||||
// This foreach expects only a type and variable because getter and releaser are generic.
|
||||
// Also the type is in short form i.e. libvlc_foo_t would be foo.
|
||||
#define VLC_FOREACH_LIST(type, variable) VLC_FOREACH(type, variable, libvlc_##type##_list_get(pvlc_libvlc), libvlc_##type##_list_release)
|
||||
|
||||
// These foreach expect no type because the type is generic, they do however
|
||||
// expect a getter to allow usage with our wrapper classes and since the getter
|
||||
// will most likely not be generic.
|
||||
// For instance libvlc_audio_get_track_description returns a generic
|
||||
// libvlc_track_description_t pointer. So the specific audio_track function
|
||||
// relates to the generic track description type.
|
||||
#define VLC_FOREACH_TRACK(variable, getter) VLC_FOREACH(track_description, variable, getter, libvlc_track_description_list_release)
|
||||
#define VLC_FOREACH_MODULE(variable, getter) VLC_FOREACH(module_description, variable, getter, libvlc_module_description_list_release)
|
||||
|
||||
/**
|
||||
* \brief Singleton class containing a libvlc instance.
|
||||
*
|
||||
* This class is a convenience class implementing the singleton pattern to hold
|
||||
* an instance of libvlc. This instance is necessary to call various libvlc
|
||||
* functions (such as creating a new mediaplayer instance).
|
||||
*
|
||||
* To initialize the object call init(), this will create the actualy LibVLC
|
||||
* instance and then try to initialize the libvlc instance itself.
|
||||
* init() returns false in case the libvlc instance could not be created.
|
||||
*
|
||||
* For convenience reasons there is also a libvlc macro which gets the LibVLC
|
||||
* instance and then the libvlc_instance_t form that. Note that this macro
|
||||
* does not check whether LibVLC actually got initialized, so it should only
|
||||
* be used when you can be absolutely sure that init() was already called
|
||||
*
|
||||
* \code
|
||||
* LibVLC::init(0); // init LibVLC
|
||||
* if (!LibVLC::self) {
|
||||
* exit(1); // error if self is null
|
||||
* }
|
||||
* libvlc_media_player_new(libvlc); // use libvlc macro
|
||||
* \endcode
|
||||
*
|
||||
* \author Harald Sitter <sitter@kde->org>
|
||||
*/
|
||||
class LibVLC
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* The singleton itself. Beware that this returns 0 unless init was called.
|
||||
*
|
||||
* \returns LibVLC instance or 0 if there is none.
|
||||
*
|
||||
* \see init
|
||||
*/
|
||||
static LibVLC *self;
|
||||
|
||||
/**
|
||||
* \returns the contained libvlc instance.
|
||||
*/
|
||||
libvlc_instance_t *vlc()
|
||||
{
|
||||
return m_vlcInstance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct singleton and initialize and launch the VLC library.
|
||||
*
|
||||
* \return VLC initialization result
|
||||
*/
|
||||
static bool init();
|
||||
|
||||
/**
|
||||
* \returns the most recent error message of libvlc
|
||||
*/
|
||||
static const char *errorMessage();
|
||||
|
||||
/**
|
||||
* Destruct the LibVLC singleton and release the contained libvlc instance.
|
||||
*/
|
||||
~LibVLC();
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(LibVLC)
|
||||
|
||||
/**
|
||||
* Private default constructor, to create LibVLC call init instead.
|
||||
*
|
||||
* \see init
|
||||
*/
|
||||
LibVLC();
|
||||
|
||||
libvlc_instance_t *m_vlcInstance;
|
||||
};
|
||||
|
||||
#endif // LIBVLC_H
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
Copyright (C) 2012 Harald Sitter <sitter@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef PHONON_VLC_MIME_H
|
||||
#define PHONON_VLC_MIME_H
|
||||
|
||||
#include <QtCore/QStringList>
|
||||
|
||||
namespace Phonon {
|
||||
namespace VLC {
|
||||
|
||||
static QStringList mimeTypeList()
|
||||
{
|
||||
// In CMake we null-terminate this list for ease of iteration.
|
||||
const char *c_strings[] = @PHONON_VLC_MIME_TYPES_C_ARRAY@;
|
||||
|
||||
QStringList list;
|
||||
int i = 0;
|
||||
while (c_strings[i])
|
||||
list.append(QLatin1String(c_strings[i++]));
|
||||
return list;
|
||||
}
|
||||
|
||||
} // namespace VLC
|
||||
} // namespace Phonon
|
||||
|
||||
#endif // PHONON_VLC_MIME_H
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
Copyright (C) 2012 Harald Sitter <sitter@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef PHONON_VLC_VSTRING_H
|
||||
#define PHONON_VLC_VSTRING_H
|
||||
|
||||
#include <QtCore/QString>
|
||||
#include <vlc/libvlc.h>
|
||||
#include <vlc/libvlc_version.h>
|
||||
|
||||
/**
|
||||
* @brief The VString class wraps around a char* returned from libvlc functions.
|
||||
* Directly from libvlc functions returned cstrings are unique in two ways.
|
||||
* For one they are to be freed by the caller, and for another they are always
|
||||
* UTF8 (as VLC internally only uses UTF8).
|
||||
*
|
||||
* Particularly the first point is where VString comes in, it will on destruction
|
||||
* call libvlc_free to free the string, thus avoiding memleaks.
|
||||
* Additionally it conveniently converts to QString using either toQString
|
||||
* or implicit cast to QString which makes it completely transparent to other
|
||||
* functions. It also prevents you from carrying the cstring out of scope and
|
||||
* render implicit copies of it invalid once free is called somewhere.
|
||||
* Both functions use QString::fromUtf8 and are therefore the best way to
|
||||
* process the string.
|
||||
*/
|
||||
class VString
|
||||
{
|
||||
public:
|
||||
explicit VString(char *vlcString) : m_vlcString(vlcString) {}
|
||||
~VString()
|
||||
{
|
||||
libvlc_free(m_vlcString);
|
||||
}
|
||||
|
||||
// VLC internally only uses UTF8!
|
||||
QString toQString() { return QString::fromUtf8(m_vlcString); }
|
||||
operator QString() { return toQString(); }
|
||||
|
||||
private:
|
||||
VString() {}
|
||||
|
||||
char *m_vlcString;
|
||||
};
|
||||
|
||||
#endif // PHONON_VLC_VSTRING_H
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
Copyright (C) 2010 Benoit Calvez <benoit@litchis.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef NSVIDEOVIEW_H
|
||||
#define NSVIDEOVIEW_H
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@interface VideoView : NSView
|
||||
- (void)addVoutSubview: (NSView *)view;
|
||||
- (void)removeVoutSubview: (NSView *)view;
|
||||
- (BOOL)stretchesVideo;
|
||||
@end
|
||||
|
||||
#endif // NSVIDEOVIEW_H
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
Copyright (C) 2010 Benoit Calvez <benoit@litchis.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "nsvideoview.h"
|
||||
|
||||
@implementation VideoView
|
||||
- (void)addVoutSubview:(NSView *)view
|
||||
{
|
||||
[view setFrame:[self bounds]];
|
||||
[self addSubview:view];
|
||||
[view setAutoresizingMask: NSViewHeightSizable |NSViewWidthSizable];
|
||||
}
|
||||
- (void)removeVoutSubview:(NSView *)view
|
||||
{
|
||||
[view removeFromSuperview];
|
||||
}
|
||||
- (BOOL)stretchesVideo
|
||||
{
|
||||
//Whatever you would want
|
||||
return NO;
|
||||
}
|
||||
|
||||
@end
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
Copyright (C) 2010 Benoit Calvez <benoit@litchis.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef VLCMACWIDGET_H
|
||||
#define VLCMACWIDGET_H
|
||||
|
||||
#include <QMacCocoaViewContainer>
|
||||
|
||||
#import <qmaccocoaviewcontainer_mac.h>
|
||||
|
||||
class VlcMacWidget : public QMacCocoaViewContainer
|
||||
{
|
||||
public:
|
||||
explicit VlcMacWidget(QWidget *parent = 0);
|
||||
};
|
||||
|
||||
|
||||
#endif // VLCMACWIDGET_H
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
Copyright (C) 2010 Benoit Calvez <benoit@litchis.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "vlcmacwidget.h"
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import "nsvideoview.h"
|
||||
|
||||
#include <QtCore/QtDebug>
|
||||
|
||||
VlcMacWidget::VlcMacWidget(QWidget *parent) : QMacCocoaViewContainer(0, parent)
|
||||
{
|
||||
// Many Cocoa objects create temporary autorelease objects,
|
||||
// so create a pool to catch them.
|
||||
@autoreleasepool {
|
||||
VideoView *videoView = [[VideoView alloc] init];
|
||||
|
||||
this->setCocoaView(videoView);
|
||||
|
||||
// Release our reference, since our super class takes ownership and we
|
||||
// don't need it anymore (except with Qt 5.8.0 because of a regression).
|
||||
if (strcmp(qVersion(), "5.8.0")) {
|
||||
[videoView release];
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,200 @@
|
|||
/*
|
||||
Copyright (C) 2010-2012 Harald Sitter <apachelogger@ubuntu.com>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) version 3, or any
|
||||
later version accepted by the membership of KDE e.V. (or its
|
||||
successor approved by the membership of KDE e.V.), Nokia Corporation
|
||||
(or its successors, if any) and the KDE Free Qt Foundation, which shall
|
||||
act as a proxy defined in Section 6 of version 3 of the license.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "videodataoutput.h"
|
||||
|
||||
#include <phonon/medianode.h>
|
||||
#include <phonon/audiooutput.h>
|
||||
#include <phonon/experimental/abstractvideodataoutput.h>
|
||||
|
||||
#include <QMetaObject>
|
||||
|
||||
#include "utils/debug.h"
|
||||
#include "media.h"
|
||||
#include "mediaobject.h"
|
||||
|
||||
using namespace Phonon::Experimental;
|
||||
|
||||
namespace Phonon
|
||||
{
|
||||
namespace VLC
|
||||
{
|
||||
|
||||
VideoDataOutput::VideoDataOutput(QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_frontend(0)
|
||||
{
|
||||
}
|
||||
|
||||
VideoDataOutput::~VideoDataOutput()
|
||||
{
|
||||
}
|
||||
|
||||
void VideoDataOutput::handleConnectToMediaObject(MediaObject *mediaObject)
|
||||
{
|
||||
Q_UNUSED(mediaObject);
|
||||
setCallbacks(m_player);
|
||||
}
|
||||
|
||||
void VideoDataOutput::handleDisconnectFromMediaObject(MediaObject *mediaObject)
|
||||
{
|
||||
Q_UNUSED(mediaObject);
|
||||
unsetCallbacks(m_player);
|
||||
}
|
||||
|
||||
void VideoDataOutput::handleAddToMedia(Media *media)
|
||||
{
|
||||
media->addOption(":video");
|
||||
}
|
||||
|
||||
Experimental::AbstractVideoDataOutput *VideoDataOutput::frontendObject() const
|
||||
{
|
||||
return m_frontend;
|
||||
}
|
||||
|
||||
void VideoDataOutput::setFrontendObject(Experimental::AbstractVideoDataOutput *frontend)
|
||||
{
|
||||
m_frontend = frontend;
|
||||
}
|
||||
|
||||
void *VideoDataOutput::lockCallback(void **planes)
|
||||
{
|
||||
m_mutex.lock();
|
||||
DEBUG_BLOCK;
|
||||
planes[0] = reinterpret_cast<void *>(m_frame.data0.data());
|
||||
planes[1] = reinterpret_cast<void *>(m_frame.data1.data());
|
||||
planes[2] = reinterpret_cast<void *>(m_frame.data2.data());
|
||||
return 0;
|
||||
}
|
||||
|
||||
void VideoDataOutput::unlockCallback(void *picture, void *const*planes)
|
||||
{
|
||||
Q_UNUSED(picture);
|
||||
Q_UNUSED(planes);
|
||||
DEBUG_BLOCK;
|
||||
|
||||
// For some reason VLC yields BGR24, so we swap it to RGB
|
||||
if (m_frame.format == Experimental::VideoFrame2::Format_RGB888) {
|
||||
uchar *data = (uchar *) m_frame.data0.data();
|
||||
uchar tmp;
|
||||
for (int i = 0; i < m_frame.data0.size(); i += 3) {
|
||||
tmp = data[i];
|
||||
data[i] = data[i+2];
|
||||
data[i+2] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_frontend)
|
||||
m_frontend->frameReady(m_frame);
|
||||
|
||||
m_mutex.unlock();
|
||||
}
|
||||
|
||||
void VideoDataOutput::displayCallback(void *picture)
|
||||
{
|
||||
Q_UNUSED(picture);
|
||||
DEBUG_BLOCK;
|
||||
// We send the frame while unlocking as we could loose syncing otherwise.
|
||||
// With VDO the consumer is expected to ensure syncness while not blocking
|
||||
// unlock for long periods of time. Good luck with that... -.-
|
||||
}
|
||||
|
||||
static VideoFrame2::Format fourccToFormat(const char *fourcc)
|
||||
{
|
||||
if (qstrcmp(fourcc, "RV24"))
|
||||
return VideoFrame2::Format_RGB888;
|
||||
else if (qstrcmp(fourcc, "RV32"))
|
||||
return VideoFrame2::Format_RGB32;
|
||||
else if (qstrcmp(fourcc, "YV12"))
|
||||
return VideoFrame2::Format_YV12;
|
||||
else if (qstrcmp(fourcc, "YUY2"))
|
||||
return VideoFrame2::Format_YUY2;
|
||||
else
|
||||
return VideoFrame2::Format_Invalid;
|
||||
}
|
||||
|
||||
static const vlc_chroma_description_t *setFormat(VideoFrame2::Format format, char **chroma)
|
||||
{
|
||||
switch (format) {
|
||||
case VideoFrame2::Format_Invalid:
|
||||
*chroma = 0;
|
||||
return 0;
|
||||
case VideoFrame2::Format_RGB32:
|
||||
qstrcpy(*chroma, "RV32");
|
||||
return vlc_fourcc_GetChromaDescription(VLC_CODEC_RGB32);
|
||||
case VideoFrame2::Format_RGB888:
|
||||
qstrcpy(*chroma, "RV24");
|
||||
return vlc_fourcc_GetChromaDescription(VLC_CODEC_RGB24);
|
||||
case VideoFrame2::Format_YV12:
|
||||
qstrcpy(*chroma, "YV12");
|
||||
return vlc_fourcc_GetChromaDescription(VLC_CODEC_YV12);
|
||||
case VideoFrame2::Format_YUY2:
|
||||
qstrcpy(*chroma, "YUY2");
|
||||
return vlc_fourcc_GetChromaDescription(VLC_CODEC_YUYV);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned VideoDataOutput::formatCallback(char *chroma,
|
||||
unsigned *width, unsigned *height,
|
||||
unsigned *pitches, unsigned *lines)
|
||||
{
|
||||
DEBUG_BLOCK;
|
||||
|
||||
m_frame.width = *width;
|
||||
m_frame.height = *height;
|
||||
|
||||
const vlc_chroma_description_t *chromaDesc = 0;
|
||||
|
||||
QSet<VideoFrame2::Format> allowedFormats = m_frontend->allowedFormats();
|
||||
VideoFrame2::Format suggestedFormat = fourccToFormat(chroma);
|
||||
if (suggestedFormat != VideoFrame2::Format_Invalid
|
||||
&& allowedFormats.contains(suggestedFormat)) { // Use suggested
|
||||
chromaDesc = setFormat(suggestedFormat, &chroma);
|
||||
m_frame.format = suggestedFormat;
|
||||
} else { // Pick first and use that
|
||||
foreach (const VideoFrame2::Format &format, allowedFormats) {
|
||||
chromaDesc = setFormat(format, &chroma);
|
||||
if (chroma) {
|
||||
m_frame.format = format;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Q_ASSERT(chromaDesc);
|
||||
|
||||
unsigned int bufferSize = setPitchAndLines(chromaDesc, *width, *height, pitches, lines);
|
||||
|
||||
m_frame.data0.resize(pitches[0] * lines[0]);
|
||||
m_frame.data1.resize(pitches[1] * lines[1]);
|
||||
m_frame.data2.resize(pitches[2] * lines[0]);
|
||||
|
||||
return bufferSize;
|
||||
}
|
||||
|
||||
void VideoDataOutput::formatCleanUpCallback()
|
||||
{
|
||||
DEBUG_BLOCK;
|
||||
}
|
||||
|
||||
} // namespace VLC
|
||||
} // namespace Phonon
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
Copyright (C) 2012 Harald Sitter <sitter@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef Phonon_VLC_VIDEODATAOUTPUT_H
|
||||
#define Phonon_VLC_VIDEODATAOUTPUT_H
|
||||
|
||||
#include <QMutex>
|
||||
#include <QObject>
|
||||
|
||||
#include <phonon/experimental/videodataoutputinterface.h>
|
||||
#include <phonon/experimental/videoframe2.h>
|
||||
|
||||
#include "sinknode.h"
|
||||
#include "videomemorystream.h"
|
||||
|
||||
namespace Phonon
|
||||
{
|
||||
namespace VLC
|
||||
{
|
||||
|
||||
/**
|
||||
* @author Harald Sitter <apachelogger@ubuntu.com>
|
||||
*/
|
||||
class VideoDataOutput : public QObject, public SinkNode,
|
||||
public Experimental::VideoDataOutputInterface, private VideoMemoryStream
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(Phonon::Experimental::VideoDataOutputInterface)
|
||||
public:
|
||||
explicit VideoDataOutput(QObject *parent);
|
||||
~VideoDataOutput();
|
||||
|
||||
void handleConnectToMediaObject(MediaObject *mediaObject);
|
||||
void handleDisconnectFromMediaObject(MediaObject *mediaObject);
|
||||
void handleAddToMedia(Media *media);
|
||||
|
||||
Experimental::AbstractVideoDataOutput *frontendObject() const;
|
||||
void setFrontendObject(Experimental::AbstractVideoDataOutput *frontend);
|
||||
|
||||
virtual void *lockCallback(void **planes);
|
||||
virtual void unlockCallback(void *picture,void *const *planes);
|
||||
virtual void displayCallback(void *picture);
|
||||
|
||||
virtual unsigned formatCallback(char *chroma,
|
||||
unsigned *width, unsigned *height,
|
||||
unsigned *pitches,
|
||||
unsigned *lines);
|
||||
virtual void formatCleanUpCallback();
|
||||
|
||||
private:
|
||||
Experimental::AbstractVideoDataOutput *m_frontend;
|
||||
Experimental::VideoFrame2 m_frame;
|
||||
QByteArray m_buffer;
|
||||
QMutex m_mutex;
|
||||
};
|
||||
|
||||
} // namespace VLC
|
||||
} // namespace Phonon
|
||||
|
||||
#endif // PHONON_VLC_VIDEODATAOUTPUT_H
|
|
@ -0,0 +1,147 @@
|
|||
/*
|
||||
Copyright (C) 2012 Harald Sitter <sitter@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "videomemorystream.h"
|
||||
|
||||
#include "mediaplayer.h"
|
||||
|
||||
namespace Phonon {
|
||||
namespace VLC {
|
||||
|
||||
static inline VideoMemoryStream *p_this(void *opaque) { return static_cast<VideoMemoryStream *>(opaque); }
|
||||
static inline VideoMemoryStream *p_this(void **opaque) { return static_cast<VideoMemoryStream *>(*opaque); }
|
||||
#define P_THIS p_this(opaque)
|
||||
|
||||
VideoMemoryStream::VideoMemoryStream()
|
||||
{
|
||||
}
|
||||
|
||||
VideoMemoryStream::~VideoMemoryStream()
|
||||
{
|
||||
}
|
||||
|
||||
static inline qint64 gcd(qint64 a, qint64 b)
|
||||
{
|
||||
while( b )
|
||||
{
|
||||
qint64 c = a % b;
|
||||
a = b;
|
||||
b = c;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
static int lcm(int a, int b)
|
||||
{
|
||||
return a * b / GCD( a, b );
|
||||
}
|
||||
|
||||
unsigned VideoMemoryStream::setPitchAndLines(const vlc_chroma_description_t *desc,
|
||||
unsigned width, unsigned height,
|
||||
unsigned *pitches, unsigned *lines,
|
||||
unsigned *visiblePitches, unsigned *visibleLines)
|
||||
{
|
||||
// Mostly taken from vlc/src/misc/picture.c
|
||||
// Simple alignment would be an option but I trust the VLC guys they know what they are doing.
|
||||
int i_modulo_w = 1;
|
||||
int i_modulo_h = 1;
|
||||
unsigned int i_ratio_h = 1;
|
||||
for( unsigned i = 0; i < desc->plane_count; i++ )
|
||||
{
|
||||
i_modulo_w = lcm( i_modulo_w, 8 * desc->p[i].w.den );
|
||||
i_modulo_h = lcm( i_modulo_h, 8 * desc->p[i].h.den );
|
||||
if( i_ratio_h < desc->p[i].h.den )
|
||||
i_ratio_h = desc->p[i].h.den;
|
||||
|
||||
}
|
||||
i_modulo_h = lcm( i_modulo_h, 32 );
|
||||
|
||||
const int i_width_aligned = ( width + i_modulo_w - 1 ) / i_modulo_w * i_modulo_w;
|
||||
const int i_height_aligned = ( height + i_modulo_h - 1 ) / i_modulo_h * i_modulo_h;
|
||||
const int i_height_extra = 2 * i_ratio_h; /* This one is a hack for some ASM functions */
|
||||
|
||||
unsigned int bufferSize = 0;
|
||||
for(unsigned i = 0; i < desc->plane_count; ++i)
|
||||
{
|
||||
pitches[i] = i_width_aligned * desc->p[i].w.num / desc->p[i].w.den * desc->pixel_size;
|
||||
if (visiblePitches)
|
||||
visiblePitches[i] = width * desc->p[i].w.num / desc->p[i].w.den * desc->pixel_size;
|
||||
|
||||
lines[i] = (i_height_aligned + i_height_extra ) * desc->p[i].h.num / desc->p[i].h.den;
|
||||
if (visibleLines)
|
||||
visibleLines[i] = height * desc->p[i].h.num / desc->p[i].h.den;
|
||||
|
||||
bufferSize += pitches[i] * lines[i];
|
||||
}
|
||||
|
||||
return bufferSize;
|
||||
}
|
||||
|
||||
void VideoMemoryStream::setCallbacks(MediaPlayer *player)
|
||||
{
|
||||
libvlc_video_set_callbacks(player->libvlc_media_player(),
|
||||
lockCallbackInternal,
|
||||
unlockCallbackInternal,
|
||||
displayCallbackInternal,
|
||||
this);
|
||||
libvlc_video_set_format_callbacks(player->libvlc_media_player(),
|
||||
formatCallbackInternal,
|
||||
formatCleanUpCallbackInternal);
|
||||
}
|
||||
|
||||
void VideoMemoryStream::unsetCallbacks(MediaPlayer *player)
|
||||
{
|
||||
libvlc_video_set_callbacks(player->libvlc_media_player(),
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0);
|
||||
libvlc_video_set_format_callbacks(player->libvlc_media_player(),
|
||||
0,
|
||||
0);
|
||||
}
|
||||
|
||||
|
||||
void *VideoMemoryStream::lockCallbackInternal(void *opaque, void **planes)
|
||||
{
|
||||
return P_THIS->lockCallback(planes);
|
||||
}
|
||||
|
||||
void VideoMemoryStream::unlockCallbackInternal(void *opaque, void *picture, void *const*planes)
|
||||
{
|
||||
P_THIS->unlockCallback(picture, planes);
|
||||
}
|
||||
|
||||
void VideoMemoryStream::displayCallbackInternal(void *opaque, void *picture)
|
||||
{
|
||||
P_THIS->displayCallback(picture);
|
||||
}
|
||||
|
||||
unsigned VideoMemoryStream::formatCallbackInternal(void **opaque, char *chroma,
|
||||
unsigned *width, unsigned *height,
|
||||
unsigned *pitches, unsigned *lines)
|
||||
{
|
||||
return P_THIS->formatCallback(chroma, width, height, pitches, lines);
|
||||
}
|
||||
|
||||
void VideoMemoryStream::formatCleanUpCallbackInternal(void *opaque)
|
||||
{
|
||||
P_THIS->formatCleanUpCallback();
|
||||
}
|
||||
|
||||
} // namespace VLC
|
||||
} // namespace Phonon
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
Copyright (C) 2012 Harald Sitter <sitter@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef PHONON_VLC_VIDEOMEMORYSTREAM_H
|
||||
#define PHONON_VLC_VIDEOMEMORYSTREAM_H
|
||||
|
||||
// VLC 3.0 uses the restrict keyword. restrict is not a thing in C++, so
|
||||
// depending on the compiler you use an extension keyword or drop it entirely.
|
||||
#if defined(Q_CC_GNU)
|
||||
#define restrict __restrict__
|
||||
#elif defined(Q_CC_MSVC)
|
||||
#define restrict __restrict
|
||||
#else
|
||||
#define restrict
|
||||
#endif
|
||||
|
||||
#include <vlc/plugins/vlc_common.h>
|
||||
#include <vlc/plugins/vlc_fourcc.h>
|
||||
|
||||
namespace Phonon {
|
||||
namespace VLC {
|
||||
|
||||
class MediaPlayer;
|
||||
|
||||
class VideoMemoryStream
|
||||
{
|
||||
public:
|
||||
explicit VideoMemoryStream();
|
||||
virtual ~VideoMemoryStream();
|
||||
|
||||
/**
|
||||
* @returns overall buffersize needed
|
||||
*/
|
||||
static unsigned setPitchAndLines(const vlc_chroma_description_t *chromaDescription,
|
||||
unsigned width, unsigned height,
|
||||
unsigned *pitches, unsigned *lines,
|
||||
unsigned *visiblePitches = 0, unsigned *visibleLines = 0);
|
||||
|
||||
void setCallbacks(Phonon::VLC::MediaPlayer *player);
|
||||
void unsetCallbacks(Phonon::VLC::MediaPlayer *player);
|
||||
|
||||
protected:
|
||||
virtual void *lockCallback(void **planes) = 0;
|
||||
virtual void unlockCallback(void *picture,void *const *planes) = 0;
|
||||
virtual void displayCallback(void *picture) = 0;
|
||||
|
||||
virtual unsigned formatCallback(char *chroma,
|
||||
unsigned *width, unsigned *height,
|
||||
unsigned *pitches,
|
||||
unsigned *lines) = 0;
|
||||
virtual void formatCleanUpCallback() = 0;
|
||||
|
||||
private:
|
||||
static void *lockCallbackInternal(void *opaque, void **planes);
|
||||
static void unlockCallbackInternal(void *opaque, void *picture, void *const *planes);
|
||||
static void displayCallbackInternal(void *opaque, void *picture);
|
||||
|
||||
static unsigned formatCallbackInternal(void **opaque, char *chroma,
|
||||
unsigned *width, unsigned *height,
|
||||
unsigned *pitches,
|
||||
unsigned *lines);
|
||||
static void formatCleanUpCallbackInternal(void *opaque);
|
||||
|
||||
};
|
||||
|
||||
} // namespace VLC
|
||||
} // namespace Phonon
|
||||
|
||||
#endif // PHONON_VLC_VIDEOMEMORYSTREAM_H
|
|
@ -0,0 +1,545 @@
|
|||
/*
|
||||
Copyright (C) 2007-2008 Tanguy Krotoff <tkrotoff@gmail.com>
|
||||
Copyright (C) 2008 Lukas Durfina <lukas.durfina@gmail.com>
|
||||
Copyright (C) 2009 Fathi Boudra <fabo@kde.org>
|
||||
Copyright (C) 2009-2011 vlc-phonon AUTHORS <kde-multimedia@kde.org>
|
||||
Copyright (C) 2011-2021 Harald Sitter <sitter@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "videowidget.h"
|
||||
|
||||
#include <QGuiApplication>
|
||||
#include <QPainter>
|
||||
#include <QPaintEvent>
|
||||
|
||||
#include <vlc/vlc.h>
|
||||
|
||||
#include "utils/debug.h"
|
||||
#include "mediaobject.h"
|
||||
#include "media.h"
|
||||
|
||||
#include "video/videomemorystream.h"
|
||||
|
||||
namespace Phonon {
|
||||
namespace VLC {
|
||||
|
||||
#define DEFAULT_QSIZE QSize(320, 240)
|
||||
|
||||
class SurfacePainter : public VideoMemoryStream
|
||||
{
|
||||
public:
|
||||
void handlePaint(QPaintEvent *event)
|
||||
{
|
||||
// Mind that locking here is still faster than making this lockfree by
|
||||
// dispatching QEvents.
|
||||
// Plus VLC can actually skip frames as necessary.
|
||||
QMutexLocker lock(&m_mutex);
|
||||
Q_UNUSED(event);
|
||||
|
||||
if (m_frame.isNull()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QPainter painter(widget);
|
||||
// When using OpenGL for the QPaintEngine drawing the same QImage twice
|
||||
// does not actually result in a texture change for one reason or another.
|
||||
// So we simply create new images for every event. This is plenty cheap
|
||||
// as the QImage only points to the plane data (it can't even make it
|
||||
// properly shared as it does not know that the data belongs to a QBA).
|
||||
// TODO: investigate if this is still necessary. This was added for gwenview, but with Qt 5.15 the problem
|
||||
// can't be produced.
|
||||
painter.drawImage(drawFrameRect(), QImage(m_frame));
|
||||
event->accept();
|
||||
}
|
||||
|
||||
VideoWidget *widget;
|
||||
|
||||
private:
|
||||
virtual void *lockCallback(void **planes)
|
||||
{
|
||||
m_mutex.lock();
|
||||
planes[0] = (void *) m_frame.bits();
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual void unlockCallback(void *picture,void *const *planes)
|
||||
{
|
||||
Q_UNUSED(picture);
|
||||
Q_UNUSED(planes);
|
||||
m_mutex.unlock();
|
||||
}
|
||||
|
||||
virtual void displayCallback(void *picture)
|
||||
{
|
||||
Q_UNUSED(picture);
|
||||
if (widget)
|
||||
widget->update();
|
||||
}
|
||||
|
||||
virtual unsigned formatCallback(char *chroma,
|
||||
unsigned *width, unsigned *height,
|
||||
unsigned *pitches,
|
||||
unsigned *lines)
|
||||
{
|
||||
QMutexLocker lock(&m_mutex);
|
||||
// Surface rendering is a fallback system used when no efficient rendering implementation is available.
|
||||
// As such we only support RGB32 for simplicity reasons and this will almost always mean software scaling.
|
||||
// And since scaling is unavoidable anyway we take the canonical frame size and then scale it on our end via
|
||||
// QPainter, again, greater simplicity at likely no real extra cost since this is all super inefficient anyway.
|
||||
// Also, since aspect ratio can be change mid-playback by the user, doing the scaling on our end means we
|
||||
// don't need to restart the entire player to retrigger format calculation.
|
||||
// With all that in mind we simply use the canonical size and feed VLC the QImage's pitch and lines as
|
||||
// effectively the VLC vout is the QImage so its constraints matter.
|
||||
|
||||
// per https://wiki.videolan.org/Hacker_Guide/Video_Filters/#Pitch.2C_visible_pitch.2C_planes_et_al.
|
||||
// it would seem that we can use either real or visible pitches and lines as VLC generally will iterate the
|
||||
// smallest value when moving data between two entities. i.e. since QImage will at most paint NxM anyway,
|
||||
// we may just go with its values as calculating the real pitch/line of the VLC picture_t for RV32 wouldn't
|
||||
// change the maximum pitch/lines we can paint on the output side.
|
||||
|
||||
qstrcpy(chroma, "RV32");
|
||||
m_frame = QImage(*width, *height, QImage::Format_RGB32);
|
||||
Q_ASSERT(!m_frame.isNull()); // ctor may construct null if allocation fails
|
||||
m_frame.fill(0);
|
||||
pitches[0] = m_frame.bytesPerLine();
|
||||
lines[0] = m_frame.sizeInBytes() / m_frame.bytesPerLine();
|
||||
|
||||
return m_frame.sizeInBytes();
|
||||
}
|
||||
|
||||
virtual void formatCleanUpCallback()
|
||||
{
|
||||
// Lazy delete the object to avoid callbacks from VLC after deletion.
|
||||
if (!widget) {
|
||||
// The widget member is set to null by the widget destructor, so when this condition is true the
|
||||
// widget had already been destroyed and we can't possibly receive a paint event anymore, meaning
|
||||
// we need no lock here. If it were any other way we'd have trouble with synchronizing deletion
|
||||
// without deleting a locked mutex.
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
|
||||
QRect scaleToAspect(QRect srcRect, int w, int h) const
|
||||
{
|
||||
float width = srcRect.width();
|
||||
float height = srcRect.width() * (float(h) / float(w));
|
||||
if (height > srcRect.height()) {
|
||||
height = srcRect.height();
|
||||
width = srcRect.height() * (float(w) / float(h));
|
||||
}
|
||||
return QRect(0, 0, (int)width, (int)height);
|
||||
}
|
||||
|
||||
QRect drawFrameRect() const
|
||||
{
|
||||
QRect widgetRect = widget->rect();
|
||||
QRect drawFrameRect;
|
||||
switch (widget->aspectRatio()) {
|
||||
case Phonon::VideoWidget::AspectRatioWidget:
|
||||
drawFrameRect = widgetRect;
|
||||
// No more calculations needed.
|
||||
return drawFrameRect;
|
||||
case Phonon::VideoWidget::AspectRatio4_3:
|
||||
drawFrameRect = scaleToAspect(widgetRect, 4, 3);
|
||||
break;
|
||||
case Phonon::VideoWidget::AspectRatio16_9:
|
||||
drawFrameRect = scaleToAspect(widgetRect, 16, 9);
|
||||
break;
|
||||
case Phonon::VideoWidget::AspectRatioAuto:
|
||||
drawFrameRect = QRect(0, 0, m_frame.width(), m_frame.height());
|
||||
break;
|
||||
}
|
||||
|
||||
// Scale m_drawFrameRect to fill the widget
|
||||
// without breaking aspect:
|
||||
float widgetWidth = widgetRect.width();
|
||||
float widgetHeight = widgetRect.height();
|
||||
float frameWidth = widgetWidth;
|
||||
float frameHeight = drawFrameRect.height() * float(widgetWidth) / float(drawFrameRect.width());
|
||||
|
||||
switch (widget->scaleMode()) {
|
||||
case Phonon::VideoWidget::ScaleAndCrop:
|
||||
if (frameHeight < widgetHeight) {
|
||||
frameWidth *= float(widgetHeight) / float(frameHeight);
|
||||
frameHeight = widgetHeight;
|
||||
}
|
||||
break;
|
||||
case Phonon::VideoWidget::FitInView:
|
||||
if (frameHeight > widgetHeight) {
|
||||
frameWidth *= float(widgetHeight) / float(frameHeight);
|
||||
frameHeight = widgetHeight;
|
||||
}
|
||||
break;
|
||||
}
|
||||
drawFrameRect.setSize(QSize(int(frameWidth), int(frameHeight)));
|
||||
drawFrameRect.moveTo(int((widgetWidth - frameWidth) / 2.0f),
|
||||
int((widgetHeight - frameHeight) / 2.0f));
|
||||
return drawFrameRect;
|
||||
}
|
||||
|
||||
// Could ReadWriteLock two frames so VLC can write while we paint.
|
||||
QImage m_frame;
|
||||
QMutex m_mutex;
|
||||
};
|
||||
|
||||
VideoWidget::VideoWidget(QWidget *parent) :
|
||||
BaseWidget(parent),
|
||||
SinkNode(),
|
||||
m_videoSize(DEFAULT_QSIZE),
|
||||
m_aspectRatio(Phonon::VideoWidget::AspectRatioAuto),
|
||||
m_scaleMode(Phonon::VideoWidget::FitInView),
|
||||
m_filterAdjustActivated(false),
|
||||
m_brightness(0.0),
|
||||
m_contrast(0.0),
|
||||
m_hue(0.0),
|
||||
m_saturation(0.0),
|
||||
m_surfacePainter(0)
|
||||
{
|
||||
// We want background painting so Qt autofills with black.
|
||||
setAttribute(Qt::WA_NoSystemBackground, false);
|
||||
|
||||
// Required for dvdnav
|
||||
#ifdef __GNUC__
|
||||
#warning dragonplayer munches on our mouse events, so clicking in a DVD menu does not work - vlc 1.2 where are thu?
|
||||
#endif // __GNUC__
|
||||
setMouseTracking(true);
|
||||
|
||||
// setBackgroundColor
|
||||
QPalette p = palette();
|
||||
p.setColor(backgroundRole(), Qt::black);
|
||||
setPalette(p);
|
||||
setAutoFillBackground(true);
|
||||
}
|
||||
|
||||
VideoWidget::~VideoWidget()
|
||||
{
|
||||
if (m_surfacePainter)
|
||||
m_surfacePainter->widget = 0; // Lazy delete
|
||||
}
|
||||
|
||||
void VideoWidget::handleConnectToMediaObject(MediaObject *mediaObject)
|
||||
{
|
||||
connect(mediaObject, SIGNAL(hasVideoChanged(bool)),
|
||||
SLOT(updateVideoSize(bool)));
|
||||
connect(mediaObject, SIGNAL(hasVideoChanged(bool)),
|
||||
SLOT(processPendingAdjusts(bool)));
|
||||
connect(mediaObject, SIGNAL(currentSourceChanged(MediaSource)),
|
||||
SLOT(clearPendingAdjusts()));
|
||||
|
||||
clearPendingAdjusts();
|
||||
}
|
||||
|
||||
void VideoWidget::handleDisconnectFromMediaObject(MediaObject *mediaObject)
|
||||
{
|
||||
// Undo all connections or path creation->destruction->creation can cause
|
||||
// duplicated connections or getting singals from two different MediaObjects.
|
||||
disconnect(mediaObject, 0, this, 0);
|
||||
}
|
||||
|
||||
void VideoWidget::handleAddToMedia(Media *media)
|
||||
{
|
||||
media->addOption(":video");
|
||||
|
||||
if (!m_surfacePainter) {
|
||||
#if defined(Q_OS_MAC)
|
||||
m_player->setNsObject(cocoaView());
|
||||
#elif defined(Q_OS_UNIX)
|
||||
if (QGuiApplication::platformName().contains(QStringLiteral("xcb"), Qt::CaseInsensitive)) {
|
||||
m_player->setXWindow(winId());
|
||||
} else {
|
||||
enableSurfacePainter();
|
||||
}
|
||||
#elif defined(Q_OS_WIN)
|
||||
m_player->setHwnd((HWND)winId());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
Phonon::VideoWidget::AspectRatio VideoWidget::aspectRatio() const
|
||||
{
|
||||
return m_aspectRatio;
|
||||
}
|
||||
|
||||
void VideoWidget::setAspectRatio(Phonon::VideoWidget::AspectRatio aspect)
|
||||
{
|
||||
DEBUG_BLOCK;
|
||||
if (!m_player)
|
||||
return;
|
||||
|
||||
m_aspectRatio = aspect;
|
||||
|
||||
switch (m_aspectRatio) {
|
||||
// FIXME: find a way to implement aspectratiowidget, it is meant to scale
|
||||
// and stretch (i.e. scale to window without retaining aspect ratio).
|
||||
case Phonon::VideoWidget::AspectRatioAuto:
|
||||
m_player->setVideoAspectRatio(QByteArray());
|
||||
return;
|
||||
case Phonon::VideoWidget::AspectRatio4_3:
|
||||
m_player->setVideoAspectRatio("4:3");
|
||||
return;
|
||||
case Phonon::VideoWidget::AspectRatio16_9:
|
||||
m_player->setVideoAspectRatio("16:9");
|
||||
return;
|
||||
}
|
||||
warning() << "The aspect ratio" << aspect << "is not supported by Phonon VLC.";
|
||||
}
|
||||
|
||||
Phonon::VideoWidget::ScaleMode VideoWidget::scaleMode() const
|
||||
{
|
||||
return m_scaleMode;
|
||||
}
|
||||
|
||||
void VideoWidget::setScaleMode(Phonon::VideoWidget::ScaleMode scale)
|
||||
{
|
||||
#ifdef __GNUC__
|
||||
#warning OMG WTF
|
||||
#endif
|
||||
m_scaleMode = scale;
|
||||
switch (m_scaleMode) {
|
||||
}
|
||||
warning() << "The scale mode" << scale << "is not supported by Phonon VLC.";
|
||||
}
|
||||
|
||||
qreal VideoWidget::brightness() const
|
||||
{
|
||||
return m_brightness;
|
||||
}
|
||||
|
||||
void VideoWidget::setBrightness(qreal brightness)
|
||||
{
|
||||
DEBUG_BLOCK;
|
||||
if (!m_player) {
|
||||
return;
|
||||
}
|
||||
if (!enableFilterAdjust()) {
|
||||
// Add to pending adjusts
|
||||
m_pendingAdjusts.insert(QByteArray("setBrightness"), brightness);
|
||||
return;
|
||||
}
|
||||
|
||||
// VLC operates within a 0.0 to 2.0 range for brightness.
|
||||
m_brightness = brightness;
|
||||
m_player->setVideoAdjust(libvlc_adjust_Brightness,
|
||||
phononRangeToVlcRange(m_brightness, 2.0));
|
||||
}
|
||||
|
||||
qreal VideoWidget::contrast() const
|
||||
{
|
||||
return m_contrast;
|
||||
}
|
||||
|
||||
void VideoWidget::setContrast(qreal contrast)
|
||||
{
|
||||
DEBUG_BLOCK;
|
||||
if (!m_player) {
|
||||
return;
|
||||
}
|
||||
if (!enableFilterAdjust()) {
|
||||
// Add to pending adjusts
|
||||
m_pendingAdjusts.insert(QByteArray("setContrast"), contrast);
|
||||
return;
|
||||
}
|
||||
|
||||
// VLC operates within a 0.0 to 2.0 range for contrast.
|
||||
m_contrast = contrast;
|
||||
m_player->setVideoAdjust(libvlc_adjust_Contrast, phononRangeToVlcRange(m_contrast, 2.0));
|
||||
}
|
||||
|
||||
qreal VideoWidget::hue() const
|
||||
{
|
||||
return m_hue;
|
||||
}
|
||||
|
||||
void VideoWidget::setHue(qreal hue)
|
||||
{
|
||||
DEBUG_BLOCK;
|
||||
if (!m_player) {
|
||||
return;
|
||||
}
|
||||
if (!enableFilterAdjust()) {
|
||||
// Add to pending adjusts
|
||||
m_pendingAdjusts.insert(QByteArray("setHue"), hue);
|
||||
return;
|
||||
}
|
||||
|
||||
// VLC operates within a 0 to 360 range for hue.
|
||||
// Phonon operates on -1.0 to 1.0, so we need to consider 0 to 180 as
|
||||
// 0 to 1.0 and 180 to 360 as -1 to 0.0.
|
||||
// 360/0 (0)
|
||||
// ___
|
||||
// / \
|
||||
// 270 (-.25) | | 90 (.25)
|
||||
// \___/
|
||||
// 180 (1/-1)
|
||||
// (-.25 is 360 minus 90 (vlcValue of .25).
|
||||
m_hue = hue;
|
||||
const int vlcValue = static_cast<int>(phononRangeToVlcRange(qAbs(hue), 180.0, false));
|
||||
int value = 0;
|
||||
if (hue >= 0)
|
||||
value = vlcValue;
|
||||
else
|
||||
value = 360.0 - vlcValue;
|
||||
m_player->setVideoAdjust(libvlc_adjust_Hue, value);
|
||||
}
|
||||
|
||||
qreal VideoWidget::saturation() const
|
||||
{
|
||||
return m_saturation;
|
||||
}
|
||||
|
||||
void VideoWidget::setSaturation(qreal saturation)
|
||||
{
|
||||
DEBUG_BLOCK;
|
||||
if (!m_player) {
|
||||
return;
|
||||
}
|
||||
if (!enableFilterAdjust()) {
|
||||
// Add to pending adjusts
|
||||
m_pendingAdjusts.insert(QByteArray("setSaturation"), saturation);
|
||||
return;
|
||||
}
|
||||
|
||||
// VLC operates within a 0.0 to 3.0 range for saturation.
|
||||
m_saturation = saturation;
|
||||
m_player->setVideoAdjust(libvlc_adjust_Saturation,
|
||||
phononRangeToVlcRange(m_saturation, 3.0));
|
||||
}
|
||||
|
||||
QWidget *VideoWidget::widget()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
QSize VideoWidget::sizeHint() const
|
||||
{
|
||||
return m_videoSize;
|
||||
}
|
||||
|
||||
void VideoWidget::updateVideoSize(bool hasVideo)
|
||||
{
|
||||
if (hasVideo) {
|
||||
m_videoSize = m_player->videoSize();
|
||||
updateGeometry();
|
||||
update();
|
||||
} else
|
||||
m_videoSize = DEFAULT_QSIZE;
|
||||
}
|
||||
|
||||
void VideoWidget::setVisible(bool visible)
|
||||
{
|
||||
if (window() && window()->testAttribute(Qt::WA_DontShowOnScreen) && !m_surfacePainter) {
|
||||
enableSurfacePainter();
|
||||
}
|
||||
QWidget::setVisible(visible);
|
||||
}
|
||||
|
||||
void VideoWidget::processPendingAdjusts(bool videoAvailable)
|
||||
{
|
||||
if (!videoAvailable || !m_mediaObject || !m_mediaObject->hasVideo()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QHashIterator<QByteArray, qreal> it(m_pendingAdjusts);
|
||||
while (it.hasNext()) {
|
||||
it.next();
|
||||
QMetaObject::invokeMethod(this, it.key().constData(), Q_ARG(qreal, it.value()));
|
||||
}
|
||||
m_pendingAdjusts.clear();
|
||||
}
|
||||
|
||||
void VideoWidget::clearPendingAdjusts()
|
||||
{
|
||||
m_pendingAdjusts.clear();
|
||||
}
|
||||
|
||||
void VideoWidget::paintEvent(QPaintEvent *event)
|
||||
{
|
||||
Q_UNUSED(event);
|
||||
if (m_surfacePainter)
|
||||
m_surfacePainter->handlePaint(event);
|
||||
}
|
||||
|
||||
bool VideoWidget::enableFilterAdjust(bool adjust)
|
||||
{
|
||||
DEBUG_BLOCK;
|
||||
// Need to check for MO here, because we can get called before a VOut is actually
|
||||
// around in which case we just ignore this.
|
||||
if (!m_mediaObject || !m_mediaObject->hasVideo()) {
|
||||
debug() << "no mo or no video!!!";
|
||||
return false;
|
||||
}
|
||||
if ((!m_filterAdjustActivated && adjust) ||
|
||||
(m_filterAdjustActivated && !adjust)) {
|
||||
debug() << "adjust: " << adjust;
|
||||
m_player->setVideoAdjust(libvlc_adjust_Enable, static_cast<int>(adjust));
|
||||
m_filterAdjustActivated = adjust;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
float VideoWidget::phononRangeToVlcRange(qreal phononValue, float upperBoundary,
|
||||
bool shift)
|
||||
{
|
||||
// VLC operates on different ranges than Phonon. Phonon always uses a range of
|
||||
// -1:1 with 0 as the default value.
|
||||
// It is therefore necessary to convert between the two schemes using sophisticated magic.
|
||||
// First the incoming range is locked between -1..1, then depending on shift
|
||||
// either normalized to 0..2 or 0..1 and finally a new value is calculated
|
||||
// depending on the upperBoundary and the normalized range.
|
||||
float value = static_cast<float>(phononValue);
|
||||
float range = 2.0; // The default normalized range will be 0..2 = 2
|
||||
|
||||
// Ensure valid range
|
||||
if (value < -1.0)
|
||||
value = -1.0;
|
||||
else if (value > 1.0)
|
||||
value = 1.0;
|
||||
|
||||
if (shift)
|
||||
value += 1.0; // Shift into 0..2 range
|
||||
else {
|
||||
// Chop negative value; normalize to 0..1 = range 1
|
||||
if (value < 0.0)
|
||||
value = 0.0;
|
||||
range = 1.0;
|
||||
}
|
||||
|
||||
return (value * (upperBoundary/range));
|
||||
}
|
||||
|
||||
QImage VideoWidget::snapshot() const
|
||||
{
|
||||
DEBUG_BLOCK;
|
||||
if (m_player)
|
||||
return m_player->snapshot();
|
||||
else
|
||||
return QImage();
|
||||
}
|
||||
|
||||
void VideoWidget::enableSurfacePainter()
|
||||
{
|
||||
if (m_surfacePainter) {
|
||||
return;
|
||||
}
|
||||
|
||||
debug() << "ENABLING SURFACE PAINTING";
|
||||
m_surfacePainter = new SurfacePainter;
|
||||
m_surfacePainter->widget = this;
|
||||
m_surfacePainter->setCallbacks(m_player);
|
||||
}
|
||||
|
||||
} // namespace VLC
|
||||
} // namespace Phonon
|
|
@ -0,0 +1,253 @@
|
|||
/*
|
||||
Copyright (C) 2007-2008 Tanguy Krotoff <tkrotoff@gmail.com>
|
||||
Copyright (C) 2008 Lukas Durfina <lukas.durfina@gmail.com>
|
||||
Copyright (C) 2009 Fathi Boudra <fabo@kde.org>
|
||||
Copyright (C) 2009-2011 vlc-phonon AUTHORS <kde-multimedia@kde.org>
|
||||
Copyright (C) 2011-2019 Harald Sitter <sitter@kde.org>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef PHONON_VLC_VIDEOWIDGET_H
|
||||
#define PHONON_VLC_VIDEOWIDGET_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
#include <phonon/videowidgetinterface.h>
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
#include "video/mac/vlcmacwidget.h"
|
||||
typedef VlcMacWidget BaseWidget;
|
||||
#else
|
||||
typedef QWidget BaseWidget;
|
||||
#endif
|
||||
|
||||
#include "sinknode.h"
|
||||
|
||||
namespace Phonon {
|
||||
namespace VLC {
|
||||
|
||||
class SurfacePainter;
|
||||
|
||||
/** \brief Implements the Phonon VideoWidget MediaNode, responsible for displaying video
|
||||
*
|
||||
* Phonon video is displayed using this widget. It implements the VideoWidgetInterface.
|
||||
* It is connected to a media object that provides the video source. Methods to control
|
||||
* video settings such as brightness or contrast are provided.
|
||||
*/
|
||||
class VideoWidget : public BaseWidget, public SinkNode, public VideoWidgetInterface44
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(Phonon::VideoWidgetInterface44)
|
||||
public:
|
||||
/**
|
||||
* Constructs a new VideoWidget with the given parent. The video settings members
|
||||
* are set to their default values.
|
||||
*/
|
||||
explicit VideoWidget(QWidget *parent);
|
||||
|
||||
/**
|
||||
* Death to the VideoWidget!
|
||||
*/
|
||||
~VideoWidget();
|
||||
|
||||
/**
|
||||
* Connects the VideoWidget to a media object by setting the video widget
|
||||
* window system identifier of the media object to that of the owned private
|
||||
* video widget. It also connects the signal from the mediaObject regarding
|
||||
* a resize of the video.
|
||||
*
|
||||
* If the mediaObject was connected to another VideoWidget, the connection is
|
||||
* lost.
|
||||
*
|
||||
* \see MediaObject
|
||||
* \param mediaObject What media object to connect to
|
||||
* \reimp
|
||||
*/
|
||||
void handleConnectToMediaObject(MediaObject *mediaObject);
|
||||
/** \reimp */
|
||||
void handleDisconnectFromMediaObject(MediaObject *mediaObject);
|
||||
/** \reimp */
|
||||
void handleAddToMedia(Media *media);
|
||||
|
||||
/**
|
||||
* \return The aspect ratio previously set for the video widget
|
||||
*/
|
||||
Phonon::VideoWidget::AspectRatio aspectRatio() const;
|
||||
|
||||
/**
|
||||
* Set the aspect ratio of the video.
|
||||
* VLC accepted formats are x:y (4:3, 16:9, etc...) expressing the global image aspect.
|
||||
*/
|
||||
void setAspectRatio(Phonon::VideoWidget::AspectRatio aspect);
|
||||
|
||||
/**
|
||||
* \return The scale mode previously set for the video widget
|
||||
*/
|
||||
Phonon::VideoWidget::ScaleMode scaleMode() const;
|
||||
|
||||
/**
|
||||
* Set how the video is scaled, keeping the aspect ratio into account when the video is resized.
|
||||
*
|
||||
* The ScaleMode enumeration describes how to treat aspect ratio during resizing of video.
|
||||
* \li Phonon::VideoWidget::FitInView - the video will be fitted to fill the view keeping aspect ratio
|
||||
* \li Phonon::VideoWidget::ScaleAndCrop - the video is scaled
|
||||
*/
|
||||
void setScaleMode(Phonon::VideoWidget::ScaleMode scale);
|
||||
|
||||
/**
|
||||
* \return The brightness previously set for the video widget
|
||||
*/
|
||||
qreal brightness() const;
|
||||
|
||||
/**
|
||||
* Set the brightness of the video
|
||||
*/
|
||||
Q_INVOKABLE void setBrightness(qreal brightness);
|
||||
|
||||
/**
|
||||
* \return The contrast previously set for the video widget
|
||||
*/
|
||||
qreal contrast() const;
|
||||
|
||||
/**
|
||||
* Set the contrast of the video
|
||||
*/
|
||||
Q_INVOKABLE void setContrast(qreal contrast);
|
||||
|
||||
/**
|
||||
* \return The hue previously set for the video widget
|
||||
*/
|
||||
qreal hue() const;
|
||||
|
||||
/**
|
||||
* Set the hue of the video
|
||||
*/
|
||||
Q_INVOKABLE void setHue(qreal hue);
|
||||
|
||||
/**
|
||||
* \return The saturation previously set for the video widget
|
||||
*/
|
||||
qreal saturation() const;
|
||||
|
||||
/**
|
||||
* Set the saturation of the video
|
||||
*/
|
||||
Q_INVOKABLE void setSaturation(qreal saturation);
|
||||
|
||||
/**
|
||||
* \return The owned widget that is used for the actual draw.
|
||||
*/
|
||||
QWidget *widget();
|
||||
|
||||
/// \reimp
|
||||
QSize sizeHint() const;
|
||||
|
||||
void setVisible(bool visible);
|
||||
|
||||
private slots:
|
||||
/// Updates the sizeHint to match the native size of the video.
|
||||
/// \param hasVideo \c true when there is a video, \c false otherwise
|
||||
void updateVideoSize(bool hasVideo);
|
||||
|
||||
/**
|
||||
* Sets all pending video adjusts (hue, brightness etc.) that the application
|
||||
* wanted to set before the vidoe became available.
|
||||
*
|
||||
* \param videoAvailable whether or not video is available at the time of calling
|
||||
*/
|
||||
void processPendingAdjusts(bool videoAvailable);
|
||||
|
||||
/**
|
||||
* Clears all pending video adjusts (hue, brightness etc.).
|
||||
*/
|
||||
void clearPendingAdjusts();
|
||||
|
||||
protected:
|
||||
/// \reimp
|
||||
void paintEvent(QPaintEvent *event);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Sets whether filter adjust is active or not.
|
||||
*
|
||||
* \param adjust true if adjust is supposed to be activated, false if not
|
||||
*
|
||||
* \returns whether the adjust request was accepted, if not the callee should
|
||||
* add the request to m_pendingAdjusts for later processing once a video
|
||||
* became available. Adjusts get accepted always except when
|
||||
* MediaObject::hasVideo() is false, so it is not related to the
|
||||
* actual execution of the request.
|
||||
*/
|
||||
bool enableFilterAdjust(bool adjust = true);
|
||||
|
||||
/**
|
||||
* Converts a Phonon range to a VLC value range.
|
||||
*
|
||||
* A Phonon range is always a qreal between -1.0 and 1.0, a VLC range however
|
||||
* can be any between 0 and 360. This functon maps the Phonon value to an
|
||||
* appropriate value within a specified target range.
|
||||
*
|
||||
* \param phononValue the incoming Phonon specific value, should be -1.0:1.0
|
||||
* should it however not be within that range will it be
|
||||
* manually locked (i.e. exceeding values become either -1.0 or 1.0)
|
||||
* \param upperBoundary the upper boundary for the target range. The lower
|
||||
* boundary is currently always assumed to be 0
|
||||
* \param shift whether or not to shift the Phonon range to positive values
|
||||
* before mapping to VLC values (useful when our 0 must be a VLC 0).
|
||||
* Please note that if you do not shift the range will be reduced to
|
||||
* 0:1, phononValue < 0 will be set to 0.
|
||||
*
|
||||
* \returns float usable to VLC
|
||||
*/
|
||||
static float phononRangeToVlcRange(qreal phononValue, float upperBoundary,
|
||||
bool shift = true);
|
||||
|
||||
/**
|
||||
* \return The snapshot of the current video frame.
|
||||
*/
|
||||
QImage snapshot() const;
|
||||
|
||||
/**
|
||||
* Enables the mighty surface painter (qpaints frames).
|
||||
*/
|
||||
void enableSurfacePainter();
|
||||
|
||||
/**
|
||||
* Pending video adjusts the application tried to set before we actually
|
||||
* had a video to set them on.
|
||||
*/
|
||||
QHash<QByteArray, qreal> m_pendingAdjusts;
|
||||
|
||||
/**
|
||||
* Original size of the video, needed for sizeHint().
|
||||
*/
|
||||
QSize m_videoSize;
|
||||
|
||||
Phonon::VideoWidget::AspectRatio m_aspectRatio;
|
||||
Phonon::VideoWidget::ScaleMode m_scaleMode;
|
||||
|
||||
bool m_filterAdjustActivated;
|
||||
qreal m_brightness;
|
||||
qreal m_contrast;
|
||||
qreal m_hue;
|
||||
qreal m_saturation;
|
||||
|
||||
SurfacePainter *m_surfacePainter;
|
||||
};
|
||||
|
||||
} // namespace VLC
|
||||
} // namespace Phonon
|
||||
|
||||
#endif // PHONON_VLC_VIDEOWIDGET_H
|
|
@ -0,0 +1,40 @@
|
|||
#!/usr/bin/env ruby
|
||||
# Copyright (C) 2011 Harald Sitter <sitter@kde.org>
|
||||
#
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2.1 of the License, or (at your option) any later version.
|
||||
#
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
for file in Dir.glob("src/**")
|
||||
line_count = 1
|
||||
has_open_ifdef = false
|
||||
|
||||
next if File.directory?(file)
|
||||
|
||||
File.open(file, 'r').each_line do | line |
|
||||
if line =~ /#\s*ifdef\s*__GNUC__\s*/
|
||||
has_open_ifdef = true
|
||||
end
|
||||
|
||||
if line =~ /#\s*endif\s*/
|
||||
has_open_ifdef = false
|
||||
end
|
||||
|
||||
if line =~ /#\s*warning\s*/ and not has_open_ifdef
|
||||
raise("unprotected warning in (#{file}:#{line_count}), please add #ifdef __GNUC__")
|
||||
end
|
||||
|
||||
line_count += 1
|
||||
end
|
||||
end
|
||||
|
||||
puts ("All good :)")
|
Loading…
Reference in New Issue