Import Upstream version 1.12.7

This commit is contained in:
wangdi1 2022-07-20 17:35:10 +08:00
commit 7189d70440
178 changed files with 48766 additions and 0 deletions

44
.gitignore vendored Normal file
View File

@ -0,0 +1,44 @@
*.la
*.lo
*.log
*.memlog
*.o
*.swp
*.tar.xz
*.trs
.deps/
.dirstamp
.libs/
Makefile
Makefile.in
aclocal.m4
autom4te.cache/
build-aux/
config.h
config.h.in
config.h.in~
config.log
config.status
configure
libtool
m4/
miracle-dhcp
miracle-sinkctl
miracle-wifictl
miracle-wifid
miracle-uibcctl
miraclectl
miracled
stamp-h1
test-suite.log
test_rtsp
test_valgrind
test_wpas
wpa_cli
wpa_supplicant
CMakeFiles/
cmake_install.cmake
CMakeCache.txt
libmiracle-shared.a
install_manifest.txt
/build/

35
.semaphore/semaphore.yml Normal file
View File

@ -0,0 +1,35 @@
version: v1.0
name: Docker
agent:
machine:
type: e1-standard-2
os_image: ubuntu1804
global_job_config:
secrets:
- name: dockerhub
blocks:
- name: Checkout
task:
jobs:
- name: Checkout
commands:
- checkout
- name: Build
task:
jobs:
- name: Autotools
commands:
- checkout
- docker build -t autotools -f autotools.Dockerfile .
- name: Cmake
commands:
- checkout
- docker build -t cmake -f cmake.Dockerfile .
- name: meson
commands:
- checkout
- docker build -t meson -f meson.Dockerfile .

16
.travis.yml Normal file
View File

@ -0,0 +1,16 @@
language: c
services:
- docker
jobs:
include:
- stage: autotools
script:
docker build -t autotools -f autotools.Dockerfile .
- stage: cmake
script:
docker build -t cmake -f cmake.Dockerfile .
- stage: meson
script:
docker build -t meson -f meson.Dockerfile .

52
CMakeLists.txt Normal file
View File

@ -0,0 +1,52 @@
cmake_minimum_required(VERSION 2.8)
project(Miraclecast)
SET(PACKAGE_NAME kylin-miraclecast)
SET(PACKAGE_VERSION 1)
SET(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}")
SET(CMAKE_BUILD_TYPE "Debug")
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake
${CMAKE_MODULE_PATH})
set(CMAKE_C_FLAGS "-std=gnu11 ${CMAKE_C_FLAGS}")
add_definitions(-D_GNU_SOURCE)
SET(BUILD_BINDIR "${CMAKE_INSTALL_PREFIX}/bin")
OPTION(BUILD_ENABLE_DEBUG "Enable Debug" ON )
OPTION(RELY_UDEV "Rely in udev tag to select device" OFF )
OPTION(BUILD_TESTS "Enable TEST" ON )
OPTION(BUILD_ENABLE_CPPCHECK "Enable CPPCheck static analysis" OFF )
if(BUILD_ENABLE_DEBUG)
add_definitions(-DBUILD_ENABLE_DEBUG)
endif()
set(SYSCONFDIR "/etc" CACHE STRING "system config dir")
set(DATADIR "${CMAKE_INSTALL_PREFIX}/share" CACHE STRING "shared data dir")
find_package(PkgConfig)
pkg_check_modules (GLIB2 REQUIRED glib-2.0)
pkg_check_modules (UDEV REQUIRED libudev)
pkg_check_modules (SYSTEMD REQUIRED libsystemd)
CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/config.h.cmake ${CMAKE_BINARY_DIR}/config.h)
if(BUILD_ENABLE_CPPCHECK)
find_program(CMAKE_C_CPPCHECK NAMES cppcheck)
if (CMAKE_C_CPPCHECK)
list(
APPEND CMAKE_C_CPPCHECK
"--enable=warning"
"--inline-suppr"
"--std=c11"
"-D__SIZEOF_POINTER__=8"
)
endif()
endif()
add_subdirectory(src)
add_subdirectory(res)
add_subdirectory(test)

36
COPYING Normal file
View File

@ -0,0 +1,36 @@
= Authors =
This software was written by:
David Herrmann <dh.herrmann@gmail.com>
= Copyright Notice =
This software is licensed under the terms of the LGPL. Please see each source
file for the related copyright notice and license.
If a file does not contain a copright notice, the following notice shall apply:
MiracleCast - Wifi-Display/Miracast Implementation
Copyright (c) 2013-2014 David Herrmann <dh.herrmann@gmail.com>
MiracleCast 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.
MiracleCast 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 MiracleCast; If not, see <http://www.gnu.org/licenses/>.
== Third-Party Source ==
src/shl_htable.[ch]: Released under the conditions of the LGPLv2+.
Please see LICENSE_htable for more.
src/dhcp/*: Released under the conditions of the GPLv2.
Please see LICENSE_gdhcp for more.

340
LICENSE_gdhcp Normal file
View File

@ -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.

510
LICENSE_htable Normal file
View File

@ -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!

502
LICENSE_lgpl Normal file
View File

@ -0,0 +1,502 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin Street, 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 Street, 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!

24
Makefile.am Normal file
View File

@ -0,0 +1,24 @@
SUBDIRS = src res test
EXTRA_DIST = README.md \
COPYING \
NEWS
ACLOCAL_AMFLAGS = -I m4
.PHONY: lcov genlcov lcov-clean
lcov:
-$(MAKE) $(AM_MAKEFLAGS) -k check
$(MAKE) $(AM_MAKEFLAGS) genlcov
# we have to massage the lcov.info file slightly to hide the effect of libtool
# placing the objects files in the .libs/ directory separate from the *.c
genlcov:
$(LTP) --directory $(top_builddir) --capture --output-file miraclecast-lcov.info --test-name GLIB_PERF --no-checksum
LANG=C $(LTP_GENHTML) --prefix $(top_builddir) --output-directory miraclecast-lcov --title "Miraclecast Code Coverage" --legend --show-details miraclecast-lcov.info
lcov-clean:
-$(LTP) --directory $(top_builddir) -z
-rm -rf miraclecast-lcov.info miraclecast-lcov
-find -name '*.gcda' -print | xargs -Ix rm x

4
NEWS Normal file
View File

@ -0,0 +1,4 @@
= MiracleCast Release News =
CHANGES WITH 1:
* TODO

154
README.md Normal file
View File

@ -0,0 +1,154 @@
# MiracleCast - Wifi-Display/Miracast Implementation
[![Join the chat at https://gitter.im/albfan/miraclecast](https://badges.gitter.im/albfan/miraclecast.svg)](https://gitter.im/albfan/miraclecast?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Semaphore CI Build Status](https://albfan.semaphoreci.com/badges/miraclecast/branches/master.svg?style=shields)](https://albfan.semaphoreci.com/projects/miraclecast)
[![Travis CI Build Status](https://travis-ci.org/albfan/miraclecast.svg?branch=master)](https://travis-ci.org/albfan/miraclecast)
[![Coverage Status](https://coveralls.io/repos/github/albfan/miraclecast/badge.svg?branch=master)](https://coveralls.io/github/albfan/miraclecast?branch=master)
The MiracleCast project provides software to connect external monitors to your system via Wi-Fi. It is compatible to the Wifi-Display specification also known as Miracast. MiracleCast implements the Display-Source as well as Display-Sink side.
The Display-Source side allows you to connect external displays to your system and stream local content to the device. A lot of effort is put into making this as easy as connecting external displays via HDMI.
On the other hand, the Display-Sink side allows you to create wifi-capable external displays yourself. You can use it on your embedded devices or even on full desktops to allow other systems to use your device as external display.
## Requirements
The MiracleCast projects requires the following software to be installed:
- **systemd**: A system management daemon. It is used for device-management (udev), dbus management (sd-bus) and service management.
Systemd >= 221 will work out of the box. For earlier versions systemd must be compiled with --enable-kdbus, even though kdbus isn't used, but only the independent, experimental sd-libraries.
*required*: >=systemd-213
- **glib**: A utility library. Used by the current DHCP implementation. Will be removed once sd-dns gains DHCP-server capabilities.
*required*: ~=glib2-2.38 (might work with older releases, untested..)
- **check**: Test-suite for C programs. Used for optional tests of the MiracleCast code base.
*optional*: ~=check-0.9.11 (might work with older releases, untested..)
- **gstreamer**: MiracleCast rely on gstreamer to show cast its output. You can test if all needed is installed launching [res/test-viewer.sh](https://github.com/albfan/miraclecast/blob/master/res/test-viewer.sh)
- **P2P Wi-Fi device** Although widespread these days, there are some devices not compatible with [Wi-Fi Direct](http://en.wikipedia.org/wiki/Wi-Fi_Direct) (prior know as Wi-Fi P2P). Test yours with [res/test-hardware-capabilities.sh](https://github.com/albfan/miraclecast/blob/master/res/test-hardware-capabilities.sh)
- copy the dbus policy **res/org.freedesktop.miracle.conf** to `/etc/dbus-1/system.d/`
## Build and install
To compile MiracleCast, you can choose from:
- [autotools](http://en.wikipedia.org/wiki/GNU_build_system)
- [cmake](http://en.wikipedia.org/wiki/CMake)
- [meson](http://mesonbuild.com/)
See more info on wiki [Building](https://github.com/albfan/miraclecast/wiki/Building)
## Automatic interface selection with udev
If you want to select the interface to start miraclecast with, add a udev rule with the script [res/write-udev-rule.sh](https://github.com/albfan/miraclecast/blob/master/res/write-udev-rule.sh) and configure miraclecast with
$ ../configure --enable-rely-udev
You can also choose the interface with `--interface` option for miracle-wifid.
## Linux Flavours and general compilation instructions
### Ubuntu
Check your systemd version with:
$ systemctl --version
If you are on 221 or above your systemd has kdbus enabled.
If you are below 221, an alternative repo was created to install systemd with dbus
https://github.com/albfan/systemd-ubuntu-with-dbus
See there was interface changes on systemd 219, if you are below that version, use branch [systemd-219](https://github.com/albfan/miraclecast/tree/systemd-219) to compile miraclecast
> See specific instructions on that repo
### Arch linux
Use existing [AUR package](https://aur.archlinux.org/packages/miraclecast-git/). Remember to enable kdus to systemd-git dependency if you are below 221 systemd.
$ export _systemd_git_kdbus=--enable-kdbus
You can achieve installation using [yaourt](https://wiki.archlinux.org/index.php/Yaourt)
### Other flavours
If you feel confidence enough (since systemd is the entrypoint for an OS) extract instructions from arch linux AUR PKGBUILD:
- [systemd-kdbus](https://aur.archlinux.org/cgit/aur.git/tree/PKGBUILD?h=systemd-kdbus)
- [miraclecast](https://aur.archlinux.org/cgit/aur.git/tree/PKGBUILD?h=miraclecast)
## Documentation
### Steps to use it as sink
1. shutdown wpa_supplicant and NetworkManager
$ systemctl stop NetworkManager.service
$ systemctl stop wpa_supplicant.service
2. launch wifi daemon
$ sudo miracle-wifid &
3. launch sink control (your network card will be detected. here 3)
$ sudo miracle-sinkctl
[ADD] Link: 3
4. run WiFi Display on link:
> run 3
5. Pair your machine with other miracast device (mirroring)
6. See your screen device on this machine
### Steps to use it as peer
1. Repeat steps 1 and 2 from "use as sink"
2. launch wifi control
$ sudo miracle-wifictl
3. Enable visibility for other devices
4. Locate them using scanning
> p2p-scan
5. Apart from list, or show info with peer &lt;mac&gt; there's nothing useful here by now. For a Q&D see [Using as peer](https://github.com/albfan/miraclecast/issues/4)
## UIBC
> The User Input Back Channel (UIBC) is an optional WFD feature that when implemented facilitates communication of user inputs to a User Interface, present at the WFD Sink, to the WFD Source.
To use it just add `--uibc` on `miracle-sinkctl` startup. Single mouse events and key events are implemented.
## Autocompletion
Source [res/miraclecast-completion](https://github.com/albfan/miraclecast/blob/master/res/miraclecast-completion) for autocompletion
## License
This software is licensed under the terms of the GNU-LGPL license. Please see ./COPYING for further information.
## Credits
This software is originally maintained by: David Herrmann dh.herrmann@gmail.com
This fork is maintained by: Alberto Fanjul albertofanjul@gmail.com
If you have any questions, do not hesitate to contact one of the maintainers.
## Additional urls
- Website: http://www.freedesktop.org/wiki/Software/miracle
- Original repo: git://people.freedesktop.org/~dvdhrm/miracle
- Fork repo: https://github.com/albfan/miraclecast
- Technical spec: https://www.wi-fi.org/file/wi-fi-display-technical-specification-v11 (free registration required)

72
autogen.sh Executable file
View File

@ -0,0 +1,72 @@
#!/bin/sh
set -e
oldpwd=$(pwd)
topdir=$(dirname $0)
cd $topdir
#intltoolize --force --automake
autoreconf --force --install --symlink
libdir() {
echo $(cd "$1/$(gcc -print-multi-os-directory)"; pwd)
}
args="\
--sysconfdir=/etc \
--localstatedir=/var \
--libdir=$(libdir /usr/lib) \
"
if [ -f "$topdir/.config.args" ]; then
args="$args $(cat $topdir/.config.args)"
fi
cd $oldpwd
if [ "x$1" = "xc" ]; then
shift
args="$args $@"
$topdir/configure CFLAGS='-g -O0 -ftrapv' $args
make clean
elif [ "x$1" = "xg" ]; then
shift
args="$args $@"
$topdir/configure CFLAGS='-g -O0 -ftrapv' $args
make clean
elif [ "x$1" = "xa" ]; then
shift
args="$args $@"
$topdir/configure CFLAGS='-g -O0 -Wsuggest-attribute=pure -Wsuggest-attribute=const -ftrapv' $args
make clean
elif [ "x$1" = "xl" ]; then
shift
args="$args $@"
$topdir/configure CC=clang CFLAGS='-g -O0 -ftrapv' $args
make clean
elif [ "x$1" = "xs" ]; then
shift
args="$args $@"
scan-build $topdir/configure CFLAGS='-std=gnu99 -g -O0 -ftrapv' $args
scan-build make
else
cat <<EOF
----------------------------------------------------------------
Initialized build system. For a common configuration please run:
----------------------------------------------------------------
$topdir/configure CFLAGS='-g -O0 -ftrapv' $args
or run $0 with param:
- c: compilation
- g: debugging
- a: pure/const warning
- l: clang build
- s: scan-build reporting
EOF
fi

11
autotools.Dockerfile Normal file
View File

@ -0,0 +1,11 @@
FROM docker.io/albfan/miraclecast-ci
COPY . ./
RUN rm -rf build-autotools ; \
mkdir build-autotools; \
cd build-autotools; \
../autogen.sh; \
../configure; \
make; \
make check

9
cmake.Dockerfile Normal file
View File

@ -0,0 +1,9 @@
FROM docker.io/albfan/miraclecast-ci
COPY . ./
RUN rm -rf build-cmake; \
mkdir build-cmake; \
cd build-cmake; \
cmake ..; \
make

29
cmake/FindReadline.cmake Normal file
View File

@ -0,0 +1,29 @@
# from http://websvn.kde.org/trunk/KDE/kdeedu/cmake/modules/FindReadline.cmake
# http://websvn.kde.org/trunk/KDE/kdeedu/cmake/modules/COPYING-CMAKE-SCRIPTS
# --> BSD licensed
#
# GNU Readline library finder
if(READLINE_INCLUDE_DIR AND READLINE_LIBRARY AND NCURSES_LIBRARY)
set(READLINE_FOUND TRUE)
else(READLINE_INCLUDE_DIR AND READLINE_LIBRARY AND NCURSES_LIBRARY)
FIND_PATH(READLINE_INCLUDE_DIR readline/readline.h
/usr/include/readline
)
# 2008-04-22 The next clause used to read like this:
#
# FIND_LIBRARY(READLINE_LIBRARY NAMES readline)
# FIND_LIBRARY(NCURSES_LIBRARY NAMES ncurses )
# include(FindPackageHandleStandardArgs)
# FIND_PACKAGE_HANDLE_STANDARD_ARGS(Readline DEFAULT_MSG NCURSES_LIBRARY READLINE_INCLUDE_DIR READLINE_LIBRARY )
#
# I was advised to modify it such that it will find an ncurses library if
# required, but not if one was explicitly given, that is, it allows the
# default to be overridden. PH
FIND_LIBRARY(READLINE_LIBRARY NAMES readline)
include(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(Readline DEFAULT_MSG READLINE_INCLUDE_DIR READLINE_LIBRARY )
MARK_AS_ADVANCED(READLINE_INCLUDE_DIR READLINE_LIBRARY)
endif(READLINE_INCLUDE_DIR AND READLINE_LIBRARY AND NCURSES_LIBRARY)

18
common.am Normal file
View File

@ -0,0 +1,18 @@
AM_CFLAGS = -Wall \
-pipe \
-fno-common \
-ffast-math \
-fdiagnostics-show-option \
-fno-strict-aliasing \
-fvisibility=hidden \
-ffunction-sections \
-fdata-sections
AM_CPPFLAGS = -include $(top_builddir)/config.h \
-I $(top_srcdir)/src \
-I $(top_srcdir)/src/shared
AM_LDFLAGS = -Wl,--as-needed \
-Wl,--gc-sections \
-Wl,-z,relro \
-Wl,-z,now

8
config.h.cmake Normal file
View File

@ -0,0 +1,8 @@
#ifndef CONFIG_H
#define CONFIG_H
#cmakedefine BUILD_BINDIR "@BUILD_BINDIR@"
#cmakedefine PACKAGE_STRING "@PACKAGE_STRING@"
#endif // CONFIG_H

191
configure.ac Normal file
View File

@ -0,0 +1,191 @@
#
# MiracleCast - build configuration script
# Copyright (c) 2013-2014 David Herrmann <dh.herrmann@gmail.com>
#
AC_PREREQ(2.68)
AC_INIT([miracle],
[1],
[http://www.freedesktop.org/wiki/Software/miracle],
[miracle],
[http://www.freedesktop.org/wiki/Software/miracle])
AC_CONFIG_SRCDIR([src/miracled.h])
AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_HEADER(config.h)
AC_USE_SYSTEM_EXTENSIONS
AC_SYS_LARGEFILE
AC_CANONICAL_HOST
AM_INIT_AUTOMAKE([foreign 1.11 subdir-objects dist-xz no-dist-gzip tar-pax -Wall -Werror -Wno-portability])
AM_SILENT_RULES([yes])
AC_SUBST(PACKAGE_DESCRIPTION, ["Wifi-Display/Miracast Implementation"])
AC_PROG_CC
AC_PROG_CC_C99
AM_PROG_CC_C_O
m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
AC_PROG_SED
AC_PROG_MKDIR_P
AC_PROG_LN_S
AC_PROG_GREP
AC_PROG_AWK
LT_PREREQ(2.2)
LT_INIT
LT_LIB_M
AC_ARG_ENABLE([rely-udev],
AS_HELP_STRING([--enable-rely-udev], [Use tagged device with miraclecast]), AC_DEFINE([RELY_UDEV], [], [Rely on udev to find miraclecast device]))
AC_ARG_ENABLE([log-debug],
AS_HELP_STRING([--disable-log-debug], [Disable log debug]), , AC_DEFINE([BUILD_ENABLE_DEBUG], [], [Enable debug log level]))
#
# Mandatory dependencies
#
m4_ifdef([PKG_CHECK_MODULES], [
PKG_CHECK_MODULES([DEPS], [libudev libsystemd > 219])
PKG_CHECK_MODULES([GLIB], [glib-2.0])
])
AC_CHECK_HEADERS(readline/readline.h,, AC_MSG_ERROR(GNU readline not found))
#
# Test for "check" which we use for our test-suite. If not found, we disable
# all tests.
#
m4_ifdef([PKG_CHECK_MODULES], [
PKG_CHECK_MODULES([CHECK], [check],
[have_check=yes], [have_check=no])
])
AM_CONDITIONAL([BUILD_HAVE_CHECK], [test "x$have_check" = "xyes"])
if test "x$have_check" = "xyes"
then
dnl ************************************
dnl *** Enable lcov coverage reports ***
dnl ************************************
AC_ARG_ENABLE(gcov,
AS_HELP_STRING([--enable-gcov],
[Enable gcov]),
[use_gcov=$enableval], [use_gcov=no])
if test "x$use_gcov" = "xyes"; then
dnl we need gcc:
if test "$GCC" != "yes"; then
AC_MSG_ERROR([GCC is required for --enable-gcov])
fi
dnl Check if ccache is being used
AC_CHECK_PROG(SHTOOL, shtool, shtool)
case `$SHTOOL path $CC` in
*ccache*[)] gcc_ccache=yes;;
*[)] gcc_ccache=no;;
esac
if test "$gcc_ccache" = "yes" && (test -z "$CCACHE_DISABLE" || test "$CCACHE_DISABLE" != "1"); then
AC_MSG_ERROR([ccache must be disabled when --enable-gcov option is used. You can disable ccache by setting environment variable CCACHE_DISABLE=1.])
fi
ltp_version_list="1.6 1.7 1.8 1.10 1.11 1.12"
AC_CHECK_PROG(LTP, lcov, lcov)
AC_CHECK_PROG(LTP_GENHTML, genhtml, genhtml)
if test "$LTP"; then
AC_CACHE_CHECK([for ltp version], glib_cv_ltp_version, [
glib_cv_ltp_version=invalid
ltp_version=`$LTP -v 2>/dev/null | $SED -e 's/^.* //'`
for ltp_check_version in $ltp_version_list; do
if test "$ltp_version" = "$ltp_check_version"; then
glib_cv_ltp_version="$ltp_check_version (ok)"
fi
done
])
else
ltp_msg="To enable code coverage reporting you must have one of the following LTP versions installed: $ltp_version_list"
AC_MSG_ERROR([$ltp_msg])
fi
case $glib_cv_ltp_version in
""|invalid[)]
ltp_msg="You must have one of the following versions of LTP: $ltp_version_list (found: $ltp_version)."
AC_MSG_ERROR([$ltp_msg])
LTP="exit 0;"
;;
esac
if test -z "$LTP_GENHTML"; then
AC_MSG_ERROR([Could not find genhtml from the LTP package])
fi
AC_DEFINE(HAVE_GCOV, 1, [Whether you have gcov])
dnl Remove all optimization flags from CFLAGS
changequote({,})
CFLAGS=`echo "$CFLAGS" | $SED -e 's/-O[0-9]*//g'`
changequote([,])
dnl Add the special gcc flags
CFLAGS="$CFLAGS -O0 -fprofile-arcs -ftest-coverage"
LDFLAGS="$LDFLAGS -lgcov"
fi
fi
#
# Makefile vars
# After everything is configured, we create all makefiles.
#
AC_CONFIG_FILES([Makefile
res/Makefile
src/Makefile
src/ctl/Makefile
src/dhcp/Makefile
src/shared/Makefile
src/wifi/Makefile
src/uibc/Makefile
test/Makefile])
AC_OUTPUT
#
# Configuration output
# Show configuration to the user so they can check whether everything was
# configured as expected.
#
if test "x$have_check" = "xyes"
then
AC_MSG_NOTICE([Build configuration:
prefix: $prefix
exec-prefix: $exec_prefix
bindir: $bindir
libdir: $libdir
includedir: $includedir
Miscellaneous Options:
building tests: $have_check
code coverage: $use_gcov
Compilation
mkdir build && cd build
"${MAKE-make}" to start compilation process
"${MAKE-make}" check to pass test])
else
AC_MSG_NOTICE([Build configuration:
prefix: $prefix
exec-prefix: $exec_prefix
bindir: $bindir
libdir: $libdir
includedir: $includedir
Miscellaneous Options:
building tests: $have_check
Compilation
mkdir build && cd build
"${MAKE-make}" to start compilation process])
fi

8
debian/README.Debian vendored Executable file
View File

@ -0,0 +1,8 @@
miraclecast for Debian
Please edit this to provide information specific to
this miraclecast Debian package.
(Automatically generated by debmake Version 4.3.1)
-- di wang <wangdi1@kylinos.cn> Tue, 30 Mar 2021 10:12:44 +0800

6
debian/changelog vendored Normal file
View File

@ -0,0 +1,6 @@
kylin-miraclecast (1.12.7-ok1) v101; urgency=medium
* Bug号 :
* 需求号:
* 其他 : openkylin 第一版提交,并修改包名
-- wangdi <wangdi1@kylinos.cn> Wed, 20 Jul 2022 17:29:06 +0800

1
debian/compat vendored Executable file
View File

@ -0,0 +1 @@
11

16
debian/control vendored Executable file
View File

@ -0,0 +1,16 @@
Source: kylin-miraclecast
Section: utils
Priority: optional
Maintainer: di wang <wangdi1@kylinos.cn>
Build-Depends: debhelper (>=11~), cmake (>=3.15), libglib2.0-dev, libudev-dev, libsystemd-dev, libreadline-dev, check, libdbus-1-dev, libdbus-glib-1-dev, libgtk-3-dev, libpango1.0-dev, libharfbuzz-dev, libcairo2-dev, libgdk-pixbuf2.0-dev, libatk1.0-dev,qtbase5-dev,libgstreamer1.0-dev,librust-gstreamer-video-sys-dev,qtmultimedia5-dev,libukcc-dev,qttools5-dev-tools,libqt5svg5-dev, libgsettings-qt-dev,libmatekbd-dev,libqt5x11extras5-dev,libxklavier-dev,libkf5screen-dev,libkf5screen-bin,libkf5i18n-dev,libkf5windowsystem-dev,libkf5xmlgui-dev,libkf5globalaccel-dev,qtdeclarative5-dev,libdconf-dev,libasound2-dev,libxml2-dev,libcanberra-dev,libmate-desktop-dev, libx11-dev,libxkbfile-dev,libboost-dev, libxcb-xkb-dev,libpolkit-qt5-1-dev,libpulse-dev, libkf5bluezqt-dev,libpwquality-dev,xserver-xorg-dev,libupower-glib-dev, libpam0g-dev, libopencv-dev,libmatemixer-dev,libkysdk-qtwidgets-dev,pkg-config
Standards-Version: 4.1.4
Homepage: <insert the upstream URL, if relevant>
Package: kylin-miraclecast
Architecture: any
Essential:no
Depends: ${misc:Depends}, ${shlibs:Depends}, wpasupplicant (>=2:2.9-1kylin4.8), udev, network-manager, systemd, libsystemd0, dbus, libdbus-1-3, gstreamer1.0-plugins-bad, gstreamer1.0-plugins-base, gstreamer1.0-plugins-good, gstreamer1.0-libav, gstreamer1.0-tools, gstreamer1.0-x, gstreamer1.0-alsa, gir1.2-gstreamer-1.0, gir1.2-gst-plugins-base-1.0, libgstreamer-gl1.0-0, libgstreamer-plugins-base1.0-0, libgstreamer-plugins-good1.0-0, libgstreamer-plugins-bad1.0-0, libgstreamer1.0-0, gstreamer1.0-vaapi, va-driver-all, ukui-control-center (>=3.1.1+1103),ubuntukylin-theme (>=2.0.81), kylin-miraclecast-frontend
Description: auto-generated package by debmake
This Debian binary package was auto-generated by the
debmake(1) command provided by the debmake package.

3225
debian/copyright vendored Executable file

File diff suppressed because it is too large Load Diff

6
debian/install vendored Normal file
View File

@ -0,0 +1,6 @@
gstplayer-1.0/castplayer /usr/bin/
plugin/projection/translations/zh_CN.qm /usr/share/projection/translations/
plugin/projection/translations/zh_CN.ts /usr/share/projection/translations/
plugin/projection/translations/en_US.qm /usr/share/projection/translations/
plugin/projection/translations/en_US.ts /usr/share/projection/translations/
libprojection.so /usr/share/projection/translations/

17
debian/postinst vendored Executable file
View File

@ -0,0 +1,17 @@
#!/bin/bash
#This is a script executed after package installed
set -e
SO_PATH="/usr/lib/`/usr/bin/dpkg-architecture -qDEB_TARGET_MULTIARCH`/ukui-control-center/libprojection.so"
mv /usr/share/projection/translations/libprojection.so $SO_PATH
#DEBHELPER#
PROG_PNUM=`ps -ef | grep miracle-agent | grep -v grep | awk '{print $2}'`
if [ $PROG_PNUM ];then
if [ $PROG_PNUM -gt 0 ];then
echo "restart miralcecast agent"
kill -9 $PROG_PNUM
fi
fi

4
debian/postrm vendored Normal file
View File

@ -0,0 +1,4 @@
#!/bin/sh
set -e
rm -rf /root/.config/miracast
#DEBHELPER#

10
debian/preinst vendored Executable file
View File

@ -0,0 +1,10 @@
#!/bin/bash
#This is a script executed after package installed
set -e
#path="/usr/lib/`/usr/bin/dpkg-architecture -qDEB_TARGET_MULTIARCH`/ukui-control-center/libprojection.so"
#dpkg-divert --package kylin-miraclecast --rename --divert "$path"".old" --add $path
rm -rf /root/.config/miracast
echo "REMOVE old config path"

35
debian/rules vendored Executable file
View File

@ -0,0 +1,35 @@
#!/usr/bin/make -f
# You must remove unused comment lines for the released package.
#export DH_VERBOSE = 1
#export DEB_BUILD_MAINT_OPTIONS = hardening=+all
#export DEB_CFLAGS_MAINT_APPEND = -Wall -pedantic
#export DEB_LDFLAGS_MAINT_APPEND = -Wl,--as-needed
%:
# dh $@ --buildsystem=cmake
dh $@ --with autoreconf
override_dh_auto_configure:
dh_auto_configure --sourcedirectory=gstplayer-1.0 \
--buildsystem=qmake
dh_auto_configure --sourcedirectory=plugin/projection \
--buildsystem=qmake
dh_auto_configure -O--buildsystem=cmake
override_dh_auto_build:
dh_auto_build --sourcedirectory=gstplayer-1.0 \
--buildsystem=qmake
dh_auto_build --sourcedirectory=plugin/projection \
--buildsystem=qmake
dh_auto_build -O--buildsystem=cmake
override_dh_auto_clean:
dh_auto_clean --sourcedirectory=gstplayer-1.0 \
--buildsystem=qmake
dh_auto_clean --sourcedirectory=plugin/projection \
--buildsystem=qmake
dh_auto_clean -O--buildsystem=cmake
dh_autoreconf_clean -O--buildsystem=cmake
dh_clean -O--buildsystem=cmake
#override_dh_autoreconf:
# dh_autoreconf -- ./autogen.sh
override_dh_installsystemd:
dh_installsystemd --restart-after-upgrade miracle-wifid.service

1
debian/source/format vendored Executable file
View File

@ -0,0 +1 @@
3.0 (quilt)

2
debian/source/local-options vendored Executable file
View File

@ -0,0 +1,2 @@
#abort-on-upstream-changes
#unapply-patches

2
debian/watch vendored Executable file
View File

@ -0,0 +1,2 @@
# You must remove unused comment lines for the released package.
version=3

View File

@ -0,0 +1,54 @@
#-------------------------------------------------
#
# Project created by QtCreator 2019-08-30T14:43:25
#
#-------------------------------------------------
QT += core gui widgets multimedia multimediawidgets dbus
TARGET = castplayer
TEMPLATE = app
# The following define makes your compiler emit warnings if you use
# any feature of Qt which has been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
INCLUDEPATH += /usr/lib/gcc/x86_64-linux-gnu/9/include
TRANSLATIONS += zh_CN.ts \
en_US.ts
# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
CONFIG += c++11 \
link_pkgconfig
PKGCONFIG += gstreamer-1.0 \
gstreamer-video-1.0
SOURCES += \
main.cpp \
mobiletype.cpp \
playwidget.cpp
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
FORMS += \
mobiletype.ui \
playwidget.ui
HEADERS += \
mobiletype.h \
playwidget.h
RESOURCES += \
pic.qrc \
translator.qrc

1
gstplayer-1.0/en_US.qm Normal file
View File

@ -0,0 +1 @@
<クd<>箆!ソ`。スン

122
gstplayer-1.0/en_US.ts Normal file
View File

@ -0,0 +1,122 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="zh_CN">
<context>
<name>MobileType</name>
<message>
<location filename="mobiletype.ui" line="26"/>
<source>MobileType</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="mobiletype.ui" line="50"/>
<source>Mobiletype</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="mobiletype.ui" line="76"/>
<source>huawei</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="mobiletype.ui" line="81"/>
<source>xiaomi</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="mobiletype.ui" line="86"/>
<source>other</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="mobiletype.ui" line="113"/>
<source>Confirm</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="mobiletype.ui" line="132"/>
<source>Ignore</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<location filename="main.cpp" line="90"/>
<source>huawei</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main.cpp" line="94"/>
<source>xiaomi</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main.cpp" line="194"/>
<source>projection</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main.cpp" line="197"/>
<source>Notedevice can not support uibc</source>
<oldsource>Notethe access device does not support control return.</oldsource>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main.cpp" line="198"/>
<source>Can&apos;t be controlled by keyboard/mouse.</source>
<oldsource>Access device cannot be controlled using the keyboard and mouse.</oldsource>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>playWidget</name>
<message>
<location filename="playwidget.ui" line="17"/>
<source>Form</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="playwidget.ui" line="76"/>
<location filename="playwidget.cpp" line="774"/>
<location filename="playwidget.cpp" line="802"/>
<source>SD</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="playwidget.ui" line="96"/>
<source></source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="playwidget.ui" line="116"/>
<source></source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="playwidget.ui" line="136"/>
<source></source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="playwidget.ui" line="156"/>
<source></source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="playwidget.cpp" line="786"/>
<source>HD</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="playwidget.cpp" line="789"/>
<source>warning</source>
<translation></translation>
</message>
<message>
<location filename="playwidget.cpp" line="789"/>
<source>The current device does not support hard decoding</source>
<translation type="unfinished"></translation>
</message>
</context>
</TS>

325
gstplayer-1.0/main.cpp Normal file
View File

@ -0,0 +1,325 @@
#include <glib.h>
#include <gst/gst.h>
#include <gst/video/videooverlay.h>
#include <QApplication>
#include <QWidget>
#include <QtMultimediaWidgets/QVideoWidget>
#include <QTimer>
#include <QDebug>
#include <QCommandLineParser>
#include <QDBusInterface>
#include <QProcess>
#include <QStringList>
#include "playwidget.h"
#include <QTranslator>
#include "mobiletype.h"
#include <signal.h>
#include <iostream>
using namespace std;
static WId winId;
//hardsoft decode by default
static QString decodeFlag="hard";
static bool xvFlags = true; //部分显卡不支持xvimagesink
void my_exit(int arg)
{
cout<<"closed"<<endl;
qDebug()<<"player quit by signal kill term"<<endl;
exit(0);
}
static GstBusSyncReply create_window(GstBus *bus, GstMessage *message, GstPipeline *pipeline)
{
if (!gst_is_video_overlay_prepare_window_handle_message(message))
return GST_BUS_PASS;
qDebug() << "Received bus message";
gst_video_overlay_set_window_handle(GST_VIDEO_OVERLAY(GST_MESSAGE_SRC(message)), winId);
gst_message_unref(message);
return GST_BUS_DROP;
}
static void setenv()
{
QString LIST_VGA = "lspci";
QString output="";
QStringList sl={};
QProcess proc ;
proc.start(LIST_VGA);
proc.waitForFinished();
QString res=proc.readAllStandardOutput();
if(res!=NULL&&res.contains("VGA"))
{
sl=res.split('\n');
for(int i=0;i<sl.size();i++)
{
if(sl[i].contains("VGA"))
{
output+=sl[i]+'\n';
}
}
}
qDebug()<<"set env";
qDebug()<<output;
QString str = "Graphics";
bool UHD = false;
if(output.contains(str))
{
int pos = output.indexOf(str);
QString str1 = output.mid(pos+9,1);
if(str1 == "(")
{
UHD = true;
}
}
if(output.contains("AMD"))
{
//remove hardsoft decode function on AMD Oland VGA
if(output.contains("Oland"))
{
decodeFlag = "kylin";
}
else
{
qputenv("LIBVA_DRIVER_NAME", "radeonsi");
qputenv("GST_VAAPI_ALL_DRIVERS", "1");
}
}
else if(output.contains("Intel"))
{
if(UHD)
{
decodeFlag = "kylin";
}else
{
qputenv("LIBVA_DRIVER_NAME", "i965");
}
}
else
{
decodeFlag = "kylin";
}
if(output.contains("Loongson") || output.contains("Renoir") || output.contains("Zhaoxin") || output.contains("0709")) //部分显卡不支持xvimagesink
{
xvFlags =false;
qDebug()<<"current device cannot use xviamgesink";
}
qDebug()<<decodeFlag;
qDebug()<<"lenove can not support"<<UHD;
}
static void changeMobileType(QString type){
int manufacturer;
qDebug() << type;
if (type == QObject::tr("huawei"))
{
manufacturer = 6;
}
else if (type == QObject::tr("xiaomi"))
{
manufacturer = 7;
}
else
{
manufacturer = 8;
}
QDBusInterface *m_pServiceInterface = new QDBusInterface("org.freedesktop.miracleagent",
"/org/freedesktop/miracleagent",
"org.freedesktop.miracleagent.op",
QDBusConnection::sessionBus());
m_pServiceInterface->call("SetManufacturer",manufacturer);
QString a1=QString("%1").arg(manufacturer);
cout << a1.toLatin1().data() << endl;
}
static void showChangeMobileTypeDialog(){
MobileType * dialog = new MobileType();
QObject::connect(dialog, &MobileType::sendMobileType, [=](QString type){
changeMobileType (type);
});
dialog->exec();
}
// Code to play rtsp stream on qt widgets
int main(int argc, char *argv[])
{
#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
#endif
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
#endif
sigset(SIGTERM,my_exit);
QApplication app(argc, argv);
QTranslator translator;
QLocale locale;
if (locale.language() == QLocale::Chinese){
translator.load(":/zh_CN.qm");
app.installTranslator(&translator);
}
else if (locale.language() == QLocale::English){
translator.load(":/en_US.qm");
app.installTranslator(&translator);
}
app.connect(&app, SIGNAL(lastWindowClosed()), &app, SLOT(quit ()));
setenv();
gst_init (&argc, &argv);
QCommandLineParser parser;
QCommandLineOption option_audio("a","enable audio support");
QCommandLineOption option_scale("s","scale to resolution","split with x","scale");
QCommandLineOption option_debug("d","debug level","debug","1");
QCommandLineOption option_port("p","port for rtsp","port","1991");
QCommandLineOption option_r("r","resolution","split with x","1920x1080");
QCommandLineOption option_uibc("uibc","supported resolutions masks (CEA VESA HH)");
QCommandLineOption option_hidc("hidc","enable hidc control back");
QCommandLineOption option_kylinpc("kylinpc","kylinpc or not");
QCommandLineOption option_manufacturer("m","Confirm mobile type","manufacturer","5");
parser.addHelpOption();
parser.addVersionOption();
parser.addOption(option_audio);
parser.addOption(option_scale);
parser.addOption(option_port);
parser.addOption(option_r);
parser.addOption(option_debug);
parser.addOption(option_uibc);
parser.addOption(option_hidc);
parser.addOption(option_kylinpc);
parser.addOption(option_manufacturer);
parser.process(app);
int audio=0;
int scale=0;
int uibc=1;
int hidc=0;
int resolution=0;
int arg_width=1920;
int arg_height=1080;
int arg_port=888;
int kylinpc = 0;
int manufacturer = 5;
if (parser.isSet(option_audio))
{
audio=1;
}
if (parser.isSet(option_uibc))
{
uibc=1;
}
else
{
QDBusInterface interface( "org.freedesktop.Notifications",
"/org/freedesktop/Notifications",
"org.freedesktop.Notifications",
QDBusConnection::sessionBus());
QString appname = QObject::tr("projection");
quint32 notify_id = 0;
QString app_icon = "kylin-miracast";
QString tilte = QObject::tr("Notedevice can not support uibc");
QString body = QObject::tr("Can't be controlled by keyboard/mouse.");
qint32 timeout = -1;
QStringList arry1;
QVariantMap arry2;
interface.call(QLatin1String("Notify"),appname,notify_id,app_icon,tilte,body,arry1,arry2,timeout);
}
if (parser.isSet(option_hidc))
{
hidc=1;
}
if (parser.isSet(option_r))
{
resolution=1;
QStringList list = parser.value(option_r).split("x");
//**************************************************************
//**************************************************************
//下一行要记得修改哦
arg_width=list[0].toInt();
arg_height=list[1].toInt();
qDebug()<<arg_width <<" "<<arg_height;
}
if (parser.isSet(option_scale))
{
scale=1;
QStringList list = parser.value(option_scale).split("x");
//**************************************************************
//**************************************************************
//下一行要记得修改哦
arg_width=list[0].toInt();
arg_height=list[1].toInt();
}
if (parser.isSet(option_port))
{
arg_port=parser.value(option_port).toInt();
qDebug()<<"port is"<<arg_port;
}
if (parser.isSet(option_debug))
{
qDebug()<<parser.value(option_debug);
}
if (parser.isSet(option_kylinpc))
{
kylinpc = 1;
}
if (parser.isSet(option_manufacturer))
{
manufacturer = parser.value(option_manufacturer).toInt();
qDebug()<<"manufacturer is"<<manufacturer;
if (manufacturer == 5 && kylinpc == 0)
{
showChangeMobileTypeDialog();
}
else
{
QString a1=QString("%1").arg(manufacturer);
cout << a1.toLatin1().data() << endl;
}
}
// prepare the ui
playWidget window;
if (locale.language() == QLocale::Chinese){
window.setWindowTitle("投屏播放器");
}
else if (locale.language() == QLocale::English){
window.setWindowTitle("MiracastPlayer");
}
window.resize(arg_width,arg_height);
window.showFullScreen();
window.setWidgetSize(arg_width,arg_height);
window.setargv( audio, scale, uibc, hidc, resolution, arg_width, arg_height, arg_port,decodeFlag,kylinpc,xvFlags);
window.init_mouse();
window.init_keyboard();
//window.setWindowFlags(Qt::FramelessWindowHint);
window.show();
int ret = app.exec();
window.hide();
return ret;
}

View File

@ -0,0 +1,21 @@
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <glib.h>
#include <gst/gst.h>
#include <gst/video/videooverlay.h>
#include <QWidget>
#include <QTimer>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}

View File

@ -0,0 +1,22 @@
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H

View File

@ -0,0 +1,24 @@
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow" >
<property name="geometry" >
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle" >
<string>MainWindow</string>
</property>
<widget class="QMenuBar" name="menuBar" />
<widget class="QToolBar" name="mainToolBar" />
<widget class="QWidget" name="centralWidget" />
<widget class="QStatusBar" name="statusBar" />
</widget>
<layoutDefault spacing="6" margin="11" />
<pixmapfunction></pixmapfunction>
<resources/>
<connections/>
</ui>

View File

@ -0,0 +1,46 @@
#include "mobiletype.h"
#include "ui_mobiletype.h"
MobileType::MobileType(QWidget *parent) :
QDialog(parent),
ui(new Ui::MobileType)
{
ui->setupUi(this);
setAttribute(Qt::WA_DeleteOnClose);
QPalette pa;
pa.setColor(QPalette::WindowText, Qt::red);
ui->label->setPalette(pa);
QLocale locale;
if (locale.language() == QLocale::Chinese){
ui->ChangeMobileType->setText("请确认设备类型");
ui->ignoreBtn->setText("取消");
ui->label->setText("注意:重新更换设备型号需删除该历史设备记录,先关闭再开启投屏功能。");
ui->label->setWordWrap(true);
setWindowTitle("投屏");
}
else if (locale.language() == QLocale::English){
ui->ChangeMobileType->setText("Please confirm the device type");
ui->ignoreBtn->setText("Cancel");
QString newStrMsg = "Note: to replace the device model again, you need to delete the historical device record. Turn off and then turn on the screen projection function.";
QFontMetrics fontWidth(ui->label->font());//得到每个字符的宽度
QString elideNote = fontWidth.elidedText(newStrMsg, Qt::ElideRight, 429);//最大宽度150像素
ui->label->setText(elideNote);//显示省略好的字符串
ui->label->setToolTip(newStrMsg);//设置tooltips
setWindowTitle("cast");
}
connect(ui->ignoreBtn, &QPushButton::clicked, [=]{
close();
});
connect(ui->confirmBtn, &QPushButton::clicked, [=]{
emit sendMobileType(ui->comboBox->currentText());
close();
});
}
MobileType::~MobileType()
{
delete ui;
}

View File

@ -0,0 +1,27 @@
#ifndef MOBILETYPE_H
#define MOBILETYPE_H
#include <QDialog>
#include <QPainter>
#include <QPainterPath>
namespace Ui {
class MobileType;
}
class MobileType : public QDialog
{
Q_OBJECT
public:
explicit MobileType(QWidget *parent = nullptr);
~MobileType();
private:
Ui::MobileType *ui;
Q_SIGNALS:
void sendMobileType(QString name);
};
#endif // MOBILETYPE_H

245
gstplayer-1.0/mobiletype.ui Normal file
View File

@ -0,0 +1,245 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MobileType</class>
<widget class="QDialog" name="MobileType">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>520</width>
<height>176</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>520</width>
<height>176</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>520</width>
<height>176</height>
</size>
</property>
<property name="windowTitle">
<string>cast</string>
</property>
<property name="windowIcon">
<iconset resource="pic.qrc">
<normaloff>:/src/kylin-projection.svg</normaloff>:/src/kylin-projection.svg</iconset>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<property name="spacing">
<number>0</number>
</property>
<item row="0" column="0">
<layout class="QGridLayout" name="gridLayout">
<property name="spacing">
<number>0</number>
</property>
<item row="0" column="0">
<layout class="QVBoxLayout" name="verticalLayout" stretch="2,3,2">
<property name="spacing">
<number>0</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout" stretch="98,318">
<property name="spacing">
<number>8</number>
</property>
<property name="sizeConstraint">
<enum>QLayout::SetDefaultConstraint</enum>
</property>
<property name="leftMargin">
<number>24</number>
</property>
<property name="topMargin">
<number>8</number>
</property>
<property name="rightMargin">
<number>24</number>
</property>
<property name="bottomMargin">
<number>8</number>
</property>
<item>
<widget class="QLabel" name="ChangeMobileType">
<property name="minimumSize">
<size>
<width>0</width>
<height>30</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>318</width>
<height>30</height>
</size>
</property>
<property name="text">
<string>Please confirm the device type</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="comboBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>98</width>
<height>36</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>318</width>
<height>36</height>
</size>
</property>
<item>
<property name="text">
<string>huawei</string>
</property>
</item>
<item>
<property name="text">
<string>xiaomi</string>
</property>
</item>
<item>
<property name="text">
<string>other</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="leftMargin">
<number>24</number>
</property>
<property name="topMargin">
<number>8</number>
</property>
<property name="rightMargin">
<number>24</number>
</property>
<property name="bottomMargin">
<number>8</number>
</property>
<item>
<widget class="QLabel" name="label">
<property name="minimumSize">
<size>
<width>0</width>
<height>60</height>
</size>
</property>
<property name="text">
<string>Note: to replace the device model again, you need to delete the historical device record. Turn off and then turn on the screen projection function.</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="spacing">
<number>16</number>
</property>
<property name="leftMargin">
<number>24</number>
</property>
<property name="topMargin">
<number>8</number>
</property>
<property name="rightMargin">
<number>24</number>
</property>
<property name="bottomMargin">
<number>8</number>
</property>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="ignoreBtn">
<property name="minimumSize">
<size>
<width>120</width>
<height>33</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>120</width>
<height>33</height>
</size>
</property>
<property name="text">
<string>Cancel</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="confirmBtn">
<property name="minimumSize">
<size>
<width>120</width>
<height>33</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>120</width>
<height>33</height>
</size>
</property>
<property name="text">
<string>Confirm</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
<resources>
<include location="pic.qrc"/>
</resources>
<connections/>
</ui>

6
gstplayer-1.0/pic.qrc Normal file
View File

@ -0,0 +1,6 @@
<RCC>
<qresource prefix="/">
<file>src/kylin-projection.svg</file>
<file>src/kylin-projection.png</file>
</qresource>
</RCC>

1036
gstplayer-1.0/playwidget.cpp Normal file

File diff suppressed because it is too large Load Diff

131
gstplayer-1.0/playwidget.h Normal file
View File

@ -0,0 +1,131 @@
#ifndef PLAYWIDGET_H
#define PLAYWIDGET_H
#include <QWidget>
#include <QDebug>
#include <QTimer>
#include <QMouseEvent>
#include <QPalette>
#include <gst/gst.h>
#include <gst/video/videooverlay.h>
#include <QCloseEvent>
#include <QResizeEvent>
#include <QPushButton>
#include <QVBoxLayout>
namespace Ui {
class playWidget;
}
class playWidget : public QWidget
{
Q_OBJECT
public:
explicit playWidget(QWidget *parent = nullptr);
~playWidget();
void init();
void initUI();
void setWidgetSize(int x, int y);
void init_mouse();
void init_keyboard();
static WId winID;
void setenv();
void preparePipeline();
bool setPlayerPipe(GstElement *pipe);
void setargv(int audio, int scale, int uibc, int hidc, int resolution, int arg_width, int arg_height, int arg_port, QString decodeFlag, int kylinPc, bool xv);
int kylinPc;
private:
Ui::playWidget *ui;
int left_time=0;
int reso=0;
int uibc=1;
int hidc=0;
const int cons_leftBtnPressed=0;
const int cons_noBtnPressed=1;
const int cons_wheelRoll=2; //滚轮滑动
const int cons_keyPressed=2;
const int cons_keyReleased=3;
const int cons_nullBtn=0;
const int cons_leftBtn=1;
const int cons_midBtn=2;
const int cons_rightBtn=4;
int hid_key_event=0;
int hid_mouse_event=1;
int window_width=0;
int window_height=0;
int widget_width=0;
int widget_height=0;
int half_area_width=0;
int half_area_height=0;
int half_def_width=0;
int half_def_height=0;
int min_hor_pos=0;
int max_hor_pos=0;
int min_ver_pos=0;
int max_ver_pos=0;
int uibc_x=-1;
int uibc_y=-1;
int widget_show_flag=1;
int circle_flag=0;
QString decodeFlag="hard";
int audio=0;
int scale=0;
int resolution=0;
int arg_width=1920;
int arg_height=1080;
int arg_port=888;
const gchar*hardPip;
const gchar*softPip;
GstElement *softPipeline;
GstElement *hardPipeline;
GstBus *bus;
GstElement*currentPipe;
QByteArray ba1;
QByteArray ba;
QPushButton *pushButton_allscreen;
QPushButton *pushButton_changeDecode;
QPushButton *pushButton_back;
QPushButton *pushButton_fun;
QPushButton *pushButton_home;
QVBoxLayout*mLayout;
int current_width = 0;
int current_height = 0;
bool xvFlags = true;
bool updateFlag =false;
public slots:
void time_update();
void home_clicked();
void back_clicked();
void fun_clicked();
void screen_clicked();
protected:
void mousePressEvent(QMouseEvent *event);
void mouseReleaseEvent(QMouseEvent *event);
void mouseMoveEvent(QMouseEvent *event);
void mouseDoubleClickEvent(QMouseEvent *event);
void wheelEvent(QWheelEvent * event);
void keyPressEvent(QKeyEvent * event);
void keyReleaseEvent(QKeyEvent * event);
void circleMouse(QMouseEvent *e);
void resizeEvent(QResizeEvent *e);
private slots:
void on_pushButton_allscreen_2_clicked();
void closeEvent(QCloseEvent *event);
};
#endif // PLAYWIDGET_H

View File

@ -0,0 +1,57 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>playWidget</class>
<widget class="QWidget" name="playWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1920</width>
<height>1080</height>
</rect>
</property>
<property name="mouseTracking">
<bool>true</bool>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item row="0" column="0">
<widget class="QWidget" name="widget" native="true">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="font">
<font>
<pointsize>11</pointsize>
</font>
</property>
<property name="mouseTracking">
<bool>true</bool>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

Binary file not shown.

After

Width:  |  Height:  |  Size: 441 B

View File

@ -0,0 +1 @@
<svg id="投屏2.0_复制" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 96 96"><defs><linearGradient id="未命名的渐变_33" x1="48" y1="6" x2="48" y2="90" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#57ccff"/><stop offset="1" stop-color="#3081e2"/></linearGradient></defs><rect x="6" y="6" width="84" height="84" rx="9" fill="url(#未命名的渐变_33)"/><path d="M63.5,62A1.5,1.5,0,1,0,65,63.5,1.5,1.5,0,0,0,63.5,62Z" fill="#fff"/><path d="M69,39a2,2,0,0,1,2,2V65a2,2,0,0,1-2,2H57a2,2,0,0,1-2-2V41a2,2,0,0,1,2-2H69m0-2H57a4,4,0,0,0-4,4V65a4,4,0,0,0,4,4H69a4,4,0,0,0,4-4V41a4,4,0,0,0-4-4Z" fill="#fff"/><path d="M51,62H33.5a1.5,1.5,0,0,0,0,3H51V62Z" fill="#fff"/><polygon points="46 57 42 57 42 63 46 63 46 57 46 57" fill="#fff"/><path d="M26,55a2,2,0,0,1-2-2V31a2,2,0,0,1,2-2H62a2,2,0,0,1,2,2v4h3V31a5,5,0,0,0-5-5H26a5,5,0,0,0-5,5V53a5,5,0,0,0,5,5H51V55Z" fill="#fff"/></svg>

After

Width:  |  Height:  |  Size: 943 B

View File

@ -0,0 +1,6 @@
<RCC>
<qresource prefix="/">
<file>zh_CN.qm</file>
<file>en_US.qm</file>
</qresource>
</RCC>

BIN
gstplayer-1.0/zh_CN.qm Normal file

Binary file not shown.

130
gstplayer-1.0/zh_CN.ts Normal file
View File

@ -0,0 +1,130 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="zh_CN" sourcelanguage="en">
<context>
<name>MobileType</name>
<message>
<source>MobileType</source>
<translation type="vanished"></translation>
</message>
<message>
<location filename="mobiletype.ui" line="14"/>
<source>cast</source>
<translatorcomment></translatorcomment>
<translation></translation>
</message>
<message>
<location filename="mobiletype.ui" line="81"/>
<source>Please confirm the device type</source>
<translation></translation>
</message>
<message>
<location filename="mobiletype.ui" line="107"/>
<source>huawei</source>
<translation></translation>
</message>
<message>
<location filename="mobiletype.ui" line="112"/>
<source>xiaomi</source>
<translation></translation>
</message>
<message>
<location filename="mobiletype.ui" line="117"/>
<source>other</source>
<translation></translation>
</message>
<message>
<location filename="mobiletype.ui" line="147"/>
<source>Note: to replace the device model again, you need to delete the historical device record. Turn off and then turn on the screen projection function.</source>
<oldsource>Note: to replace the mobile phone model again, you need to delete the historical device record. Turn off and then turn on the screen projection function.</oldsource>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="mobiletype.ui" line="198"/>
<source>Cancel</source>
<translation></translation>
</message>
<message>
<location filename="mobiletype.ui" line="217"/>
<source>Confirm</source>
<translation></translation>
</message>
<message>
<source>Save</source>
<translation type="vanished"></translation>
</message>
<message>
<source>Ignore</source>
<translation type="vanished"></translation>
</message>
<message>
<source>Incorrect selection will affect the use</source>
<translation type="vanished">使</translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<location filename="main.cpp" line="118"/>
<source>huawei</source>
<translation></translation>
</message>
<message>
<location filename="main.cpp" line="122"/>
<source>xiaomi</source>
<translation></translation>
</message>
<message>
<location filename="main.cpp" line="234"/>
<source>projection</source>
<translation></translation>
</message>
<message>
<location filename="main.cpp" line="237"/>
<source>Notedevice can not support uibc</source>
<oldsource>Notethe access device does not support control return.</oldsource>
<translation></translation>
</message>
<message>
<location filename="main.cpp" line="238"/>
<source>Can&apos;t be controlled by keyboard/mouse.</source>
<oldsource>Access device cannot be controlled using the keyboard and mouse.</oldsource>
<translation>使</translation>
</message>
</context>
<context>
<name>playWidget</name>
<message>
<location filename="playwidget.ui" line="17"/>
<source>Form</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="playwidget.cpp" line="103"/>
<location filename="playwidget.cpp" line="969"/>
<location filename="playwidget.cpp" line="1001"/>
<source>SD</source>
<translation></translation>
</message>
<message>
<location filename="playwidget.cpp" line="981"/>
<source>HD</source>
<translation></translation>
</message>
<message>
<location filename="playwidget.cpp" line="987"/>
<source>warning</source>
<translation></translation>
</message>
<message>
<location filename="playwidget.cpp" line="987"/>
<source>The current device does not support hard decoding</source>
<translation></translation>
</message>
<message>
<location filename="playwidget.cpp" line="987"/>
<source>Yes</source>
<translation></translation>
</message>
</context>
</TS>

0
m4/.gitkeep Normal file
View File

7
meson.Dockerfile Normal file
View File

@ -0,0 +1,7 @@
FROM docker.io/albfan/miraclecast-ci
COPY . ./
RUN rm -rf build-meson; \
meson build-meson; \
ninja -C build-meson

45
meson.build Normal file
View File

@ -0,0 +1,45 @@
project('Miraclecast',
'c',
version: '1',
meson_version: '>=0.39',
default_options: ['buildtype=debugoptimized', 'c_std=gnu11']
)
add_project_arguments('-D_GNU_SOURCE', language: 'c')
conf_data = configuration_data()
conf_data.set_quoted('BUILD_BINDIR',
join_paths(get_option('prefix'), get_option('bindir'))
)
conf_data.set_quoted('PACKAGE_STRING',
'@0@ @1@'.format(meson.project_name(), meson.project_version())
)
configure_file(output: 'config.h',
configuration: conf_data
)
c_compiler = meson.get_compiler('c')
readline = c_compiler.find_library('readline', required: true)
if readline.found()
add_project_arguments('-DHAVE_READLINE', language: 'c')
endif
if get_option('build-enable-debug')
add_project_arguments('-DBUILD_ENABLE_DEBUG', language: 'c')
endif
if get_option('rely-udev')
add_project_arguments('-DRELY_UDEV', language: 'c')
endif
glib2 = dependency('glib-2.0')
udev = dependency('libudev')
libsystemd = dependency('libsystemd')
subdir('src')
subdir('res')
if get_option('build-tests')
subdir('test')
endif

12
meson_options.txt Normal file
View File

@ -0,0 +1,12 @@
option('build-enable-debug',
type: 'boolean',
value: true,
description: 'Enable Debug')
option('rely-udev',
type: 'boolean',
value: false,
description: 'Rely in udev tag to select device')
option('build-tests',
type: 'boolean',
value: true,
description: 'Enable TEST')

View File

@ -0,0 +1,35 @@
#include "drownlabel.h"
#include "projection.h"
#define ICONSIZE 18,18
DrownLabel::DrownLabel(QWidget * parent) : QLabel(parent)
{
setFixedSize(36,36);
loadPixmap(isChecked);
this->setProperty("useIconHighlightEffect", 0x2);
}
DrownLabel::~DrownLabel()
{
}
void DrownLabel::setDropDownStatus(bool status)
{
isChecked = status;
loadPixmap(isChecked);
}
void DrownLabel::loadPixmap(bool isChecked)
{
if (isChecked) {
setPixmap(QIcon::fromTheme("ukui-down-symbolic").pixmap(ICONSIZE));
} else {
setPixmap(QIcon::fromTheme("ukui-up-symbolic").pixmap(ICONSIZE));
}
}
void DrownLabel::mouseReleaseEvent(QMouseEvent *event)
{
emit labelClicked();
QWidget::mouseReleaseEvent(event);
}

View File

@ -0,0 +1,26 @@
#ifndef DROWNLABEL_H
#define DROWNLABEL_H
#include <QObject>
#include <QLabel>
#include <QWidget>
#include <QMouseEvent>
class DrownLabel : public QLabel
{
Q_OBJECT
public:
explicit DrownLabel(QWidget * parent = nullptr);
~DrownLabel();
void setDropDownStatus(bool status);
bool isChecked = false;
private:
void loadPixmap(bool isChecked);
protected:
virtual void mouseReleaseEvent(QMouseEvent * event);
Q_SIGNALS:
void labelClicked();
};
#endif // DROWNLABEL_H

View File

@ -0,0 +1,9 @@
#LIBINTERFACE_NAME = $$qtLibraryTarget(drownlabel)
SOURCES += \
$$PWD/DrownLabel/drownlabel.cpp \
HEADERS += \
$$PWD/DrownLabel/drownlabel.h \

View File

@ -0,0 +1,111 @@
#include "changeprojectionname.h"
#include "ui_changeprojectionname.h"
#include <QDebug>
//extern void qt_blurImage(QImage &blurImage, qreal radius, bool quality, int transposed);
ChangeProjectionName::ChangeProjectionName(QWidget *parent)
:
QDialog(parent),
ui(new Ui::ChangeProjectionName)
{
ui->setupUi(this);
//setWindowFlags(Qt::FramelessWindowHint | Qt::Tool);
// setWindowFlags(Qt::WindowCloseButtonHint);
// setAttribute(Qt::WA_TranslucentBackground);
setAttribute(Qt::WA_DeleteOnClose);
QPalette pa;
pa.setColor(QPalette::WindowText, Qt::red);
ui->tipLabel_2->setPalette(pa);
ui->lineEdit->setMaxLength(32);
ui->lineEdit->setAttribute(Qt::WA_InputMethodEnabled, false);
ui->saveBtn->setEnabled(false);
QLocale locale;
if (locale.language() == QLocale::English){
QString newStrMsg = "Device Name";
QFontMetrics fontWidth(ui->ChangeProjectionname->font());//得到每个字符的宽度
QString elideNote = fontWidth.elidedText(newStrMsg, Qt::ElideRight, 74);//最大宽度74像素
ui->ChangeProjectionname->setText(elideNote);//显示省略好的字符串
ui->ChangeProjectionname->setToolTip(newStrMsg);//设置tooltips
}
connect(ui->lineEdit, &QLineEdit::textChanged, this, [=](QString txt){
if (txt.toLocal8Bit().length() > 31){
ui->lineEdit->setFocusPolicy(Qt::NoFocus);
QString StrMsg = tr("The length must be 1-32 characters");
QFontMetrics fontWidth(ui->tipLabel_2->font());//得到每个字符的宽度
QString elideNote_2 = fontWidth.elidedText(StrMsg, Qt::ElideRight, 298);//最大宽度74像素
ui->tipLabel_2->setText(elideNote_2);
ui->tipLabel_2->setToolTip(StrMsg);
// ui->tipLabel_2->setText(tr("The length must be 1-32 characters"));
// ui->saveBtn->setEnabled(false);
}else {
ui->tipLabel_2->setText(tr(""));
}
if (!txt.isEmpty()){
ui->saveBtn->setEnabled(true);
} else {
ui->saveBtn->setEnabled(false);
}
});
connect(ui->cancelBtn, &QPushButton::clicked, [=]{
close();
});
connect(ui->saveBtn, &QPushButton::clicked, [=]{
emit sendNewProjectionName(ui->lineEdit->text());
close();
});
}
ChangeProjectionName::~ChangeProjectionName()
{
delete ui;
}
//void ChangeProjectionName::paintEvent(QPaintEvent *event) {
// Q_UNUSED(event)
// QPainter p(this);
// p.setRenderHint(QPainter::Antialiasing);
// QPainterPath rectPath;
// rectPath.addRoundedRect(this->rect().adjusted(10, 10, -10, -10), 6, 6);
// // 画一个黑底
// QPixmap pixmap(this->rect().size());
// pixmap.fill(Qt::transparent);
// QPainter pixmapPainter(&pixmap);
// pixmapPainter.setRenderHint(QPainter::Antialiasing);
// pixmapPainter.setPen(Qt::transparent);
// pixmapPainter.setBrush(Qt::black);
// pixmapPainter.setOpacity(0.65);
// pixmapPainter.drawPath(rectPath);
// pixmapPainter.end();
// // 模糊这个黑底
// QImage img = pixmap.toImage();
// qt_blurImage(img, 10, false, false);
// // 挖掉中心
// pixmap = QPixmap::fromImage(img);
// QPainter pixmapPainter2(&pixmap);
// pixmapPainter2.setRenderHint(QPainter::Antialiasing);
// pixmapPainter2.setCompositionMode(QPainter::CompositionMode_Clear);
// pixmapPainter2.setPen(Qt::transparent);
// pixmapPainter2.setBrush(Qt::transparent);
// pixmapPainter2.drawPath(rectPath);
// // 绘制阴影
// p.drawPixmap(this->rect(), pixmap, pixmap.rect());
// // 绘制一个背景
// p.save();
// p.fillPath(rectPath,palette().color(QPalette::Base));
// p.restore();
//}

View File

@ -0,0 +1,30 @@
#ifndef CHANGEPROJECTIONNAME_H
#define CHANGEPROJECTIONNAME_H
#include <QDialog>
#include <QPainter>
#include <QPainterPath>
namespace Ui {
class ChangeProjectionName;
}
class ChangeProjectionName : public QDialog
{
Q_OBJECT
public:
explicit ChangeProjectionName(QWidget *parent = nullptr);
~ChangeProjectionName();
private:
Ui::ChangeProjectionName *ui;
//protected:
// void paintEvent(QPaintEvent *);
Q_SIGNALS:
void sendNewProjectionName(QString name);
};
#endif // CHANGEUSERNAME_H

View File

@ -0,0 +1,277 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ChangeProjectionName</class>
<widget class="QDialog" name="ChangeProjectionName">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>420</width>
<height>184</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>420</width>
<height>184</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>420</width>
<height>184</height>
</size>
</property>
<property name="windowTitle">
<string>Projection to this pc</string>
</property>
<property name="windowIcon">
<iconset resource="pic.qrc">
<normaloff>:/ukui-control-center.png</normaloff>:/ukui-control-center.png</iconset>
</property>
<property name="sizeGripEnabled">
<bool>false</bool>
</property>
<property name="modal">
<bool>false</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QWidget" name="widget" native="true">
<property name="minimumSize">
<size>
<width>420</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>420</width>
<height>16777215</height>
</size>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>24</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>24</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Minimum</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>16</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="spacing">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="ChangeProjectionname">
<property name="minimumSize">
<size>
<width>74</width>
<height>36</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>74</width>
<height>36</height>
</size>
</property>
<property name="text">
<string>Device Name</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="lineEdit">
<property name="minimumSize">
<size>
<width>298</width>
<height>36</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>298</width>
<height>36</height>
</size>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="spacing">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="tipLabel">
<property name="minimumSize">
<size>
<width>74</width>
<height>36</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>74</width>
<height>36</height>
</size>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="tipLabel_2">
<property name="minimumSize">
<size>
<width>298</width>
<height>36</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>298</width>
<height>36</height>
</size>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_6">
<property name="spacing">
<number>16</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="cancelBtn">
<property name="minimumSize">
<size>
<width>96</width>
<height>36</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>100</width>
<height>33</height>
</size>
</property>
<property name="text">
<string>Cancel</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="saveBtn">
<property name="minimumSize">
<size>
<width>96</width>
<height>36</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>96</width>
<height>36</height>
</size>
</property>
<property name="text">
<string>Save</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Minimum</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>24</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources>
<include location="pic.qrc"/>
</resources>
<connections/>
</ui>

View File

@ -0,0 +1,7 @@
<RCC>
<qresource prefix="/new/prefix1"/>
<qresource prefix="/">
<file>touping.png</file>
<file>ukui-control-center.png</file>
</qresource>
</RCC>

View File

@ -0,0 +1,933 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd.
*
* 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.
*
*/
#include "projection.h"
#include "ui_projection.h"
#include <QProcess>
#include <QMessageBox>
#include <QIcon>
#include <QDebug>
#include <QMouseEvent>
#define ITEMFIXEDHEIGH 58
#define THEME_QT_SCHEMA "org.ukui.style"
#define MODE_QT_KEY "style-name"
#define SYSTEM_CMD_ERROR -1
enum {
NOT_SUPPORT_P2P = 0,
SUPPORT_P2P_WITHOUT_DEV,
SUPPORT_P2P_PERFECT,
OP_NO_RESPONSE,
NO_SERVICE
};
enum {
PROJECTION_RUNNING = 256,
DAEMON_NOT_RUNNING = 512
};
Projection::Projection()
{
qDebug()<<"123456456";
QTranslator *translator = new QTranslator(this);
translator->load("/usr/share/projection/translations/" + QLocale::system().name());
QApplication::installTranslator(translator);
pluginName = tr("Projection");
pluginType = DEVICES;
ui = new Ui::Projection;
pluginWidget = new QWidget;
pluginWidget->setAttribute(Qt::WA_StyledBackground,true);
pluginWidget->setAttribute(Qt::WA_DeleteOnClose);
ui->setupUi(pluginWidget);
QPalette pa;
pa.setColor(QPalette::WindowText, Qt::red);
ui->tipLabel->setPalette(pa);
ui->tipLabel2->setPalette(pa);
ui->tipLabel2->setFixedWidth(ui->widget_7->width()-ui->label_5->width()-48);
projectionBtn = new KSwitchButton(pluginWidget);
pincodeBtn = new KSwitchButton(pluginWidget);
miracastBtn = new KSwitchButton(pluginWidget);
dropDownLabel = new DrownLabel(pluginWidget);
ui->horizontalLayout_12->addWidget(dropDownLabel);
// ui->pinframe->hide();
init_button_status(get_process_status());
// qDebug()<<"---- Projection contructed, then subscribe slot func ";
connect(projectionBtn, SIGNAL(stateChanged(bool)), this, SLOT(projectionButtonClickSlots(bool)));
connect(pincodeBtn, SIGNAL(stateChanged(bool)), this, SLOT(pincodeButtonClickSlots(bool)));
// connect(miracastBtn, SIGNAL(stateChanged(bool)), this, SLOT(miracastsourceButtonClickSlots(bool)));
connect(ui->pushButton, &QPushButton::clicked, this, [=](){
pushButtonClickSlots();
});
connect(dropDownLabel, &DrownLabel::labelClicked, [=](){
debusFileConfig();
onDrownLabelClicked();
});
// m_pin = new QLabel(pluginWidget);
// ui->label->setStyleSheet("QLabel{font-size: 18px; color: palette(windowText);}");
ui->label->setStyleSheet("QLabel{color: palette(windowText);}");
//~ contents_path /projection/Open Projection
ui->titleLabel->setStyleSheet("QLabel{color: palette(windowText);}");
pa.setColor(QPalette::WindowText, Qt::gray);
ui->label_2->setPalette(pa);
ui->label_4->setPalette(pa);
ui->pushButton->setEnabled(false);
ui->pushButton->setStyleSheet("color: gray");
ui->pushButton->setText(tr("Find device"));
ui->titleLabel_3->setStyleSheet("QLabel{color:palette(windowText);}");
m_pServiceInterface = new QDBusInterface("org.freedesktop.miracleagent",
"/org/freedesktop/miracleagent",
"org.freedesktop.miracleagent.op",
QDBusConnection::sessionBus());
QString path=QDir::homePath()+"/.config/miracast.ini";
QSettings *setting=new QSettings(path,QSettings::IniFormat);
setting->beginGroup("projection");
bool bo=setting->contains("host");
qDebug()<<bo<<"bo";
if (!bo) {
QDBusInterface *hostInterface = new QDBusInterface("org.freedesktop.hostname1",
"/org/freedesktop/hostname1",
"org.freedesktop.hostname1",
QDBusConnection::systemBus());
hostName = hostInterface->property("Hostname").value<QString>();
setting->setValue("host",hostName);
setting->sync();
setting->endGroup();
initComponent();
}else {
hostName = setting->value("host").toString();
}
//ui->projectionNameWidget->setFixedHeight(40);
// setLabelText(ui->projectionName,hostName);
QFontMetrics fontMetrics(ui->projectionName->font());
int fontSize = fontMetrics.width(hostName);
if((ui->widget_9->width()-ui->titleLabel->width()-projectionBtn->width()-46) <= fontSize){
ui->projectionName->setFixedWidth(ui->widget_9->width()-ui->titleLabel->width()-projectionBtn->width()-46);
}
if((ui->widget_9->width()-ui->titleLabel->width()-projectionBtn->width()-46) > fontSize){
ui->projectionName->setFixedWidth(fontSize);
}
ui->projectionName->setText(hostName);
getSystemFontFamily();//建立GSetting监听系统字体
ui->projectionNameChange->setProperty("useIconHighlightEffect", 0x8);
ui->projectionNameChange->setPixmap(QIcon::fromTheme("document-edit-symbolic").pixmap(ui->projectionNameChange->size()));
ui->projectionNameWidget->installEventFilter(this);
ui->horizontalLayout->addWidget(projectionBtn);
ui->horizontalLayout_17->addWidget(pincodeBtn);
ui->horizontalLayout_6->addWidget(miracastBtn);
initComponent();
debusFileConfig();
ui->widget_4->installEventFilter(this);
ui->widget_5->installEventFilter(this);
ui->widget_6->installEventFilter(this);
ui->widget_7->installEventFilter(this);
ui->widget_9->installEventFilter(this);
QLocale locale;
if (locale.language() == QLocale::English){
connect(this,&Projection::resize,[=](){
setLabelText(ui->label_2,"Wireless LAN connection may be interrupted during projection.");
setLabelText(ui->titleLabel_3,"You need to match the PIN code when projecting the screen to the pc");
setLabelText(ui->label_3,"Open(PIN authentication is not supported temporarily.)");
setLabelText(ui->label_4,"When enabled,the project to this PC feature stops.");
});
}
}
void Projection::debusFileConfig()
{
QDBusInterface*mInterface = new QDBusInterface("org.freedesktop.miracle.wifi",
"/org/freedesktop/miracle/wifi/ui",
"org.freedesktop.miracle.wifi.ui",
QDBusConnection::systemBus());
QDBusMessage result = mInterface->call("QueryConnectedDevice");
qDebug()<<"----------"<<result;
deleteAllitemsOfLayout( ui->verticalLayout_2);
QList<QVariant> outArgs = result.arguments();
QVariant first = outArgs.at(0);
QMap<QString,QString>deviceName;
const QDBusArgument &dbusArgs = first.value<QDBusArgument>();
dbusArgs.beginMap();
while (!dbusArgs.atEnd()) {
QString key;
QString value;
dbusArgs.beginMapEntry();
dbusArgs >> key >> value ;
qDebug() << key<< "数值" <<value;
deviceName.insert(key,value);
dbusArgs.endMapEntry();
}
dbusArgs.endMap();
QMap<QString, QString>::iterator iter = deviceName.begin();
while (iter != deviceName.end())
{
QString value = iter.value();
QHBoxLayout *addLyt = new QHBoxLayout;
addLyt->setContentsMargins(0,17,0,17);
QLabel *iconLabel = new QLabel(ui->widget_2);
QLabel *textLabel = new QLabel(ui->widget_2);
QPushButton *iconBtn = new QPushButton(ui->widget_2);
textLabel->setText(iter.key());
iconLabel->setPixmap(QIcon::fromTheme("phone-apple-iphone-symbolic").pixmap(QSize(16,16)));
iconLabel->setProperty("useIconHighlightEffect", 0x8);
iconBtn->setMaximumSize(QSize(36,36));
iconBtn->setIconSize(QSize(16, 16));
iconBtn->setIcon(QIcon::fromTheme("edit-delete-symbolic"));
iconBtn->setProperty("useIconHighlightEffect", 0x8);
iconBtn->setProperty("isWindowButton", 0x1);
iconBtn->setFlat(true);
QPalette paletteLan = iconBtn->palette();
paletteLan.setColor(QPalette::Highlight, Qt::transparent);
paletteLan.setBrush(QPalette::Button, QBrush(QColor(1,1,1,0)));
iconBtn->setPalette(paletteLan);
addLyt->addItem(new QSpacerItem(16,10,QSizePolicy::Fixed));
addLyt->addWidget(iconLabel);
addLyt->addItem(new QSpacerItem(13,10,QSizePolicy::Fixed));
addLyt->addWidget(textLabel);
addLyt->addItem(new QSpacerItem(712,10,QSizePolicy::Expanding));
addLyt->addWidget(iconBtn);
addLyt->addItem(new QSpacerItem(16,10,QSizePolicy::Fixed));
QFrame *line = new QFrame(ui->widget_2);
line->setLineWidth(0);
line->setFixedHeight(1);
line->setFrameShape(QFrame::Shape::HLine);
line->setStyleSheet("color: rgb(244, 244, 244);opacity:1;");
ui->verticalLayout_2->addWidget(line);
ui->verticalLayout_2->addLayout(addLyt);
if (iter == deviceName.begin()){
delete line;
}
connect(iconBtn, &QPushButton::clicked, this, [=] {
QDBusInterface*mInterface = new QDBusInterface("org.freedesktop.miracle.wifi",
"/org/freedesktop/miracle/wifi/ui",
"org.freedesktop.miracle.wifi.ui",
QDBusConnection::systemBus());
QDBusMessage result = mInterface->call("DeleteConnectedDevice",value);
QList<QVariant> outArgs = result.arguments();
bool res = outArgs.at(0).value<int>();
if (!res){
debusFileConfig();
}
});
iter++;
}
ui->widget_2->update();
}
void Projection::deleteAllitemsOfLayout(QLayout *layout)
{
QLayoutItem *child;
while ((child = layout->takeAt(0)) != nullptr)
{
///setParent为NULL防止删除之后界面不消失
if(child->widget())
{
child->widget()->setParent(nullptr);
}else if(child->layout()){
deleteAllitemsOfLayout(child->layout());
}
delete child;
}
}
void Projection::changeProjectionName(QString name){
qDebug() << name;
QString path=QDir::homePath()+"/.config/miracast.ini";
QSettings *setting=new QSettings(path,QSettings::IniFormat);
setting->beginGroup("projection");
setting->setValue("host",name);
setting->sync();
setting->endGroup();
m_pServiceInterface->call("UiSetName",name);
QFontMetrics fontMetrics(ui->projectionName->font());
int fontSize = fontMetrics.width(name);
if((ui->widget_9->width()-ui->titleLabel->width()-projectionBtn->width()-46) <= fontSize){
ui->projectionName->setFixedWidth(ui->widget_9->width()-ui->titleLabel->width()-projectionBtn->width()-46);
}
if((ui->widget_9->width()-ui->titleLabel->width()-projectionBtn->width()-46) > fontSize){
ui->projectionName->setFixedWidth(fontSize);
}
// setLabelText(ui->projectionName,name);
ui->projectionName->setText(name);
}
void Projection::getSystemFontFamily()
{
const QByteArray id("org.ukui.style");
QGSettings * fontSetting = new QGSettings(id, QByteArray(), this);
connect(fontSetting, &QGSettings::changed,[=](QString key) {
if ("systemFont" == key || "systemFontSize" ==key) {
QString path=QDir::homePath()+"/.config/miracast.ini";
QSettings *setting=new QSettings(path,QSettings::IniFormat);
setting->beginGroup("projection");
QString name = setting->value("host").toString();
setting->sync();
setting->endGroup();
QFontMetrics fontMetrics(ui->projectionName->font());
int fontSize = fontMetrics.width(name);
if((ui->widget_9->width()-ui->titleLabel->width()-projectionBtn->width()-46) <= fontSize){
ui->projectionName->setFixedWidth(ui->widget_9->width()-ui->titleLabel->width()-projectionBtn->width()-46);
}
if((ui->widget_9->width()-ui->titleLabel->width()-projectionBtn->width()-46) > fontSize){
ui->projectionName->setFixedWidth(fontSize);
}
// setLabelText(ui->projectionName,name);
ui->projectionName->setText(name);
}
});
}
void Projection::showChangeProjectionNameDialog(){
ChangeProjectionName * dialog = new ChangeProjectionName();
connect(dialog, &ChangeProjectionName::sendNewProjectionName, [=](QString name){
changeProjectionName(name);
});
dialog->exec();
}
bool Projection::getWifiStatus() {
QDBusInterface interface( "org.freedesktop.NetworkManager",
"/org/freedesktop/NetworkManager",
"org.freedesktop.DBus.Properties",
QDBusConnection::systemBus() );
// 获取当前wifi是否打开
QDBusReply<QVariant> m_result = interface.call("Get", "org.freedesktop.NetworkManager", "WirelessEnabled");
if (m_result.isValid()) {
bool status = m_result.value().toBool();
return status;
} else {
qDebug()<<"org.freedesktop.NetworkManager get invalid"<<endl;
return false;
}
}
void Projection::setWifiStatus(bool status) {
QString wifiStatus = status ? "on" : "off";
QString program = "nmcli";
QStringList arg;
arg << "radio" << "wifi" << wifiStatus;
QProcess *nmcliCmd = new QProcess(this);
nmcliCmd->start(program, arg);
nmcliCmd->waitForStarted();
}
void Projection::setLabelText(QLabel *label, QString text)
{
QFontMetrics fontMetrics(label->font());
int fontSize = fontMetrics.width(text);
if (fontSize > label->width()) {
label->setText(fontMetrics.elidedText(text, Qt::ElideRight, label->width()));
label->setToolTip(text);
} else {
label->setText(text);
label->setToolTip("");
}
}
bool Projection::eventFilter(QObject *watched, QEvent *event){
QLocale locale;
QMouseEvent * mouseEvent = static_cast<QMouseEvent *>(event);
if (watched == ui->projectionNameWidget){
if (event->type() == QEvent::MouseButtonPress){
if (mouseEvent->button() == Qt::LeftButton ){
showChangeProjectionNameDialog();
}
}
}
else if (watched == ui->widget_9 ) {
if (event->type() == QEvent::Resize) {
QFontMetrics fontMetrics(ui->projectionName->font());
int fontSize = fontMetrics.width(ui->projectionName->text());
if((ui->widget_9->width()-ui->titleLabel->width()-projectionBtn->width()-46) <= fontSize){
ui->projectionName->setFixedWidth(ui->widget_9->width()-ui->titleLabel->width()-projectionBtn->width()-46);
emit resize();
}
if((ui->widget_9->width()-ui->titleLabel->width()-projectionBtn->width()-46) > fontSize){
ui->projectionName->setFixedWidth(fontSize);
emit resize();
}
ui->label_2->setFixedWidth(ui->widget_9->width()-106);
emit resize();
}
}
else if (watched == ui->widget_4 ) {
if (event->type() == QEvent::Resize) {
ui->titleLabel_3->setFixedWidth(ui->widget_4->width()-106);
emit resize();
}
}
else if (watched == ui->widget_5 ) {
if (event->type() == QEvent::Resize) {
ui->label_3->setFixedWidth(ui->widget_5->width()-246);
ui->label_4->setFixedWidth(ui->widget_5->width()-246);
emit resize();
}
}
else if (watched == ui->widget_6 ) {
if (event->type() == QEvent::Resize) {
ui->tipLabel->setFixedWidth(ui->widget_5->width()-256);
emit resize();
}
}
else if (watched == ui->widget_7 ) {
if (event->type() == QEvent::Resize && locale.language() == QLocale::English) {
ui->tipLabel2->setFixedWidth(ui->widget_5->width()-326);
emit resize();
}
else if (event->type() == QEvent::Resize && locale.language() == QLocale::Chinese) {
ui->tipLabel2->setFixedWidth(ui->widget_5->width()-ui->label_5->width()-48);
}
}
return QObject::eventFilter(watched, event);
}
void Projection::onDrownLabelClicked()
{
if (dropDownLabel->isChecked) {
ui->widget_2->hide();
dropDownLabel->setDropDownStatus(false);
} else {
ui->widget_2->show();
dropDownLabel->setDropDownStatus(true);
}
}
void Projection::catchsignal()
{
while (1)
{
m_pServiceInterface = new QDBusInterface("org.freedesktop.miracle.wifi",
"/org/freedesktop/miracle/wifi/ui",
"org.freedesktop.miracle.wifi.ui",
QDBusConnection::systemBus());
if (m_pServiceInterface->isValid()) {
connect(m_pServiceInterface,SIGNAL(PinCode(QString, QString)),this,SLOT(projectionPinSlots(QString,QString)));
return;
}else {
delete m_pServiceInterface;
delaymsec(1000);
}
}
\
}
void Projection::delaymsec(int msec)
{
QTime dieTime = QTime::currentTime().addMSecs(msec);
while( QTime::currentTime() < dieTime )
QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
}
Projection::~Projection()
{
delete ui;
delete m_pServiceInterface;
}
QString Projection::plugini18nName(){
QFile server("/usr/bin/miracle-wifid");
QFile agent("/usr/bin/miracle-agent");
int projectionstatus;
QDBusMessage result = m_pServiceInterface->call("PreCheck");
QList<QVariant> outArgs = result.arguments();
projectionstatus = outArgs.at(0).value<int>();
if(!server.exists() || !agent.exists() || NO_SERVICE == projectionstatus)
return NULL;
return pluginName;
}
int Projection::pluginTypes(){
return pluginType;
}
int Projection::get_process_status(void)
{
int res;
do{
res = system("checkDaemonRunning.sh");
}while(SYSTEM_CMD_ERROR == res);
return res;
}
int Projection::get_process_source_status(void)
{
QString path=QDir::homePath()+"/.config/miracastsource.ini";
QSettings *setting=new QSettings(path,QSettings::IniFormat);
setting->beginGroup("projection");
QString method;
bool bo=setting->contains("miracastsource");
if (!bo) {
method = "false";
return 0;
}else {
method = setting->value("miracastsource").toString();
if (method == "true")
{
return 1;
}
else
{
return 0;
}
}
}
void Projection::init_button_status(int status)
{
// qDebug()<<"---- button init status "<<status;
if (status == PROJECTION_RUNNING) {
projectionBtn->setChecked(true);
}
else {
projectionBtn->setChecked(false);//projection not switch-on, or daemon programs not running at all
}
}
void Projection::init_source_button_status(int status)
{
// qDebug()<<"---- button init status "<<status;
if (status == 1) {
// miracastBtn->setChecked(true);
}
else {
// miracastBtn->setChecked(false);//projection not switch-on, or daemon programs not running at all
}
}
int Projection::get_pin_button_status(void)
{
QString path=QDir::homePath()+"/.config/miracast.ini";
QSettings *setting=new QSettings(path,QSettings::IniFormat);
setting->beginGroup("projection");
QString method;
bool bo=setting->contains("config_method");
if (!bo) {
method = "display";
m_pServiceInterface->call("UiSetConfigMethods","display");
return 1;
}else {
method = setting->value("config_method").toString();
m_pServiceInterface->call("UiSetConfigMethods",method);
if (method == "display")
{
return 1;
}
else
{
return 0;
}
}
}
void Projection::init_pin_button_status(int status)
{
qDebug() << status;
if (status) {
pincodeBtn->setChecked(true);
}
else {
pincodeBtn->setChecked(false);
}
}
QWidget *Projection::pluginUi(){
int res;
int projectionstatus;
int source_res;
int pin_res;
res = get_process_status();
source_res=get_process_source_status();
pin_res = get_pin_button_status();
init_button_status(res);
init_pin_button_status(pin_res);
init_source_button_status(source_res);
if (res == DAEMON_NOT_RUNNING){
projectionstatus = NO_SERVICE;
}
else{
QDBusMessage result = m_pServiceInterface->call("PreCheck");
QList<QVariant> outArgs = result.arguments();
projectionstatus = outArgs.at(0).value<int>();
qDebug() << "---->" << projectionstatus;
}
ui->widget_3->show();
ui->widget_4->show();
ui->widget_5->hide();
ui->widget_6->show();
ui->widget_7->hide();
ui->widget_9->show();
ui->label->show();
QLocale locale;
if (locale.language() == QLocale::Chinese){
ui->tipLabel->setText(tr("(No wireless network card is detected or the network card driver does not support it.)"));
ui->tipLabel2->setText(tr("(No wireless network card is detected or the network card driver does not support it.)"));
}
else if (locale.language() == QLocale::English){
setLabelText(ui->tipLabel,"(No wireless network card is detected or the network card driver does not support it.)");
setLabelText(ui->tipLabel2,"(No wireless network card is detected or the network card driver does not support it.)");
connect(this,&Projection::resize,[=](){
setLabelText(ui->tipLabel,"(No wireless network card is detected or the network card driver does not support it.)");
setLabelText(ui->tipLabel2,"(No wireless network card is detected or the network card driver does not support it.)");
});
}
ui->tipLabel->show();
ui->tipLabel2->show();
if (dropDownLabel->isChecked){
ui->widget_2->show();
}
else{
ui->widget_2->hide();
}
//First, we check whether service process is running
if (NO_SERVICE == projectionstatus) {
QLocale locale;
if (locale.language() == QLocale::Chinese){
ui->tipLabel->setText(tr("(No wireless network card is detected or the network card driver does not support it.)"));
ui->tipLabel2->setText(tr("(No wireless network card is detected or the network card driver does not support it.)"));
}
else if (locale.language() == QLocale::English){
setLabelText(ui->tipLabel,"(No wireless network card is detected or the network card driver does not support it.)");
setLabelText(ui->tipLabel2,"(No wireless network card is detected or the network card driver does not support it.)");
connect(this,&Projection::resize,[=](){
setLabelText(ui->tipLabel,"(No wireless network card is detected or the network card driver does not support it.)");
setLabelText(ui->tipLabel2,"(No wireless network card is detected or the network card driver does not support it.)");
});
}
ui->tipLabel->show();
ui->tipLabel2->show();
projectionBtn->setChecked(false);
// miracastBtn->setChecked(false);
projectionBtn->setCheckable(false);
// miracastBtn->setCheckable(false);
}
//Then let's check whether hardware is ok
else if (NOT_SUPPORT_P2P == projectionstatus) {
projectionBtn->setChecked(false);
// miracastBtn->setChecked(false);
projectionBtn->setCheckable(false);
// miracastBtn->setCheckable(false);
}
else if (SUPPORT_P2P_PERFECT == projectionstatus) {
if(getWifiStatus())
{
qDebug()<<"wifi is on now";
ui->tipLabel->hide();
ui->tipLabel2->hide();
projectionBtn->setCheckable(true);
// miracastBtn->setCheckable(true);
}
else
{
qDebug()<<"wifi is off now";
QLocale locale;
if (locale.language() == QLocale::Chinese){
ui->tipLabel->setText(tr("(WLAN is not turned on. You need to turn on WLAN to use this function.)"));
ui->tipLabel2->setText(tr("(WLAN is not turned on. You need to turn on WLAN to use this function.)"));
}
else if (locale.language() == QLocale::English){
setLabelText(ui->tipLabel,"(WLAN is not turned on. You need to turn on WLAN to use this function.)");
setLabelText(ui->tipLabel2,"(WLAN is not turned on. You need to turn on WLAN to use this function.)");
connect(this,&Projection::resize,[=](){
setLabelText(ui->tipLabel,"(WLAN is not turned on. You need to turn on WLAN to use this function.)");
setLabelText(ui->tipLabel2,"(WLAN is not turned on. You need to turn on WLAN to use this function.)");
});
}
ui->tipLabel->show();
ui->tipLabel2->show();
projectionBtn->setChecked(false);
// miracastBtn->setChecked(false);
projectionBtn->setCheckable(false);
// miracastBtn->setCheckable(false);
ui->widget_6->update();
ui->widget_7->update();
}
}
else if (SUPPORT_P2P_WITHOUT_DEV == projectionstatus) {
if(getWifiStatus())
{
qDebug()<<"wifi is on now";
ui->tipLabel->hide();
ui->tipLabel2->show();
projectionBtn->setCheckable(true);
// miracastBtn->setCheckable(false);
}
else
{
qDebug()<<"wifi is off now";
QLocale locale;
if (locale.language() == QLocale::Chinese){
ui->tipLabel->setText(tr("(WLAN is not turned on. You need to turn on WLAN to use this function.)"));
ui->tipLabel2->setText(tr("(WLAN is not turned on. You need to turn on WLAN to use this function.)"));
}
else if (locale.language() == QLocale::English){
setLabelText(ui->tipLabel,"(WLAN is not turned on. You need to turn on WLAN to use this function.)");
setLabelText(ui->tipLabel2,"(WLAN is not turned on. You need to turn on WLAN to use this function.)");
connect(this,&Projection::resize,[=](){
setLabelText(ui->tipLabel,"(WLAN is not turned on. You need to turn on WLAN to use this function.)");
setLabelText(ui->tipLabel2,"(WLAN is not turned on. You need to turn on WLAN to use this function.)");
});
}
ui->tipLabel->show();
ui->tipLabel2->show();
projectionBtn->setChecked(false);
projectionBtn->setCheckable(false);
// miracastBtn->setCheckable(false);
}
}
else if (OP_NO_RESPONSE == projectionstatus) {
projectionBtn->setCheckable(false);
// miracastBtn->setCheckable(false);
}
if (res == PROJECTION_RUNNING)//如果接收端已开启
{
// miracastBtn->setChecked(false);
// miracastBtn->setCheckable(false);
}
if(source_res==1)//如果投射端已开启
{
projectionBtn->setChecked(false);
projectionBtn->setCheckable(false);
}
//监听WLAN开关
QDBusConnection::systemBus().connect(QString(), QString("/org/freedesktop/NetworkManager"), "org.freedesktop.NetworkManager", "PropertiesChanged", this, SLOT(netPropertiesChangeSlot(QMap<QString,QVariant>)));
return pluginWidget;
}
void Projection::netPropertiesChangeSlot(QMap<QString, QVariant> property) {
if (property.keys().contains("WirelessEnabled")) {
qDebug()<<"WLAN status changed";
pluginUi();
}
}
const QString Projection::name() const {
return QStringLiteral("projection");
}
bool Projection::isShowOnHomePage() const
{
return false;
}
QIcon Projection::icon() const
{
return QIcon::fromTheme("ukui-miracast-symbolic");
}
bool Projection::isEnable() const
{
return true;
}
void Projection::projectionPinSlots(QString type, QString pin) {
if (type.contains("clear")) {
//m_pin->clear();
} else {
qDebug()<<pin;
//m_pin->setText(pin);
}
}
void Projection::projectionButtonClickSlots(bool status) {
int config_method = pinCodeStatus(2);
if (status){
QDBusMessage result;
if (config_method){
result = m_pServiceInterface->call("Start",ui->projectionName->text(),"display");
}
else{
result = m_pServiceInterface->call("Start",ui->projectionName->text(),"pbc");
}
QList<QVariant> outArgs = result.arguments();
int res = outArgs.at(0).value<int>();
if(!res)
{
// miracastBtn->setCheckable(false);
}
} else {
m_pServiceInterface->call("Stop");
int projectionstatus;
QDBusMessage result = m_pServiceInterface->call("PreCheck");
QList<QVariant> outArgs = result.arguments();
projectionstatus = outArgs.at(0).value<int>();
if (SUPPORT_P2P_PERFECT == projectionstatus){
// miracastBtn->setCheckable(true);
}
}
}
void Projection::pincodeButtonClickSlots(bool status) {
QDBusMessage result;
QString path=QDir::homePath()+"/.config/miracast.ini";
QSettings *setting=new QSettings(path,QSettings::IniFormat);
setting->beginGroup("projection");
if (status){
pinCodeStatus(1);
result = m_pServiceInterface->call("UiSetConfigMethods","display");
setting->setValue("config_method","display");
} else {
pinCodeStatus(0);
result = m_pServiceInterface->call("UiSetConfigMethods","pbc");
setting->setValue("config_method","pbc");
}
setting->sync();
setting->endGroup();
QList<QVariant> outArgs = result.arguments();
int res = outArgs.at(0).value<int>();
if(res)
qDebug()<<"Fail.";
else
qDebug()<<"Success.";
}
void Projection::pushButtonClickSlots() {
QDBusInterface interface_2( "com.operate.wirelessscreen",
"/",
"com.operate.wirelessscreen",
QDBusConnection::sessionBus() );
QDBusReply<int> m_result = interface_2.call("operate_wireless_screen",1);
if (m_result.isValid()) {
qDebug()<<"open res is"<<m_result<<endl;
} else {
qDebug()<<"open failed"<<endl;
}
if(m_result==1)
{
projectionBtn->setCheckable(false);
}
}
void Projection::miracastsourceButtonClickSlots(bool status)
{
QString path=QDir::homePath()+"/.config/miracastsource.ini";
QSettings *setting=new QSettings(path,QSettings::IniFormat);
setting->beginGroup("projection");
if (status)
{
ui->pushButton->setEnabled(true);
QString styleSheetDark = QString ("background:rgba(44,50,57,%1);color:white;");
QString styleSheetLight = QString ("background:rgba(255,255,255,%1);color:rgba(58,67,78,0.25);");
QGSettings gsetting(QString("org.ukui.style").toLocal8Bit());
if (gsetting.get("style-name").toString() != "ukui-light"){
ui->pushButton->setStyleSheet(styleSheetLight);
}
else{
ui->pushButton->setStyleSheet(styleSheetDark);
}
projectionBtn->setCheckable(false);
setting->setValue("miracastsource","true");
}
else
{
ui->pushButton->setEnabled(false);
ui->pushButton->setStyleSheet("color: gray");
projectionBtn->setCheckable(true);
setting->setValue("miracastsource","false");
QDBusInterface interface_2( "com.operate.wirelessscreen",
"/",
"com.operate.wirelessscreen",
QDBusConnection::sessionBus() );
interface_2.call("operate_wireless_screen",0);
}
setting->sync();
setting->endGroup();
}
int Projection::pinCodeStatus(int key)
{
if (key == 0){
config_status = false;
return 2;
}
else if (key == 1){
config_status = true;
return 2;
}
else{
if (config_status)
return 1;
else
return 0;
}
}
void Projection::initComponent(){
addWgt = new HoverWidget("");
addWgt->setObjectName("addwgt");
addWgt->setMinimumSize(QSize(580, 64));
addWgt->setMaximumSize(QSize(16777215, 64));
addWgt->setStyleSheet("HoverWidget#addwgt{background: palette(base); border-radius: 4px;}HoverWidget:hover:!pressed#addwgt{background: #2FB3E8; border-radius: 4px;}");
QHBoxLayout *addLyt = new QHBoxLayout;
QLabel * iconLabel = new QLabel();
QLabel * textLabel = new QLabel(tr("Add Bluetooths"));
QPixmap pixgray = ImageUtil::loadSvg(":/img/titlebar/add.svg", "black", 12);
iconLabel->setPixmap(pixgray);
addLyt->addItem(new QSpacerItem(8,10,QSizePolicy::Fixed));
addLyt->addWidget(iconLabel);
addLyt->addItem(new QSpacerItem(16,10,QSizePolicy::Fixed));
addLyt->addWidget(textLabel);
addLyt->addStretch();
addWgt->setLayout(addLyt);
addWgt->hide();
}
QString Projection::translationPath() const
{
return "/usr/share/projection/translations/%1.ts";
}
void Projection::initSearchText()
{
//~ contents_path /projection/Open projection
}

View File

@ -0,0 +1,128 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd.
*
* 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.
*
*/
#ifndef PROJECTION_H
#define PROJECTION_H
#include <QObject>
#include <QtPlugin>
#include <QTimer>
#include <QtDBus>
#include <QGSettings/QGSettings>
#include <QLabel>
#include <QRegExpValidator>
#include <ukcc/widgets/hoverwidget.h>
#include <ukcc/widgets/imageutil.h>
#include <ukcc/widgets/switchbutton.h>
#include "changeprojectionname.h"
//#include <ukcc/widgets/hoverbtn.h>
#include "kswitchbutton.h"
using namespace kdk;
#include <ukcc/interface/interface.h>
#include "../component/DrownLabel/drownlabel.h"
namespace Ui {
class Projection;
}
class Projection : public QObject, CommonInterface
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.ukcc.CommonInterface")
Q_INTERFACES(CommonInterface)
public:
Projection();
~Projection();
QString plugini18nName() Q_DECL_OVERRIDE;
int pluginTypes() Q_DECL_OVERRIDE;
QWidget * pluginUi() Q_DECL_OVERRIDE;
const QString name() const Q_DECL_OVERRIDE;
bool isShowOnHomePage() const Q_DECL_OVERRIDE;
QIcon icon() const Q_DECL_OVERRIDE;
bool isEnable() const Q_DECL_OVERRIDE;
QString translationPath() const Q_DECL_OVERRIDE;
bool getWifiStatus();
void setWifiStatus(bool status);
void debusFileConfig();
void deleteAllitemsOfLayout(QLayout* layout);
public:
void initComponent();
void showChangeProjectionNameDialog();
void changeProjectionName(QString name);
protected:
bool eventFilter(QObject *watched, QEvent *event);
private:
Ui::Projection *ui;
QString pluginName;
int pluginType;
QWidget * pluginWidget;
HoverWidget * addWgt;
KSwitchButton *projectionBtn;
KSwitchButton *pincodeBtn;
KSwitchButton *miracastBtn;
DrownLabel *dropDownLabel = nullptr;
QLabel *m_pin;
bool enter = false;
QString hostName;
QMap<QString,QString>deviceName;
private:
QTimer * pTimer;
QDBusInterface *m_pServiceInterface;
bool m_bbluetoothStatus;
QGSettings * qtSettings;
bool m_autoclose = false;
void catchsignal();
void delaymsec(int msec);
int get_process_status(void);
int get_process_source_status(void);
int get_pin_button_status(void);
void init_button_status(int);
void init_pin_button_status(int);
void init_source_button_status(int);
void initSearchText(); // 搜索翻译
int pinCodeStatus(int);
void setLabelText(QLabel *label,QString text);
void getSystemFontFamily();
bool key = true;
bool config_status = false;
public slots:
void projectionButtonClickSlots(bool status);
void pincodeButtonClickSlots(bool status);
void miracastsourceButtonClickSlots(bool status);
void pushButtonClickSlots();
void onDrownLabelClicked();
void projectionPinSlots(QString type,QString pin);
void netPropertiesChangeSlot(QMap<QString, QVariant> property);
Q_SIGNALS:
void resize();
};
#endif // PROJECTION_H

View File

@ -0,0 +1,62 @@
#-------------------------------------------------
#
# Project created by QtCreator 2019-02-28T14:09:42
#
#-------------------------------------------------
QT += widgets
QT += core gui widgets dbus
TEMPLATE = lib
CONFIG += plugin
CONFIG += link_pkgconfig
PKGCONFIG += gsettings-qt \
kysdk-qtwidgets
include(../component/drownlabel.pri)
LIBS += -lukcc
TARGET = $$qtLibraryTarget(projection)
DESTDIR = ../..
target.path = $$[QT_INSTALL_LIBS]/ukui-control-center
TRANSLATIONS += translations/zh_CN.ts \
translations/en_US.ts
isEmpty(PREFIX) {
PREFIX = /usr
}
qm_files.path = $${PREFIX}/share/projection/translations
qm_files.files = translations/*
CONFIG(release, debug|release) {
!system($$PWD/translate_generation.sh): error("Failed to generate translation")
}
INCLUDEPATH += \
$$PROJECT_COMPONENTSOURCE \
$$PROJECT_ROOTDIR \
INCLUDEPATH += /usr/lib/gcc/aarch64-linux-gnu/9/include/
#DEFINES += QT_DEPRECATED_WARNINGS
SOURCES += \
projection.cpp \
changeprojectionname.cpp
HEADERS += \
projection.h \
changeprojectionname.h
FORMS += \
projection.ui \
changeprojectionname.ui \
INSTALLS += target \
qm_files \
RESOURCES += \
pic.qrc

View File

@ -0,0 +1,906 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Projection</class>
<widget class="QWidget" name="Projection">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>820</width>
<height>727</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="windowTitle">
<string notr="true">Printer</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_6">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QWidget" name="widget_6" native="true">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_10">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QFrame" name="frame_5">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>16</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>8</number>
</property>
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Projection to the pc</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="tipLabel">
<property name="minimumSize">
<size>
<width>0</width>
<height>20</height>
</size>
</property>
<property name="text">
<string>(No wireless network card is detected or the network card driver does not support it.)</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>394</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QFrame" name="frame">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="frameShape">
<enum>QFrame::Box</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QWidget" name="widget_9" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>80</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>80</height>
</size>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>16</number>
</property>
<property name="topMargin">
<number>8</number>
</property>
<property name="rightMargin">
<number>8</number>
</property>
<property name="bottomMargin">
<number>8</number>
</property>
<item>
<layout class="QVBoxLayout" name="verticalLayout_4">
<property name="spacing">
<number>8</number>
</property>
<item>
<widget class="QWidget" name="widget_8" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="titleLabel">
<property name="text">
<string>Allow android phone or pc to be projected to the pc:</string>
</property>
</widget>
</item>
<item>
<widget class="QWidget" name="projectionNameWidget" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_5">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="projectionName">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>22</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="projectionNameChange">
<property name="minimumSize">
<size>
<width>15</width>
<height>22</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>15</width>
<height>22</height>
</size>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_7">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Wireless LAN connection may be interrupted during projection.</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Expanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>500</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<widget class="Line" name="line">
<property name="minimumSize">
<size>
<width>0</width>
<height>1</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>1</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">color: rgb(244, 244, 244);
opacity:1;</string>
</property>
<property name="lineWidth">
<number>0</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QWidget" name="widget_4" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>60</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>60</height>
</size>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_17">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>16</number>
</property>
<property name="topMargin">
<number>8</number>
</property>
<property name="rightMargin">
<number>8</number>
</property>
<property name="bottomMargin">
<number>8</number>
</property>
<item>
<widget class="QLabel" name="titleLabel_3">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>You need to match the PIN code when projecting the screen to the pc</string>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_6">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Expanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>535</width>
<height>15</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<widget class="Line" name="line_2">
<property name="minimumSize">
<size>
<width>0</width>
<height>1</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>1</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">color: rgb(244, 244, 244);
opacity:1;</string>
</property>
<property name="lineWidth">
<number>0</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QWidget" name="widget_3" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>60</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>60</height>
</size>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_12">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>16</number>
</property>
<property name="topMargin">
<number>8</number>
</property>
<property name="rightMargin">
<number>8</number>
</property>
<property name="bottomMargin">
<number>8</number>
</property>
<item>
<widget class="QLabel" name="deviceLabel">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Historical equipment</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Expanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>663</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QWidget" name="widget_2" native="true">
<property name="styleSheet">
<string notr="true"/>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_11">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="spacing">
<number>0</number>
</property>
<property name="sizeConstraint">
<enum>QLayout::SetMaximumSize</enum>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
</layout>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Minimum</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>32</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QWidget" name="widget_7" native="true">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">border-right-color: rgb(85, 255, 127);</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_13">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QFrame" name="frame_6">
<property name="minimumSize">
<size>
<width>0</width>
<height>40</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>40</height>
</size>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_16">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>16</number>
</property>
<property name="topMargin">
<number>8</number>
</property>
<property name="rightMargin">
<number>8</number>
</property>
<property name="bottomMargin">
<number>8</number>
</property>
<item>
<widget class="QLabel" name="label_5">
<property name="minimumSize">
<size>
<width>0</width>
<height>30</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>30</height>
</size>
</property>
<property name="text">
<string>Connect to wireless display</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="tipLabel2">
<property name="minimumSize">
<size>
<width>0</width>
<height>30</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>30</height>
</size>
</property>
<property name="text">
<string>(No wireless network card is detected or the network card driver does not support it.)</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>394</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QWidget" name="widget_5" native="true">
<property name="minimumSize">
<size>
<width>0</width>
<height>80</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>80</height>
</size>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_7">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QFrame" name="frame3">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="frameShape">
<enum>QFrame::Box</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_6">
<property name="spacing">
<number>8</number>
</property>
<property name="leftMargin">
<number>16</number>
</property>
<property name="topMargin">
<number>8</number>
</property>
<property name="rightMargin">
<number>8</number>
</property>
<property name="bottomMargin">
<number>8</number>
</property>
<item>
<layout class="QVBoxLayout" name="verticalLayout_8">
<property name="spacing">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>Open(PIN authentication is not supported temporarily.)</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_4">
<property name="text">
<string>When enabled,the project to this pc feature stops.</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Maximum</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>380</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="pushButton">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>136</width>
<height>36</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>146</width>
<height>36</height>
</size>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections/>
</ui>

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

@ -0,0 +1,15 @@
#!/bin/bash
ts_list=(`ls translations/*.ts`)
source /etc/os-release
version=(`echo $ID`)
for ts in "${ts_list[@]}"
do
printf "\nprocess ${ts}\n"
if [ "$version" == "fedora" ] || [ "$version" == "opensuse-leap" ] || [ "$version" == "opensuse-tumbleweed" ];then
lrelease-qt5 "${ts}"
else
lrelease "${ts}"
fi
done

View File

@ -0,0 +1,108 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="en_US">
<context>
<name>ChangeProjectionName</name>
<message>
<location filename="../changeprojectionname.ui" line="26"/>
<source>Projection to this pc</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../changeprojectionname.ui" line="120"/>
<source>Device Name</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../changeprojectionname.ui" line="225"/>
<source>Cancel</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../changeprojectionname.ui" line="244"/>
<source>Save</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../changeprojectionname.cpp" line="38"/>
<source>The length must be 1-32 characters</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>Projection</name>
<message>
<location filename="../projection.ui" line="101"/>
<source>Projection to the pc</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../projection.ui" line="117"/>
<location filename="../projection.ui" line="719"/>
<location filename="../projection.cpp" line="596"/>
<location filename="../projection.cpp" line="597"/>
<location filename="../projection.cpp" line="620"/>
<location filename="../projection.cpp" line="621"/>
<source>(No wireless network card is detected or the network card driver does not support it.)</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../projection.ui" line="241"/>
<source>Allow android phone or pc to be projected to the pc:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../projection.ui" line="326"/>
<source>Wireless LAN connection may be interrupted during projection.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../projection.ui" line="431"/>
<source>You need to match the PIN code when projecting the screen to the pc</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../projection.ui" line="531"/>
<source>Historical equipment</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../projection.ui" line="700"/>
<source>Connect to wireless display</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../projection.ui" line="822"/>
<source>Open(PIN authentication is not supported temporarily.)</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../projection.ui" line="832"/>
<source>When enabled,the project to this pc feature stops.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../projection.cpp" line="52"/>
<source>Projection</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../projection.cpp" line="93"/>
<source>Find device</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../projection.cpp" line="659"/>
<location filename="../projection.cpp" line="660"/>
<location filename="../projection.cpp" line="694"/>
<location filename="../projection.cpp" line="695"/>
<source>(WLAN is not turned on. You need to turn on WLAN to use this function.)</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../projection.cpp" line="907"/>
<source>Add Bluetooths</source>
<translation type="unfinished"></translation>
</message>
</context>
</TS>

Binary file not shown.

View File

@ -0,0 +1,363 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="zh_CN">
<context>
<name>ChangeProjectionName</name>
<message>
<source>Name is too long, change another one.</source>
<translation type="vanished"></translation>
</message>
<message>
<source>Change Username</source>
<translation type="vanished"></translation>
</message>
<message>
<source>Change Name</source>
<translation type="vanished"></translation>
</message>
<message>
<source>Projection to this computer</source>
<translation type="vanished"></translation>
</message>
<message>
<location filename="../changeprojectionname.ui" line="26"/>
<source>Projection to this pc</source>
<translation></translation>
</message>
<message>
<location filename="../changeprojectionname.ui" line="120"/>
<source>Device Name</source>
<translation></translation>
</message>
<message>
<source>Changename</source>
<translation type="vanished"></translation>
</message>
<message>
<source>ChangeProjectionname</source>
<translation type="vanished"></translation>
</message>
<message>
<location filename="../changeprojectionname.ui" line="244"/>
<source>Save</source>
<translation></translation>
</message>
<message>
<location filename="../changeprojectionname.ui" line="225"/>
<source>Cancel</source>
<translation></translation>
</message>
<message>
<source>Name is too long.</source>
<translation type="vanished"></translation>
</message>
<message>
<source>The input character length exceeds the limit.</source>
<translation type="vanished"></translation>
</message>
<message>
<location filename="../changeprojectionname.cpp" line="38"/>
<source>The length must be 1-32 characters</source>
<translation> 1-32 </translation>
</message>
</context>
<context>
<name>Projection</name>
<message>
<source>projection</source>
<translation type="vanished"></translation>
</message>
<message>
<source>Projection to this computer</source>
<translation type="vanished"></translation>
</message>
<message>
<location filename="../projection.cpp" line="52"/>
<source>Projection</source>
<translation></translation>
</message>
<message>
<location filename="../projection.cpp" line="659"/>
<location filename="../projection.cpp" line="660"/>
<location filename="../projection.cpp" line="694"/>
<location filename="../projection.cpp" line="695"/>
<source>(WLAN is not turned on. You need to turn on WLAN to use this function.)</source>
<translation>(WLAN未开启使WLAN)</translation>
</message>
<message>
<source>(No wireless network card is detected or the network card driver does not support it.).</source>
<translation type="vanished">线使</translation>
</message>
<message>
<source>Allow Android phones or computers to be projected to this computer</source>
<translation type="vanished">Andriod手机或电脑投屏到此电脑</translation>
</message>
<message>
<source>Projection to the computer</source>
<translation type="vanished"></translation>
</message>
<message>
<source>Allow android phone or pc to be projected to the pc.</source>
<translation type="vanished"></translation>
</message>
<message>
<source>Wireless LAN transmission may be interrupted during projection</source>
<translation type="vanished">线</translation>
</message>
<message>
<source>You need to match the PIN code when projecting the screen to this computer</source>
<translation type="vanished">PIN码</translation>
</message>
<message>
<location filename="../projection.ui" line="117"/>
<location filename="../projection.ui" line="719"/>
<location filename="../projection.cpp" line="596"/>
<location filename="../projection.cpp" line="597"/>
<location filename="../projection.cpp" line="620"/>
<location filename="../projection.cpp" line="621"/>
<source>(No wireless network card is detected or the network card driver does not support it.)</source>
<translation>(线)</translation>
</message>
<message>
<source>PIN code authentication projection is not supported temporarily.</source>
<translation type="vanished">PIN码认证投射</translation>
</message>
<message>
<source>You need to match the pin code when projecting the screen to this computer</source>
<translation type="vanished">pin码</translation>
</message>
<message>
<location filename="../projection.ui" line="101"/>
<source>Projection to the pc</source>
<translation></translation>
</message>
<message>
<source>Allow android phone or pc to be projected to the pc</source>
<translation type="vanished">Android手机或电脑投屏到此电脑</translation>
</message>
<message>
<location filename="../projection.ui" line="241"/>
<source>Allow android phone or pc to be projected to the pc:</source>
<translation>Andriod手机或电脑投屏到此电脑</translation>
</message>
<message>
<source>Wireless LAN transmission may be interrupted during projection.</source>
<translation type="vanished">线</translation>
</message>
<message>
<location filename="../projection.ui" line="326"/>
<source>Wireless LAN connection may be interrupted during projection.</source>
<translation>线</translation>
</message>
<message>
<location filename="../projection.ui" line="431"/>
<source>You need to match the PIN code when projecting the screen to the pc</source>
<translation>PIN码</translation>
</message>
<message>
<location filename="../projection.ui" line="531"/>
<source>Historical equipment</source>
<translation></translation>
</message>
<message>
<location filename="../projection.ui" line="700"/>
<source>Connect to wireless display</source>
<translation>线</translation>
</message>
<message>
<source>Open(PIN authentication and receiving end of SP1 version is not supported.)</source>
<translation type="vanished">PIN码认证和投射到SP1版本的接收端</translation>
</message>
<message>
<source>Open(PIN authentication and receiving end of SP1 version is not supported temporarily.)</source>
<translation type="vanished">PIN码认证和投射到SP1版本的接收端</translation>
</message>
<message>
<location filename="../projection.ui" line="822"/>
<source>Open(PIN authentication is not supported temporarily.)</source>
<translation>PIN码认证</translation>
</message>
<message>
<location filename="../projection.ui" line="832"/>
<source>When enabled,the project to this pc feature stops.</source>
<translation></translation>
</message>
<message>
<source>Open(The function doesn&apos;t support pin code authentication temporarily.)</source>
<translation type="vanished">PIN码认证</translation>
</message>
<message>
<source>Open(This function does not support PIN code authentication temporarily.)</source>
<translation type="vanished">PIN码认证</translation>
</message>
<message>
<source>Open</source>
<translation type="vanished"></translation>
</message>
<message>
<source>When enabled, the project to this PC feature stops.PIN code authentication projection is not supported temporarily.</source>
<translation type="vanished">PIN码认证</translation>
</message>
<message>
<source>When enabled, the project to this PC feature stops.</source>
<translation type="vanished"></translation>
</message>
<message>
<source>refreshBtn</source>
<translation type="vanished"></translation>
</message>
<message>
<source>Open projection</source>
<translation type="vanished"></translation>
<extra-contents_path>/projection/Open projection</extra-contents_path>
</message>
<message>
<source>Disable Pin Code</source>
<translation type="vanished">Pin码</translation>
</message>
<message>
<source>refresh</source>
<translation type="vanished"></translation>
</message>
<message>
<source>Delete</source>
<translation type="vanished"></translation>
</message>
<message>
<source>Failed to remove device</source>
<translation type="vanished"></translation>
</message>
<message>
<source>Device deleted successfully</source>
<translation type="vanished"></translation>
</message>
<message>
<source>Multi screen collaboration</source>
<translation type="vanished"></translation>
</message>
<message>
<location filename="../projection.cpp" line="93"/>
<source>Find device</source>
<translation></translation>
</message>
<message>
<source>Please click refresh and try again</source>
<translation type="vanished"></translation>
</message>
<message>
<source>warning</source>
<translation type="vanished"></translation>
</message>
<message>
<source>Yes</source>
<translation type="vanished"></translation>
</message>
<message>
<source>Please restart the screen projection button</source>
<translation type="vanished"></translation>
</message>
<message>
<source>tips</source>
<translation type="vanished"></translation>
</message>
<message>
<source>Please restart the screen projection switch button</source>
<translation type="vanished"></translation>
</message>
<message>
<source>Receive terminal is </source>
<translation type="vanished"></translation>
</message>
<message>
<source>Service exception,please restart the system</source>
<translation type="vanished"></translation>
</message>
<message>
<source>After deleting the device, you need to restart the projection to take effect</source>
<translation type="vanished"></translation>
</message>
<message>
<source>Please keep WLAN on;
Wireless-network functions will be invalid when the screen projection on</source>
<translation type="vanished">使WLAN处于开启状态线</translation>
</message>
<message>
<source>Please keep WLAN on;
Wireless will be temporarily disconnected when the screen projection on</source>
<translation type="vanished">使WLAN处于开启状态线</translation>
</message>
<message>
<source>After opening the switch button,open the projection screen in the mobile phone drop-down menu,follow the prompts.See the user manual for details</source>
<translation type="vanished"></translation>
</message>
<message>
<source>List of connected devices</source>
<translation type="vanished"></translation>
</message>
<message>
<source>It is recommended to restart the screen after deleting the device</source>
<translation type="vanished"></translation>
</message>
<message>
<source>WLAN is off, please turn on WLAN</source>
<translation type="vanished">WLAN未开启WLAN开关</translation>
</message>
<message>
<source>Wireless network card is busy. Please try again later</source>
<translation type="vanished">线</translation>
</message>
<message>
<source>Projection is </source>
<translation type="vanished"></translation>
</message>
<message>
<source>on</source>
<translation type="vanished"></translation>
</message>
<message>
<source>off</source>
<translation type="vanished"></translation>
</message>
<message>
<source>The projection function is </source>
<translation type="vanished"></translation>
</message>
<message>
<source>tuen on</source>
<translation type="vanished"></translation>
</message>
<message>
<source>turn off</source>
<translation type="vanished"></translation>
</message>
<message>
<source>turn on</source>
<translation type="obsolete"></translation>
</message>
<message>
<source>Please enable or refresh the scan at the projection device</source>
<translation type="vanished"></translation>
</message>
<message>
<source>You need to turn on the projection again</source>
<translation type="vanished"></translation>
</message>
<message>
<source>You need to turn on the screen again</source>
<translation type="vanished"></translation>
</message>
<message>
<source>Failed to execute. Please reopen the page later</source>
<translation type="vanished"></translation>
</message>
<message>
<source>Projection Name</source>
<translation type="vanished"></translation>
</message>
<message>
<location filename="../projection.cpp" line="907"/>
<source>Add Bluetooths</source>
<translation></translation>
</message>
</context>
</TS>

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

48
res/CMakeLists.txt Normal file
View File

@ -0,0 +1,48 @@
execute_process(
COMMAND ${PKG_CONFIG_EXECUTABLE} --variable=system_bus_services_dir dbus-1
OUTPUT_VARIABLE DBUS_SYSTEM_SERVICES_DIR
OUTPUT_STRIP_TRAILING_WHITESPACE
)
execute_process(
COMMAND ${PKG_CONFIG_EXECUTABLE} --variable=systemdsystemunitdir systemd
OUTPUT_VARIABLE SYSTEMD_SYSTEM_UNIT_DIR
OUTPUT_STRIP_TRAILING_WHITESPACE
)
configure_file(
miracle-wifid.service.cmake
miracle-wifid.service
)
install(
FILES ${CMAKE_CURRENT_BINARY_DIR}/miracle-wifid.service
DESTINATION ${SYSTEMD_SYSTEM_UNIT_DIR}/
)
install(
CODE "execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink ${SYSTEMD_SYSTEM_UNIT_DIR}/miracle-wifid.service \$ENV{DESTDIR}${SYSTEMD_SYSTEM_UNIT_DIR}/dbus-org.freedesktop.miracle.wifi.service)"
)
INSTALL(
PROGRAMS uibc-viewer
DESTINATION bin
)
INSTALL(
PROGRAMS checkhardware.sh checkDaemonRunning.sh checkFrontendRunning.sh execstart.sh recover_wpas.sh
DESTINATION bin
)
INSTALL(
FILES org.freedesktop.miracle.conf
DESTINATION ${SYSCONFDIR}/dbus-1/system.d
)
INSTALL(
FILES miracle-agent.desktop
DESTINATION ${SYSCONFDIR}/xdg/autostart
)
INSTALL(
FILES miracle-wifid miracle-sinkctl miracle-wifictl
DESTINATION ${DATADIR}/bash-completion/completions
)

9
res/Makefile.am Normal file
View File

@ -0,0 +1,9 @@
bin_SCRIPTS = miracle-gst gstplayer uibc-viewer miracle-omxplayer
EXTRA_DIST = wpa.conf
dbuspolicydir=$(sysconfdir)/dbus-1/system.d
dbuspolicy_DATA = org.freedesktop.miracle.conf
bashcompletiondir=${datadir}/bash-completion/completions
bashcompletion_DATA=miracle-wifid miracle-sinkctl miracle-wifictl

463
res/castplayer Executable file
View File

@ -0,0 +1,463 @@
#!/usr/bin/python3 -u
import gi
import argparse
import dbus
import os
HOME_DIR = os.environ['HOME']
if os.path.exists(HOME_DIR+'/.config/tpConfig.txt'):
with open(HOME_DIR+'/.config/tpConfig.txt', 'r') as f:
decodeFlag = f.read()
else:
decodeFlag = "kylin"
def setEnv():
LIST_VGA = "lspci | grep VGA"
output = os.popen(LIST_VGA).read()
if "AMD" in output:
os.putenv("LIBVA_DRIVER_NAME", "radeonsi")
os.putenv("GST_VAAPI_ALL_DRIVERS", "1")
elif "Intel" in output:
os.putenv("LIBVA_DRIVER_NAME", "i965")
else:
# have no hardware, execute software decode
decodeFlag = "kylin"
if decodeFlag == "hard":
setEnv()
gi.require_version('Gst', '1.0')
gi.require_version('Gtk', '3.0')
gi.require_version('GstVideo', '1.0')
gi.require_version('GdkX11', '3.0')
from gi.repository import GObject, Gst, Gtk, Gdk, GLib,GdkPixbuf
# Needed for window.get_xid(), xvimagesink.set_window_handle(), respectively:
from gi.repository import GdkX11, GstVideo
# GObject.threads_init()
Gst.init(None)
class Player(object):
def __init__(self, **kwargs):
self.hidc = True
self.cons_LeftBtnPressed = 0
self.cons_NoBtnPressed = 1
self.cons_KeyPressed = 2
self.cons_KeyReleased = 3
self.cons_NullBtn = 0
self.cons_LeftBtn = 1
self.cons_MidBtn = 2
self.cons_RightBtn = 4
self.hid_key_event = 0
self.hid_mouse_event = 1
resolution = kwargs.get("resolution")
if resolution:
split = resolution.split("x")
self.width = int(split[0])
self.height = int(split[1])
scale = kwargs.get("scale")
if scale:
split = scale.split("x")
self.width = int(split[0])
self.height = int(split[1])
self.uibc_enabled = 0
uibc_enabled = kwargs.get("uibc")
if uibc_enabled:
self.uibc_enabled = 1
debug = kwargs.get("debug")
if debug:
Gst.debug_set_active(True)
Gst.debug_set_threshold_from_string(debug, True)
port = kwargs.get("port")
uri = kwargs.get("uri")
self.window = Gtk.Window()
self.window.set_name('MiracastPlayer')
self.window.set_title('MiracastPlayer')
# self.window.connect('realize', self.realize_cbk)
self.window.connect('destroy', self.quit)
self.window.connect('delete_event', self.confirm)
# self.window.connect('button-press-event', self.on_double_clicked)
self.window.connect('button-press-event', self.on_mouse_pressed)
self.window.connect('button-release-event', self.on_mouse_pressed)
self.window.connect('motion-notify-event', self.on_mouse_moved)
self.window.connect('key-press-event', self.on_key_pressed)
self.window.connect('key-release-event', self.on_key_pressed)
self.window.connect('scroll-event', self.on_scroll)
if os.path.exists('/usr/share/icons/ukui-icon-theme-fashion/128x128/apps/kylin-miracast.png'):
img = GdkPixbuf.Pixbuf.new_from_file('/usr/share/icons/ukui-icon-theme-fashion/128x128/apps/kylin-miracast.png')
self.window.set_icon(img)
# if hasattr(self,'width') and hasattr(self,'height'):
self.window.set_default_size(self.width, self.height)
self.window.fullscreen()
self.isFullScreen = True
self.drawingarea = Gtk.DrawingArea()
self.window.add(self.drawingarea)
_dbus = dbus.SessionBus()
proxy = _dbus.get_object('org.gnome.SessionManager', '/org/gnome/SessionManager')
# self.SessionManagerIface = dbus.Interface(proxy, 'org.gnome.SessionManager')
self.Inhibit = proxy.get_dbus_method('Inhibit', 'org.gnome.SessionManager')
self.Uninhibit = proxy.get_dbus_method('Uninhibit', 'org.gnome.SessionManager')
self.sessmngCookie = 0
# if hasattr(self,'width') and hasattr(self,'height'):
self.drawingarea.set_size_request(self.width,self.height)
half_area_width = self.drawingarea.get_allocation().width / 2
half_area_height = self.drawingarea.get_allocation().height / 2
half_def_width = self.width / 2
half_def_height = self.height / 2
self.min_hor_pos = half_area_width - half_def_width
self.max_hor_pos = half_area_width + half_def_width
self.min_ver_pos = half_area_height - half_def_height
self.max_ver_pos = half_area_height + half_def_height
self.drawingarea.add_events(Gdk.EventMask.BUTTON_PRESS_MASK|Gdk.EventMask.BUTTON_RELEASE_MASK)
self.drawingarea.add_events(Gdk.EventMask.POINTER_MOTION_MASK)
self.drawingarea.add_events(Gdk.EventMask.BUTTON1_MOTION_MASK)
self.drawingarea.add_events(Gdk.EventMask.KEY_PRESS_MASK)
self.drawingarea.add_events(Gdk.EventMask.SCROLL_MASK)
audio = kwargs.get("audio")
self.playbin = None
self.uibc_x = -1
self.uibc_y = -1
#Create GStreamer pipeline
if uri is not None:
self.pipeline = Gst.Pipeline()
# Create GStreamer elements
self.playbin = Gst.ElementFactory.make('playbin', "source")
if not uri.startswith("http://") or not uri.startswith("http://") or not uri.startswith("file://"):
if not uri.startswith("/"):
uri = os.path.abspath(uri)
uri = "file://"+uri
# Set properties
self.playbin.set_property('uri', uri)
# Add playbin to the pipeline
self.pipeline.add(self.playbin)
else:
gstcommand = "udpsrc port="+str(port)+" caps=\"application/x-rtp, media=video\" ! rtpjitterbuffer latency=20 ! rtpmp2tdepay ! tsdemux "
if audio:
gstcommand += "name=demuxer demuxer. "
gstcommand += "! queue name=video_ch max-size-buffers=0 max-size-time=0 ! h264parse ! queue name=dec0 max-size-buffers=0 max-size-time=0 "
if "hard"==decodeFlag:
gstcommand += "! vaapih264dec "
else:
gstcommand += "! avdec_h264 max-threads=0 skip-frame=1 output-corrupt=false "
gstcommand += "! videoconvert n-threads=0 !"
if scale:
gstcommand += "videoscale method=1 ! video/x-raw,width="+str(self.width)+",height="+str(self.height)+" ! "
gstcommand += " autovideosink force-aspect-ratio=false sync=false async=false "
if audio:
gstcommand += "demuxer. ! queue max-size-buffers=0 max-size-time=0 ! aacparse ! avdec_aac ! audioconvert ! audioresample ! autoaudiosink sync=false "
self.pipeline = Gst.parse_launch(gstcommand)
# Create bus to get events from GStreamer pipeline
self.bus = self.pipeline.get_bus()
self.bus.add_signal_watch()
self.bus.connect('message::eos', self.on_eos)
self.bus.connect('message::error', self.on_error)
# This is needed to make the video output in our DrawingArea:
self.bus.enable_sync_message_emission()
self.bus.connect('sync-message::element', self.on_sync_message)
self.bus.connect('message', self.on_message)
self.success = False
def start_cursor_timer(self):
if(self.timer_tag == -1):
self.timer_tag = GLib.timeout_add(3000, self.on_cursor_timer_out)
def stop_cursor_timer(self):
if(-1 != self.timer_tag):
GLib.source_remove(self.timer_tag)
self.timer_tag = -1
def on_cursor_timer_out(self):
# print("HANDLE TIMER .....")
self.hide_cursor(self.window)
def hide_cursor(self, window):
if(self.cursor_hidden is False):
cursor = Gdk.Cursor(Gdk.CursorType.BLANK_CURSOR)
window.get_window().set_cursor(cursor)
self.cursor_hidden = True
self.stop_cursor_timer()
# print("hide cursor ............")
def show_cursor(self, widget):
if(self.cursor_hidden is True):
cursor = Gdk.Cursor(Gdk.CursorType.ARROW)
widget.get_window().set_cursor(cursor)
self.cursor_hidden = False
self.stop_cursor_timer()
self.start_cursor_timer()
# print("show cursor ............")
def calc_delta(self, oldval, newval):
temp = newval - oldval
if(temp > 127):
temp = 127
elif(temp < -127):
temp = -127
if(temp < 0):
temp += 2**8
return temp
def on_mouse_moved(self, widget, event):
self.show_cursor(widget)
if(self.hidc is True):
#mouse drag event
if event.state & Gdk.ModifierType.BUTTON1_MASK:
type = self.cons_LeftBtnPressed
button = self.cons_LeftBtn #mouse left button
else:
type = self.cons_NoBtnPressed
button = self.cons_NullBtn
uibc_x = int(event.x - self.min_hor_pos)
uibc_y = int(event.y - self.min_ver_pos)
delta_x = 0
delta_y = 0
if(self.uibc_x >= 0 and self.uibc_y >= 0):
delta_x = self.calc_delta(self.uibc_x, uibc_x)
delta_y = self.calc_delta(self.uibc_y, uibc_y)
self.uibc_x = uibc_x
self.uibc_y = uibc_y
print('{0},{1},{2},{3},{4}'.format(self.hid_mouse_event, type, button, delta_x, delta_y))
def on_mouse_pressed(self, widget, event):
#double-click means quit fullscreen mode
if event.type == Gdk.EventType._2BUTTON_PRESS:
self.handle_double_clicked(widget, event)
return
if(self.hidc is True):
if event.type == Gdk.EventType.BUTTON_PRESS:
type = self.cons_LeftBtnPressed
else:
type = self.cons_NoBtnPressed
if event.button == 1:
button = self.cons_LeftBtn
elif event.button == 2:
button = self.cons_MidBtn
if event.button == 3:
button = self.cons_RightBtn
# uibc_x = int(event.x - self.min_hor_pos)
# uibc_y = int(event.y - self.min_ver_pos)
# delta_x = 0
# delta_y = 0
# if(self.uibc_x >= 0 and self.uibc_y >= 0):
# delta_x = self.calc_delta(self.uibc_x, uibc_x)
# delta_y = self.calc_delta(self.uibc_y, uibc_y)
# self.uibc_x = uibc_x
# self.uibc_y = uibc_y
# print('1,{0},{1},{2},{3}'.format(type, button, delta_x, delta_y))
print('{0},{1},{2},0,0'.format(self.hid_mouse_event, type, button))
else:
#<type>,<count>,<id>,<x>,<y>
if event.type == Gdk.EventType.BUTTON_PRESS:
type = 0
else:
type = 1
width = self.drawingarea.get_allocation().width
height = self.drawingarea.get_allocation().height
half_area_width = width / 2
half_area_height = height / 2
half_def_width = self.width / 2
half_def_height = self.height / 2
min_hor_pos = half_area_width - half_def_width
max_hor_pos = half_area_width + half_def_width
min_ver_pos = half_area_height - half_def_height
max_ver_pos = half_area_height + half_def_height
pos_event_x = event.x
pos_event_y = event.y
if self.min_hor_pos <= pos_event_x <= self.max_hor_pos and self.min_ver_pos <= pos_event_y <= self.max_ver_pos:
uibc_x = int(pos_event_x - self.min_hor_pos)
uibc_y = int(pos_event_y - self.min_ver_pos)
print('{0},1,0,{1},{2}'.format(type, uibc_x , uibc_y))
def on_scroll(self, widget, event):
if(self.hidc is True):
#<mouse_type, press/release, button, x, y>
if event.direction == Gdk.ScrollDirection.DOWN:
scroll_step = -1
elif event.direction == Gdk.ScrollDirection.UP:
scroll_step = 1
else:
scroll_step = 0
if scroll_step != 0:
print('1,1,4,0,0,{0}'.format(scroll_step))
def on_key_pressed(self, widget, event):
if(self.uibc_enabled):
if(self.hidc is True):
if event.type == Gdk.EventType.KEY_PRESS:
print ("{0},{1},0x{2:04x}" .format(self.hid_key_event, self.cons_KeyPressed, event.keyval))
elif event.type == Gdk.EventType.KEY_RELEASE:
print ("{0},{1},0x{2:04x}" .format(self.hid_key_event, self.cons_KeyReleased, event.keyval))
#<key_type, pressed/released, button>
else:
print("3,0x%04X,0x0000" % event.keyval)
if event.type == Gdk.EventType.KEY_PRESS:
self.show_cursor(widget)
def handle_double_clicked(self, widget, event):
self.show_cursor(widget)
if event.button == 1 and event.type == Gdk.EventType._2BUTTON_PRESS:
if True == self.isFullScreen:
self.window.unfullscreen()
self.isFullScreen = False
# self.SessionManagerIface.Uninhibit(self.sessmngCookie)
self.Uninhibit(self.sessmngCookie)
self.sessmngCookie = 0
else:
self.window.fullscreen()
self.isFullScreen = True
# self.sessmngCookie = self.SessionManagerIface.Inhibit("castplayer", 0, "full screen", 8)
self.sessmngCookie = self.Inhibit("castplayer", 0, "full screen", 8)
def on_message(self, bus, message):
if self.playbin:
videoPad = self.playbin.emit("get-video-pad", 0)
if videoPad and not self.success:
videoPadCapabilities = videoPad.get_current_caps()
if videoPadCapabilities:
(self.success, self.videoWidth) = \
videoPadCapabilities.get_structure(0).get_int("width")
(self.success, self.videoHeight) = \
videoPadCapabilities.get_structure(0).get_int("height")
if self.success:
print("{0} {1}".format(self.videoWidth, self.videoHeight))
self.drawingarea.set_size_request(self.videoWidth, self.videoHeight)
def run(self):
self.window.show_all()
# You need to get the XID after window.show_all(). You shouldn't get it
# in the on_sync_message() handler because threading issues will cause
# segfaults there.
window = self.drawingarea.get_property('window')
if hasattr(window,'get_xid'):
self.xid = self.drawingarea.get_property('window').get_xid()
self.pipeline.set_state(Gst.State.PLAYING)
# self.sessmngCookie = self.SessionManagerIface.Inhibit("castplayer", 0, "full screen", 8)
# self.sessmngCookie = self.Inhibit("castplayer", 0, "full screen", 8)
# self.Uninhibit(0)
self.cursor_hidden = False
self.timer_tag = -1
self.hide_cursor(self.window)
Gtk.main()
def confirm(self, window, event=None):
dialog = Gtk.MessageDialog(window, 0, Gtk.MessageType.QUESTION, Gtk.ButtonsType.YES_NO, "选择\"是\"将关闭窗口,连接会断开!\n选择\"否\"取消当前操作")
resp = dialog.run()
ret = False
if resp == Gtk.ResponseType.NO:
ret = True
dialog.destroy()
return ret
def quit(self, window):
# self.Uninhibit(self.sessmngCookie)
# self.sessmngCookie = 0
self.pipeline.set_state(Gst.State.NULL)
Gtk.main_quit()
def on_sync_message(self, bus, msg):
if msg.get_structure().get_name() == 'prepare-window-handle':
print(self.drawingarea.get_allocation())
if hasattr(self,'xid'):
msg.src.set_window_handle(self.xid)
def on_eos(self, bus, msg):
print('on_eos(): seeking to start of video')
self.pipeline.seek_simple(
Gst.Format.TIME,
Gst.SeekFlags.FLUSH | Gst.SeekFlags.KEY_UNIT,
0
)
def on_error(self, bus, msg):
print('on_error():', msg.parse_error())
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument("uri", nargs="?", help="Uri to play")
parser.add_argument("-v", "--version", help="Show package version")
parser.add_argument("--log-level", metavar="lvl", help="Maximum level for log messages")
parser.add_argument("-p", "--port", type=int, default=1991, help="Port for rtsp")
parser.add_argument("-a", "--audio", dest="audio", action="store_true", help="Enable audio support")
parser.add_argument("-s", "--scale", metavar="WxH", help="Scale to resolution")
parser.add_argument("-d", "--debug", help="Debug")
parser.add_argument("--uibc", type=int, help="Supported uibc-ctl:1 or 0")
parser.add_argument("--res", metavar="n,n,n", help="Supported resolutions masks (CEA, VESA, HH)")
# res
# " default CEA %08X\n"
# " default VESA %08X\n"
# " default HH %08X\n"
parser.add_argument("-r", "--resolution", help="Resolution")
parser.set_defaults(audio=True)
args = parser.parse_args()
p = Player(**vars(args))
p.run()

23
res/checkDaemonRunning.sh Executable file
View File

@ -0,0 +1,23 @@
#!/bin/bash
#judge if daemon program is running
AGT_PNUM=`ps -ef | grep 'miracle-agent' | grep -v grep | wc -l`
SRV_PNUM=`ps -ef | grep 'miracle-wifid' | grep -v grep | wc -l`
if [ $AGT_PNUM -eq 0 ] || [ $SRV_PNUM -eq 0 ]
then
echo "miraclecast daemon not running"
exit 2
fi
#judge if supplicant program is running
PROG_PNUM=`ps -ef | grep 'wpa_supplicant -c' | grep -v grep | wc -l`
if [ $PROG_PNUM -gt 0 ]
then
exit 1
fi
exit 0

View File

@ -0,0 +1,14 @@
#!/bin/bash
#judge if frontend program is running
PROG_PNUM=`ps -ef | grep 'miraclecast-frontend' | grep -v grep | wc -l`
if [ $PROG_PNUM -gt 0 ]
then
echo "miracast frontend is running"
exit 1
else
echo "miracast frontend not running"
fi

165
res/checkhardware.sh Executable file
View File

@ -0,0 +1,165 @@
#!/bin/bash
eval SCRIPT_DEBUG="\$$(basename $0 .sh | tr - _)_DEBUG"
SCRIPT_DEBUG=${SCRIPT_DEBUG:--1}
if [ "$SCRIPT_DEBUG" -ge 1 ]
then
set -x
fi
if [ "$SCRIPT_DEBUG" -ge 10 ]
then
set -v
fi
IFNAME=$1
##START of common funcs, moved to /home/$USR/.config/miracast latter
LOOPBACK=772
function find_choosable_networknames {
for i in $( ls /sys/class/net )
do
if [ $( cat /sys/class/net/$i/type ) != $LOOPBACK ]
then
echo $i
fi
done
}
function find_wireless_network_interfaces {
for i in $( find_choosable_networknames )
do
if [ -d /sys/class/net/$i/wireless ]
then
echo $i
fi
done
}
function find_physical_for_network_interface {
PHY_INDEX=$(iw dev $1 info | grep wiphy | awk '{print $2}')
if [ -n "$PHY_INDEX" ]
then
echo phy$PHY_INDEX
fi
}
function search_p2p_capabilities {
WI_DEVICE=$1
PHY_DEVICE=$(find_physical_for_network_interface $WI_DEVICE)
SUCC=0
FAIL=1
if [ -z "$PHY_DEVICE" ]
then
echo "cannot find physical device for $WI_DEVICE"
return
fi
if iw phy $PHY_DEVICE info | grep -Pzo "(?s)Supported interface modes.*Supported commands" | grep "P2P" &> /dev/null
then
echo $WI_DEVICE supports P2P
else
echo Sorry, $WI_DEVICE do not support P2P
# exit 1
fi
}
function search_p2p_dev_capabilities {
WI_DEVICE=$1
PHY_DEVICE=$(find_physical_for_network_interface $WI_DEVICE)
SUCC=0
FAIL=1
if [ -z "$PHY_DEVICE" ]
then
echo "cannot find physical device for $WI_DEVICE"
return
fi
if iw phy $PHY_DEVICE info | grep -Pzo "(?s)Supported interface modes.*Supported commands" | grep "P2P-device" &> /dev/null
then
if udevadm info --query=all --path=/sys/class/net/$WI_DEVICE | grep "ID_NET_DRIVER" | grep -E "(8821ce|88x2ce)" &> /dev/null
then
echo Sorry, $WI_DEVICE do not support P2P-DEVICE
else
echo $WI_DEVICE supports P2P-DEVICE
fi
else
echo Sorry, $WI_DEVICE do not support P2P-DEVICE
# exit 1
fi
}
function check_pci_wnic_vendor_support {
WI_DEVICE=$1
if udevadm info --query=all --path=/sys/class/net/$WI_DEVICE | grep "ID_NET_DRIVER" | grep -E "(8812au|8821cu)" &> /dev/null
then
echo "wireless card not ok"
else
echo "wireless card ok"
fi
}
##END of common funcs, moved to /home/$USR/.config/miracast latter
WIFI_COUNT=0
WIFI_NAMES="$(find_wireless_network_interfaces)"
if [ -n "$WIFI_NAMES" ]
then
WIFI_COUNT=$(echo "$WIFI_NAMES" | wc -l)
fi
if [ 0 = $WIFI_COUNT ]
then
echo There is no wireless devices available
exit 1
elif [ 1 = $WIFI_COUNT ]
then
WIFI_NAME="$WIFI_NAMES"
elif [ 2 -ge $WIFI_COUNT ]
then
echo Support Only one wireless card @v1.0
fi
RTL8821CE=$(check_pci_wnic_vendor_support $IFNAME)
echo $RTL8821CE
TARGET="not"
if [[ $RTL8821CE =~ $TARGET ]]
then
echo "RTL8821CE not support at present"
exit 1
fi
RETSTR=$(search_p2p_capabilities $IFNAME)
echo $RETSTR
if [[ $RETSTR =~ $TARGET ]]
then
echo "FAILURE"
exit 1
fi
P2PDEVSTR=$(search_p2p_dev_capabilities $IFNAME)
echo $P2PDEVSTR
if [[ $P2PDEVSTR =~ $TARGET ]]
then
echo "network will be disabled while projection"
exit 2
else
echo "p2p-device support, so wifi and widi at the same time"
fi
AGENT_PNAME="miracle-agent"
AGENT_PNUM=`ps -ef | grep $AGENT_PNAME | grep -v grep | wc -l`
if [ $AGENT_PNUM -gt 0 ]
then
echo "SUCCESS"
else
echo "Agent not running!!! Quit..."
exit 1
fi
exit 0

20
res/execstart.sh Executable file
View File

@ -0,0 +1,20 @@
#!/bin/bash
hw_arch=$(uname -m)
echo $hw_arch|logger
if [ $hw_arch = "loongarch64" ]
then
echo "gdb loongarch64"|logger
gdb /usr/bin/miracle-wifid -batch -ex "set args --use-dev --log-level info --lazy-managed --config-methods display --wpa-loglevel trace" -ex "set logging file /home/execstart.gdb" -ex "set logging on" -ex "run" -ex "thread apply all backtrace" -ex "quit"
echo "gdb loongarch64 success"|logger
else
echo "other arch"|logger
/usr/bin/miracle-wifid \
--use-dev \
--log-level info \
--lazy-managed \
--config-methods display
echo "other arch success"|logger
fi

18
res/kill-wpa.sh Executable file
View File

@ -0,0 +1,18 @@
#!/bin/bash
. miracle-utils.sh
kill_ubuntu_network_manager
WPA_PID=$(find_wpa_supplicant_pid)
if [ -n "$WPA_PID" ]
then
echo killing existing wpa_supplicant connection
sudo kill -9 $WPA_PID
else
echo cannot find wpa_supplicant connection to kill
if [[ $_ == $0 ]]
then
exit 1
fi
fi

13
res/meson.build Normal file
View File

@ -0,0 +1,13 @@
install_data(
'org.freedesktop.miracle.conf',
install_dir: join_paths(get_option('sysconfdir'), 'dbus-1', 'system.d')
)
install_data('miracle-gst', 'gstplayer', 'uibc-viewer',
install_dir: get_option('bindir'),
install_mode: 'rwxr-xr-x')
install_data(
'miracle-wifid', 'miracle-sinkctl', 'miracle-wifictl',
install_dir: join_paths(get_option('datadir'), 'bash-completions', 'completions')
)

13
res/miracle-agent.desktop Normal file
View File

@ -0,0 +1,13 @@
[Desktop Entry]
Name=miracle-agent-shell
#comment=shell of miracleagent.service
#Comment[zh_CN]=任务栏
#Exec=systemctl --user enable miracle-agent.service && systemctl --user start miracle-agent.service
Exec=/usr/bin/miracle-agent
Terminal=false
Type=Application
#Icon=panel
X-UKUI-AutoRestart=true
#OnlyShowIn=UKUI
NoDisplay=true
#X-UKUI-Autostart-Phase=Panel

108
res/miracle-gst Executable file
View File

@ -0,0 +1,108 @@
#!/bin/bash
function help {
local scriptname="$(basename $0)"
cat >&2 <<EOF
$scriptname [options]
play rtp stream
Options:
-r Resolution
-s <Width>x<height> Scale
-d <level> Log level for gst
-p <port> Port for stream
-a Enables audio
-h Show this help
Examples:
# play stream on port 7236
$ $scriptname -p 7236
# play stream with resolution 800x600
$ $scriptname -s 800x600
# play stream with audio
$ $scriptname -a
# play stream with debug level 3
$ $scriptname -d 3
EOF
}
DEBUG='0'
AUDIO='0'
SCALE='0'
while getopts "r:d:as:p:h" optname
do
case "$optname" in
"h")
help
exit 0
;;
"d")
DEBUG=`echo ${OPTARG} | tr -d ' '`
;;
"r")
RESOLUTION=`echo ${OPTARG} | tr -d ' '`
;;
"a")
AUDIO='1'
;;
"p")
PORT=`echo ${OPTARG} | tr -d ' '`
;;
"s")
SCALE='1'
WIDTH=`echo ${OPTARG} | tr -d ' ' | cut -dx -f 1`
HEIGHT=`echo ${OPTARG} | tr -d ' ' | cut -dx -f 2`
;;
"?")
echo "Unknown option $OPTARG"
;;
*)
echo "Unknown parameter $OPTARG"
help
exit 1
;;
esac
done
RUN="/usr/bin/gst-launch-1.0 -v "
if [ $DEBUG != '0' ]
then
RUN+="--gst-debug=${DEBUG} "
fi
RUN+="udpsrc port=$PORT buffer-size=212992 caps=\"application/x-rtp, media=video\" ! rtpjitterbuffer latency=20 ! rtpmp2tdepay ! tsdemux "
if [ $AUDIO == '1' ]
then
RUN+="name=demuxer demuxer. "
fi
# RUN+="! queue max-size-buffers=0 max-size-time=0 ! h264parse ! avdec_h264 ! videoconvert ! "
# RUN+="! queue max-size-buffers=0 max-size-time=0 ! h264parse ! avdec_h264 ! videoconvert ! videorate ! video/x-raw,framerate=1/1 !"
# RUN+="! queue max-size-buffers=0 max-size-time=0 ! h264parse ! avdec_h264 ! videoconvert ! videorate drop-only=true max-rate=2 !"
#videoconvert n-threads=4 !
RUN+="! queue name=video_ch max-size-buffers=0 max-size-time=0 ! h264parse ! queue name=dec0 max-size-buffers=0 max-size-time=0 ! avdec_h264 max-threads=4 skip-frame=1 output-corrupt=false ! videoconvert n-threads=4 !"
#RUN+="! queue name=video_ch max-size-buffers=0 max-size-time=0 ! h264parse ! queue name=dec0 ! avdec_h264_omx_dec skip-frame=1 ! videoconvert n-threads=4 !"
if [ $SCALE == '1' ]
then
RUN+="videoscale method=1 ! video/x-raw,width=${WIDTH},height=${HEIGHT} ! "
fi
#RUN+="glimagesinkelement sync=false "
#RUN+="autovideosink sync=false async=false "
#RUN+="v4l2sink sync=false "
RUN+=" xvimagesink display=:0 force-aspect-ratio=false sync=false async=false "
if [ $AUDIO == '1' ]
then
RUN+="demuxer. ! queue name=audio_ch max-size-buffers=0 max-size-time=0 ! aacparse ! avdec_aac ! audioconvert ! audioresample ! autoaudiosink "
fi
echo "running: $RUN"
exec ${RUN}

69
res/miracle-omxplayer Executable file
View File

@ -0,0 +1,69 @@
#!/bin/bash
function help {
local scriptname="$(basename $0)"
cat >&2 <<EOF
$scriptname [options]
play rtp stream with omxplayer
Options:
-r Resolution
-s <Width>x<height> Scale
-d <level> Log level for gst
-p <port> Port for stream
-a Enables audio
-h Show this help
Examples:
# play stream on port 7236
$ $scriptname -p 7236
EOF
}
DEBUG='0'
AUDIO='0'
SCALE='0'
while getopts "r:d:as:p:h" optname
do
case "$optname" in
"h")
help
exit 0
;;
"d")
DEBUG=`echo ${OPTARG} | tr -d ' '`
;;
"r")
RESOLUTION=`echo ${OPTARG} | tr -d ' '`
;;
"a")
AUDIO='1'
;;
"p")
PORT=`echo ${OPTARG} | tr -d ' '`
;;
"s")
SCALE='1'
WIDTH=`echo ${OPTARG} | tr -d ' ' | cut -dx -f 1`
HEIGHT=`echo ${OPTARG} | tr -d ' ' | cut -dx -f 2`
;;
"?")
echo "Unknown option $OPTARG"
;;
*)
echo "Unknown parameter $OPTARG"
help
exit 1
;;
esac
done
RUN="omxplayer -live -b -o hdmi rtp://@:$PORT"
echo "running: $RUN"
exec ${RUN}

85
res/miracle-sinkctl Executable file
View File

@ -0,0 +1,85 @@
#
# Autocompletion for miraclecast commands
#
# Maintainer: Alberto Fanjul <albertofanjul@gmail.com>
#
function _miracle-sinkctl() {
local cur prev
_get_comp_words_by_ref cur
prev=${COMP_WORDS[COMP_CWORD-1]}
case "$prev" in
--log-level)
COMPREPLY=($(compgen -W 'fatal alert critical error warning notice info debug trace 1 2 3 4 5 6 7 8' -- "$cur"))
return 0
;;
esac
COMPREPLY=($(compgen -W "$(_parse_help miracle-sinkctl) $(_parse_short_help miracle-sinkctl)" -- "$cur"))
}
_parse_short_help ()
{
eval local cmd=$( quote "$1" );
local line;
{
case $cmd in
-)
cat
;;
*)
LC_ALL=C "$( dequote "$cmd" )" ${2:---help} 2>&1
;;
esac
} | while read -r line; do
[[ $line == *([[:blank:]])-* ]] || continue;
while [[ $line =~ ((^|[^-])-[A-Za-z0-9?][[:space:]]+)\[?[A-Z0-9]+\]? ]]; do
line=${line/"${BASH_REMATCH[0]}"/"${BASH_REMATCH[1]}"};
done;
__parse_short_options "${line// or /, }";
done
}
__parse_short_options ()
{
local option option2 i IFS='
,/|';
option=;
local -a array;
read -a array <<< "$1";
for i in "${array[@]}";
do
case "$i" in
---*)
break
;;
--?*)
break
;;
-?*)
option=$i;
break
;;
*)
break
;;
esac;
done;
[[ -n $option ]] || return;
IFS='
';
if [[ $option =~ (\[((no|dont)-?)\]). ]]; then
option2=${option/"${BASH_REMATCH[1]}"/};
option2=${option2%%[<{().[]*};
printf '%s\n' "${option2/=*/=}";
option=${option/"${BASH_REMATCH[1]}"/"${BASH_REMATCH[2]}"};
fi;
option=${option%%[<{().[]*};
printf '%s\n' "${option/=*/=}"
}
complete -F _miracle-sinkctl miracle-sinkctl
# ex: filetype=sh

203
res/miracle-utils.sh Executable file
View File

@ -0,0 +1,203 @@
#http://lxr.linux.no/linux+v3.0/include/linux/if_arp.h#L67
ARPHRD_LOOPBACK=772
#
# Find all interfaces except loopback one
#
function find_choosable_networknames {
for i in $( ls /sys/class/net )
do
if [ $( cat /sys/class/net/$i/type ) != $ARPHRD_LOOPBACK ]
then
echo $i
fi
done
}
#
# find wireless interfaces
#
function find_wireless_network_interfaces {
for i in $( find_choosable_networknames )
do
if [ -d /sys/class/net/$i/wireless ]
then
echo $i
fi
done
}
#
# show pci slot
#
function show_pci_slot {
basename $(readlink /sys/class/net/$1/device) | cut -d: -f2 | sed 's/^0*//'
}
#
# test if interface is connected
#
function is_interface_connected {
test x$( cat /sys/class/net/$1/carrier 2>/dev/null) = x1
}
#
# find wireless pci slot
#
function find_wireless_pci_slot {
for i in $( find_wireless_network_interfaces )
do
show_pci_slot $i
done
}
#
# find wireless pci slot
#
function find_wireless_ifindex {
for i in $( find_wireless_network_interfaces )
do
show_ifindex $i
done
}
#
# find wireless connected interfaces
#
function find_wireless_connected_network_interfaces {
for i in $( find_wireless_network_interfaces )
do
if is_interface_connected $i
then
echo $i
fi
done
}
#
# find physical for interface if exists
#
function find_physical_for_network_interface {
PHY_INDEX=$(iw dev $1 info | grep wiphy | awk '{print $2}')
if [ -n "$PHY_INDEX" ]
then
echo phy$PHY_INDEX
fi
}
#
# find interface index for interface
#
function show_ifindex {
IF_INDEX=$(iw dev $1 info | grep ifindex | awk '{print $2}')
if [ -n "$IF_INDEX" ]
then
echo $IF_INDEX
fi
}
#
# Check interface for P2P capabilities
#
function search_p2p_capabilities {
WI_DEVICE=$1
PHY_DEVICE=$(find_physical_for_network_interface $WI_DEVICE)
if [ -z "$PHY_DEVICE" ]
then
echo "cannot find physical device for $WI_DEVICE"
return
fi
if iw phy $PHY_DEVICE info | grep -Pzo "(?s)Supported interface modes.*Supported commands" | grep "P2P" &> /dev/null
then
echo $WI_DEVICE supports P2P
else
echo Sorry, $WI_DEVICE do not support P2P
exit 1
fi
}
#
# show wpa_supplicant command
#
function show_wpa_supplicant_process {
ps -ef | grep "wpa_supplican[t] "
}
#
# show wpa_supplicant command
#
function show_wpa_supplicant_command {
show_wpa_supplicant_process | awk '{print substr($0, index($0,$8))}'
}
#
# find wpa_supplicant pid
#
function find_wpa_supplicant_pid {
show_wpa_supplicant_process | awk '{print $2}'
}
#
# checking if distro is archlinux
#
function check_archlinux_distro {
test -f "/etc/arch-release"
}
#
# checking if distro is ubuntu
#
function check_ubuntu_distro {
cat /proc/version | grep -i ubuntu
}
#
# checking if distro is debian
#
function check_debian_distro {
cat /proc/version | grep -i debian
}
#
# ubuntu manager restarts automatically wpa_supplicant
#
function kill_ubuntu_network_manager {
if check_ubuntu_distro || check_debian_distro
then
echo stopping NetworkManager
sudo service NetworkManager stop
fi
}
#
# arch linux manager restarts automatically wpa_supplicant
#
function kill_archlinux_network_manager {
if check_ubuntu_distro
then
echo stopping NetworkManager
sudo systemctl stop Network.service
fi
}
#
# start ubuntu manager
#
function start_ubuntu_network_manager {
if check_ubuntu_distro || check_debian_distro
then
echo starting NetworkManager
sudo service NetworkManager start
fi
}
#
# start arch linux manager
#
function start_archlinux_network_manager {
if check_archlinux_distro
then
echo starting NetworkManager
sudo systemctl start Network.service
fi
}

69
res/miracle-vlc Executable file
View File

@ -0,0 +1,69 @@
#!/bin/bash
function help {
local scriptname="$(basename $0)"
cat >&2 <<EOF
$scriptname [options]
play rtp stream with vlc
Options:
-r Resolution
-s <Width>x<height> Scale
-d <level> Log level for gst
-p <port> Port for stream
-a Enables audio
-h Show this help
Examples:
# play stream on port 7236
$ $scriptname -p 7236
EOF
}
DEBUG='0'
AUDIO='0'
SCALE='0'
while getopts "r:d:as:p:h" optname
do
case "$optname" in
"h")
help
exit 0
;;
"d")
DEBUG=`echo ${OPTARG} | tr -d ' '`
;;
"r")
RESOLUTION=`echo ${OPTARG} | tr -d ' '`
;;
"a")
AUDIO='1'
;;
"p")
PORT=`echo ${OPTARG} | tr -d ' '`
;;
"s")
SCALE='1'
WIDTH=`echo ${OPTARG} | tr -d ' ' | cut -dx -f 1`
HEIGHT=`echo ${OPTARG} | tr -d ' ' | cut -dx -f 2`
;;
"?")
echo "Unknown option $OPTARG"
;;
*)
echo "Unknown parameter $OPTARG"
help
exit 1
;;
esac
done
RUN="vlc rtp://@:$PORT"
echo "running: $RUN"
exec ${RUN}

85
res/miracle-wifictl Executable file
View File

@ -0,0 +1,85 @@
#
# Autocompletion for miracle-wifictl
#
# Maintainer: Alberto Fanjul <albertofanjul@gmail.com>
#
function _miracle-wifictl() {
local cur prev
_get_comp_words_by_ref cur
prev=${COMP_WORDS[COMP_CWORD-1]}
case "$prev" in
--log-level)
COMPREPLY=($(compgen -W 'fatal alert critical error warning notice info debug trace 1 2 3 4 5 6 7 8' -- "$cur"))
return 0
;;
esac
COMPREPLY=($(compgen -W "$(_parse_help miracle-wifictl) $(_parse_short_help miracle-wifictl)" -- "$cur"))
}
_parse_short_help ()
{
eval local cmd=$( quote "$1" );
local line;
{
case $cmd in
-)
cat
;;
*)
LC_ALL=C "$( dequote "$cmd" )" ${2:---help} 2>&1
;;
esac
} | while read -r line; do
[[ $line == *([[:blank:]])-* ]] || continue;
while [[ $line =~ ((^|[^-])-[A-Za-z0-9?][[:space:]]+)\[?[A-Z0-9]+\]? ]]; do
line=${line/"${BASH_REMATCH[0]}"/"${BASH_REMATCH[1]}"};
done;
__parse_short_options "${line// or /, }";
done
}
__parse_short_options ()
{
local option option2 i IFS='
,/|';
option=;
local -a array;
read -a array <<< "$1";
for i in "${array[@]}";
do
case "$i" in
---*)
break
;;
--?*)
break
;;
-?*)
option=$i;
break
;;
*)
break
;;
esac;
done;
[[ -n $option ]] || return;
IFS='
';
if [[ $option =~ (\[((no|dont)-?)\]). ]]; then
option2=${option/"${BASH_REMATCH[1]}"/};
option2=${option2%%[<{().[]*};
printf '%s\n' "${option2/=*/=}";
option=${option/"${BASH_REMATCH[1]}"/"${BASH_REMATCH[2]}"};
fi;
option=${option%%[<{().[]*};
printf '%s\n' "${option/=*/=}"
}
complete -F _miracle-wifictl miracle-wifictl
# ex: filetype=sh

95
res/miracle-wifid Executable file
View File

@ -0,0 +1,95 @@
#
# Autocompletion for miracle-wifid
#
# Maintainer: Alberto Fanjul <albertofanjul@gmail.com>
#
function _miracle-wifid() {
local cur prev
_get_comp_words_by_ref cur
prev=${COMP_WORDS[COMP_CWORD-1]}
case "$prev" in
--config-methods)
COMPREPLY=($(compgen -W 'pbc pin usba ethernet label display ext_nfc_token int_nfc_token nfc_interface push_button keypad virtual_display physical_display virtual_push_button physical_push_button' -- "$cur"))
return 0
;;
--log-level)
COMPREPLY=($(compgen -W 'fatal alert critical error warning notice info debug trace 1 2 3 4 5 6 7 8' -- "$cur"))
return 0
;;
--wpa-loglevel)
COMPREPLY=($(compgen -W 'fatal alert critical error warning notice info debug trace 1 2 3 4 5 6 7 8' -- "$cur"))
return 0
;;
esac
COMPREPLY=($(compgen -W "$(_parse_help miracle-wifid) $(_parse_short_help miracle-wifid)" -- "$cur"))
}
_parse_short_help ()
{
eval local cmd=$( quote "$1" );
local line;
{
case $cmd in
-)
cat
;;
*)
LC_ALL=C "$( dequote "$cmd" )" ${2:---help} 2>&1
;;
esac
} | while read -r line; do
[[ $line == *([[:blank:]])-* ]] || continue;
while [[ $line =~ ((^|[^-])-[A-Za-z0-9?][[:space:]]+)\[?[A-Z0-9]+\]? ]]; do
line=${line/"${BASH_REMATCH[0]}"/"${BASH_REMATCH[1]}"};
done;
__parse_short_options "${line// or /, }";
done
}
__parse_short_options ()
{
local option option2 i IFS='
,/|';
option=;
local -a array;
read -a array <<< "$1";
for i in "${array[@]}";
do
case "$i" in
---*)
break
;;
--?*)
break
;;
-?*)
option=$i;
break
;;
*)
break
;;
esac;
done;
[[ -n $option ]] || return;
IFS='
';
if [[ $option =~ (\[((no|dont)-?)\]). ]]; then
option2=${option/"${BASH_REMATCH[1]}"/};
option2=${option2%%[<{().[]*};
printf '%s\n' "${option2/=*/=}";
option=${option/"${BASH_REMATCH[1]}"/"${BASH_REMATCH[2]}"};
fi;
option=${option%%[<{().[]*};
printf '%s\n' "${option/=*/=}"
}
complete -F _miracle-wifid miracle-wifid
# ex: filetype=sh

View File

@ -0,0 +1,23 @@
[Unit]
Description=Miraclecast WiFi Daemon
After=dbus.service
Requires=network.target
[Service]
BusName=org.freedesktop.miracle.wifi
Environment=PATH=/sbin:/usr/bin
# ExecStart=@CMAKE_INSTALL_PREFIX@/bin/miracle-wifid \
# --use-dev \
# --log-level info \
# --lazy-managed \
# --config-methods display \
# --wpa-loglevel trace
ExecStart=/usr/bin/execstart.sh
ExecStop=/usr/bin/recover_wpas.sh
#CapabilityBoundingSet=CAP_NET_ADMIN \
# CAP_NET_BIND_SERVICE \
# CAP_NET_RAW
[Install]
WantedBy=multi-user.target
Alias=dbus-org.freedesktop.miracle.wifi.service

View File

@ -0,0 +1,20 @@
[Unit]
Description=Miraclecast WiFi Daemon
After=dbus.service
Requires=network.target
[Service]
BusName=@dbus_name_prefix@.wifi
Environment=PATH=/sbin:/usr/bin
ExecStart=@exec_path@/miracle-wifid \
--use-dev \
--log-level error \
--lazy-managed \
--config-methods display
#CapabilityBoundingSet=CAP_NET_ADMIN \
# CAP_NET_BIND_SERVICE \
# CAP_NET_RAW
[Install]
WantedBy=multi-user.target
Alias=dbus-@dbus_name_prefix@.wifi.service

View File

@ -0,0 +1,18 @@
FROM debian:buster-slim
RUN dpkg --add-architecture i386
RUN apt-get update && apt-get install -y \
build-essential \
systemd \
libglib2.0-dev \
libreadline-dev \
libudev-dev \
libsystemd-dev \
libusb-dev \
automake \
autoconf \
libtool \
cmake \
meson

60
res/miraclecast.spec Normal file
View File

@ -0,0 +1,60 @@
%global commit c3c868e523f450ad4f0d77f5484a3b61f08120b7
%global shortcommit %(c=%{commit}; echo ${c:0:7})
Name: miraclecast
Version: 1.0
Release: 1.git%{shortcommit}%{?dist}
Summary: Connect external monitors to your system via Wifi-Display
License: LGPL
URL: https://github.com/albfan/miraclecast
Source0: https://github.com/albfan/miraclecast/archive/%{commit}/%{name}-%{shortcommit}.tar.gz
BuildRequires: autoconf, automake, libtool
BuildRequires: readline-devel, glib2-devel, systemd-devel
%description
The MiracleCast project provides software to connect external monitors to your system via Wi-Fi. It is compatible to the Wifi-Display specification also known as Miracast. MiracleCast implements the Display-Source as well as Display-Sink side.
The Display-Source side allows you to connect external displays to your system and stream local content to the device. A lot of effort is put into making this as easy as connecting external displays via HDMI.
On the other hand, the Display-Sink side allows you to create wifi-capable external displays yourself. You can use it on your embedded devices or even on full desktops to allow other systems to use your device as external display.
%prep
%autosetup -n %{name}-%{shortcommit}
%build
mkdir build
cd build
../autogen.sh g --prefix=%{_prefix}
%make_build
%install
rm -rf $RPM_BUILD_ROOT
cd build
%make_install
%files
%license COPYING LICENSE_gdhcp LICENSE_htable LICENSE_lgpl
%doc README.md
%{_sysconfdir}/dbus-1/system.d/org.freedesktop.miracle.conf
%{_bindir}/miracle-wifictl
%{_bindir}/miracle-omxplayer
%{_bindir}/miracle-gst
%{_bindir}/miracle-sinkctl
%{_bindir}/miracled
%{_bindir}/miracle-dhcp
%{_bindir}/miracle-uibcctl
%{_bindir}/miracle-wifid
%{_bindir}/gstplayer
%{_bindir}/uibc-viewer
%{_datadir}/bash-completion/completions/miracle-wifictl
%{_datadir}/bash-completion/completions/miracle-sinkctl
%{_datadir}/bash-completion/completions/miracle-wifid
%changelog
* Wed Nov 21 2018 Graham White
- first build

View File

@ -0,0 +1,24 @@
This file can be used with the rpmbuild or mock commands to create a binary RPM. Tested and working on Fedora 28 x86\_64.
Example usage (for Fedora 28 systems):
1. Create a tar.gz file of the source code and add the short name of the commit to the tar file, for the most recent commit at the time of writing this would be:
* `git clone https://github.com/albfan/miraclecast.git miraclecast-c3c868e`
* `tar -zcf miraclecast-c3c868e.tar.gz miraclecast-c3c868e`
2. Create a Source RPM
* `rpmbuild -bs miraclecast.spec --define "_sourcedir $PWD"`
Then build the RPM with one of the following:
* Using mock (assuming you're in the dir where the .src.rpm file is):
* `mock --arch=x86_64 -r fedora-28-x86_64 --resultdir=results miraclecast-1.0-1.gitc3c868e.fc28.src.rpm`
OR
* Using rpmbuild (assuming you're in the dir where the .src.rpm file is):
* `rpmbuild -ra miraclecast-1.0-1.gitc3c868e.fc28.src.rpm`
OR
* Using rpmbuild (assuming you're in the dir where the .spec and .tar.gz files are):
* `rpmbuild -bs miraclecast.spec --define "_sourcedir $PWD"``

57
res/normal-wifi.sh Executable file
View File

@ -0,0 +1,57 @@
#!/bin/bash
./kill-wpa.sh
. miracle-utils.sh
ETHER_NAMES=$(find_choosable_networknames)
ETHER_COUNT=$(echo "$ETHER_NAMES" | wc -l)
if [ 0 = $ETHER_COUNT ]
then
echo There is no net devices avaliable
exit 1
elif [ 1 = $ETHER_COUNT ]
then
ETHERNAME="$ETHER_NAMES"
elif [ 2 -le $ETHER_COUNT ]
then
echo choose device for normal connection:
QUIT="exit"
select et_name in $ETHER_NAMES $QUIT
do
case $et_name
in
"$QUIT")
exit
;;
"")
if [ "$REPLY" = $QUIT ]
then
exit
else
echo unknow $REPLY
fi
;;
*)
ETHERNAME=$et_name
break
;;
esac
done
fi
# default path for config file
CONFIG_FILE=${1:-/run/network/wpa_supplicant_${ETHERNAME}.conf}
echo starting wpa_supplicant for normal connection
if check_ubuntu_distro || check_debian_distro
then
start_ubuntu_network_manager
sudo wpa_supplicant -B -u -s -O /var/run/wpa_supplicant
else
sudo wpa_supplicant -B -u -P /run/wpa_supplicant_${ETHERNAME}pid -i ${ETHERNAME} -D nl80211 -c$CONFIG_FILE
fi

View File

@ -0,0 +1,107 @@
<?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 MiracleCast.
-->
<busconfig>
<policy user="root">
<allow own="org.freedesktop.miracle"/>
<allow own="org.freedesktop.miracle.wifi"/>
<allow send_destination="org.freedesktop.miracle"/>
<allow send_destination="org.freedesktop.miracle.wifi"/>
<allow receive_sender="org.freedesktop.miracle"/>
<allow receive_sender="org.freedesktop.miracle.wifi"/>
<allow receive_sender="org.freedesktop.miracleagent"/>
<allow receive_sender="org.freedesktop.login1"/>
</policy>
<policy context="default">
<deny send_destination="org.freedesktop.miracle"/>
<deny send_destination="org.freedesktop.miracle.wifi"/>
<allow send_destination="org.freedesktop.miracle"
send_interface="org.freedesktop.DBus.Introspectable"/>
<allow send_destination="org.freedesktop.miracle.wifi"
send_interface="org.freedesktop.DBus.Introspectable"/>
<allow send_destination="org.freedesktop.miracle"
send_interface="org.freedesktop.DBus.Peer"/>
<allow send_destination="org.freedesktop.miracle.wifi"
send_interface="org.freedesktop.DBus.Peer"/>
<allow send_destination="org.freedesktop.miracle"
send_interface="org.freedesktop.DBus.ObjectManager"/>
<allow send_destination="org.freedesktop.miracle.wifi"
send_interface="org.freedesktop.DBus.ObjectManager"/>
<allow send_destination="org.freedesktop.miracle"
send_interface="org.freedesktop.DBus.Properties"
send_member="Get"/>
<allow send_destination="org.freedesktop.miracle.wifi"
send_interface="org.freedesktop.DBus.Properties"
send_member="Get"/>
<allow send_destination="org.freedesktop.miracle"
send_interface="org.freedesktop.DBus.Properties"
send_member="GetAll"/>
<allow send_destination="org.freedesktop.miracle.wifi"
send_interface="org.freedesktop.DBus.Properties"
send_member="GetAll"/>
<allow send_destination="org.freedesktop.miracle.wifi"
send_interface="org.freedesktop.miracle.wifi.ui"
send_member="UsrDisconnect"/>
<allow send_destination="org.freedesktop.miracle.wifi"
send_interface="org.freedesktop.miracle.wifi.ui"
send_member="ProjectionOp"/>
<allow send_destination="org.freedesktop.miracle.wifi"
send_interface="org.freedesktop.miracle.wifi.ui"
send_member="HandShake"/>
<allow send_destination="org.freedesktop.miracle.wifi"
send_interface="org.freedesktop.miracle.wifi.ui"
send_member="SetSinkName"/>
<allow send_destination="org.freedesktop.miracle.wifi"
send_interface="org.freedesktop.miracle.wifi.ui"
send_member="SetSinkConfigMethods"/>
<allow send_destination="org.freedesktop.miracle.wifi"
send_interface="org.freedesktop.miracle.wifi.ui"
send_member="QueryConnectedDevice"/>
<allow send_destination="org.freedesktop.miracle.wifi"
send_interface="org.freedesktop.miracle.wifi.ui"
send_member="DeleteConnectedDevice"/>
<allow send_destination="org.freedesktop.miracle.wifi"
send_interface="org.freedesktop.miracle.wifi.ui"
send_member="StartWpas"/>
<allow send_destination="org.freedesktop.miracle.wifi"
send_interface="org.freedesktop.miracle.wifi.ui"
send_member="StopWpas"/>
<allow send_destination="org.freedesktop.miracle.wifi"
send_interface="org.freedesktop.miracle.wifi.ui"
send_member="ResolutionUpdate"/>
<allow send_destination="org.freedesktop.miracle.wifi"
send_interface="org.freedesktop.miracle.wifi.ui"
send_member="AgtStartR2Sess"/>
<allow send_destination="org.freedesktop.miracle.wifi"
send_interface="org.freedesktop.miracle.wifi.ui"
send_member="QueryWpaStopped"/>
<allow send_destination="org.freedesktop.miracle.wifi"
send_interface="org.freedesktop.miracle.wifi.ui"
send_member="SetManufacturer"/>
<allow send_destination="org.freedesktop.miracle.wifi"
send_interface="org.freedesktop.miracle.wifi.ui"
send_member="QueryGroupInfo"/>
<allow send_destination="org.freedesktop.miracle.wifi"
send_interface="org.freedesktop.miracle.wifi.ui"
send_member="userChosen"/>
<allow receive_sender="org.freedesktop.miracle"/>
<allow receive_sender="org.freedesktop.miracle.wifi"/>
<allow receive_sender="org.freedesktop.login1"/>
</policy>
</busconfig>

107
res/projectionStart.sh Executable file
View File

@ -0,0 +1,107 @@
#!/bin/bash
eval SCRIPT_DEBUG="\$$(basename $0 .sh | tr - _)_DEBUG"
SCRIPT_DEBUG=${SCRIPT_DEBUG:--1}
if [ "$SCRIPT_DEBUG" -ge 1 ]
then
set -x
fi
if [ "$SCRIPT_DEBUG" -ge 10 ]
then
set -v
fi
##START of common funcs, moved to /home/$USR/.config/miracast latter
LOOPBACK=772
function find_choosable_networknames {
for i in $( ls /sys/class/net )
do
if [ $( cat /sys/class/net/$i/type ) != $LOOPBACK ]
then
echo $i
fi
done
}
function find_wireless_network_interfaces {
for i in $( find_choosable_networknames )
do
if [ -d /sys/class/net/$i/wireless ]
then
echo $i
fi
done
}
function find_physical_for_network_interface {
PHY_INDEX=$(iw dev $1 info | grep wiphy | awk '{print $2}')
if [ -n "$PHY_INDEX" ]
then
echo phy$PHY_INDEX
fi
}
function search_p2p_capabilities {
WI_DEVICE=$1
PHY_DEVICE=$(find_physical_for_network_interface $WI_DEVICE)
SUCC=0
FAIL=1
if [ -z "$PHY_DEVICE" ]
then
echo "cannot find physical device for $WI_DEVICE"
return
fi
if iw phy $PHY_DEVICE info | grep -Pzo "(?s)Supported interface modes.*Supported commands" | grep "P2P" &> /dev/null
then
echo $WI_DEVICE supports P2P
else
echo Sorry, $WI_DEVICE do not support P2P
# exit 1
fi
}
##END of common funcs, moved to /home/$USR/.config/miracast latter
WIFI_COUNT=0
WIFI_NAMES="$(find_wireless_network_interfaces)"
if [ -n "$WIFI_NAMES" ]
then
WIFI_COUNT=$(echo "$WIFI_NAMES" | wc -l)
fi
if [ 0 = $WIFI_COUNT ]
then
echo There is no wireless devices available
exit 1
elif [ 1 = $WIFI_COUNT ]
then
WIFI_NAME="$WIFI_NAMES"
elif [ 2 -ge $WIFI_COUNT ]
then
echo Support Only one wireless card @v1.0
fi
RETSTR=$(search_p2p_capabilities $WIFI_NAME)
echo $RETSTR
TARGET="not"
if [[ $RETSTR =~ $TARGET ]]
then
echo "FAILURE"
exit 1
fi
AGENT_PNAME="miracle-agent"
AGENT_PNUM=`ps -ef | grep $AGENT_PNAME | grep -v grep | wc -l`
if [ $AGENT_PNUM -gt 0 ]
then
echo "SUCCESS"
else
echo "Agent not running!!! Quit..."
exit 1
fi
nmcli device set $WIFI_NAME managed no
systemctl restart miracle-wifid.service

58
res/projectionStop.sh Executable file
View File

@ -0,0 +1,58 @@
#!/bin/bash
eval SCRIPT_DEBUG="\$$(basename $0 .sh | tr - _)_DEBUG"
SCRIPT_DEBUG=${SCRIPT_DEBUG:--1}
if [ "$SCRIPT_DEBUG" -ge 1 ]
then
set -x
fi
if [ "$SCRIPT_DEBUG" -ge 10 ]
then
set -v
fi
##common funcs, moved to /home/$USR/.config/miracast
LOOPBACK=772
function find_choosable_networknames {
for i in $( ls /sys/class/net )
do
if [ $( cat /sys/class/net/$i/type ) != $LOOPBACK ]
then
echo $i
fi
done
}
function find_wireless_network_interfaces {
for i in $( find_choosable_networknames )
do
if [ -d /sys/class/net/$i/wireless ]
then
echo $i
fi
done
}
##END of common funcs, moved to /home/$USR/.config/miracast
WIFI_COUNT=0
WIFI_NAMES="$(find_wireless_network_interfaces)"
if [ -n "$WIFI_NAMES" ]
then
WIFI_COUNT=$(echo "$WIFI_NAMES" | wc -l)
fi
if [ 0 = $WIFI_COUNT ]
then
echo There is no wireless devices available
exit 1
elif [ 1 = $WIFI_COUNT ]
then
WIFI_NAME="$WIFI_NAMES"
elif [ 2 -ge $WIFI_COUNT ]
then
echo Support Only one wireless card @v1.0
fi
systemctl stop miracle-wifid.service
nmcli device set $WIFI_NAME managed yes

6
res/recover_wpas.sh Executable file
View File

@ -0,0 +1,6 @@
#!/bin/bash
sudo systemctl unmask wpa_supplicant.service
sudo systemctl start wpa_supplicant.service
echo "We recover wpa_supplicant.service !!!!!!!!!!!!!!!"

1
res/show_wpa.sh Executable file
View File

@ -0,0 +1 @@
ps -ef | grep wpa_supplican[t]

View File

@ -0,0 +1,61 @@
#!/bin/bash
eval SCRIPT_DEBUG="\$$(basename $0 .sh | tr - _)_DEBUG"
SCRIPT_DEBUG=${SCRIPT_DEBUG:--1}
if [ "$SCRIPT_DEBUG" -ge 1 ]
then
set -x
fi
if [ "$SCRIPT_DEBUG" -ge 10 ]
then
set -v
fi
. miracle-utils.sh
WIFI_COUNT=0
WIFI_NAMES="$(find_wireless_network_interfaces)"
if [ -n "$WIFI_NAMES" ]
then
WIFI_COUNT=$(echo "$WIFI_NAMES" | wc -l)
fi
if [ 0 = $WIFI_COUNT ]
then
echo There is no wireless devices available
exit 1
elif [ 1 = $WIFI_COUNT ]
then
WIFI_NAME="$WIFI_NAMES"
elif [ 2 -ge $WIFI_COUNT ]
then
echo Choose wireless device:
PS3="device: "
QUIT="exit"
select wi_name in $WIFI_NAMES $QUIT
do
case $wi_name
in
"$QUIT")
exit
;;
"")
if [ "$REPLY" = $QUIT ]
then
exit
else
echo unknow $REPLY
fi
;;
*)
WIFI_NAME=$wi_name
break
;;
esac
done
fi
search_p2p_capabilities $WIFI_NAME

Some files were not shown because too many files have changed in this diff Show More