Initial commit
This commit is contained in:
commit
3fba92fb74
|
@ -0,0 +1,37 @@
|
|||
.tarball-version
|
||||
.version
|
||||
.*.swp
|
||||
ABOUT-NLS
|
||||
build-aux
|
||||
intltool-extract.in
|
||||
intltool-merge.in
|
||||
intltool-update.in
|
||||
*~
|
||||
*.tar.gz
|
||||
.deps
|
||||
.libs
|
||||
*.la
|
||||
*.lo
|
||||
*.o
|
||||
Makefile
|
||||
Makefile.in
|
||||
aclocal.m4
|
||||
autom4te.cache
|
||||
compile
|
||||
config.guess
|
||||
config.h
|
||||
config.h.in
|
||||
config.log
|
||||
config.rpath
|
||||
config.status
|
||||
config.sub
|
||||
configure
|
||||
depcomp
|
||||
install-sh
|
||||
libltdl
|
||||
libtool
|
||||
ltmain.sh
|
||||
missing
|
||||
mkinstalldirs
|
||||
stamp-*
|
||||
.dirstamp
|
|
@ -0,0 +1,340 @@
|
|||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 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.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, 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 or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
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 give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
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 Program or any portion
|
||||
of it, thus forming a work based on the Program, 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) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
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 Program, 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 Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) 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; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, 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 executable. However, as a
|
||||
special exception, the source code 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.
|
||||
|
||||
If distribution of executable or 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 counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program 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.
|
||||
|
||||
5. 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 Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program 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 to
|
||||
this License.
|
||||
|
||||
7. 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 Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program 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 Program.
|
||||
|
||||
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.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program 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.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the 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 Program
|
||||
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 Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, 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
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "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 PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. 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 PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Library General
|
||||
Public License instead of this License.
|
|
@ -0,0 +1,510 @@
|
|||
|
||||
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
|
||||
|
||||
How to Apply These Terms to Your New Libraries
|
||||
|
||||
If you develop a new library, and you want it to be of the greatest
|
||||
possible use to the public, we recommend making it free software that
|
||||
everyone can redistribute and change. You can do so by permitting
|
||||
redistribution under these terms (or, alternatively, under the terms
|
||||
of the ordinary General Public License).
|
||||
|
||||
To apply these terms, attach the following notices to the library.
|
||||
It is safest to attach them to the start of each source file to most
|
||||
effectively convey the exclusion of warranty; and each file should
|
||||
have at least the "copyright" line and a pointer to where the full
|
||||
notice is found.
|
||||
|
||||
|
||||
<one line to give the library's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
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, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or
|
||||
your school, if any, to sign a "copyright disclaimer" for the library,
|
||||
if necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
||||
library `Frob' (a library for tweaking knobs) written by James
|
||||
Random Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1990
|
||||
Ty Coon, President of Vice
|
||||
|
||||
That's all there is to it!
|
||||
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
# This file is part of PulseAudio.
|
||||
#
|
||||
# PulseAudio 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 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# PulseAudio 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
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
|
||||
EXTRA_DIST = \
|
||||
bootstrap.sh \
|
||||
git-version-gen \
|
||||
LICENSE \
|
||||
GPL \
|
||||
LGPL \
|
||||
PROTOCOL \
|
||||
README
|
||||
|
||||
SUBDIRS = src
|
||||
|
||||
DIST_SUBDIRS = pkgconfig \
|
||||
doc \
|
||||
man \
|
||||
po \
|
||||
src
|
||||
|
||||
MAINTAINERCLEANFILES =
|
||||
noinst_DATA =
|
||||
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
pkgconfig_DATA = pkgconfig/libpulsevideo.pc
|
||||
|
||||
eolspace:
|
||||
find \( -name '*.c' -o -name '*.h' -o -name 'Makefile.am' \) -exec perl -i -pe 's/\s+\n$$/\1\n/;' \{\} \;
|
||||
|
||||
untabify:
|
||||
find \( -name '*.c' -o -name '*.h' \) -exec perl -i -pe 's/\t/ /g;' \{\} \;
|
||||
|
||||
fedora-snapshot: dist
|
||||
cp $(distdir).tar.gz $$HOME/git.fedora/pulseaudio/$(distdir).tar.gz
|
||||
|
||||
dist-hook:
|
||||
echo $(VERSION) > $(distdir)/.tarball-version
|
||||
echo $(VERSION) > $(distdir)/.version
|
||||
|
||||
.PHONY: distcleancheck
|
||||
|
||||
# see git-version-gen
|
||||
BUILT_SOURCES = $(top_srcdir)/.version
|
||||
$(top_srcdir)/.version:
|
||||
echo $(VERSION) > $@-t && mv $@-t $@
|
||||
|
||||
DISTCLEANFILES = \
|
||||
po/.intltool-merge-cache
|
|
@ -0,0 +1,12 @@
|
|||
Pulsevideo
|
||||
----------
|
||||
|
||||
Pulsevideo is a user space API to deal with video. This includes:
|
||||
|
||||
- Make availabe sources of video (such as from a capture devices or
|
||||
application provided streams)
|
||||
- Accessing sources of video for consumption.
|
||||
|
||||
Video providers and consumers are implemented as separate processes
|
||||
communicating with DBUS and exchanging video frames using fd passing.
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
#!/bin/sh
|
||||
|
||||
# This file is part of PulseVideo
|
||||
#
|
||||
# PulseAudio 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 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# PulseAudio 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
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# Only there to make jhbuild happy
|
||||
|
||||
NOCONFIGURE=1 ./bootstrap.sh
|
||||
|
||||
exec ./configure "$@"
|
|
@ -0,0 +1,55 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# This file is part of PulseVideo
|
||||
#
|
||||
# PulseAudio 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 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# PulseAudio 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
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
case $(uname) in
|
||||
*Darwin*)
|
||||
LIBTOOLIZE="glibtoolize"
|
||||
;;
|
||||
esac
|
||||
test "x$LIBTOOLIZE" = "x" && LIBTOOLIZE=libtoolize
|
||||
|
||||
if [ -f .git/hooks/pre-commit.sample -a ! -f .git/hooks/pre-commit ] ; then
|
||||
cp -p .git/hooks/pre-commit.sample .git/hooks/pre-commit && \
|
||||
chmod +x .git/hooks/pre-commit && \
|
||||
echo "Activated pre-commit hook."
|
||||
fi
|
||||
|
||||
if [ -f .tarball-version ]; then
|
||||
echo "Marking tarball version as modified."
|
||||
echo -n `cat .tarball-version | sed 's/-rebootstrapped$//'`-rebootstrapped >.tarball-version
|
||||
fi
|
||||
|
||||
# We check for this here, because if pkg-config is not found in the
|
||||
# system, it's likely that the pkg.m4 macro file is also not present,
|
||||
# which will make PKG_PROG_PKG_CONFIG be undefined and the generated
|
||||
# configure file faulty.
|
||||
if ! pkg-config --version &>/dev/null; then
|
||||
echo "pkg-config is required to bootstrap this program" &>/dev/null
|
||||
DIE=1
|
||||
fi
|
||||
|
||||
# Other necessary programs
|
||||
intltoolize --version >/dev/null || DIE=1
|
||||
test "$DIE" = 1 && exit 1
|
||||
|
||||
autopoint --force
|
||||
AUTOPOINT='intltoolize --automake --copy' autoreconf --force --install --verbose
|
||||
|
||||
if test "x$NOCONFIGURE" = "x"; then
|
||||
CFLAGS="$CFLAGS -g -O0" ./configure --sysconfdir=/etc --localstatedir=/var --enable-force-preopen "$@"
|
||||
make clean
|
||||
fi
|
|
@ -0,0 +1,213 @@
|
|||
AC_PREREQ(2.63)
|
||||
|
||||
AC_INIT(pulsevideo, 0.1)
|
||||
AC_CONFIG_SRCDIR([src/daemon/main.c])
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
AC_CONFIG_AUX_DIR([build-aux])
|
||||
AM_INIT_AUTOMAKE([foreign 1.11 -Wall -Wno-portability subdir-objects silent-rules color-tests dist-xz tar-ustar])
|
||||
|
||||
AS_IF([! test -n "$VERSION"], [
|
||||
AC_MSG_ERROR([git-version-gen failed])
|
||||
])
|
||||
|
||||
m4_define(pa_major, `echo $VERSION | cut -d. -f1 | cut -d- -f1`)
|
||||
m4_define(pa_minor, `echo $VERSION | cut -d. -f2 | cut -d- -f1`)
|
||||
|
||||
AC_SUBST(PV_MAJOR, pa_major)
|
||||
AC_SUBST(PV_MINOR, pa_minor)
|
||||
AC_SUBST(PV_MAJORMINOR, pa_major.pa_minor)
|
||||
|
||||
AC_SUBST(PV_API_VERSION, 0)
|
||||
AC_SUBST(PV_PROTOCOL_VERSION, 0)
|
||||
|
||||
# The stable ABI for client applications, for the version info x:y:z
|
||||
# always will hold y=z
|
||||
AC_SUBST(LIBPULSE_VERSION_INFO, [0:0:0])
|
||||
|
||||
dnl sets host_* variables
|
||||
AC_CANONICAL_HOST
|
||||
|
||||
AC_DEFINE_UNQUOTED([CANONICAL_HOST], "$host", [Canonical host string.])
|
||||
|
||||
AC_CHECK_PROG([STOW], [stow], [yes], [no])
|
||||
|
||||
AS_IF([test "x$STOW" = "xyes" && test -d /usr/local/stow], [
|
||||
AC_MSG_NOTICE([*** Found /usr/local/stow: default install prefix set to /usr/local/stow/${PACKAGE_NAME}-${PACKAGE_VERSION} ***])
|
||||
ac_default_prefix="/usr/local/stow/${PACKAGE_NAME}-${PACKAGE_VERSION}"
|
||||
])
|
||||
|
||||
AM_SILENT_RULES([yes])
|
||||
|
||||
#### Checks for programs. ####
|
||||
|
||||
# mkdir -p
|
||||
|
||||
AC_PROG_MKDIR_P
|
||||
|
||||
# ln -s
|
||||
|
||||
AC_PROG_LN_S
|
||||
|
||||
# CC
|
||||
|
||||
AC_PROG_CC
|
||||
AC_PROG_CC_C99
|
||||
AM_PROG_CC_C_O
|
||||
# Only required if you want the WebRTC canceller -- no runtime dep on
|
||||
# libstdc++ otherwise
|
||||
AC_PROG_CXX
|
||||
AC_PROG_GCC_TRADITIONAL
|
||||
AC_USE_SYSTEM_EXTENSIONS
|
||||
|
||||
# M4
|
||||
|
||||
AC_CHECK_PROGS([M4], gm4 m4, no)
|
||||
AS_IF([test "x$M4" = "xno"], AC_MSG_ERROR([m4 missing]))
|
||||
|
||||
# pkg-config
|
||||
|
||||
PKG_PROG_PKG_CONFIG
|
||||
|
||||
#### Compiler flags ####
|
||||
|
||||
AX_APPEND_COMPILE_FLAGS(
|
||||
[-Wall -W -Wextra -pipe -Wno-long-long -Wno-overlength-strings -Wunsafe-loop-optimizations -Wundef -Wformat=2 -Wlogical-op -Wsign-compare -Wformat-security -Wmissing-include-dirs -Wformat-nonliteral -Wold-style-definition -Wpointer-arith -Winit-self -Wdeclaration-after-statement -Wfloat-equal -Wmissing-prototypes -Wstrict-prototypes -Wredundant-decls -Wmissing-declarations -Wmissing-noreturn -Wshadow -Wendif-labels -Wcast-align -Wstrict-aliasing -Wwrite-strings -Wno-unused-parameter -ffast-math -fno-common -fdiagnostics-show-option -fdiagnostics-color=auto],
|
||||
[], [-pedantic -Werror])
|
||||
|
||||
AS_CASE([" $CFLAGS "], [*" -O0 "*], [], [
|
||||
# Don't append the flag if it already exists.
|
||||
# Only enable fastpath asserts when doing a debug build, e.g. from bootstrap.sh.
|
||||
AX_APPEND_FLAG([-DFASTPATH], [CPPFLAGS])
|
||||
|
||||
# Cannot use AX_APPEND_FLAG here, as it assumes no space inside the added flags.
|
||||
# Cannot append flags with AX_APPEND_FLAG one by one, as this would destroy all fortifications
|
||||
# if CPPFLAGS already contain -D_FORTIFY_SOURCE=2.
|
||||
|
||||
# Warnings to be aware of that appear with -D_FORTIFY_SOURCE=2 but without -U_FORTIFY_SOURCE:
|
||||
# On Fedora 20 with -O0: #warning _FORTIFY_SOURCE requires compiling with optimization (-O) [-Wcpp]
|
||||
# On Gentoo with -O2: "_FORTIFY_SOURCE" redefined [enabled by default]
|
||||
AS_VAR_APPEND([CPPFLAGS],[" -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2"])
|
||||
])
|
||||
|
||||
#### Linker flags ####
|
||||
|
||||
# Check whether the linker supports the -version-script option.
|
||||
# The Make variable $(srcdir) needs to be in the LDFLAGS in that form,
|
||||
# so that it is expanded the right way in every subdir.
|
||||
AX_CHECK_LINK_FLAG(["-Wl,-version-script=${srcdir}/src/map-file"],
|
||||
[VERSIONING_LDFLAGS='-Wl,-version-script=$(abs_top_srcdir)/src/map-file'])
|
||||
AC_SUBST([VERSIONING_LDFLAGS])
|
||||
|
||||
# Use immediate (now) bindings; avoids the funky re-call in itself.
|
||||
# The -z now syntax is lifted from Sun's linker and works with GNU's too, other linkers might be added later.
|
||||
AX_APPEND_LINK_FLAGS([-Wl,-z,now], [IMMEDIATE_LDFLAGS])
|
||||
AC_SUBST([IMMEDIATE_LDFLAGS])
|
||||
|
||||
# On ELF systems we don't want the libraries to be unloaded since we don't clean them up properly,
|
||||
# so we request the nodelete flag to be enabled.
|
||||
# On other systems, we don't really know how to do that, but it's welcome if somebody can tell.
|
||||
AX_APPEND_LINK_FLAGS([-Wl,-z,nodelete], [NODELETE_LDFLAGS])
|
||||
AC_SUBST([NODELETE_LDFLAGS])
|
||||
|
||||
# Check for the proper way to build libraries that have no undefined symbols
|
||||
case $host in
|
||||
# FreeBSD (et al.) does not complete linking for shared objects when pthreads
|
||||
# are requested, as different implementations are present.
|
||||
*-freebsd* | *-openbsd*) ;;
|
||||
*)
|
||||
for possible_flag in "-Wl,--no-undefined" "-Wl,-z,defs"; do
|
||||
AX_CHECK_LINK_FLAG([$possible_flag], [NOUNDEFINED_LDFLAGS="$possible_flag"; break])
|
||||
done
|
||||
;;
|
||||
esac
|
||||
AC_SUBST([NOUNDEFINED_LDFLAGS])
|
||||
|
||||
#### libtool stuff ####
|
||||
|
||||
LT_PREREQ(2.4)
|
||||
LT_INIT([dlopen win32-dll disable-static])
|
||||
|
||||
dnl As an extra safety device, check for lt_dladvise_init() which is
|
||||
dnl only implemented in libtool 2.x, and refine as we go if we have
|
||||
dnl refined requirements.
|
||||
dnl
|
||||
dnl Check the header files first since the system may have a
|
||||
dnl libltdl.so for runtime, but no headers, and we want to bail out as
|
||||
dnl soon as possible.
|
||||
dnl
|
||||
dnl We don't need any special variable for this though, since the user
|
||||
dnl can give the proper place to find libltdl through the standard
|
||||
dnl variables like LDFLAGS and CPPFLAGS.
|
||||
|
||||
AC_CHECK_HEADER([ltdl.h],
|
||||
[AC_CHECK_LIB([ltdl], [lt_dladvise_init], [LIBLTDL=-lltdl], [LIBLTDL=])],
|
||||
[LIBLTDL=])
|
||||
|
||||
AS_IF([test "x$LIBLTDL" = "x"],
|
||||
[AC_MSG_ERROR([Unable to find libltdl version 2. Makes sure you have libtool 2.4 or later installed.])])
|
||||
AC_SUBST([LIBLTDL])
|
||||
|
||||
###################################
|
||||
# External libraries #
|
||||
###################################
|
||||
|
||||
#### Valgrind (optional) ####
|
||||
|
||||
AC_CHECK_HEADERS_ONCE([valgrind/memcheck.h])
|
||||
|
||||
#### GLib ####
|
||||
|
||||
PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.32, dummy=yes,
|
||||
AC_MSG_ERROR(GLib >= 2.32 is required))
|
||||
AC_SUBST(GLIB_CFLAGS)
|
||||
AC_SUBST(GLIB_LIBS)
|
||||
|
||||
PKG_CHECK_MODULES(GIOUNIX, gio-unix-2.0 >= 2.32, dummy=yes,
|
||||
AC_MSG_ERROR(GIO-Unix >= 2.32 is required))
|
||||
GLIB_CFLAGS="$GLIB_CFLAGS $GIOUNIX_CFLAGS"
|
||||
GLIB_LIBS="$GLIB_LIBS $GIOUNIX_LIBS"
|
||||
|
||||
AC_MSG_CHECKING([for glib-mkenums script])
|
||||
GLIB_MKENUMS=`$PKG_CONFIG --variable=glib_mkenums glib-2.0`
|
||||
AS_IF([test "x$GLIB_MKENUMS" = "x"],
|
||||
[AC_MSG_ERROR([glib-mkenums not listed in glib-2.0 pkg-config file])],
|
||||
[AC_SUBST([GLIB_MKENUMS])
|
||||
AC_MSG_RESULT([$GLIB_MKENUMS])])
|
||||
|
||||
AC_SUBST([GDBUS_CODEGEN], [`$PKG_CONFIG --variable gdbus_codegen gio-2.0`])
|
||||
|
||||
#### GStreamer ####
|
||||
|
||||
PKG_CHECK_MODULES(GST, gstreamer-1.0 >= 1.4.0, dummy=yes,
|
||||
AC_MSG_ERROR(GStreamer >= 1.4.0 is required))
|
||||
AC_SUBST(GST_CFLAGS)
|
||||
AC_SUBST(GST_LIBS)
|
||||
|
||||
#### Build and Install man pages ####
|
||||
|
||||
AC_ARG_ENABLE([manpages],
|
||||
AS_HELP_STRING([--disable-manpages],[Disable building and installation of man pages]))
|
||||
|
||||
AM_CONDITIONAL([BUILD_MANPAGES], [test "x$enable_manpages" != "xno"])
|
||||
|
||||
dnl *** output files ***
|
||||
|
||||
dnl keep this alphabetic per directory, please
|
||||
AC_CONFIG_FILES([
|
||||
Makefile
|
||||
src/Makefile
|
||||
pkgconfig/libpulsevideo.pc
|
||||
])
|
||||
AC_OUTPUT
|
||||
|
||||
echo "
|
||||
|
||||
Configuration
|
||||
Version : ${VERSION}
|
||||
Source code location : ${srcdir}
|
||||
Prefix : ${prefix}
|
||||
Compiler : ${CC}
|
||||
|
||||
pulsevideo configured. Type 'make' to build.
|
||||
"
|
|
@ -0,0 +1 @@
|
|||
org-pulsevideo-*.xml
|
|
@ -0,0 +1,84 @@
|
|||
Source
|
||||
------
|
||||
|
||||
Service: org.pulsevideo
|
||||
Interface: org.pulsevideo.Source1
|
||||
Object Path: freely definable
|
||||
|
||||
|
||||
The Source object defines a source of video. You can query the list of
|
||||
supported formats and get a SourceOutput object that can be used to
|
||||
control the video Source.
|
||||
|
||||
|
||||
Methods a{a{sv}} GetCapabilities (dict args)
|
||||
|
||||
Get a list of supported formats
|
||||
|
||||
Possible Errors: org.pulsevideo.Error.NotAuthorized
|
||||
org.pulsevideo.Error.Failed
|
||||
|
||||
object CreateSourceOutput (dict args)
|
||||
|
||||
Create a sourceoutput with given capabilities
|
||||
|
||||
Possible Errors: org.pulsevideo.Error.NotAuthorized
|
||||
org.pulsevideo.Error.Failed
|
||||
|
||||
void RemoveSourceOutput (object sourceoutput)
|
||||
|
||||
Remove a sourceoutput.
|
||||
|
||||
Possible Errors: org.pulsevideo.Error.NotAuthorized
|
||||
org.pulsevideo.Error.Failed
|
||||
|
||||
Properties string Name [readonly]
|
||||
|
||||
Name of the source
|
||||
|
||||
strinf Priority [readonly]
|
||||
|
||||
Priority of the source
|
||||
|
||||
|
||||
|
||||
SourceOutput
|
||||
------------
|
||||
|
||||
Service org.pulsevideo
|
||||
Interface org.pulsevideo.SourceOutput1
|
||||
Object Path: freely definable
|
||||
|
||||
Methods fd Acquire()
|
||||
|
||||
Acquire transport file descriptor read and .
|
||||
|
||||
Possible Errors: org.pulsevideo.Error.NotAuthorized
|
||||
org.pulsevideo.Error.Failed
|
||||
|
||||
void Release ()
|
||||
|
||||
Release transport file descriptor
|
||||
|
||||
|
||||
|
||||
Properties object Source [readonly]
|
||||
|
||||
Path of the Source object
|
||||
|
||||
dict transport [readonly]
|
||||
|
||||
Transport properties
|
||||
|
||||
|
||||
|
||||
Client
|
||||
------
|
||||
|
||||
Service org.pulsevideo
|
||||
Interface org.pulsevideo.Client1
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,170 @@
|
|||
#!/bin/sh
|
||||
# Print a version string.
|
||||
scriptversion=2012-09-25.20
|
||||
|
||||
# Copyright (C) 2007-2008 Free Software Foundation
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# This script is derived from GIT-VERSION-GEN from GIT: http://git.or.cz/.
|
||||
# It may be run two ways:
|
||||
# - from a git repository in which the "git describe" command below
|
||||
# produces useful output (thus requiring at least one signed tag)
|
||||
# - from a non-git-repo directory containing a .tarball-version file, which
|
||||
# presumes this script is invoked like "./git-version-gen .tarball-version".
|
||||
|
||||
# In order to use intra-version strings in your project, you will need two
|
||||
# separate generated version string files:
|
||||
#
|
||||
# .tarball-version - present only in a distribution tarball, and not in
|
||||
# a checked-out repository. Created with contents that were learned at
|
||||
# the last time autoconf was run, and used by git-version-gen. Must not
|
||||
# be present in either $(srcdir) or $(builddir) for git-version-gen to
|
||||
# give accurate answers during normal development with a checked out tree,
|
||||
# but must be present in a tarball when there is no version control system.
|
||||
# Therefore, it cannot be used in any dependencies. GNUmakefile has
|
||||
# hooks to force a reconfigure at distribution time to get the value
|
||||
# correct, without penalizing normal development with extra reconfigures.
|
||||
#
|
||||
# .version - present in a checked-out repository and in a distribution
|
||||
# tarball. Usable in dependencies, particularly for files that don't
|
||||
# want to depend on config.h but do want to track version changes.
|
||||
# Delete this file prior to any autoconf run where you want to rebuild
|
||||
# files to pick up a version string change; and leave it stale to
|
||||
# minimize rebuild time after unrelated changes to configure sources.
|
||||
#
|
||||
# It is probably wise to add these two files to .gitignore, so that you
|
||||
# don't accidentally commit either generated file.
|
||||
#
|
||||
# Use the following line in your configure.ac, so that $(VERSION) will
|
||||
# automatically be up-to-date each time configure is run (and note that
|
||||
# since configure.ac no longer includes a version string, Makefile rules
|
||||
# should not depend on configure.ac for version updates).
|
||||
#
|
||||
# AC_INIT([GNU project],
|
||||
# m4_esyscmd([build-aux/git-version-gen .tarball-version]),
|
||||
# [bug-project@example])
|
||||
#
|
||||
# Then use the following lines in your Makefile.am, so that .version
|
||||
# will be present for dependencies, and so that .tarball-version will
|
||||
# exist in distribution tarballs.
|
||||
#
|
||||
# BUILT_SOURCES = $(top_srcdir)/.version
|
||||
# $(top_srcdir)/.version:
|
||||
# echo $(VERSION) > $@-t && mv $@-t $@
|
||||
# dist-hook:
|
||||
# echo $(VERSION) > $(distdir)/.tarball-version
|
||||
# echo $(VERSION) > $(distdir)/.version
|
||||
|
||||
case $# in
|
||||
1) ;;
|
||||
*) echo 1>&2 "Usage: $0 \$srcdir/.tarball-version"; exit 1;;
|
||||
esac
|
||||
|
||||
tarball_version_file=$1
|
||||
nl='
|
||||
'
|
||||
v=
|
||||
|
||||
# First see if there is a tarball-only version file.
|
||||
# then try "git describe", then default.
|
||||
if test -f $tarball_version_file
|
||||
then
|
||||
v=`cat $tarball_version_file` || exit 1
|
||||
case $v in
|
||||
*$nl*) v= ;; # reject multi-line output
|
||||
[0-9]*) ;;
|
||||
*) v= ;;
|
||||
esac
|
||||
test -z "$v" \
|
||||
&& echo "$0: WARNING: $tarball_version_file seems to be damaged" 1>&2
|
||||
fi
|
||||
|
||||
# This is presently used by the GNOME-OSTree build system; it
|
||||
# helps support the case where the meta-build system has already
|
||||
# determined the git revision, but we may not be able to run "git describe"
|
||||
# because we're inside a chroot.
|
||||
if test -n "$GIT_DESCRIBE_FOR_BUILD";
|
||||
then
|
||||
v=$GIT_DESCRIBE_FOR_BUILD
|
||||
fi
|
||||
|
||||
if test -n "$v"
|
||||
then
|
||||
: # use $v
|
||||
elif test -e .git \
|
||||
&& v=`git describe --abbrev=4 --match='v[0-9]*' HEAD 2>/dev/null` \
|
||||
&& [ -n "$v" ]
|
||||
then
|
||||
# If we are on a "dev" tag, we need to check that it is not the same
|
||||
# reference as the a previous version tag (this only happens when we are
|
||||
# working with a release tag).
|
||||
# NB The below trick relies on the $v being an exact tag to work which
|
||||
# will only work when HEAD == tag. When further commits have been made on top
|
||||
# of the tag, the $v will be supplimented with the number of commits since
|
||||
# that tag and the commit ref of the most recent commit and thus will
|
||||
# fail the test below (as intended)
|
||||
v2=`git describe --abbrev=4 --match='v[0-9]\.[0-9]' --contains $v 2>/dev/null | cut -d'^' -f1`
|
||||
[ -n "$v2" ] && v=$v2
|
||||
|
||||
# Is this a new git that lists number of commits since the last
|
||||
# tag or the previous older version that did not?
|
||||
# Newer: v6.10-77-g0f8faeb
|
||||
# Older: v6.10-g0f8faeb
|
||||
# case $v in
|
||||
# *-*-*) : git describe is okay three part flavor ;;
|
||||
# *-*)
|
||||
# : git describe is older two part flavor
|
||||
# # Recreate the number of commits and rewrite such that the
|
||||
# # result is the same as if we were using the newer version
|
||||
# # of git describe.
|
||||
# vtag=`echo "$v" | sed 's/-.*//'`
|
||||
# numcommits=`git rev-list "$vtag"..HEAD | wc -l`
|
||||
# v=`echo "$v" | sed "s/\(.*\)-\(.*\)/\1-$numcommits-\2/"`;
|
||||
# ;;
|
||||
# esac
|
||||
|
||||
# Change the first '-' to a '.', so version-comparing tools work properly.
|
||||
# Remove the "g" in git describe's output string, to save a byte.
|
||||
# v=`echo "$v" | sed 's/-/./;s/\(.*\)-g/\1-/'`;
|
||||
:
|
||||
else
|
||||
echo 1>&2 "$0: Failed to determine git revision"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
v=`echo "$v" |sed 's/^v//'`
|
||||
|
||||
# Don't declare a version "dirty" merely because a time stamp has changed.
|
||||
git status > /dev/null 2>&1
|
||||
|
||||
dirty=`sh -c 'git diff-index --name-only HEAD' 2>/dev/null` || dirty=
|
||||
case "$dirty" in
|
||||
'') ;;
|
||||
*) # Append the suffix only if there isn't one already.
|
||||
case $v in
|
||||
*-dirty) ;;
|
||||
*) v="$v-dirty" ;;
|
||||
esac ;;
|
||||
esac
|
||||
|
||||
# Omit the trailing newline, so that m4_esyscmd can use the result directly.
|
||||
echo "$v" | tr -d '\012'
|
||||
|
||||
# Local variables:
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-end: "$"
|
||||
# End:
|
|
@ -0,0 +1,11 @@
|
|||
prefix=/usr/local
|
||||
exec_prefix=${prefix}
|
||||
libdir=${exec_prefix}/lib
|
||||
includedir=${prefix}/include
|
||||
modlibexecdir=@modlibexecdir@
|
||||
|
||||
Name: libpulsevideo
|
||||
Description: PulseVideo Client Interface
|
||||
Version: 0.1
|
||||
Libs: -L${libdir} -lpulsevideo @PTHREAD_LIBS@
|
||||
Cflags: -I${includedir} -D_REENTRANT
|
|
@ -0,0 +1,11 @@
|
|||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
libdir=@libdir@
|
||||
includedir=@includedir@
|
||||
modlibexecdir=@modlibexecdir@
|
||||
|
||||
Name: libpulsevideo
|
||||
Description: PulseVideo Client Interface
|
||||
Version: @PACKAGE_VERSION@
|
||||
Libs: -L${libdir} -lpulsevideo @PTHREAD_LIBS@
|
||||
Cflags: -I${includedir} -D_REENTRANT
|
|
@ -0,0 +1,3 @@
|
|||
pulsevideo
|
||||
test-client
|
||||
test-subscribe
|
|
@ -0,0 +1,228 @@
|
|||
# This file is part of PulseVideo.
|
||||
#
|
||||
# Copyright 2015 Wim Taymans <wim.taymans@gmail.com>
|
||||
#
|
||||
# PulseVideo 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 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# PulseVideo 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
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with PulseVideo; if not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
###################################
|
||||
# Extra directories #
|
||||
###################################
|
||||
|
||||
pulsevideoincludedir=$(includedir)/client
|
||||
pulsevideoserverincludedir=$(includedir)/server
|
||||
pulsevideolibexecdir=$(libexecdir)/client
|
||||
dbuspolicydir=$(sysconfdir)/dbus-1/system.d
|
||||
|
||||
###################################
|
||||
# Compiler/linker flags #
|
||||
###################################
|
||||
|
||||
AM_CPPFLAGS = \
|
||||
-I$(top_srcdir)/src \
|
||||
-I$(top_srcdir)/src/modules \
|
||||
-I$(top_builddir)/src/modules \
|
||||
-DPV_SRCDIR=\"$(abs_srcdir)\" \
|
||||
-DPV_BUILDDIR=\"$(abs_builddir)\"
|
||||
AM_CFLAGS = $(GLIB_CFLAGS) $(GST_CFLAGS)
|
||||
AM_CXXFLAGS = $(AM_CFLAGS)
|
||||
SERVER_CFLAGS = -D__INCLUDED_FROM_PULSE_VIDEO
|
||||
|
||||
AM_LIBADD = $(GLIB_LIBS) $(INTLLIBS) $(GST_LIBS)
|
||||
AM_LDADD = $(GLIB_LIBS) $(GST_LIBS) $(INTLLIBS)
|
||||
AM_LDFLAGS = $(NODELETE_LDFLAGS)
|
||||
|
||||
FOREIGN_CFLAGS = -w
|
||||
|
||||
###################################
|
||||
# Extra files #
|
||||
###################################
|
||||
|
||||
EXTRA_DIST = \
|
||||
src/version.h.in \
|
||||
daemon/pulsevideo-system.conf
|
||||
|
||||
dbuspolicy_DATA = \
|
||||
daemon/pulsevideo-system.conf
|
||||
|
||||
###################################
|
||||
# Includes #
|
||||
###################################
|
||||
|
||||
enumtypesincludes = client/pv-context.h \
|
||||
client/pv-stream.h \
|
||||
client/pv-subscribe.h
|
||||
|
||||
client/pv-enumtypes.h: $(enumtypesincludes)
|
||||
$(AM_V_GEN)$(GLIB_MKENUMS) \
|
||||
--fhead "#ifndef __PV_ENUM_TYPES_H__\n#define __PV_ENUM_TYPES_H__\n\n#include <glib-object.h>\n\nG_BEGIN_DECLS\n" \
|
||||
--fprod "\n/* enumerations from \"@filename@\" */\n" \
|
||||
--vhead "GType @enum_name@_get_type (void);\n#define PV_TYPE_@ENUMSHORT@ (@enum_name@_get_type())\n" \
|
||||
--ftail "G_END_DECLS\n\n#endif /* __PV_ENUM_TYPES_H__ */" \
|
||||
$^ > client/pv-enumtypes.h
|
||||
|
||||
client/pv-enumtypes.c: $(enumtypesincludes) client/pv-enumtypes.h
|
||||
$(AM_V_GEN)$(GLIB_MKENUMS) \
|
||||
--fhead "#include \"pv-enumtypes.h\"\n#include <client/pulsevideo.h>\n#define C_ENUM(v) ((gint) v)\n#define C_FLAGS(v) ((guint) v)\n " \
|
||||
--fprod "\n/* enumerations from \"@filename@\" */" \
|
||||
--vhead "GType\n@enum_name@_get_type (void)\n{\n static gsize id = 0;\n static const G@Type@Value values[] = {" \
|
||||
--vprod " { C_@TYPE@(@VALUENAME@), \"@VALUENAME@\", \"@valuenick@\" }," \
|
||||
--vtail " { 0, NULL, NULL }\n };\n\n if (g_once_init_enter (&id)) {\n GType tmp = g_@type@_register_static (\"@EnumName@\", values);\n g_once_init_leave (&id, tmp);\n }\n\n return (GType) id;\n}" \
|
||||
$^ > client/pv-enumtypes.c
|
||||
|
||||
|
||||
dbus/org-pulsevideo.c: dbus/org-pulsevideo.h
|
||||
dbus/org-pulsevideo.h: dbus/org.pulsevideo.xml
|
||||
$(AM_V_GEN) $(GDBUS_CODEGEN) \
|
||||
--c-generate-object-manager \
|
||||
--interface-prefix org.pulsevideo. \
|
||||
--generate-c-code dbus/org-pulsevideo \
|
||||
--generate-docbook ../doc/org-pulsevideo \
|
||||
--c-namespace Pv dbus/org.pulsevideo.xml
|
||||
|
||||
built_header_make = client/pv-enumtypes.h dbus/org-pulsevideo.h
|
||||
built_source_make = client/pv-enumtypes.c dbus/org-pulsevideo.c
|
||||
|
||||
BUILT_SOURCES = $(built_header_make) \
|
||||
$(built_source_make)
|
||||
|
||||
CLEANFILES = $(built_header_make) $(built_source_make)
|
||||
|
||||
###################################
|
||||
# Main daemon #
|
||||
###################################
|
||||
|
||||
bin_PROGRAMS = pulsevideo
|
||||
|
||||
pulsevideo_SOURCES = \
|
||||
daemon/main.c
|
||||
|
||||
pulsevideo_CFLAGS = $(AM_CFLAGS)
|
||||
pulsevideo_LDADD = $(AM_LDADD) libpulsevideocore-@PV_MAJORMINOR@.la libpulsevideo-@PV_MAJORMINOR@.la $(LIBLTDL)
|
||||
# This is needed because automake doesn't properly expand the foreach below
|
||||
pulsevideo_DEPENDENCIES = libpulsevideocore-@PV_MAJORMINOR@.la libpulsevideo-@PV_MAJORMINOR@.la
|
||||
pulsevideo_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) $(IMMEDIATE_LDFLAGS)
|
||||
|
||||
###################################
|
||||
# Test programs #
|
||||
###################################
|
||||
noinst_LTLIBRARIES =
|
||||
|
||||
TESTS_default =
|
||||
|
||||
TESTS_norun = test-client \
|
||||
test-subscribe
|
||||
|
||||
# These tests need a running pulsevideo daemon
|
||||
TESTS_daemon =
|
||||
|
||||
noinst_PROGRAMS = $(TESTS_default) $(TESTS_norun) $(TESTS_daemon)
|
||||
|
||||
test_client_SOURCES = tests/test-client.c
|
||||
test_client_CFLAGS = $(AM_CFLAGS)
|
||||
test_client_LDADD = $(AM_LDADD) libpulsevideo-@PV_MAJORMINOR@.la
|
||||
test_client_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
|
||||
|
||||
test_subscribe_SOURCES = tests/test-subscribe.c
|
||||
test_subscribe_CFLAGS = $(AM_CFLAGS)
|
||||
test_subscribe_LDADD = $(AM_LDADD) libpulsevideo-@PV_MAJORMINOR@.la
|
||||
test_subscribe_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
|
||||
|
||||
###################################
|
||||
# Client library #
|
||||
###################################
|
||||
|
||||
pulsevideoinclude_HEADERS = \
|
||||
client/pv-context.h \
|
||||
client/pv-enumtypes.h \
|
||||
client/pv-stream.h \
|
||||
client/pv-subscribe.h \
|
||||
client/pv-subscribe.h \
|
||||
dbus/org-pulsevideo.h
|
||||
|
||||
lib_LTLIBRARIES = \
|
||||
libpulsevideo-@PV_MAJORMINOR@.la
|
||||
|
||||
# Public interface
|
||||
libpulsevideo_@PV_MAJORMINOR@_la_SOURCES = \
|
||||
client/pv-context.h client/pv-context.c \
|
||||
client/pv-enumtypes.h client/pv-enumtypes.c \
|
||||
client/pv-stream.h client/pv-stream.c \
|
||||
dbus/org-pulsevideo.c
|
||||
|
||||
|
||||
libpulsevideo_@PV_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS)
|
||||
libpulsevideo_@PV_MAJORMINOR@_la_LDFLAGS = $(AM_LDFLAGS) -avoid-version
|
||||
libpulsevideo_@PV_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) $(LTLIBICONV)
|
||||
|
||||
###################################
|
||||
# Daemon core library #
|
||||
###################################
|
||||
|
||||
lib_LTLIBRARIES += libpulsevideocore-@PV_MAJORMINOR@.la
|
||||
|
||||
# Pure core stuff
|
||||
libpulsevideocore_@PV_MAJORMINOR@_la_SOURCES = \
|
||||
server/pv-client.c server/pv-client.h \
|
||||
server/pv-daemon.c server/pv-daemon.h \
|
||||
server/pv-source-output.c server/pv-source-output.h \
|
||||
server/pv-source.c server/pv-source.h \
|
||||
modules/v4l2/pv-v4l2-source.c
|
||||
|
||||
libpulsevideocore_@PV_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) $(SERVER_CFLAGS)
|
||||
libpulsevideocore_@PV_MAJORMINOR@_la_LDFLAGS = $(AM_LDFLAGS) -avoid-version
|
||||
libpulsevideocore_@PV_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) $(LIBLTDL) $(LTLIBICONV)
|
||||
|
||||
###################################
|
||||
# Some minor stuff #
|
||||
###################################
|
||||
|
||||
DISTCLEANFILES =
|
||||
|
||||
install-exec-hook:
|
||||
rm -f $(DESTDIR)$(modlibexecdir)/*.la
|
||||
|
||||
uninstall-hook:
|
||||
rm -f $(DESTDIR)$(modlibexecdir)/*.so
|
||||
|
||||
# Automatically generate linker version script. We use the same one for all public .sos
|
||||
update-map-file:
|
||||
( echo "PULSE_0 {" ; \
|
||||
echo "global:" ; \
|
||||
ctags -I PV_GCC_MALLOC,PV_GCC_ALLOC_SIZE2,PV_GCC_ALLOC_SIZE,PV_GCC_PURE,PV_GCC_CONST,PV_GCC_DEPRECATED,PV_GCC_PRINTF_ATTR -f - --c-kinds=p $(pulsevideoinclude_HEADERS) | awk '/^pa_/ { print $$1 ";" }' | sort ; \
|
||||
echo "local:" ; \
|
||||
echo "*;" ; \
|
||||
echo "};" ) > $(srcdir)/map-file
|
||||
|
||||
update-all: update-map-file
|
||||
|
||||
# Force installation order of libraries. libtool relinks on install time, in
|
||||
# which case libpulsecommon has to be installed before others, but the padsp
|
||||
# preload library has to be done after the normal libraries (e.g. libpulse)
|
||||
# ...
|
||||
# Unfortunately automake behaviour means that rules without commands also
|
||||
# override build-in rules, so it's not trivial to add dependencies.
|
||||
# See http://debbugs.gnu.org/cgi/bugreport.cgi?bug=7328 for the workaround
|
||||
# ...
|
||||
# Isn't libtool/autotools fun!
|
||||
|
||||
installlibLTLIBRARIES = install-libLTLIBRARIES
|
||||
$(installlibLTLIBRARIES): install-pkglibLTLIBRARIES
|
||||
|
||||
installmodlibexecLTLIBRARIES = install-modlibexecLTLIBRARIES
|
||||
$(installmodlibexecLTLIBRARIES): install-pkglibLTLIBRARIES
|
||||
|
||||
installpadsplibLTLIBRARIES = install-padsplibLTLIBRARIES
|
||||
$(installpadsplibLTLIBRARIES): install-libLTLIBRARIES
|
||||
|
||||
.PHONY: update-all update-map-file coverage
|
|
@ -0,0 +1,2 @@
|
|||
pv-enumtypes.c
|
||||
pv-enumtypes.h
|
|
@ -0,0 +1,28 @@
|
|||
/* Pulsevideo
|
||||
* Copyright (C) 2015 Wim Taymans <wim.taymans@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __PULSEVIDEO_H__
|
||||
#define __PULSEVIDEO_H__
|
||||
|
||||
#include <client/pv-context.h>
|
||||
#include <client/pv-stream.h>
|
||||
#include <client/pv-subscribe.h>
|
||||
|
||||
#endif /* __PULSEVIDEO_H__ */
|
||||
|
|
@ -0,0 +1,502 @@
|
|||
/* Pulsevideo
|
||||
* Copyright (C) 2015 Wim Taymans <wim.taymans@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "server/pv-daemon.h"
|
||||
|
||||
#include "client/pv-context.h"
|
||||
#include "client/pv-enumtypes.h"
|
||||
#include "client/pv-subscribe.h"
|
||||
|
||||
#include "dbus/org-pulsevideo.h"
|
||||
|
||||
struct _PvContextPrivate
|
||||
{
|
||||
gchar *name;
|
||||
GVariant *properties;
|
||||
|
||||
guint id;
|
||||
GDBusConnection *connection;
|
||||
|
||||
PvContextFlags flags;
|
||||
PvContextState state;
|
||||
|
||||
PvDaemon1 *daemon;
|
||||
|
||||
gchar *client_path;
|
||||
PvClient1 *client;
|
||||
|
||||
PvSubscriptionFlags subscription_mask;
|
||||
GDBusObjectManager *client_manager;
|
||||
};
|
||||
|
||||
|
||||
#define PV_CONTEXT_GET_PRIVATE(obj) \
|
||||
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), PV_TYPE_CONTEXT, PvContextPrivate))
|
||||
|
||||
G_DEFINE_TYPE (PvContext, pv_context, G_TYPE_OBJECT);
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_NAME,
|
||||
PROP_PROPERTIES,
|
||||
PROP_STATE,
|
||||
PROP_SUBSCRIPTION_MASK,
|
||||
PROP_CONNECTION,
|
||||
PROP_CLIENT_PATH
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
SIGNAL_SUBSCRIPTION_EVENT,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
static guint signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
#include "pv-subscribe.c"
|
||||
|
||||
static void
|
||||
pv_context_get_property (GObject *_object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
PvContext *context = PV_CONTEXT (_object);
|
||||
PvContextPrivate *priv = context->priv;
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_NAME:
|
||||
g_value_set_string (value, priv->name);
|
||||
break;
|
||||
|
||||
case PROP_PROPERTIES:
|
||||
g_value_set_variant (value, priv->properties);
|
||||
break;
|
||||
|
||||
case PROP_STATE:
|
||||
g_value_set_enum (value, priv->state);
|
||||
break;
|
||||
|
||||
case PROP_SUBSCRIPTION_MASK:
|
||||
g_value_set_flags (value, priv->subscription_mask);
|
||||
break;
|
||||
|
||||
case PROP_CONNECTION:
|
||||
g_value_set_object (value, priv->connection);
|
||||
break;
|
||||
|
||||
case PROP_CLIENT_PATH:
|
||||
g_value_set_string (value, priv->client_path);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (context, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pv_context_set_property (GObject *_object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
PvContext *context = PV_CONTEXT (_object);
|
||||
PvContextPrivate *priv = context->priv;
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_NAME:
|
||||
g_free (priv->name);
|
||||
priv->name = g_value_dup_string (value);
|
||||
break;
|
||||
|
||||
case PROP_PROPERTIES:
|
||||
if (priv->properties)
|
||||
g_variant_unref (priv->properties);
|
||||
priv->properties = g_value_dup_variant (value);
|
||||
break;
|
||||
|
||||
case PROP_SUBSCRIPTION_MASK:
|
||||
priv->subscription_mask = g_value_get_flags (value);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (context, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pv_context_class_init (PvContextClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
g_type_class_add_private (klass, sizeof (PvContextPrivate));
|
||||
|
||||
gobject_class->set_property = pv_context_set_property;
|
||||
gobject_class->get_property = pv_context_get_property;
|
||||
|
||||
/**
|
||||
* PvContext:name
|
||||
*
|
||||
* The application name of the context.
|
||||
*/
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_NAME,
|
||||
g_param_spec_string ("name",
|
||||
"Name",
|
||||
"The application name",
|
||||
NULL,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
/**
|
||||
* PvContext:properties
|
||||
*
|
||||
* Properties of the context.
|
||||
*/
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_PROPERTIES,
|
||||
g_param_spec_variant ("properties",
|
||||
"Properties",
|
||||
"Extra properties",
|
||||
G_VARIANT_TYPE_VARIANT,
|
||||
NULL,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
/**
|
||||
* PvContext:state
|
||||
*
|
||||
* The state of the context.
|
||||
*/
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_STATE,
|
||||
g_param_spec_enum ("state",
|
||||
"State",
|
||||
"The context state",
|
||||
PV_TYPE_CONTEXT_STATE,
|
||||
PV_CONTEXT_STATE_UNCONNECTED,
|
||||
G_PARAM_READABLE |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
/**
|
||||
* PvContext:subscription-mask
|
||||
*
|
||||
* A mask for what object notifications will be signaled with
|
||||
* PvContext:subscription-event
|
||||
*/
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_SUBSCRIPTION_MASK,
|
||||
g_param_spec_flags ("subscription-mask",
|
||||
"Subscription Mask",
|
||||
"The object to receive subscription events of",
|
||||
PV_TYPE_SUBSCRIPTION_FLAGS,
|
||||
0,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
/**
|
||||
* PvContext:connection
|
||||
*
|
||||
* The connection of the context.
|
||||
*/
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_CONNECTION,
|
||||
g_param_spec_object ("connection",
|
||||
"Connection",
|
||||
"The DBus connection",
|
||||
G_TYPE_DBUS_CONNECTION,
|
||||
G_PARAM_READABLE |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
/**
|
||||
* PvContext:client-path
|
||||
*
|
||||
* The client object path of the context.
|
||||
*/
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_CLIENT_PATH,
|
||||
g_param_spec_string ("client-path",
|
||||
"Client Path",
|
||||
"The client object path",
|
||||
NULL,
|
||||
G_PARAM_READABLE |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
/**
|
||||
* PvContext:subscription-event
|
||||
* @context: The #PvContext emitting the signal.
|
||||
* @event: A #PvSubscriptionEvent
|
||||
* @flags: #PvSubscriptionFlags indicating the object
|
||||
* @path: the object path
|
||||
*
|
||||
* Notify about a new object that was added/removed/modified.
|
||||
*/
|
||||
signals[SIGNAL_SUBSCRIPTION_EVENT] = g_signal_new ("subscription-event",
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
g_cclosure_marshal_generic,
|
||||
G_TYPE_NONE,
|
||||
3,
|
||||
PV_TYPE_SUBSCRIPTION_EVENT,
|
||||
PV_TYPE_SUBSCRIPTION_FLAGS,
|
||||
G_TYPE_STRING);
|
||||
}
|
||||
|
||||
static void
|
||||
pv_context_init (PvContext * context)
|
||||
{
|
||||
PvContextPrivate *priv = context->priv = PV_CONTEXT_GET_PRIVATE (context);
|
||||
|
||||
priv->state = PV_CONTEXT_STATE_UNCONNECTED;
|
||||
}
|
||||
|
||||
/**
|
||||
* pv_context_new:
|
||||
* @name: an application name
|
||||
* @properties: optional properties
|
||||
*
|
||||
* Make a new unconnected #PvContext
|
||||
*
|
||||
* Returns: a new unconnected #PvContext
|
||||
*/
|
||||
PvContext *
|
||||
pv_context_new (const gchar *name, GVariant *properties)
|
||||
{
|
||||
return g_object_new (PV_TYPE_CONTEXT, "name", name, "properties", properties, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
context_set_state (PvContext *context, PvContextState state)
|
||||
{
|
||||
if (context->priv->state != state) {
|
||||
context->priv->state = state;
|
||||
g_object_notify (G_OBJECT (context), "state");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* pv_context_get_state:
|
||||
* @context: a #PvContext
|
||||
*
|
||||
* Get the state of @context.
|
||||
*
|
||||
* Returns: the state of @context
|
||||
*/
|
||||
PvContextState
|
||||
pv_context_get_state (PvContext *context)
|
||||
{
|
||||
PvContextPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (PV_IS_CONTEXT (context), PV_CONTEXT_STATE_ERROR);
|
||||
priv = context->priv;
|
||||
|
||||
return priv->state;
|
||||
}
|
||||
|
||||
static void
|
||||
on_client_proxy (GObject *source_object,
|
||||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
{
|
||||
PvContext *context = user_data;
|
||||
PvContextPrivate *priv = context->priv;
|
||||
GError *error = NULL;
|
||||
|
||||
priv->client = pv_client1_proxy_new_finish (res, &error);
|
||||
if (priv->client == NULL) {
|
||||
context_set_state (context, PV_CONTEXT_STATE_ERROR);
|
||||
g_error ("failed to get client proxy: %s", error->message);
|
||||
g_clear_error (&error);
|
||||
return;
|
||||
}
|
||||
context_set_state (context, PV_CONTEXT_STATE_READY);
|
||||
}
|
||||
|
||||
static void
|
||||
on_client_connected (GObject *source_object,
|
||||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
{
|
||||
PvContext *context = user_data;
|
||||
PvContextPrivate *priv = context->priv;
|
||||
GError *error = NULL;
|
||||
|
||||
if (!pv_daemon1_call_connect_client_finish (priv->daemon, &priv->client_path, res, &error)) {
|
||||
context_set_state (context, PV_CONTEXT_STATE_ERROR);
|
||||
g_error ("failed to connect client: %s", error->message);
|
||||
g_clear_error (&error);
|
||||
return;
|
||||
}
|
||||
|
||||
pv_client1_proxy_new (priv->connection,
|
||||
G_DBUS_PROXY_FLAGS_NONE,
|
||||
PV_DBUS_SERVICE,
|
||||
priv->client_path,
|
||||
NULL,
|
||||
on_client_proxy,
|
||||
context);
|
||||
}
|
||||
|
||||
static void
|
||||
on_daemon_connected (GObject *source_object,
|
||||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
{
|
||||
PvContext *context = user_data;
|
||||
PvContextPrivate *priv = context->priv;
|
||||
GError *error = NULL;
|
||||
|
||||
priv->daemon = pv_daemon1_proxy_new_finish (res, &error);
|
||||
if (priv->daemon == NULL) {
|
||||
context_set_state (context, PV_CONTEXT_STATE_ERROR);
|
||||
g_error ("failed to get daemon: %s", error->message);
|
||||
g_clear_error (&error);
|
||||
return;
|
||||
}
|
||||
|
||||
context_set_state (context, PV_CONTEXT_STATE_REGISTERING);
|
||||
|
||||
{
|
||||
GVariantBuilder builder;
|
||||
|
||||
g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
|
||||
g_variant_builder_add (&builder, "{sv}", "name", g_variant_new_string ("hello"));
|
||||
|
||||
pv_daemon1_call_connect_client (priv->daemon,
|
||||
g_variant_builder_end (&builder), /* GVariant *arg_properties */
|
||||
NULL, /* GCancellable *cancellable */
|
||||
on_client_connected,
|
||||
context);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
on_name_appeared (GDBusConnection *connection,
|
||||
const gchar *name,
|
||||
const gchar *name_owner,
|
||||
gpointer user_data)
|
||||
{
|
||||
PvContext *context = user_data;
|
||||
PvContextPrivate *priv = context->priv;
|
||||
|
||||
priv->connection = connection;
|
||||
|
||||
install_subscription (context);
|
||||
|
||||
pv_daemon1_proxy_new (priv->connection,
|
||||
G_DBUS_PROXY_FLAGS_NONE,
|
||||
name,
|
||||
PV_DBUS_OBJECT_SERVER,
|
||||
NULL,
|
||||
on_daemon_connected,
|
||||
user_data);
|
||||
}
|
||||
|
||||
static void
|
||||
on_name_vanished (GDBusConnection *connection,
|
||||
const gchar *name,
|
||||
gpointer user_data)
|
||||
{
|
||||
PvContext *context = user_data;
|
||||
PvContextPrivate *priv = context->priv;
|
||||
|
||||
uninstall_subscription (context);
|
||||
|
||||
priv->connection = connection;
|
||||
|
||||
if (priv->flags & PV_CONTEXT_FLAGS_NOFAIL) {
|
||||
context_set_state (context, PV_CONTEXT_STATE_CONNECTING);
|
||||
} else {
|
||||
context_set_state (context, PV_CONTEXT_STATE_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* pv_context_connect:
|
||||
* @context: a #PvContext
|
||||
* @flags: #PvContextFlags
|
||||
*
|
||||
* Connect to the daemon with @flags
|
||||
*
|
||||
* Returns: %TRUE on success.
|
||||
*/
|
||||
gboolean
|
||||
pv_context_connect (PvContext *context, PvContextFlags flags)
|
||||
{
|
||||
PvContextPrivate *priv;
|
||||
GBusNameWatcherFlags nw_flags;
|
||||
|
||||
g_return_val_if_fail (PV_IS_CONTEXT (context), FALSE);
|
||||
|
||||
priv = context->priv;
|
||||
g_return_val_if_fail (priv->connection == NULL, FALSE);
|
||||
|
||||
priv->flags = flags;
|
||||
|
||||
context_set_state (context, PV_CONTEXT_STATE_CONNECTING);
|
||||
|
||||
nw_flags = G_BUS_NAME_WATCHER_FLAGS_NONE;
|
||||
if (!(flags & PV_CONTEXT_FLAGS_NOAUTOSPAWN))
|
||||
nw_flags = G_BUS_NAME_WATCHER_FLAGS_AUTO_START;
|
||||
|
||||
priv->id = g_bus_watch_name (G_BUS_TYPE_SESSION,
|
||||
PV_DBUS_SERVICE,
|
||||
nw_flags,
|
||||
on_name_appeared,
|
||||
on_name_vanished,
|
||||
context,
|
||||
NULL);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* pv_context_get_connection:
|
||||
* @context: a #PvContext
|
||||
*
|
||||
* Get the #GDBusConnection of @context.
|
||||
*
|
||||
* Returns: the #GDBusConnection of @context or %NULL when not connected.
|
||||
*/
|
||||
GDBusConnection *
|
||||
pv_context_get_connection (PvContext *context)
|
||||
{
|
||||
g_return_val_if_fail (PV_IS_CONTEXT (context), NULL);
|
||||
|
||||
return context->priv->connection;
|
||||
}
|
||||
|
||||
/**
|
||||
* pv_context_get_client_path:
|
||||
* @context: a #PvContext
|
||||
*
|
||||
* Get the client object path that @context is registered with
|
||||
*
|
||||
* Returns: the client object path of @context or %NULL when not
|
||||
* registered.
|
||||
*/
|
||||
const gchar *
|
||||
pv_context_get_client_path (PvContext *context)
|
||||
{
|
||||
g_return_val_if_fail (PV_IS_CONTEXT (context), NULL);
|
||||
|
||||
return context->priv->client_path;
|
||||
}
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
/* Pulsevideo
|
||||
* Copyright (C) 2015 Wim Taymans <wim.taymans@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __PV_CONTEXT_H__
|
||||
#define __PV_CONTEXT_H__
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <gio/gio.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define PV_TYPE_CONTEXT (pv_context_get_type ())
|
||||
#define PV_IS_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PV_TYPE_CONTEXT))
|
||||
#define PV_IS_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PV_TYPE_CONTEXT))
|
||||
#define PV_CONTEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PV_TYPE_CONTEXT, PvContextClass))
|
||||
#define PV_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PV_TYPE_CONTEXT, PvContext))
|
||||
#define PV_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PV_TYPE_CONTEXT, PvContextClass))
|
||||
#define PV_CONTEXT_CAST(obj) ((PvContext*)(obj))
|
||||
#define PV_CONTEXT_CLASS_CAST(klass) ((PvContextClass*)(klass))
|
||||
|
||||
typedef struct _PvContext PvContext;
|
||||
typedef struct _PvContextClass PvContextClass;
|
||||
typedef struct _PvContextPrivate PvContextPrivate;
|
||||
|
||||
/**
|
||||
* PvContextFlags:
|
||||
* @PV_CONTEXT_FLAGS_NONE: no flags
|
||||
* @PV_CONTEXT_FLAGS_NOAUTOSPAWN: disable autostart of the daemon
|
||||
* @PV_CONTEXT_FLAGS_NOFAIL: Don't fail if the daemon is not available,
|
||||
* instead enter PV_CONTEXT_CONNECTING state and wait for the daemon
|
||||
* to appear.
|
||||
*
|
||||
* Context flags passed to pv_context_connect()
|
||||
*/
|
||||
typedef enum {
|
||||
PV_CONTEXT_FLAGS_NONE = 0,
|
||||
PV_CONTEXT_FLAGS_NOAUTOSPAWN = (1 << 0),
|
||||
PV_CONTEXT_FLAGS_NOFAIL = (1 << 1)
|
||||
} PvContextFlags;
|
||||
|
||||
/**
|
||||
* PvContextState:
|
||||
* @PV_CONTEXT_STATE_UNCONNECTED: not connected
|
||||
* @PV_CONTEXT_STATE_CONNECTING: connecting to daemon
|
||||
* @PV_CONTEXT_STATE_REGISTERING: registering with daemon
|
||||
* @PV_CONTEXT_STATE_READY: context is ready
|
||||
* @PV_CONTEXT_STATE_ERROR: context is in error
|
||||
*
|
||||
* The state of a #PvContext
|
||||
*/
|
||||
typedef enum {
|
||||
PV_CONTEXT_STATE_UNCONNECTED = 0,
|
||||
PV_CONTEXT_STATE_CONNECTING = 1,
|
||||
PV_CONTEXT_STATE_REGISTERING = 2,
|
||||
PV_CONTEXT_STATE_READY = 3,
|
||||
PV_CONTEXT_STATE_ERROR = 4
|
||||
} PvContextState;
|
||||
|
||||
/**
|
||||
* PvContext:
|
||||
*
|
||||
* Pulsevideo context object class.
|
||||
*/
|
||||
struct _PvContext {
|
||||
GObject object;
|
||||
|
||||
PvContextPrivate *priv;
|
||||
};
|
||||
|
||||
/**
|
||||
* PvContextClass:
|
||||
*
|
||||
* Pulsevideo context object class.
|
||||
*/
|
||||
struct _PvContextClass {
|
||||
GObjectClass parent_class;
|
||||
};
|
||||
|
||||
/* normal GObject stuff */
|
||||
GType pv_context_get_type (void);
|
||||
|
||||
PvContext * pv_context_new (const gchar *name, GVariant *properties);
|
||||
|
||||
gboolean pv_context_connect (PvContext *context, PvContextFlags flags);
|
||||
|
||||
GDBusConnection * pv_context_get_connection (PvContext *context);
|
||||
const gchar * pv_context_get_client_path (PvContext *context);
|
||||
|
||||
PvContextState pv_context_get_state (PvContext *context);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __PV_CONTEXT_H__ */
|
||||
|
|
@ -0,0 +1,731 @@
|
|||
/* Pulsevideo
|
||||
* Copyright (C) 2015 Wim Taymans <wim.taymans@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <gio/gunixfdlist.h>
|
||||
|
||||
#include "server/pv-daemon.h"
|
||||
#include "client/pv-context.h"
|
||||
#include "client/pv-stream.h"
|
||||
#include "client/pv-enumtypes.h"
|
||||
|
||||
#include "dbus/org-pulsevideo.h"
|
||||
|
||||
struct _PvStreamPrivate
|
||||
{
|
||||
PvContext *context;
|
||||
gchar *name;
|
||||
gchar *target;
|
||||
PvStreamState state;
|
||||
|
||||
PvCapture1 *capture;
|
||||
gchar *source_output_path;
|
||||
PvSourceOutput1 *source_output;
|
||||
|
||||
GSocket *socket;
|
||||
PvStreamMode mode;
|
||||
guint socket_id;
|
||||
|
||||
PvBufferInfo info;
|
||||
};
|
||||
|
||||
#define PV_STREAM_GET_PRIVATE(obj) \
|
||||
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), PV_TYPE_STREAM, PvStreamPrivate))
|
||||
|
||||
G_DEFINE_TYPE (PvStream, pv_stream, G_TYPE_OBJECT);
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_CONTEXT,
|
||||
PROP_NAME,
|
||||
PROP_STATE,
|
||||
PROP_SOCKET
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
SIGNAL_NEW_BUFFER,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
static guint signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
static void
|
||||
pv_stream_get_property (GObject *_object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
PvStream *stream = PV_STREAM (_object);
|
||||
PvStreamPrivate *priv = stream->priv;
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_CONTEXT:
|
||||
g_value_set_object (value, priv->context);
|
||||
break;
|
||||
|
||||
case PROP_NAME:
|
||||
g_value_set_string (value, priv->name);
|
||||
break;
|
||||
|
||||
case PROP_STATE:
|
||||
g_value_set_enum (value, priv->state);
|
||||
break;
|
||||
|
||||
case PROP_SOCKET:
|
||||
g_value_set_object (value, priv->socket);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (stream, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pv_stream_set_property (GObject *_object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
PvStream *stream = PV_STREAM (_object);
|
||||
PvStreamPrivate *priv = stream->priv;
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_CONTEXT:
|
||||
priv->context = g_value_dup_object (value);
|
||||
break;
|
||||
|
||||
case PROP_NAME:
|
||||
priv->name = g_value_dup_string (value);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (stream, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pv_stream_finalize (GObject * object)
|
||||
{
|
||||
PvStream *stream = PV_STREAM (object);
|
||||
PvStreamPrivate *priv = stream->priv;
|
||||
|
||||
g_free (priv->name);
|
||||
|
||||
G_OBJECT_CLASS (pv_stream_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
pv_stream_class_init (PvStreamClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
g_type_class_add_private (klass, sizeof (PvStreamPrivate));
|
||||
|
||||
gobject_class->finalize = pv_stream_finalize;
|
||||
gobject_class->set_property = pv_stream_set_property;
|
||||
gobject_class->get_property = pv_stream_get_property;
|
||||
|
||||
/**
|
||||
* PvStream:context
|
||||
*
|
||||
* The context of the stream.
|
||||
*/
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_CONTEXT,
|
||||
g_param_spec_object ("context",
|
||||
"Context",
|
||||
"The context",
|
||||
PV_TYPE_CONTEXT,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
/**
|
||||
* PvStream:name
|
||||
*
|
||||
* The name of the stream as specified at construction time.
|
||||
*/
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_NAME,
|
||||
g_param_spec_string ("name",
|
||||
"Name",
|
||||
"The name of the stream",
|
||||
NULL,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
/**
|
||||
* PvStream:state
|
||||
*
|
||||
* The state of the stream. Use the notify::state signal to be notified
|
||||
* of state changes.
|
||||
*/
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_STATE,
|
||||
g_param_spec_enum ("state",
|
||||
"State",
|
||||
"The stream state",
|
||||
PV_TYPE_STREAM_STATE,
|
||||
PV_STREAM_STATE_UNCONNECTED,
|
||||
G_PARAM_READABLE |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
|
||||
/**
|
||||
* PvStream:socket
|
||||
*
|
||||
* The socket of the stream. When doing pv_stream_start() with
|
||||
* #PV_STREAM_MODE_SOCKET, the socket will contain a data stream with
|
||||
* meta data and anciliary data containing fds with the data.
|
||||
*/
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_SOCKET,
|
||||
g_param_spec_object ("socket",
|
||||
"Socket",
|
||||
"The stream socket",
|
||||
G_TYPE_SOCKET,
|
||||
G_PARAM_READABLE |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
|
||||
|
||||
/**
|
||||
* PvStream:new-buffer
|
||||
*
|
||||
* When doing pv_stream_start() with #PV_STREAM_MODE_BUFFER, this signal
|
||||
* will be fired whenever a new buffer can be obtained with
|
||||
* pv_stream_capture_buffer().
|
||||
*/
|
||||
signals[SIGNAL_NEW_BUFFER] = g_signal_new ("new-buffer",
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
g_cclosure_marshal_generic,
|
||||
G_TYPE_NONE,
|
||||
0,
|
||||
G_TYPE_NONE);
|
||||
}
|
||||
|
||||
static void
|
||||
pv_stream_init (PvStream * stream)
|
||||
{
|
||||
PvStreamPrivate *priv = stream->priv = PV_STREAM_GET_PRIVATE (stream);
|
||||
|
||||
priv->state = PV_STREAM_STATE_UNCONNECTED;
|
||||
}
|
||||
|
||||
/**
|
||||
* pv_stream_new:
|
||||
* @context: a #PvContext
|
||||
* @name: a stream name
|
||||
*
|
||||
* Make a new unconnected #PvStream
|
||||
*
|
||||
* Returns: a new unconnected #PvStream
|
||||
*/
|
||||
PvStream *
|
||||
pv_stream_new (PvContext * context, const gchar *name)
|
||||
{
|
||||
g_return_val_if_fail (PV_IS_CONTEXT (context), NULL);
|
||||
g_return_val_if_fail (name != NULL, NULL);
|
||||
|
||||
return g_object_new (PV_TYPE_STREAM, "context", context, "name", name, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
stream_set_state (PvStream *stream, PvStreamState state)
|
||||
{
|
||||
if (stream->priv->state != state) {
|
||||
stream->priv->state = state;
|
||||
g_object_notify (G_OBJECT (stream), "state");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* pv_stream_get_state:
|
||||
* @stream: a #PvStream
|
||||
*
|
||||
* Get the state of @stream.
|
||||
*
|
||||
* Returns: the state of @stream
|
||||
*/
|
||||
PvStreamState
|
||||
pv_stream_get_state (PvStream *stream)
|
||||
{
|
||||
g_return_val_if_fail (PV_IS_STREAM (stream), PV_STREAM_STATE_ERROR);
|
||||
|
||||
return stream->priv->state;
|
||||
}
|
||||
|
||||
static void
|
||||
on_source_output1_proxy (GObject *source_object,
|
||||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
{
|
||||
PvStream *stream = user_data;
|
||||
PvStreamPrivate *priv = stream->priv;
|
||||
GError *error = NULL;
|
||||
|
||||
priv->source_output = pv_source_output1_proxy_new_finish (res, &error);
|
||||
if (priv->source_output == NULL) {
|
||||
stream_set_state (stream, PV_STREAM_STATE_ERROR);
|
||||
g_error ("failed to get source output proxy: %s", error->message);
|
||||
g_clear_error (&error);
|
||||
return;
|
||||
}
|
||||
stream_set_state (stream, PV_STREAM_STATE_READY);
|
||||
}
|
||||
|
||||
static void
|
||||
on_source_output_created (GObject *source_object,
|
||||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
{
|
||||
PvStream *stream = user_data;
|
||||
PvStreamPrivate *priv = stream->priv;
|
||||
PvContext *context = priv->context;
|
||||
GError *error = NULL;
|
||||
|
||||
if (!pv_capture1_call_create_source_output_finish (priv->capture,
|
||||
&priv->source_output_path, res, &error)) {
|
||||
stream_set_state (stream, PV_STREAM_STATE_ERROR);
|
||||
g_print ("failed to get connect capture: %s", error->message);
|
||||
g_clear_error (&error);
|
||||
return;
|
||||
}
|
||||
|
||||
pv_source_output1_proxy_new (pv_context_get_connection (context),
|
||||
G_DBUS_PROXY_FLAGS_NONE,
|
||||
PV_DBUS_SERVICE,
|
||||
priv->source_output_path,
|
||||
NULL,
|
||||
on_source_output1_proxy,
|
||||
stream);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
create_source_output (PvStream *stream)
|
||||
{
|
||||
PvStreamPrivate *priv = stream->priv;
|
||||
GVariantBuilder builder;
|
||||
|
||||
g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
|
||||
g_variant_builder_add (&builder, "{sv}", "name", g_variant_new_string ("hello"));
|
||||
|
||||
pv_capture1_call_create_source_output (priv->capture,
|
||||
priv->target ? priv->target : "/", /* const gchar *arg_source */
|
||||
g_variant_builder_end (&builder), /* GVariant *arg_props */
|
||||
NULL, /* GCancellable *cancellable */
|
||||
on_source_output_created,
|
||||
stream);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
on_source_output_removed (GObject *source_object,
|
||||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
{
|
||||
PvStream *stream = user_data;
|
||||
PvStreamPrivate *priv = stream->priv;
|
||||
GError *error = NULL;
|
||||
|
||||
if (!pv_capture1_call_remove_source_output_finish (priv->capture,
|
||||
res, &error)) {
|
||||
stream_set_state (stream, PV_STREAM_STATE_ERROR);
|
||||
g_print ("failed to disconnect: %s", error->message);
|
||||
g_clear_error (&error);
|
||||
return;
|
||||
}
|
||||
g_clear_pointer (&priv->source_output_path, g_free);
|
||||
g_clear_object (&priv->source_output);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
remove_source_output (PvStream *stream)
|
||||
{
|
||||
PvStreamPrivate *priv = stream->priv;
|
||||
|
||||
pv_capture1_call_remove_source_output (priv->capture,
|
||||
priv->source_output_path,
|
||||
NULL, /* GCancellable *cancellable */
|
||||
on_source_output_removed,
|
||||
stream);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
on_capture_proxy (GObject *source_object,
|
||||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
{
|
||||
PvStream *stream = user_data;
|
||||
PvStreamPrivate *priv = stream->priv;
|
||||
GError *error = NULL;
|
||||
|
||||
priv->capture = pv_capture1_proxy_new_finish (res, &error);
|
||||
if (priv->capture == NULL) {
|
||||
stream_set_state (stream, PV_STREAM_STATE_ERROR);
|
||||
g_error ("failed to get capture proxy: %s", error->message);
|
||||
g_clear_error (&error);
|
||||
return;
|
||||
}
|
||||
|
||||
create_source_output (stream);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* pv_stream_connect_capture:
|
||||
* @stream: a #PvStream
|
||||
* @device: the device name to connect to
|
||||
* @flags: a #PvStreamFlags
|
||||
*
|
||||
* Connect @stream for capturing from @device.
|
||||
*
|
||||
* Returns: %TRUE on success.
|
||||
*/
|
||||
gboolean
|
||||
pv_stream_connect_capture (PvStream *stream,
|
||||
const gchar *source,
|
||||
PvStreamFlags flags)
|
||||
{
|
||||
PvStreamPrivate *priv;
|
||||
PvContext *context;
|
||||
|
||||
g_return_val_if_fail (PV_IS_STREAM (stream), FALSE);
|
||||
priv = stream->priv;
|
||||
context = priv->context;
|
||||
g_return_val_if_fail (pv_context_get_state (context) == PV_CONTEXT_STATE_READY, FALSE);
|
||||
|
||||
priv->target = g_strdup (source);
|
||||
|
||||
stream_set_state (stream, PV_STREAM_STATE_CONNECTING);
|
||||
|
||||
if (priv->capture == NULL) {
|
||||
pv_capture1_proxy_new (pv_context_get_connection (context),
|
||||
G_DBUS_PROXY_FLAGS_NONE,
|
||||
PV_DBUS_SERVICE,
|
||||
pv_context_get_client_path (context),
|
||||
NULL,
|
||||
on_capture_proxy,
|
||||
stream);
|
||||
|
||||
return TRUE;
|
||||
} else {
|
||||
return create_source_output (stream);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* pv_stream_disconnect:
|
||||
* @stream: a #PvStream
|
||||
*
|
||||
* Disconnect @stream.
|
||||
*
|
||||
* Returns: %TRUE on success
|
||||
*/
|
||||
gboolean
|
||||
pv_stream_disconnect (PvStream *stream)
|
||||
{
|
||||
PvStreamPrivate *priv;
|
||||
PvContext *context;
|
||||
|
||||
g_return_val_if_fail (PV_IS_STREAM (stream), FALSE);
|
||||
priv = stream->priv;
|
||||
g_return_val_if_fail (priv->state >= PV_STREAM_STATE_READY, FALSE);
|
||||
g_return_val_if_fail (priv->capture != NULL, FALSE);
|
||||
context = priv->context;
|
||||
g_return_val_if_fail (pv_context_get_state (context) == PV_CONTEXT_STATE_READY, FALSE);
|
||||
|
||||
remove_source_output (stream);
|
||||
|
||||
stream_set_state (stream, PV_STREAM_STATE_UNCONNECTED);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
typedef struct {
|
||||
guint64 offset;
|
||||
guint64 size;
|
||||
} FDMessage;
|
||||
|
||||
static gboolean
|
||||
on_socket_data (GSocket *socket,
|
||||
GIOCondition condition,
|
||||
gpointer user_data)
|
||||
{
|
||||
PvStream *stream = user_data;
|
||||
PvStreamPrivate *priv = stream->priv;
|
||||
|
||||
switch (condition) {
|
||||
case G_IO_IN:
|
||||
{
|
||||
gssize len;
|
||||
GInputVector ivec;
|
||||
FDMessage msg;
|
||||
GSocketControlMessage **messages = NULL;
|
||||
gint num_messages = 0;
|
||||
gint flags = 0;
|
||||
GError *error = NULL;
|
||||
|
||||
ivec.buffer = &msg;
|
||||
ivec.size = sizeof (msg);
|
||||
|
||||
len = g_socket_receive_message (socket,
|
||||
NULL,
|
||||
&ivec,
|
||||
1,
|
||||
&messages,
|
||||
&num_messages,
|
||||
&flags,
|
||||
NULL,
|
||||
&error);
|
||||
|
||||
g_assert (len == sizeof (msg));
|
||||
|
||||
if (priv->info.message)
|
||||
g_object_unref (priv->info.message);
|
||||
priv->info.offset = msg.offset;
|
||||
priv->info.size = msg.size;
|
||||
priv->info.message = num_messages > 0 ? messages[0] : NULL;
|
||||
|
||||
g_signal_emit (stream, SIGNAL_NEW_BUFFER, 0, NULL);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
handle_socket (PvStream *stream, gint fd)
|
||||
{
|
||||
PvStreamPrivate *priv = stream->priv;
|
||||
GError *error = NULL;
|
||||
|
||||
g_print ("got fd %d\n", fd);
|
||||
priv->socket = g_socket_new_from_fd (fd, &error);
|
||||
if (priv->socket == NULL) {
|
||||
stream_set_state (stream, PV_STREAM_STATE_ERROR);
|
||||
g_error ("failed to create socket: %s", error->message);
|
||||
g_clear_error (&error);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (priv->mode) {
|
||||
case PV_STREAM_MODE_SOCKET:
|
||||
g_object_notify (G_OBJECT (stream), "socket");
|
||||
break;
|
||||
|
||||
case PV_STREAM_MODE_BUFFER:
|
||||
{
|
||||
GSource *source;
|
||||
|
||||
source = g_socket_create_source (priv->socket, G_IO_IN, NULL);
|
||||
g_source_set_callback (source, (GSourceFunc) on_socket_data, stream, NULL);
|
||||
priv->socket_id = g_source_attach (source, NULL);
|
||||
g_source_unref (source);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
unhandle_socket (PvStream *stream)
|
||||
{
|
||||
PvStreamPrivate *priv = stream->priv;
|
||||
|
||||
switch (priv->mode) {
|
||||
case PV_STREAM_MODE_SOCKET:
|
||||
g_clear_object (&priv->socket);
|
||||
g_object_notify (G_OBJECT (stream), "socket");
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
on_stream_acquired (GObject *source_object,
|
||||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
{
|
||||
PvStream *stream = user_data;
|
||||
PvStreamPrivate *priv = stream->priv;
|
||||
GUnixFDList *out_fd_list;
|
||||
gint fd_idx, fd;
|
||||
GVariant *out_props;
|
||||
GError *error = NULL;
|
||||
GVariant *result;
|
||||
|
||||
result = g_dbus_proxy_call_with_unix_fd_list_finish (G_DBUS_PROXY (priv->source_output), &out_fd_list, res, &error);
|
||||
if (result == NULL) {
|
||||
stream_set_state (stream, PV_STREAM_STATE_ERROR);
|
||||
g_error ("failed to acquire: %s", error->message);
|
||||
g_clear_error (&error);
|
||||
return;
|
||||
}
|
||||
|
||||
g_variant_get (result,
|
||||
"(h@a{sv})",
|
||||
&fd_idx,
|
||||
&out_props);
|
||||
|
||||
g_variant_unref (result);
|
||||
g_variant_unref (out_props);
|
||||
|
||||
if ((fd = g_unix_fd_list_get (out_fd_list, fd_idx, &error)) < 0) {
|
||||
stream_set_state (stream, PV_STREAM_STATE_ERROR);
|
||||
g_error ("failed to get FD: %s", error->message);
|
||||
g_clear_error (&error);
|
||||
return;
|
||||
}
|
||||
|
||||
handle_socket (stream, fd);
|
||||
|
||||
stream_set_state (stream, PV_STREAM_STATE_STREAMING);
|
||||
}
|
||||
|
||||
/**
|
||||
* pv_stream_start:
|
||||
* @stream: a #PvStream
|
||||
* @mode: a #PvStreamMode
|
||||
*
|
||||
* Start capturing from @stream.
|
||||
*
|
||||
* When @mode is #PV_STREAM_MODE_SOCKET, you should connect to the notify::socket
|
||||
* signal to obtain a readable socket with metadata and data.
|
||||
*
|
||||
* When @mode is ##PV_STREAM_MODE_BUFFER, you should connect to the new-buffer
|
||||
* signal and use pv_stream_capture_buffer() to get the latest metadata and
|
||||
* data.
|
||||
*
|
||||
* Returns: %TRUE on success.
|
||||
*/
|
||||
gboolean
|
||||
pv_stream_start (PvStream *stream, PvStreamMode mode)
|
||||
{
|
||||
PvStreamPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (PV_IS_STREAM (stream), FALSE);
|
||||
|
||||
priv = stream->priv;
|
||||
g_return_val_if_fail (priv->state == PV_STREAM_STATE_READY, FALSE);
|
||||
|
||||
priv->mode = mode;
|
||||
|
||||
stream_set_state (stream, PV_STREAM_STATE_STARTING);
|
||||
{
|
||||
GVariantBuilder builder;
|
||||
|
||||
g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
|
||||
g_variant_builder_add (&builder, "{sv}", "name", g_variant_new_string ("hello"));
|
||||
|
||||
pv_source_output1_call_acquire (priv->source_output,
|
||||
g_variant_builder_end (&builder), /* GVariant *arg_properties */
|
||||
NULL, /* GCancellable *cancellable */
|
||||
on_stream_acquired,
|
||||
stream);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
on_stream_released (GObject *source_object,
|
||||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
{
|
||||
PvStream *stream = user_data;
|
||||
PvStreamPrivate *priv = stream->priv;
|
||||
GError *error = NULL;
|
||||
|
||||
if (!pv_source_output1_call_release_finish (priv->source_output,
|
||||
res, &error)) {
|
||||
stream_set_state (stream, PV_STREAM_STATE_ERROR);
|
||||
g_error ("failed to release: %s", error->message);
|
||||
g_clear_error (&error);
|
||||
return;
|
||||
}
|
||||
unhandle_socket (stream);
|
||||
|
||||
stream_set_state (stream, PV_STREAM_STATE_READY);
|
||||
}
|
||||
|
||||
/**
|
||||
* pv_stream_stop:
|
||||
* @stream: a #PvStream
|
||||
*
|
||||
* Stop capturing from @stream.
|
||||
*
|
||||
* Returns: %TRUE on success.
|
||||
*/
|
||||
gboolean
|
||||
pv_stream_stop (PvStream *stream)
|
||||
{
|
||||
PvStreamPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (PV_IS_STREAM (stream), FALSE);
|
||||
|
||||
priv = stream->priv;
|
||||
g_return_val_if_fail (priv->state == PV_STREAM_STATE_STREAMING, FALSE);
|
||||
|
||||
pv_source_output1_call_release (priv->source_output,
|
||||
NULL, /* GCancellable *cancellable */
|
||||
on_stream_released,
|
||||
stream);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* pv_stream_capture_buffer:
|
||||
* @stream: a #PvStream
|
||||
* @info: a #PvBufferInfo
|
||||
*
|
||||
* Capture the next buffer from @stream. This function should be called every
|
||||
* time after the new-buffer callback has been emitted.
|
||||
*
|
||||
* Returns: %TRUE when @info contains valid information
|
||||
*/
|
||||
gboolean
|
||||
pv_stream_capture_buffer (PvStream *stream, PvBufferInfo *info)
|
||||
{
|
||||
PvStreamPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (PV_IS_STREAM (stream), FALSE);
|
||||
g_return_val_if_fail (info != NULL, FALSE);
|
||||
|
||||
priv = stream->priv;
|
||||
g_return_val_if_fail (priv->state == PV_STREAM_STATE_STREAMING, FALSE);
|
||||
|
||||
*info = priv->info;
|
||||
|
||||
return TRUE;
|
||||
}
|
|
@ -0,0 +1,113 @@
|
|||
/* Pulsevideo
|
||||
* Copyright (C) 2015 Wim Taymans <wim.taymans@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __PV_STREAM_H__
|
||||
#define __PV_STREAM_H__
|
||||
|
||||
#include <gio/gio.h>
|
||||
#include <glib-object.h>
|
||||
|
||||
#include "pv-context.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define PV_TYPE_STREAM (pv_stream_get_type ())
|
||||
#define PV_IS_STREAM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PV_TYPE_STREAM))
|
||||
#define PV_IS_STREAM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PV_TYPE_STREAM))
|
||||
#define PV_STREAM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PV_TYPE_STREAM, PvStreamClass))
|
||||
#define PV_STREAM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PV_TYPE_STREAM, PvStream))
|
||||
#define PV_STREAM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PV_TYPE_STREAM, PvStreamClass))
|
||||
#define PV_STREAM_CAST(obj) ((PvStream*)(obj))
|
||||
#define PV_STREAM_CLASS_CAST(klass) ((PvStreamClass*)(klass))
|
||||
|
||||
typedef struct _PvStream PvStream;
|
||||
typedef struct _PvStreamClass PvStreamClass;
|
||||
typedef struct _PvStreamPrivate PvStreamPrivate;
|
||||
|
||||
typedef enum {
|
||||
PV_STREAM_STATE_UNCONNECTED = 0,
|
||||
PV_STREAM_STATE_CONNECTING = 1,
|
||||
PV_STREAM_STATE_READY = 2,
|
||||
PV_STREAM_STATE_STARTING = 3,
|
||||
PV_STREAM_STATE_STREAMING = 4,
|
||||
PV_STREAM_STATE_ERROR = 5
|
||||
} PvStreamState;
|
||||
|
||||
|
||||
typedef enum {
|
||||
PV_STREAM_FLAGS_NONE = 0,
|
||||
} PvStreamFlags;
|
||||
|
||||
typedef struct {
|
||||
gint64 timestamp;
|
||||
guint64 seq;
|
||||
guint64 offset;
|
||||
guint64 size;
|
||||
GSocketControlMessage *message;
|
||||
} PvBufferInfo;
|
||||
|
||||
typedef enum {
|
||||
PV_STREAM_MODE_SOCKET = 0,
|
||||
PV_STREAM_MODE_BUFFER = 1,
|
||||
} PvStreamMode;
|
||||
|
||||
/**
|
||||
* PvStream:
|
||||
*
|
||||
* Pulsevideo stream object class.
|
||||
*/
|
||||
struct _PvStream {
|
||||
GObject object;
|
||||
|
||||
PvStreamPrivate *priv;
|
||||
};
|
||||
|
||||
/**
|
||||
* PvStreamClass:
|
||||
*
|
||||
* Pulsevideo stream object class.
|
||||
*/
|
||||
struct _PvStreamClass {
|
||||
GObjectClass parent_class;
|
||||
};
|
||||
|
||||
/* normal GObject stuff */
|
||||
GType pv_stream_get_type (void);
|
||||
|
||||
|
||||
PvStream * pv_stream_new (PvContext * context,
|
||||
const gchar *name);
|
||||
|
||||
PvStreamState pv_stream_get_state (PvStream *stream);
|
||||
|
||||
gboolean pv_stream_connect_capture (PvStream *stream,
|
||||
const gchar *source,
|
||||
PvStreamFlags flags);
|
||||
gboolean pv_stream_disconnect (PvStream *stream);
|
||||
|
||||
gboolean pv_stream_start (PvStream *stream, PvStreamMode mode);
|
||||
gboolean pv_stream_stop (PvStream *stream);
|
||||
|
||||
gboolean pv_stream_capture_buffer (PvStream *stream,
|
||||
PvBufferInfo *info);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __PV_STREAM_H__ */
|
||||
|
|
@ -0,0 +1,183 @@
|
|||
/* Pulsevideo
|
||||
* Copyright (C) 2015 Wim Taymans <wim.taymans@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
static void
|
||||
notify_subscription (PvContext *context,
|
||||
GDBusObject *object,
|
||||
GDBusInterface *interface,
|
||||
PvSubscriptionEvent event)
|
||||
{
|
||||
PvContextPrivate *priv = context->priv;
|
||||
|
||||
if (priv->subscription_mask & PV_SUBSCRIPTION_FLAGS_CLIENT) {
|
||||
if ((interface == NULL && pv_object_peek_client1 (PV_OBJECT (object))) ||
|
||||
PV_IS_CLIENT1_PROXY (interface))
|
||||
g_signal_emit (context, signals[SIGNAL_SUBSCRIPTION_EVENT], 0, event,
|
||||
PV_SUBSCRIPTION_FLAGS_CLIENT, g_dbus_object_get_object_path (object));
|
||||
}
|
||||
if (priv->subscription_mask & PV_SUBSCRIPTION_FLAGS_DEVICE) {
|
||||
if ((interface == NULL && pv_object_peek_device1 (PV_OBJECT (object))) ||
|
||||
PV_IS_DEVICE1_PROXY (interface))
|
||||
g_signal_emit (context, signals[SIGNAL_SUBSCRIPTION_EVENT], 0, event,
|
||||
PV_SUBSCRIPTION_FLAGS_DEVICE, g_dbus_object_get_object_path (object));
|
||||
}
|
||||
if (priv->subscription_mask & PV_SUBSCRIPTION_FLAGS_SOURCE) {
|
||||
if ((interface == NULL && pv_object_peek_source1 (PV_OBJECT (object))) ||
|
||||
PV_IS_SOURCE1_PROXY (interface))
|
||||
g_signal_emit (context, signals[SIGNAL_SUBSCRIPTION_EVENT], 0, event,
|
||||
PV_SUBSCRIPTION_FLAGS_SOURCE, g_dbus_object_get_object_path (object));
|
||||
}
|
||||
if (priv->subscription_mask & PV_SUBSCRIPTION_FLAGS_SOURCE_OUTPUT) {
|
||||
if ((interface == NULL && pv_object_peek_source_output1 (PV_OBJECT (object))) ||
|
||||
PV_IS_SOURCE_OUTPUT1_PROXY (interface))
|
||||
g_signal_emit (context, signals[SIGNAL_SUBSCRIPTION_EVENT], 0, event,
|
||||
PV_SUBSCRIPTION_FLAGS_SOURCE_OUTPUT, g_dbus_object_get_object_path (object));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
on_client_manager_interface_added (GDBusObjectManager *manager,
|
||||
GDBusObject *object,
|
||||
GDBusInterface *interface,
|
||||
gpointer user_data)
|
||||
{
|
||||
PvContext *context = user_data;
|
||||
notify_subscription (context, object, interface, PV_SUBSCRIPTION_EVENT_NEW);
|
||||
}
|
||||
|
||||
static void
|
||||
on_client_manager_interface_removed (GDBusObjectManager *manager,
|
||||
GDBusObject *object,
|
||||
GDBusInterface *interface,
|
||||
gpointer user_data)
|
||||
{
|
||||
PvContext *context = user_data;
|
||||
notify_subscription (context, object, interface, PV_SUBSCRIPTION_EVENT_REMOVE);
|
||||
}
|
||||
|
||||
static void
|
||||
on_client_manager_object_added (GDBusObjectManager *manager,
|
||||
GDBusObject *object,
|
||||
gpointer user_data)
|
||||
{
|
||||
PvContext *context = user_data;
|
||||
notify_subscription (context, object, NULL, PV_SUBSCRIPTION_EVENT_NEW);
|
||||
}
|
||||
|
||||
static void
|
||||
on_client_manager_object_removed (GDBusObjectManager *manager,
|
||||
GDBusObject *object,
|
||||
gpointer user_data)
|
||||
{
|
||||
PvContext *context = user_data;
|
||||
notify_subscription (context, object, NULL, PV_SUBSCRIPTION_EVENT_REMOVE);
|
||||
}
|
||||
|
||||
static void
|
||||
on_client_manager_properties_changed (GDBusObjectManagerClient *manager,
|
||||
GDBusObjectProxy *object_proxy,
|
||||
GDBusProxy *interface_proxy,
|
||||
GVariant *changed_properties,
|
||||
GStrv invalidated_properties,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_print ("properties changed\n");
|
||||
}
|
||||
|
||||
static void
|
||||
on_client_manager_signal (GDBusObjectManagerClient *manager,
|
||||
GDBusObjectProxy *object_proxy,
|
||||
GDBusProxy *interface_proxy,
|
||||
gchar *sender_name,
|
||||
gchar *signal_name,
|
||||
GVariant *parameters,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_print ("proxy signal %s\n", signal_name);
|
||||
}
|
||||
|
||||
static void
|
||||
connect_client_signals (PvContext *context)
|
||||
{
|
||||
PvContextPrivate *priv = context->priv;
|
||||
|
||||
g_signal_connect (priv->client_manager, "interface-added",
|
||||
(GCallback) on_client_manager_interface_added, context);
|
||||
g_signal_connect (priv->client_manager, "interface-removed",
|
||||
(GCallback) on_client_manager_interface_removed, context);
|
||||
g_signal_connect (priv->client_manager, "object-added",
|
||||
(GCallback) on_client_manager_object_added, context);
|
||||
g_signal_connect (priv->client_manager, "object-removed",
|
||||
(GCallback) on_client_manager_object_removed, context);
|
||||
g_signal_connect (priv->client_manager, "interface-proxy-signal",
|
||||
(GCallback) on_client_manager_signal, context);
|
||||
g_signal_connect (priv->client_manager, "interface-proxy-properties-changed",
|
||||
(GCallback) on_client_manager_properties_changed, context);
|
||||
}
|
||||
|
||||
static void
|
||||
on_client_manager_ready (GObject *source_object,
|
||||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
{
|
||||
PvContext *context = user_data;
|
||||
PvContextPrivate *priv = context->priv;
|
||||
GError *error = NULL;
|
||||
|
||||
priv->client_manager = pv_object_manager_client_new_finish (res, &error);
|
||||
if (priv->client_manager == NULL)
|
||||
goto manager_error;
|
||||
|
||||
connect_client_signals (context);
|
||||
|
||||
return;
|
||||
|
||||
/* ERRORS */
|
||||
manager_error:
|
||||
{
|
||||
g_warning ("could not create client manager: %s", error->message);
|
||||
g_clear_error (&error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
install_subscription (PvContext *context)
|
||||
{
|
||||
PvContextPrivate *priv = context->priv;
|
||||
|
||||
if (priv->client_manager)
|
||||
return;
|
||||
|
||||
pv_object_manager_client_new (pv_context_get_connection (context),
|
||||
G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE,
|
||||
PV_DBUS_SERVICE,
|
||||
PV_DBUS_OBJECT_PREFIX,
|
||||
NULL,
|
||||
on_client_manager_ready,
|
||||
context);
|
||||
}
|
||||
|
||||
static void
|
||||
uninstall_subscription (PvContext *context)
|
||||
{
|
||||
PvContextPrivate *priv = context->priv;
|
||||
|
||||
g_clear_object (&priv->client_manager);
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/* Pulsevideo
|
||||
* Copyright (C) 2015 Wim Taymans <wim.taymans@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __PV_SUBSCRIBE_H__
|
||||
#define __PV_SUBSCRIBE_H__
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef enum {
|
||||
PV_SUBSCRIPTION_FLAGS_CLIENT = (1 << 0),
|
||||
PV_SUBSCRIPTION_FLAGS_DEVICE = (1 << 1),
|
||||
PV_SUBSCRIPTION_FLAGS_SOURCE = (1 << 2),
|
||||
PV_SUBSCRIPTION_FLAGS_SOURCE_OUTPUT = (1 << 3),
|
||||
|
||||
PV_SUBSCRIPTION_FLAGS_ALL = 0xf
|
||||
} PvSubscriptionFlags;
|
||||
|
||||
typedef enum {
|
||||
PV_SUBSCRIPTION_EVENT_NEW = 0,
|
||||
PV_SUBSCRIPTION_EVENT_CHANGE = 1,
|
||||
PV_SUBSCRIPTION_EVENT_REMOVE = 2,
|
||||
} PvSubscriptionEvent;
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __PV_SUBSCRIBE_H__ */
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
/* Pulsevideo
|
||||
* Copyright (C) 2015 Wim Taymans <wim.taymans@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <gio/gio.h>
|
||||
#include <gst/gst.h>
|
||||
|
||||
#include "server/pv-daemon.h"
|
||||
|
||||
gint
|
||||
main (gint argc, gchar *argv[])
|
||||
{
|
||||
PvDaemon *daemon;
|
||||
GMainLoop *loop;
|
||||
|
||||
gst_init (&argc, &argv);
|
||||
|
||||
loop = g_main_loop_new (NULL, FALSE);
|
||||
|
||||
daemon = pv_daemon_new ();
|
||||
pv_daemon_start (daemon);
|
||||
|
||||
g_main_loop_run (loop);
|
||||
|
||||
g_main_loop_unref (loop);
|
||||
g_object_unref (daemon);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
<?xml version="1.0"?><!--*-nxml-*-->
|
||||
<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
|
||||
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
|
||||
|
||||
<!--
|
||||
This file is part of PulseVideo.
|
||||
|
||||
PulseVideo 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.
|
||||
|
||||
PulseVideo 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 PulseVideo; if not, see <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
<busconfig>
|
||||
|
||||
<!-- System-wide PulseVideo runs as 'pulsevideo' user. This fragment is
|
||||
not necessary for user PulseVideo instances. -->
|
||||
|
||||
<policy user="pulsevideo">
|
||||
<allow own="org.pulsevideo"/>
|
||||
</policy>
|
||||
|
||||
</busconfig>
|
|
@ -0,0 +1,2 @@
|
|||
org-pulsevideo.c
|
||||
org-pulsevideo.h
|
|
@ -0,0 +1,95 @@
|
|||
<node>
|
||||
<interface name='org.pulsevideo.Daemon1'>
|
||||
<property name='UserName' type='s' access='read' />
|
||||
<property name='HostName' type='s' access='read' />
|
||||
<property name='Version' type='s' access='read' />
|
||||
<property name='Name' type='s' access='read' />
|
||||
<property name='Properties' type='a{sv}' access='read' />
|
||||
<method name='ConnectClient'>
|
||||
<arg type='a{sv}' name='properties' direction='in'/>
|
||||
<arg type='o' name='client' direction='out'/>
|
||||
</method>
|
||||
<method name='DisconnectClient'>
|
||||
<arg type='o' name='client' direction='in'/>
|
||||
</method>
|
||||
</interface>
|
||||
|
||||
<interface name='org.pulsevideo.Client1'>
|
||||
<property name='Name' type='s' access='read' />
|
||||
<property name='Properties' type='a{sv}' access='read' />
|
||||
</interface>
|
||||
|
||||
<interface name='org.pulsevideo.Capture1'>
|
||||
<method name='CreateSourceOutput'>
|
||||
<arg type='o' name='source' direction='in'/>
|
||||
<arg type='a{sv}' name='props' direction='in'/>
|
||||
<arg type='o' name='output' direction='out'/>
|
||||
</method>
|
||||
<method name='RemoveSourceOutput'>
|
||||
<arg type='o' name='output' direction='in'/>
|
||||
</method>
|
||||
</interface>
|
||||
|
||||
<interface name='org.pulsevideo.Manager1'>
|
||||
<method name='AddProvider'>
|
||||
<arg type='o' name='provider' direction='in'/>
|
||||
<arg type='a{sv}' name='properties' direction='in'/>
|
||||
</method>
|
||||
<method name='RemoveProvider'>
|
||||
<arg type='o' name='provider' direction='in'/>
|
||||
</method>
|
||||
</interface>
|
||||
|
||||
<interface name='org.pulsevideo.Introspect1'>
|
||||
<method name='GetClients'>
|
||||
<arg type='ao' name='clients' direction='out'/>
|
||||
</method>
|
||||
<method name='GetProviders'>
|
||||
<arg type='ao' name='providers' direction='out'/>
|
||||
</method>
|
||||
<method name='GetSources'>
|
||||
<arg type='ao' name='sources' direction='out'/>
|
||||
</method>
|
||||
</interface>
|
||||
|
||||
<interface name='org.pulsevideo.Device1'>
|
||||
<property name='Name' type='s' access='read' />
|
||||
<property name='Properties' type='a{sv}' access='read' />
|
||||
</interface>
|
||||
|
||||
<interface name='org.pulsevideo.Source1'>
|
||||
<property name='Name' type='s' access='read' />
|
||||
<property name='Suspended' type='b' access='read' />
|
||||
<property name='Properties' type='a{sv}' access='read' />
|
||||
<method name='GetCapabilities'>
|
||||
<arg type='a{sv}' name='props' direction='in'/>
|
||||
<arg type='aa{sv}' name='caps' direction='out'/>
|
||||
</method>
|
||||
</interface>
|
||||
|
||||
<interface name='org.pulsevideo.SourceOutput1'>
|
||||
<method name='Acquire'>
|
||||
<arg type='a{sv}' name='props' direction='in'/>
|
||||
<arg type='h' name='fd' direction='out'/>
|
||||
<arg type='a{sv}' name='props' direction='out'/>
|
||||
</method>
|
||||
<method name='Release'>
|
||||
</method>
|
||||
|
||||
<!--
|
||||
<method name='Start'>
|
||||
<arg type='a{sv}' name='props' direction='in'/>
|
||||
<arg type='a{sv}' name='props' direction='out'/>
|
||||
</method>
|
||||
<method name='Stop'>
|
||||
</method>
|
||||
<signal name='NewData'>
|
||||
<arg type='h' name='data' direction='out'/>
|
||||
<arg type='a{sv}' name='props' direction='out'/>
|
||||
</signal>
|
||||
<method name='FreeData'>
|
||||
<arg type='h' name='data' direction='in'/>
|
||||
</method>
|
||||
-->
|
||||
</interface>
|
||||
</node>
|
|
@ -0,0 +1,130 @@
|
|||
/* Pulsevideo
|
||||
* Copyright (C) 2015 Wim Taymans <wim.taymans@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gio/gio.h>
|
||||
|
||||
#include "pv-v4l2-source.h"
|
||||
|
||||
#define PV_V4L2_SOURCE_GET_PRIVATE(obj) \
|
||||
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), PV_TYPE_V4L2_SOURCE, PvV4l2SourcePrivate))
|
||||
|
||||
struct _PvV4l2SourcePrivate
|
||||
{
|
||||
GstElement *pipeline;
|
||||
GstElement *sink;
|
||||
|
||||
GSocket *socket;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (PvV4l2Source, pv_v4l2_source, PV_TYPE_SOURCE);
|
||||
|
||||
static void
|
||||
setup_pipeline (PvV4l2Source *source)
|
||||
{
|
||||
PvV4l2SourcePrivate *priv = source->priv;
|
||||
|
||||
priv->pipeline = gst_parse_launch ("v4l2src ! video/x-raw,width=320,height=240,framerate=30/1 ! "
|
||||
"pvfdpay ! multisocketsink buffers-max=2 buffers-soft-max=1 "
|
||||
"recover-policy=latest sync-method=latest name=sink sync=true "
|
||||
"enable-last-sample=false", NULL);
|
||||
priv->sink = gst_bin_get_by_name (GST_BIN (priv->pipeline), "sink");
|
||||
|
||||
gst_element_set_state (priv->pipeline, GST_STATE_READY);
|
||||
}
|
||||
|
||||
static void
|
||||
on_socket_notify (GObject *gobject,
|
||||
GParamSpec *pspec,
|
||||
gpointer user_data)
|
||||
{
|
||||
PvV4l2Source *source = user_data;
|
||||
PvV4l2SourcePrivate *priv = source->priv;
|
||||
GSocket *socket;
|
||||
guint num_handles;
|
||||
|
||||
g_object_get (gobject, "socket", &socket, NULL);
|
||||
|
||||
if (socket == NULL) {
|
||||
if (priv->socket)
|
||||
g_signal_emit_by_name (priv->sink, "remove", priv->socket);
|
||||
} else {
|
||||
g_signal_emit_by_name (priv->sink, "add", socket);
|
||||
}
|
||||
priv->socket = socket;
|
||||
|
||||
g_object_get (priv->sink, "num-handles", &num_handles, NULL);
|
||||
if (num_handles == 0) {
|
||||
gst_element_set_state (priv->pipeline, GST_STATE_READY);
|
||||
} else {
|
||||
gst_element_set_state (priv->pipeline, GST_STATE_PLAYING);
|
||||
}
|
||||
}
|
||||
|
||||
static PvSourceOutput *
|
||||
v4l2_create_source_output (PvSource *source, GVariant *props, const gchar *prefix)
|
||||
{
|
||||
PvSourceOutput *output;
|
||||
|
||||
output = PV_SOURCE_CLASS (pv_v4l2_source_parent_class)->create_source_output (source, props, prefix);
|
||||
|
||||
g_signal_connect (output, "notify::socket", (GCallback) on_socket_notify, source);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
v4l2_release_source_output (PvSource *source, PvSourceOutput *output)
|
||||
{
|
||||
return PV_SOURCE_CLASS (pv_v4l2_source_parent_class)->release_source_output (source, output);
|
||||
}
|
||||
|
||||
static void
|
||||
v4l2_source_finalize (GObject * object)
|
||||
{
|
||||
G_OBJECT_CLASS (pv_v4l2_source_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
pv_v4l2_source_class_init (PvV4l2SourceClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
PvSourceClass *source_class = PV_SOURCE_CLASS (klass);
|
||||
|
||||
g_type_class_add_private (klass, sizeof (PvV4l2SourcePrivate));
|
||||
|
||||
gobject_class->finalize = v4l2_source_finalize;
|
||||
|
||||
source_class->create_source_output = v4l2_create_source_output;
|
||||
source_class->release_source_output = v4l2_release_source_output;
|
||||
}
|
||||
|
||||
static void
|
||||
pv_v4l2_source_init (PvV4l2Source * source)
|
||||
{
|
||||
source->priv = PV_V4L2_SOURCE_GET_PRIVATE (source);
|
||||
|
||||
setup_pipeline (source);
|
||||
}
|
||||
|
||||
PvSource *
|
||||
pv_v4l2_source_new (PvDaemon *daemon)
|
||||
{
|
||||
return g_object_new (PV_TYPE_V4L2_SOURCE, "daemon", daemon, NULL);
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
/* Pulsevideo
|
||||
* Copyright (C) 2015 Wim Taymans <wim.taymans@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __PV_V4L2_SOURCE_H__
|
||||
#define __PV_V4L2_SOURCE_H__
|
||||
|
||||
#include <glib-object.h>
|
||||
#include "server/pv-source.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define PV_TYPE_V4L2_SOURCE (pv_v4l2_source_get_type ())
|
||||
#define PV_IS_V4L2_SOURCE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PV_TYPE_V4L2_SOURCE))
|
||||
#define PV_IS_V4L2_SOURCE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PV_TYPE_V4L2_SOURCE))
|
||||
#define PV_V4L2_SOURCE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PV_TYPE_V4L2_SOURCE, PvV4l2SourceClass))
|
||||
#define PV_V4L2_SOURCE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PV_TYPE_V4L2_SOURCE, PvV4l2Source))
|
||||
#define PV_V4L2_SOURCE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PV_TYPE_V4L2_SOURCE, PvV4l2SourceClass))
|
||||
#define PV_V4L2_SOURCE_CAST(obj) ((PvV4l2Source*)(obj))
|
||||
#define PV_V4L2_SOURCE_CLASS_CAST(klass) ((PvV4l2SourceClass*)(klass))
|
||||
|
||||
typedef struct _PvV4l2Source PvV4l2Source;
|
||||
typedef struct _PvV4l2SourceClass PvV4l2SourceClass;
|
||||
typedef struct _PvV4l2SourcePrivate PvV4l2SourcePrivate;
|
||||
|
||||
struct _PvV4l2Source {
|
||||
PvSource object;
|
||||
|
||||
PvV4l2SourcePrivate *priv;
|
||||
};
|
||||
|
||||
struct _PvV4l2SourceClass {
|
||||
PvSourceClass parent_class;
|
||||
};
|
||||
|
||||
GType pv_v4l2_source_get_type (void);
|
||||
|
||||
PvSource * pv_v4l2_source_new (PvDaemon *daemon);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __PV_V4L2_SOURCE_H__ */
|
||||
|
|
@ -0,0 +1,279 @@
|
|||
/* Pulsevideo
|
||||
* Copyright (C) 2015 Wim Taymans <wim.taymans@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "server/pv-client.h"
|
||||
#include "server/pv-source.h"
|
||||
#include "server/pv-source-output.h"
|
||||
#include "client/pv-enumtypes.h"
|
||||
|
||||
#include "dbus/org-pulsevideo.h"
|
||||
|
||||
struct _PvClientPrivate
|
||||
{
|
||||
PvDaemon *daemon;
|
||||
gchar *object_path;
|
||||
|
||||
PvSource *source;
|
||||
|
||||
GHashTable *source_outputs;
|
||||
};
|
||||
|
||||
#define PV_CLIENT_GET_PRIVATE(obj) \
|
||||
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), PV_TYPE_CLIENT, PvClientPrivate))
|
||||
|
||||
G_DEFINE_TYPE (PvClient, pv_client, G_TYPE_OBJECT);
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_DAEMON,
|
||||
PROP_OBJECT_PATH,
|
||||
};
|
||||
|
||||
static void
|
||||
pv_client_get_property (GObject *_object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
PvClient *client = PV_CLIENT (_object);
|
||||
PvClientPrivate *priv = client->priv;
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_DAEMON:
|
||||
g_value_set_object (value, priv->daemon);
|
||||
break;
|
||||
|
||||
case PROP_OBJECT_PATH:
|
||||
g_value_set_string (value, priv->object_path);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (client, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pv_client_set_property (GObject *_object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
PvClient *client = PV_CLIENT (_object);
|
||||
PvClientPrivate *priv = client->priv;
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_DAEMON:
|
||||
priv->daemon = g_value_dup_object (value);
|
||||
break;
|
||||
|
||||
case PROP_OBJECT_PATH:
|
||||
priv->object_path = g_value_dup_string (value);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (client, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
handle_create_source_output (PvCapture1 *interface,
|
||||
GDBusMethodInvocation *invocation,
|
||||
const gchar *arg_source,
|
||||
GVariant *arg_properties,
|
||||
gpointer user_data)
|
||||
{
|
||||
PvClient *client = user_data;
|
||||
PvClientPrivate *priv = client->priv;
|
||||
PvDaemon *daemon = priv->daemon;
|
||||
PvSource *source;
|
||||
PvSourceOutput *output;
|
||||
const gchar *object_path;
|
||||
|
||||
source = pv_daemon_get_source (daemon, arg_source);
|
||||
|
||||
output = pv_source_create_source_output (source, NULL, priv->object_path);
|
||||
|
||||
object_path = pv_source_output_get_object_path (output);
|
||||
g_hash_table_insert (priv->source_outputs, g_strdup (object_path), output);
|
||||
pv_capture1_complete_create_source_output (interface, invocation, object_path);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
handle_remove_source_output (PvCapture1 *interface,
|
||||
GDBusMethodInvocation *invocation,
|
||||
const gchar *arg_output,
|
||||
gpointer user_data)
|
||||
{
|
||||
PvClient *client = user_data;
|
||||
PvClientPrivate *priv = client->priv;
|
||||
PvSourceOutput *output;
|
||||
|
||||
output = g_hash_table_lookup (priv->source_outputs, arg_output);
|
||||
if (output) {
|
||||
pv_source_release_source_output (priv->source, output);
|
||||
g_hash_table_remove (priv->source_outputs, arg_output);
|
||||
}
|
||||
|
||||
pv_capture1_complete_remove_source_output (interface, invocation);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
client_register_object (PvClient *client, const gchar *prefix)
|
||||
{
|
||||
PvClientPrivate *priv = client->priv;
|
||||
PvDaemon *daemon = priv->daemon;
|
||||
GDBusObjectSkeleton *skel;
|
||||
gchar *name;
|
||||
|
||||
name = g_strdup_printf ("%s/client", prefix);
|
||||
skel = g_dbus_object_skeleton_new (name);
|
||||
g_free (name);
|
||||
|
||||
{
|
||||
PvClient1 *iface;
|
||||
|
||||
iface = pv_client1_skeleton_new ();
|
||||
pv_client1_set_name (iface, "poppy");
|
||||
g_dbus_object_skeleton_add_interface (skel, G_DBUS_INTERFACE_SKELETON (iface));
|
||||
g_object_unref (iface);
|
||||
}
|
||||
{
|
||||
PvCapture1 *iface;
|
||||
|
||||
iface = pv_capture1_skeleton_new ();
|
||||
g_signal_connect (iface, "handle-create-source-output", (GCallback) handle_create_source_output, client);
|
||||
g_signal_connect (iface, "handle-remove-source-output", (GCallback) handle_remove_source_output, client);
|
||||
g_dbus_object_skeleton_add_interface (skel, G_DBUS_INTERFACE_SKELETON (iface));
|
||||
g_object_unref (iface);
|
||||
}
|
||||
|
||||
g_free (priv->object_path);
|
||||
priv->object_path = pv_daemon_export_uniquely (daemon, skel);
|
||||
}
|
||||
|
||||
static void
|
||||
client_unregister_object (PvClient *client)
|
||||
{
|
||||
PvClientPrivate *priv = client->priv;
|
||||
PvDaemon *daemon = priv->daemon;
|
||||
|
||||
g_hash_table_unref (priv->source_outputs);
|
||||
g_clear_object (&priv->source);
|
||||
|
||||
pv_daemon_unexport (daemon, priv->object_path);
|
||||
g_free (priv->object_path);
|
||||
}
|
||||
|
||||
static void
|
||||
pv_client_finalize (GObject * object)
|
||||
{
|
||||
PvClient *client = PV_CLIENT (object);
|
||||
|
||||
client_unregister_object (client);
|
||||
|
||||
G_OBJECT_CLASS (pv_client_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
pv_client_constructed (GObject * object)
|
||||
{
|
||||
PvClient *client = PV_CLIENT (object);
|
||||
PvClientPrivate *priv = client->priv;
|
||||
|
||||
client_register_object (client, priv->object_path);
|
||||
|
||||
G_OBJECT_CLASS (pv_client_parent_class)->constructed (object);
|
||||
}
|
||||
|
||||
static void
|
||||
pv_client_class_init (PvClientClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
g_type_class_add_private (klass, sizeof (PvClientPrivate));
|
||||
|
||||
gobject_class->finalize = pv_client_finalize;
|
||||
gobject_class->set_property = pv_client_set_property;
|
||||
gobject_class->get_property = pv_client_get_property;
|
||||
gobject_class->constructed = pv_client_constructed;
|
||||
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_DAEMON,
|
||||
g_param_spec_object ("daemon",
|
||||
"Daemon",
|
||||
"The daemon",
|
||||
PV_TYPE_DAEMON,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_OBJECT_PATH,
|
||||
g_param_spec_string ("object-path",
|
||||
"Object Path",
|
||||
"The object path",
|
||||
NULL,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
}
|
||||
|
||||
static void
|
||||
pv_client_init (PvClient * client)
|
||||
{
|
||||
PvClientPrivate *priv = client->priv = PV_CLIENT_GET_PRIVATE (client);
|
||||
|
||||
priv->source_outputs = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* pv_client_new:
|
||||
*
|
||||
* Make a new unconnected #PvClient
|
||||
*
|
||||
* Returns: a new unconnected #PvClient
|
||||
*/
|
||||
PvClient *
|
||||
pv_client_new (PvDaemon * daemon, const gchar *prefix)
|
||||
{
|
||||
g_return_val_if_fail (PV_IS_DAEMON (daemon), NULL);
|
||||
g_return_val_if_fail (g_variant_is_object_path (prefix), NULL);
|
||||
|
||||
return g_object_new (PV_TYPE_CLIENT, "daemon", daemon, "object-path", prefix, NULL);
|
||||
}
|
||||
|
||||
const gchar *
|
||||
pv_client_get_object_path (PvClient *client)
|
||||
{
|
||||
PvClientPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (PV_IS_CLIENT (client), NULL);
|
||||
priv = client->priv;
|
||||
|
||||
return priv->object_path;
|
||||
}
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
/* Pulsevideo
|
||||
* Copyright (C) 2015 Wim Taymans <wim.taymans@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __PV_CLIENT_H__
|
||||
#define __PV_CLIENT_H__
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
#include "pv-daemon.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define PV_TYPE_CLIENT (pv_client_get_type ())
|
||||
#define PV_IS_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PV_TYPE_CLIENT))
|
||||
#define PV_IS_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PV_TYPE_CLIENT))
|
||||
#define PV_CLIENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PV_TYPE_CLIENT, PvClientClass))
|
||||
#define PV_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PV_TYPE_CLIENT, PvClient))
|
||||
#define PV_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PV_TYPE_CLIENT, PvClientClass))
|
||||
#define PV_CLIENT_CAST(obj) ((PvClient*)(obj))
|
||||
#define PV_CLIENT_CLASS_CAST(klass) ((PvClientClass*)(klass))
|
||||
|
||||
typedef struct _PvClient PvClient;
|
||||
typedef struct _PvClientClass PvClientClass;
|
||||
typedef struct _PvClientPrivate PvClientPrivate;
|
||||
|
||||
/**
|
||||
* PvClient:
|
||||
*
|
||||
* Pulsevideo client object class.
|
||||
*/
|
||||
struct _PvClient {
|
||||
GObject object;
|
||||
|
||||
PvClientPrivate *priv;
|
||||
};
|
||||
|
||||
/**
|
||||
* PvClientClass:
|
||||
*
|
||||
* Pulsevideo client object class.
|
||||
*/
|
||||
struct _PvClientClass {
|
||||
GObjectClass parent_class;
|
||||
};
|
||||
|
||||
/* normal GObject stuff */
|
||||
GType pv_client_get_type (void);
|
||||
|
||||
PvClient * pv_client_new (PvDaemon *daemon, const gchar *prefix);
|
||||
|
||||
const gchar * pv_client_get_object_path (PvClient *client);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __PV_CLIENT_H__ */
|
||||
|
|
@ -0,0 +1,354 @@
|
|||
/* Pulsevideo
|
||||
* Copyright (C) 2015 Wim Taymans <wim.taymans@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <gio/gio.h>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "server/pv-daemon.h"
|
||||
#include "server/pv-client.h"
|
||||
#include "modules/v4l2/pv-v4l2-source.h"
|
||||
#include "dbus/org-pulsevideo.h"
|
||||
|
||||
#define PV_DAEMON_GET_PRIVATE(obj) \
|
||||
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), PV_TYPE_DAEMON, PvDaemonPrivate))
|
||||
|
||||
struct _PvDaemonPrivate
|
||||
{
|
||||
guint id;
|
||||
GDBusConnection *connection;
|
||||
GDBusObjectManagerServer *server_manager;
|
||||
|
||||
GHashTable *senders;
|
||||
PvSource *source;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
PvDaemon *daemon;
|
||||
gchar *sender;
|
||||
guint id;
|
||||
|
||||
GHashTable *clients;
|
||||
} SenderData;
|
||||
|
||||
static void
|
||||
client_name_appeared_handler (GDBusConnection *connection,
|
||||
const gchar *name,
|
||||
const gchar *name_owner,
|
||||
gpointer user_data)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
client_name_vanished_handler (GDBusConnection *connection,
|
||||
const gchar *name,
|
||||
gpointer user_data)
|
||||
{
|
||||
SenderData *data = user_data;
|
||||
PvDaemonPrivate *priv = data->daemon->priv;
|
||||
|
||||
g_print ("vanished client %s\n", name);
|
||||
|
||||
g_hash_table_unref (data->clients);
|
||||
g_hash_table_remove (priv->senders, data->sender);
|
||||
g_free (data->sender);
|
||||
g_bus_unwatch_name (data->id);
|
||||
g_free (data);
|
||||
}
|
||||
|
||||
static SenderData *
|
||||
sender_data_new (PvDaemon *daemon, const gchar *sender)
|
||||
{
|
||||
PvDaemonPrivate *priv = daemon->priv;
|
||||
SenderData *data;
|
||||
|
||||
data = g_new0 (SenderData, 1);
|
||||
data->daemon = daemon;
|
||||
data->sender = g_strdup (sender);
|
||||
data->clients = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
|
||||
|
||||
data->id = g_bus_watch_name_on_connection (priv->connection,
|
||||
sender,
|
||||
G_BUS_NAME_WATCHER_FLAGS_NONE,
|
||||
client_name_appeared_handler,
|
||||
client_name_vanished_handler,
|
||||
data,
|
||||
NULL);
|
||||
|
||||
g_hash_table_insert (priv->senders, data->sender, data);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
handle_connect_client (PvDaemon1 *interface,
|
||||
GDBusMethodInvocation *invocation,
|
||||
GVariant *arg_properties,
|
||||
gpointer user_data)
|
||||
{
|
||||
PvDaemon *daemon = user_data;
|
||||
PvDaemonPrivate *priv = daemon->priv;
|
||||
PvClient *client;
|
||||
const gchar *sender, *object_path;
|
||||
SenderData *data;
|
||||
|
||||
sender = g_dbus_method_invocation_get_sender (invocation);
|
||||
|
||||
g_print ("connect client %s\n", sender);
|
||||
data = g_hash_table_lookup (priv->senders, sender);
|
||||
if (data == NULL) {
|
||||
data = sender_data_new (daemon, sender);
|
||||
}
|
||||
|
||||
client = pv_client_new (daemon, PV_DBUS_OBJECT_PREFIX);
|
||||
object_path = pv_client_get_object_path (client);
|
||||
|
||||
g_hash_table_insert (data->clients, g_strdup (object_path), client);
|
||||
|
||||
pv_daemon1_complete_connect_client (interface, invocation, object_path);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
handle_disconnect_client (PvDaemon1 *interface,
|
||||
GDBusMethodInvocation *invocation,
|
||||
const gchar *arg_client,
|
||||
gpointer user_data)
|
||||
{
|
||||
PvDaemon *daemon = user_data;
|
||||
PvDaemonPrivate *priv = daemon->priv;
|
||||
const gchar *sender;
|
||||
SenderData *data;
|
||||
|
||||
sender = g_dbus_method_invocation_get_sender (invocation);
|
||||
|
||||
g_print ("disconnect client %s\n", sender);
|
||||
data = g_hash_table_lookup (priv->senders, sender);
|
||||
if (data != NULL) {
|
||||
g_hash_table_remove (data->clients, arg_client);
|
||||
}
|
||||
|
||||
pv_daemon1_complete_disconnect_client (interface, invocation);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
handle_add_provider (PvManager1 *interface,
|
||||
GDBusMethodInvocation *invocation,
|
||||
const gchar *arg_provider,
|
||||
GVariant *arg_properties,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_print ("add provider\n");
|
||||
g_dbus_method_invocation_return_dbus_error (invocation,
|
||||
"org.pulseaudio.Error.NotImplemented",
|
||||
"Operation add not yet implemented");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
handle_remove_provider (PvManager1 *interface,
|
||||
GDBusMethodInvocation *invocation,
|
||||
const gchar *arg_provider,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_print ("remove provider\n");
|
||||
g_dbus_method_invocation_return_dbus_error (invocation,
|
||||
"org.pulseaudio.Error.NotImplemented",
|
||||
"Operation remove not yet implemented");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
export_server_object (PvDaemon *daemon, GDBusObjectManagerServer *manager)
|
||||
{
|
||||
GDBusObjectSkeleton *skel;
|
||||
|
||||
skel = g_dbus_object_skeleton_new (PV_DBUS_OBJECT_SERVER);
|
||||
{
|
||||
PvDaemon1 *iface;
|
||||
|
||||
iface = pv_daemon1_skeleton_new ();
|
||||
g_signal_connect (iface, "handle-connect-client", (GCallback) handle_connect_client, daemon);
|
||||
g_signal_connect (iface, "handle-disconnect-client", (GCallback) handle_disconnect_client, daemon);
|
||||
pv_daemon1_set_user_name (iface, g_get_user_name ());
|
||||
pv_daemon1_set_host_name (iface, g_get_host_name ());
|
||||
pv_daemon1_set_version (iface, PACKAGE_VERSION);
|
||||
pv_daemon1_set_name (iface, PACKAGE_NAME);
|
||||
g_dbus_object_skeleton_add_interface (skel, G_DBUS_INTERFACE_SKELETON (iface));
|
||||
g_object_unref (iface);
|
||||
}
|
||||
{
|
||||
PvManager1 *iface;
|
||||
|
||||
iface = pv_manager1_skeleton_new ();
|
||||
g_signal_connect (iface, "handle-add-provider", (GCallback) handle_add_provider, daemon);
|
||||
g_signal_connect (iface, "handle-remove-provider", (GCallback) handle_remove_provider, daemon);
|
||||
|
||||
g_dbus_object_skeleton_add_interface (skel, G_DBUS_INTERFACE_SKELETON (iface));
|
||||
g_object_unref (iface);
|
||||
}
|
||||
g_dbus_object_manager_server_export (manager, skel);
|
||||
g_object_unref (skel);
|
||||
}
|
||||
|
||||
static void
|
||||
bus_acquired_handler (GDBusConnection *connection,
|
||||
const gchar *name,
|
||||
gpointer user_data)
|
||||
{
|
||||
PvDaemon *daemon = user_data;
|
||||
PvDaemonPrivate *priv = daemon->priv;
|
||||
|
||||
priv->connection = connection;
|
||||
}
|
||||
|
||||
static void
|
||||
name_acquired_handler (GDBusConnection *connection,
|
||||
const gchar *name,
|
||||
gpointer user_data)
|
||||
{
|
||||
PvDaemon *daemon = user_data;
|
||||
PvDaemonPrivate *priv = daemon->priv;
|
||||
GDBusObjectManagerServer *manager;
|
||||
|
||||
priv->server_manager = manager = g_dbus_object_manager_server_new (PV_DBUS_OBJECT_PREFIX);
|
||||
export_server_object (daemon, manager);
|
||||
g_dbus_object_manager_server_set_connection (manager, connection);
|
||||
}
|
||||
|
||||
static void
|
||||
name_lost_handler (GDBusConnection *connection,
|
||||
const gchar *name,
|
||||
gpointer user_data)
|
||||
{
|
||||
PvDaemon *daemon = user_data;
|
||||
PvDaemonPrivate *priv = daemon->priv;
|
||||
GDBusObjectManagerServer *manager = priv->server_manager;
|
||||
|
||||
g_dbus_object_manager_server_unexport (manager, PV_DBUS_OBJECT_SERVER);
|
||||
g_clear_object (&priv->server_manager);
|
||||
}
|
||||
|
||||
PvDaemon *
|
||||
pv_daemon_new (void)
|
||||
{
|
||||
return g_object_new (PV_TYPE_DAEMON, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
pv_daemon_start (PvDaemon *daemon)
|
||||
{
|
||||
PvDaemonPrivate *priv;
|
||||
|
||||
g_return_if_fail (PV_IS_DAEMON (daemon));
|
||||
|
||||
priv = daemon->priv;
|
||||
g_return_if_fail (priv->id == 0);
|
||||
|
||||
priv->id = g_bus_own_name (G_BUS_TYPE_SESSION,
|
||||
PV_DBUS_SERVICE,
|
||||
G_BUS_NAME_OWNER_FLAGS_REPLACE,
|
||||
bus_acquired_handler,
|
||||
name_acquired_handler,
|
||||
name_lost_handler,
|
||||
daemon,
|
||||
NULL);
|
||||
}
|
||||
|
||||
void
|
||||
pv_daemon_stop (PvDaemon *daemon)
|
||||
{
|
||||
PvDaemonPrivate *priv = daemon->priv;
|
||||
|
||||
g_return_if_fail (PV_IS_DAEMON (daemon));
|
||||
|
||||
g_bus_unown_name (priv->id);
|
||||
priv->id = 0;
|
||||
}
|
||||
|
||||
gchar *
|
||||
pv_daemon_export_uniquely (PvDaemon *daemon, GDBusObjectSkeleton *skel)
|
||||
{
|
||||
g_return_val_if_fail (PV_IS_DAEMON (daemon), NULL);
|
||||
g_return_val_if_fail (G_IS_DBUS_OBJECT_SKELETON (skel), NULL);
|
||||
|
||||
g_dbus_object_manager_server_export_uniquely (daemon->priv->server_manager, skel);
|
||||
|
||||
return g_strdup (g_dbus_object_get_object_path (G_DBUS_OBJECT (skel)));
|
||||
}
|
||||
|
||||
void
|
||||
pv_daemon_unexport (PvDaemon *daemon, const gchar *object_path)
|
||||
{
|
||||
g_return_if_fail (PV_IS_DAEMON (daemon));
|
||||
g_return_if_fail (g_variant_is_object_path (object_path));
|
||||
|
||||
g_dbus_object_manager_server_unexport (daemon->priv->server_manager, object_path);
|
||||
}
|
||||
|
||||
PvSource *
|
||||
pv_daemon_get_source (PvDaemon *daemon, const gchar *name)
|
||||
{
|
||||
PvDaemonPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (PV_IS_DAEMON (daemon), NULL);
|
||||
priv = daemon->priv;
|
||||
|
||||
if (priv->source == NULL) {
|
||||
priv->source = pv_v4l2_source_new (daemon);
|
||||
}
|
||||
return priv->source;
|
||||
}
|
||||
|
||||
G_DEFINE_TYPE (PvDaemon, pv_daemon, G_TYPE_OBJECT);
|
||||
|
||||
static void
|
||||
pv_daemon_finalize (GObject * object)
|
||||
{
|
||||
PvDaemon *daemon = PV_DAEMON_CAST (object);
|
||||
PvDaemonPrivate *priv = daemon->priv;
|
||||
|
||||
g_hash_table_unref (priv->senders);
|
||||
pv_daemon_stop (daemon);
|
||||
|
||||
G_OBJECT_CLASS (pv_daemon_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
pv_daemon_class_init (PvDaemonClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
g_type_class_add_private (klass, sizeof (PvDaemonPrivate));
|
||||
|
||||
gobject_class->finalize = pv_daemon_finalize;
|
||||
}
|
||||
|
||||
static void
|
||||
pv_daemon_init (PvDaemon * daemon)
|
||||
{
|
||||
PvDaemonPrivate *priv = daemon->priv = PV_DAEMON_GET_PRIVATE (daemon);
|
||||
|
||||
priv->senders = g_hash_table_new (g_str_hash, g_str_equal);
|
||||
}
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
/* Pulsevideo
|
||||
* Copyright (C) 2015 Wim Taymans <wim.taymans@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __PV_DAEMON_H__
|
||||
#define __PV_DAEMON_H__
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <gio/gio.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define PV_TYPE_DAEMON (pv_daemon_get_type ())
|
||||
#define PV_IS_DAEMON(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PV_TYPE_DAEMON))
|
||||
#define PV_IS_DAEMON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PV_TYPE_DAEMON))
|
||||
#define PV_DAEMON_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PV_TYPE_DAEMON, PvDaemonClass))
|
||||
#define PV_DAEMON(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PV_TYPE_DAEMON, PvDaemon))
|
||||
#define PV_DAEMON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PV_TYPE_DAEMON, PvDaemonClass))
|
||||
#define PV_DAEMON_CAST(obj) ((PvDaemon*)(obj))
|
||||
#define PV_DAEMON_CLASS_CAST(klass) ((PvDaemonClass*)(klass))
|
||||
|
||||
typedef struct _PvDaemon PvDaemon;
|
||||
typedef struct _PvDaemonClass PvDaemonClass;
|
||||
typedef struct _PvDaemonPrivate PvDaemonPrivate;
|
||||
|
||||
#include "server/pv-source.h"
|
||||
|
||||
#define PV_DBUS_SERVICE "org.pulsevideo"
|
||||
#define PV_DBUS_OBJECT_PREFIX "/org/pulsevideo"
|
||||
#define PV_DBUS_OBJECT_SERVER PV_DBUS_OBJECT_PREFIX "/server"
|
||||
#define PV_DBUS_OBJECT_SOURCE PV_DBUS_OBJECT_PREFIX "/source"
|
||||
#define PV_DBUS_OBJECT_CLIENT PV_DBUS_OBJECT_PREFIX "/client"
|
||||
|
||||
/**
|
||||
* PvDaemon:
|
||||
*
|
||||
* Pulsevideo daemon object class.
|
||||
*/
|
||||
struct _PvDaemon {
|
||||
GObject object;
|
||||
|
||||
PvDaemonPrivate *priv;
|
||||
};
|
||||
|
||||
/**
|
||||
* PvDaemonClass:
|
||||
*
|
||||
* Pulsevideo daemon object class.
|
||||
*/
|
||||
struct _PvDaemonClass {
|
||||
GObjectClass parent_class;
|
||||
};
|
||||
|
||||
/* normal GObject stuff */
|
||||
GType pv_daemon_get_type (void);
|
||||
|
||||
PvDaemon * pv_daemon_new (void);
|
||||
|
||||
void pv_daemon_start (PvDaemon *daemon);
|
||||
void pv_daemon_stop (PvDaemon *daemon);
|
||||
|
||||
gchar * pv_daemon_export_uniquely (PvDaemon *daemon, GDBusObjectSkeleton *skel);
|
||||
void pv_daemon_unexport (PvDaemon *daemon, const gchar *name);
|
||||
|
||||
PvSource * pv_daemon_get_source (PvDaemon *daemon, const gchar *name);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __PV_DAEMON_H__ */
|
||||
|
|
@ -0,0 +1,273 @@
|
|||
/* Pulsevideo
|
||||
* Copyright (C) 2015 Wim Taymans <wim.taymans@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <gio/gunixfdlist.h>
|
||||
|
||||
#include "server/pv-daemon.h"
|
||||
#include "server/pv-source-output.h"
|
||||
#include "client/pv-enumtypes.h"
|
||||
|
||||
#include "dbus/org-pulsevideo.h"
|
||||
|
||||
struct _PvSourceOutputPrivate
|
||||
{
|
||||
PvDaemon *daemon;
|
||||
gchar *object_path;
|
||||
GSocket *socket;
|
||||
};
|
||||
|
||||
#define PV_SOURCE_OUTPUT_GET_PRIVATE(obj) \
|
||||
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), PV_TYPE_SOURCE_OUTPUT, PvSourceOutputPrivate))
|
||||
|
||||
G_DEFINE_TYPE (PvSourceOutput, pv_source_output, G_TYPE_OBJECT);
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_DAEMON,
|
||||
PROP_OBJECT_PATH,
|
||||
PROP_SOCKET,
|
||||
};
|
||||
|
||||
static void
|
||||
pv_source_output_get_property (GObject *_object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
PvSourceOutput *output = PV_SOURCE_OUTPUT (_object);
|
||||
PvSourceOutputPrivate *priv = output->priv;
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_DAEMON:
|
||||
g_value_set_object (value, priv->daemon);
|
||||
break;
|
||||
|
||||
case PROP_OBJECT_PATH:
|
||||
g_value_set_string (value, priv->object_path);
|
||||
break;
|
||||
|
||||
case PROP_SOCKET:
|
||||
g_value_set_object (value, priv->socket);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (output, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pv_source_output_set_property (GObject *_object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
PvSourceOutput *output = PV_SOURCE_OUTPUT (_object);
|
||||
PvSourceOutputPrivate *priv = output->priv;
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_DAEMON:
|
||||
priv->daemon = g_value_dup_object (value);
|
||||
break;
|
||||
|
||||
case PROP_OBJECT_PATH:
|
||||
priv->object_path = g_value_dup_string (value);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (output, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
handle_acquire (PvSourceOutput1 *interface,
|
||||
GDBusMethodInvocation *invocation,
|
||||
GVariant *arg_properties,
|
||||
gpointer user_data)
|
||||
{
|
||||
PvSourceOutput *output = user_data;
|
||||
PvSourceOutputPrivate *priv = output->priv;
|
||||
GUnixFDList *fdlist;
|
||||
GVariantBuilder props;
|
||||
gint fd[2];
|
||||
|
||||
g_variant_builder_init (&props, G_VARIANT_TYPE ("a{sv}"));
|
||||
g_variant_builder_add (&props, "{sv}", "name", g_variant_new_string ("hello"));
|
||||
|
||||
socketpair (AF_UNIX, SOCK_STREAM, 0, fd);
|
||||
priv->socket = g_socket_new_from_fd (fd[0], NULL);
|
||||
g_object_notify (G_OBJECT (output), "socket");
|
||||
|
||||
fdlist = g_unix_fd_list_new ();
|
||||
g_unix_fd_list_append (fdlist, fd[1], NULL);
|
||||
g_dbus_method_invocation_return_value_with_unix_fd_list (invocation,
|
||||
g_variant_new ("(h@a{sv})", 0, g_variant_builder_end (&props)),
|
||||
fdlist);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
stop_transfer (PvSourceOutput *output)
|
||||
{
|
||||
PvSourceOutputPrivate *priv = output->priv;
|
||||
|
||||
if (priv->socket) {
|
||||
g_clear_object (&priv->socket);
|
||||
g_object_notify (G_OBJECT (output), "socket");
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
handle_release (PvSourceOutput1 *interface,
|
||||
GDBusMethodInvocation *invocation,
|
||||
gpointer user_data)
|
||||
{
|
||||
PvSourceOutput *output = user_data;
|
||||
|
||||
stop_transfer (output);
|
||||
|
||||
pv_source_output1_complete_release (interface, invocation);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
output_register_object (PvSourceOutput *output, const gchar *prefix)
|
||||
{
|
||||
PvSourceOutputPrivate *priv = output->priv;
|
||||
PvDaemon *daemon = priv->daemon;
|
||||
GDBusObjectSkeleton *skel;
|
||||
gchar *name;
|
||||
|
||||
name = g_strdup_printf ("%s/output", prefix);
|
||||
skel = g_dbus_object_skeleton_new (name);
|
||||
g_free (name);
|
||||
|
||||
{
|
||||
PvSourceOutput1 *iface;
|
||||
|
||||
iface = pv_source_output1_skeleton_new ();
|
||||
g_signal_connect (iface, "handle-acquire", (GCallback) handle_acquire, output);
|
||||
g_signal_connect (iface, "handle-release", (GCallback) handle_release, output);
|
||||
g_dbus_object_skeleton_add_interface (skel, G_DBUS_INTERFACE_SKELETON (iface));
|
||||
g_object_unref (iface);
|
||||
}
|
||||
|
||||
g_free (priv->object_path);
|
||||
priv->object_path = pv_daemon_export_uniquely (daemon, skel);
|
||||
}
|
||||
|
||||
static void
|
||||
output_unregister_object (PvSourceOutput *output)
|
||||
{
|
||||
PvSourceOutputPrivate *priv = output->priv;
|
||||
PvDaemon *daemon = priv->daemon;
|
||||
|
||||
stop_transfer (output);
|
||||
|
||||
pv_daemon_unexport (daemon, priv->object_path);
|
||||
}
|
||||
|
||||
static void
|
||||
pv_source_output_finalize (GObject * object)
|
||||
{
|
||||
PvSourceOutput *output = PV_SOURCE_OUTPUT (object);
|
||||
PvSourceOutputPrivate *priv = output->priv;
|
||||
|
||||
output_unregister_object (output);
|
||||
g_object_unref (priv->daemon);
|
||||
g_free (priv->object_path);
|
||||
|
||||
G_OBJECT_CLASS (pv_source_output_parent_class)->finalize (object);
|
||||
}
|
||||
static void
|
||||
pv_source_output_constructed (GObject * object)
|
||||
{
|
||||
PvSourceOutput *output = PV_SOURCE_OUTPUT (object);
|
||||
PvSourceOutputPrivate *priv = output->priv;
|
||||
|
||||
output_register_object (output, priv->object_path);
|
||||
|
||||
G_OBJECT_CLASS (pv_source_output_parent_class)->constructed (object);
|
||||
}
|
||||
|
||||
static void
|
||||
pv_source_output_class_init (PvSourceOutputClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
g_type_class_add_private (klass, sizeof (PvSourceOutputPrivate));
|
||||
|
||||
gobject_class->finalize = pv_source_output_finalize;
|
||||
gobject_class->set_property = pv_source_output_set_property;
|
||||
gobject_class->get_property = pv_source_output_get_property;
|
||||
gobject_class->constructed = pv_source_output_constructed;
|
||||
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_DAEMON,
|
||||
g_param_spec_object ("daemon",
|
||||
"Daemon",
|
||||
"The daemon",
|
||||
PV_TYPE_DAEMON,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_OBJECT_PATH,
|
||||
g_param_spec_string ("object-path",
|
||||
"Object Path",
|
||||
"The object path",
|
||||
NULL,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_SOCKET,
|
||||
g_param_spec_object ("socket",
|
||||
"Socket",
|
||||
"The socket with data",
|
||||
G_TYPE_SOCKET,
|
||||
G_PARAM_READABLE |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
}
|
||||
|
||||
static void
|
||||
pv_source_output_init (PvSourceOutput * output)
|
||||
{
|
||||
output->priv = PV_SOURCE_OUTPUT_GET_PRIVATE (output);
|
||||
}
|
||||
|
||||
const gchar *
|
||||
pv_source_output_get_object_path (PvSourceOutput *output)
|
||||
{
|
||||
PvSourceOutputPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (PV_IS_SOURCE_OUTPUT (output), NULL);
|
||||
priv = output->priv;
|
||||
|
||||
return priv->object_path;
|
||||
}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
/* Pulsevideo
|
||||
* Copyright (C) 2015 Wim Taymans <wim.taymans@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __PV_SOURCE_OUTPUT_H__
|
||||
#define __PV_SOURCE_OUTPUT_H__
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define PV_TYPE_SOURCE_OUTPUT (pv_source_output_get_type ())
|
||||
#define PV_IS_SOURCE_OUTPUT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PV_TYPE_SOURCE_OUTPUT))
|
||||
#define PV_IS_SOURCE_OUTPUT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PV_TYPE_SOURCE_OUTPUT))
|
||||
#define PV_SOURCE_OUTPUT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PV_TYPE_SOURCE_OUTPUT, PvSourceOutputClass))
|
||||
#define PV_SOURCE_OUTPUT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PV_TYPE_SOURCE_OUTPUT, PvSourceOutput))
|
||||
#define PV_SOURCE_OUTPUT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PV_TYPE_SOURCE_OUTPUT, PvSourceOutputClass))
|
||||
#define PV_SOURCE_OUTPUT_CAST(obj) ((PvSourceOutput*)(obj))
|
||||
#define PV_SOURCE_OUTPUT_CLASS_CAST(klass) ((PvSourceOutputClass*)(klass))
|
||||
|
||||
typedef struct _PvSourceOutput PvSourceOutput;
|
||||
typedef struct _PvSourceOutputClass PvSourceOutputClass;
|
||||
typedef struct _PvSourceOutputPrivate PvSourceOutputPrivate;
|
||||
|
||||
/**
|
||||
* PvSourceOutput:
|
||||
*
|
||||
* Pulsevideo source output object class.
|
||||
*/
|
||||
struct _PvSourceOutput {
|
||||
GObject object;
|
||||
|
||||
PvSourceOutputPrivate *priv;
|
||||
};
|
||||
|
||||
/**
|
||||
* PvSourceOutputClass:
|
||||
*
|
||||
* Pulsevideo source output object class.
|
||||
*/
|
||||
struct _PvSourceOutputClass {
|
||||
GObjectClass parent_class;
|
||||
};
|
||||
|
||||
/* normal GObject stuff */
|
||||
GType pv_source_output_get_type (void);
|
||||
|
||||
const gchar * pv_source_output_get_object_path (PvSourceOutput *output);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __PV_SOURCE_OUTPUT_H__ */
|
||||
|
|
@ -0,0 +1,288 @@
|
|||
/* Pulsevideo
|
||||
* Copyright (C) 2015 Wim Taymans <wim.taymans@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <gio/gio.h>
|
||||
|
||||
#include "server/pv-source.h"
|
||||
#include "server/pv-daemon.h"
|
||||
|
||||
#include "dbus/org-pulsevideo.h"
|
||||
|
||||
|
||||
#define PV_SOURCE_GET_PRIVATE(obj) \
|
||||
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), PV_TYPE_SOURCE, PvSourcePrivate))
|
||||
|
||||
struct _PvSourcePrivate
|
||||
{
|
||||
PvDaemon *daemon;
|
||||
gchar *object_path;
|
||||
};
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE (PvSource, pv_source, G_TYPE_OBJECT);
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_DAEMON,
|
||||
PROP_OBJECT_PATH
|
||||
};
|
||||
|
||||
static void
|
||||
pv_source_get_property (GObject *_object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
PvSource *source = PV_SOURCE (_object);
|
||||
PvSourcePrivate *priv = source->priv;
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_DAEMON:
|
||||
g_value_set_object (value, priv->daemon);
|
||||
break;
|
||||
|
||||
case PROP_OBJECT_PATH:
|
||||
g_value_set_string (value, priv->object_path);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (source, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pv_source_set_property (GObject *_object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
PvSource *source = PV_SOURCE (_object);
|
||||
PvSourcePrivate *priv = source->priv;
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_DAEMON:
|
||||
priv->daemon = g_value_dup_object (value);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (source, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
static void
|
||||
source_register_object (PvSource *source)
|
||||
{
|
||||
PvSourcePrivate *priv = source->priv;
|
||||
PvDaemon *daemon = priv->daemon;
|
||||
GDBusObjectSkeleton *skel;
|
||||
|
||||
skel = g_dbus_object_skeleton_new (PV_DBUS_OBJECT_SOURCE);
|
||||
{
|
||||
PvSource1 *iface;
|
||||
|
||||
iface = pv_source1_skeleton_new ();
|
||||
g_dbus_object_skeleton_add_interface (skel, G_DBUS_INTERFACE_SKELETON (iface));
|
||||
g_object_unref (iface);
|
||||
}
|
||||
g_free (priv->object_path);
|
||||
priv->object_path = pv_daemon_export_uniquely (daemon, skel);
|
||||
}
|
||||
|
||||
static void
|
||||
source_unregister_object (PvSource *source)
|
||||
{
|
||||
PvSourcePrivate *priv = source->priv;
|
||||
PvDaemon *daemon = priv->daemon;
|
||||
|
||||
pv_daemon_unexport (daemon, priv->object_path);
|
||||
}
|
||||
|
||||
static void
|
||||
pv_source_finalize (GObject * object)
|
||||
{
|
||||
PvSource *source = PV_SOURCE (object);
|
||||
PvSourcePrivate *priv = source->priv;
|
||||
|
||||
source_unregister_object (source);
|
||||
g_object_unref (priv->daemon);
|
||||
g_free (priv->object_path);
|
||||
|
||||
G_OBJECT_CLASS (pv_source_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
pv_source_constructed (GObject * object)
|
||||
{
|
||||
PvSource *source = PV_SOURCE (object);
|
||||
|
||||
source_register_object (source);
|
||||
|
||||
G_OBJECT_CLASS (pv_source_parent_class)->constructed (object);
|
||||
}
|
||||
|
||||
static PvSourceOutput *
|
||||
default_create_source_output (PvSource *source, GVariant *props, const gchar *prefix)
|
||||
{
|
||||
PvSourcePrivate *priv = source->priv;
|
||||
|
||||
return g_object_new (PV_TYPE_SOURCE_OUTPUT, "daemon", priv->daemon, "object-path", prefix, NULL);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
default_release_source_output (PvSource *source, PvSourceOutput *output)
|
||||
{
|
||||
g_object_unref (output);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
pv_source_class_init (PvSourceClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
g_type_class_add_private (klass, sizeof (PvSourcePrivate));
|
||||
|
||||
gobject_class->finalize = pv_source_finalize;
|
||||
gobject_class->set_property = pv_source_set_property;
|
||||
gobject_class->get_property = pv_source_get_property;
|
||||
gobject_class->constructed = pv_source_constructed;
|
||||
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_DAEMON,
|
||||
g_param_spec_object ("daemon",
|
||||
"Daemon",
|
||||
"The daemon",
|
||||
PV_TYPE_DAEMON,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_OBJECT_PATH,
|
||||
g_param_spec_string ("object-path",
|
||||
"Object Path",
|
||||
"The object path",
|
||||
NULL,
|
||||
G_PARAM_READABLE |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
|
||||
klass->create_source_output = default_create_source_output;
|
||||
klass->release_source_output = default_release_source_output;
|
||||
}
|
||||
|
||||
static void
|
||||
pv_source_init (PvSource * source)
|
||||
{
|
||||
source->priv = PV_SOURCE_GET_PRIVATE (source);
|
||||
}
|
||||
|
||||
GVariant *
|
||||
pv_source_get_capabilities (PvSource *source, GVariant *props)
|
||||
{
|
||||
PvSourceClass *klass;
|
||||
GVariant *res;
|
||||
|
||||
g_return_val_if_fail (PV_IS_SOURCE (source), NULL);
|
||||
|
||||
klass = PV_SOURCE_GET_CLASS (source);
|
||||
|
||||
if (klass->get_capabilities)
|
||||
res = klass->get_capabilities (source, props);
|
||||
else
|
||||
res = NULL;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
gboolean
|
||||
pv_source_suspend (PvSource *source)
|
||||
{
|
||||
PvSourceClass *klass;
|
||||
gboolean res;
|
||||
|
||||
g_return_val_if_fail (PV_IS_SOURCE (source), FALSE);
|
||||
|
||||
klass = PV_SOURCE_GET_CLASS (source);
|
||||
|
||||
if (klass->suspend)
|
||||
res = klass->suspend (source);
|
||||
else
|
||||
res = FALSE;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
gboolean
|
||||
pv_source_resume (PvSource *source)
|
||||
{
|
||||
PvSourceClass *klass;
|
||||
gboolean res;
|
||||
|
||||
g_return_val_if_fail (PV_IS_SOURCE (source), FALSE);
|
||||
|
||||
klass = PV_SOURCE_GET_CLASS (source);
|
||||
|
||||
if (klass->resume)
|
||||
res = klass->resume (source);
|
||||
else
|
||||
res = FALSE;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
PvSourceOutput *
|
||||
pv_source_create_source_output (PvSource *source, GVariant *props, const gchar *prefix)
|
||||
{
|
||||
PvSourceClass *klass;
|
||||
PvSourceOutput *res;
|
||||
|
||||
g_return_val_if_fail (PV_IS_SOURCE (source), NULL);
|
||||
|
||||
klass = PV_SOURCE_GET_CLASS (source);
|
||||
|
||||
if (klass->create_source_output)
|
||||
res = klass->create_source_output (source, props, prefix);
|
||||
else
|
||||
res = NULL;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
gboolean
|
||||
pv_source_release_source_output (PvSource *source, PvSourceOutput *output)
|
||||
{
|
||||
PvSourceClass *klass;
|
||||
gboolean res;
|
||||
|
||||
g_return_val_if_fail (PV_IS_SOURCE (source), FALSE);
|
||||
g_return_val_if_fail (PV_IS_SOURCE_OUTPUT (output), FALSE);
|
||||
|
||||
klass = PV_SOURCE_GET_CLASS (source);
|
||||
|
||||
if (klass->release_source_output)
|
||||
res = klass->release_source_output (source, output);
|
||||
else
|
||||
res = FALSE;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
/* Pulsevideo
|
||||
* Copyright (C) 2015 Wim Taymans <wim.taymans@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __PV_SOURCE_H__
|
||||
#define __PV_SOURCE_H__
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _PvSource PvSource;
|
||||
typedef struct _PvSourceClass PvSourceClass;
|
||||
typedef struct _PvSourcePrivate PvSourcePrivate;
|
||||
|
||||
#include "server/pv-daemon.h"
|
||||
#include "server/pv-source-output.h"
|
||||
|
||||
#define PV_TYPE_SOURCE (pv_source_get_type ())
|
||||
#define PV_IS_SOURCE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PV_TYPE_SOURCE))
|
||||
#define PV_IS_SOURCE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PV_TYPE_SOURCE))
|
||||
#define PV_SOURCE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PV_TYPE_SOURCE, PvSourceClass))
|
||||
#define PV_SOURCE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PV_TYPE_SOURCE, PvSource))
|
||||
#define PV_SOURCE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PV_TYPE_SOURCE, PvSourceClass))
|
||||
#define PV_SOURCE_CAST(obj) ((PvSource*)(obj))
|
||||
#define PV_SOURCE_CLASS_CAST(klass) ((PvSourceClass*)(klass))
|
||||
|
||||
/**
|
||||
* PvSource:
|
||||
*
|
||||
* Pulsevideo source object class.
|
||||
*/
|
||||
struct _PvSource {
|
||||
GObject object;
|
||||
|
||||
PvSourcePrivate *priv;
|
||||
};
|
||||
|
||||
/**
|
||||
* PvSourceClass:
|
||||
*
|
||||
* Pulsevideo source object class.
|
||||
*/
|
||||
struct _PvSourceClass {
|
||||
GObjectClass parent_class;
|
||||
|
||||
GVariant * (*get_capabilities) (PvSource *source, GVariant *props);
|
||||
|
||||
gboolean (*suspend) (PvSource *source);
|
||||
gboolean (*resume) (PvSource *source);
|
||||
|
||||
PvSourceOutput * (*create_source_output) (PvSource *source, GVariant *props, const gchar *prefix);
|
||||
gboolean (*release_source_output) (PvSource *source, PvSourceOutput *output);
|
||||
};
|
||||
|
||||
/* normal GObject stuff */
|
||||
GType pv_source_get_type (void);
|
||||
|
||||
PvSource * pv_source_new (PvDaemon *daemon, const gchar *prefix);
|
||||
|
||||
GVariant * pv_source_get_capabilities (PvSource *source, GVariant *props);
|
||||
|
||||
gboolean pv_source_suspend (PvSource *source);
|
||||
gboolean pv_source_resume (PvSource *source);
|
||||
|
||||
PvSourceOutput * pv_source_create_source_output (PvSource *source, GVariant *props, const gchar *prefix);
|
||||
gboolean pv_source_release_source_output (PvSource *source, PvSourceOutput *output);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __PV_SOURCE_H__ */
|
||||
|
|
@ -0,0 +1,128 @@
|
|||
/* Pulsevideo
|
||||
* Copyright (C) 2015 Wim Taymans <wim.taymans@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gio/gio.h>
|
||||
|
||||
#include <client/pv-context.h>
|
||||
#include <client/pv-stream.h>
|
||||
|
||||
#define CAPS "video/x-raw, format=(string)YUY2, width=(int)320, height=(int)240, pixel-aspect-ratio=(fraction)1/1, interlace-mode=(string)progressive, framerate=(fraction)30/1"
|
||||
|
||||
static GMainLoop *loop;
|
||||
|
||||
static void
|
||||
on_socket_notify (GObject *gobject,
|
||||
GParamSpec *pspec,
|
||||
gpointer user_data)
|
||||
{
|
||||
GSocket *socket;
|
||||
GstElement *pipeline, *src;
|
||||
|
||||
g_object_get (gobject, "socket", &socket, NULL);
|
||||
g_print ("got socket %p\n", socket);
|
||||
|
||||
pipeline = gst_parse_launch ("socketsrc name=src ! pvfddepay ! "CAPS" ! videoconvert ! xvimagesink", NULL);
|
||||
src = gst_bin_get_by_name (GST_BIN (pipeline), "src");
|
||||
|
||||
g_object_set (src, "socket", socket, NULL);
|
||||
|
||||
gst_element_set_state (pipeline, GST_STATE_PLAYING);
|
||||
}
|
||||
|
||||
static void
|
||||
on_stream_notify (GObject *gobject,
|
||||
GParamSpec *pspec,
|
||||
gpointer user_data)
|
||||
{
|
||||
PvStreamState state;
|
||||
PvStream *s = user_data;
|
||||
|
||||
g_object_get (gobject, "state", &state, NULL);
|
||||
g_print ("got stream state %d\n", state);
|
||||
|
||||
switch (state) {
|
||||
case PV_STREAM_STATE_ERROR:
|
||||
g_main_loop_quit (loop);
|
||||
break;
|
||||
case PV_STREAM_STATE_READY:
|
||||
pv_stream_start (s, PV_STREAM_MODE_SOCKET);
|
||||
break;
|
||||
case PV_STREAM_STATE_STREAMING:
|
||||
{
|
||||
PvBufferInfo info;
|
||||
|
||||
pv_stream_capture_buffer (s, &info);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
on_state_notify (GObject *gobject,
|
||||
GParamSpec *pspec,
|
||||
gpointer user_data)
|
||||
{
|
||||
PvContextState state;
|
||||
PvContext *c = user_data;
|
||||
|
||||
g_object_get (gobject, "state", &state, NULL);
|
||||
g_print ("got context state %d\n", state);
|
||||
|
||||
switch (state) {
|
||||
case PV_CONTEXT_STATE_ERROR:
|
||||
g_main_loop_quit (loop);
|
||||
break;
|
||||
case PV_CONTEXT_STATE_READY:
|
||||
{
|
||||
PvStream *stream;
|
||||
|
||||
stream = pv_stream_new (c, "test");
|
||||
g_signal_connect (stream, "notify::state", (GCallback) on_stream_notify, stream);
|
||||
g_signal_connect (stream, "notify::socket", (GCallback) on_socket_notify, stream);
|
||||
pv_stream_connect_capture (stream, NULL, 0);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
gint
|
||||
main (gint argc, gchar *argv[])
|
||||
{
|
||||
PvContext *c;
|
||||
|
||||
gst_init (&argc, &argv);
|
||||
|
||||
loop = g_main_loop_new (NULL, FALSE);
|
||||
|
||||
c = pv_context_new ("test-client", NULL);
|
||||
g_signal_connect (c, "notify::state", (GCallback) on_state_notify, c);
|
||||
pv_context_connect(c, PV_CONTEXT_FLAGS_NONE);
|
||||
|
||||
g_main_loop_run (loop);
|
||||
|
||||
g_object_unref (c);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
/* Pulsevideo
|
||||
* Copyright (C) 2015 Wim Taymans <wim.taymans@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <gst/gst.h>
|
||||
|
||||
#include <client/pv-context.h>
|
||||
#include <client/pv-subscribe.h>
|
||||
|
||||
static GMainLoop *loop;
|
||||
|
||||
static void
|
||||
subscription_cb (PvContext *context, PvSubscriptionEvent type, PvSubscriptionFlags flags,
|
||||
const gchar *object_path, gpointer user_data)
|
||||
{
|
||||
g_print ("got event %d %d %s\n", type, flags, object_path);
|
||||
}
|
||||
|
||||
static void
|
||||
on_state_notify (GObject *gobject,
|
||||
GParamSpec *pspec,
|
||||
gpointer user_data)
|
||||
{
|
||||
PvContextState state;
|
||||
PvContext *c = user_data;
|
||||
|
||||
g_object_get (gobject, "state", &state, NULL);
|
||||
g_print ("got state %d\n", state);
|
||||
|
||||
switch (state) {
|
||||
case PV_CONTEXT_STATE_ERROR:
|
||||
g_main_loop_quit (loop);
|
||||
break;
|
||||
case PV_CONTEXT_STATE_READY:
|
||||
g_object_set (c, "subscription-mask", PV_SUBSCRIPTION_FLAGS_ALL, NULL);
|
||||
g_signal_connect (c, "subscription-event", (GCallback) subscription_cb, NULL);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
gint
|
||||
main (gint argc, gchar *argv[])
|
||||
{
|
||||
PvContext *c;
|
||||
|
||||
gst_init (&argc, &argv);
|
||||
|
||||
loop = g_main_loop_new (NULL, FALSE);
|
||||
|
||||
c = pv_context_new ("test-client", NULL);
|
||||
g_signal_connect (c, "notify::state", (GCallback) on_state_notify, c);
|
||||
pv_context_connect(c, PV_CONTEXT_FLAGS_NOFAIL);
|
||||
|
||||
g_main_loop_run (loop);
|
||||
|
||||
g_object_unref (c);
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue