This commit is contained in:
RocketGod 2022-09-22 13:46:18 -07:00
parent 8347d2f50e
commit f65104c2ab
565 changed files with 0 additions and 165005 deletions

View File

@ -1,12 +0,0 @@
# These are supported funding model platforms
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
custom: ['https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=6WDFF59DL56Z2'] # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']

View File

@ -1,27 +0,0 @@
---
name: Bug report
about: Create a report to help us improve
---
##### Expected Behavior
<!-- A clear and concise description of what you expected to happen. -->
##### Actual Behavior
##### Steps To Reproduce
<!-- Explain the steps to reproduce the behavior. -->
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
##### Screenshots
<!-- If applicable, add screenshots to help explain your problem. -->
##### Platform Specifications
<!-- please complete the following information -->
- OS: [e.g. Arch Linux]
- URH version: [e.g. 2.4.2]
- Python version: [e.g. 3.7]
- Installed via [e.g. pip]

View File

@ -1,18 +0,0 @@
---
name: Feature request
about: Suggest an idea to enhance URH
---
##### Is your feature request related to a problem?
<!-- A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
-->
##### Describe the solution you'd like
<!-- A clear and concise description of what you want to happen. -->
##### Describe alternatives you've considered
<!-- A clear and concise description of any alternative solutions or features you've considered. -->
##### Additional context
<!-- Add any other context or screenshots about the feature request here. -->

View File

@ -1,195 +0,0 @@
name: CI
env:
PYTHONUNBUFFERED: 1
on:
push:
branches: [ master ]
tags: [ "v*" ]
pull_request:
branches: [ master ]
jobs:
ci:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-2019, macos-10.15]
python-version: ['3.7', '3.8', '3.9', '3.10']
architecture: [x64]
include:
- os: windows-2019
python-version: '3.7'
architecture: x86
exclude:
- os: windows-2019
python-version: '3.8'
- os: windows-2019
python-version: '3.9'
- os: windows-2019
python-version: '3.10'
- os: macOS-10.15
python-version: '3.7'
- os: macOS-10.15
python-version: '3.8'
- os: macOS-10.15
python-version: '3.10'
fail-fast: false
steps:
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
architecture: ${{ matrix.architecture }}
- name: Setup SDR Drivers (Windows)
if: startsWith(matrix.os, 'windows')
run: |
choco install wget --no-progress
wget -nv -O windrivers.zip https://github.com/jopohl/sdrbuild/releases/download/v1.1/win-$ARCH.zip
7z x windrivers.zip -osrc/urh/dev/native/lib/shared
ls src/urh/dev/native/lib/shared
shell: bash
env:
ARCH: ${{ matrix.architecture }}
- name: Install Dependencies
run: |
pip install wheel
pip install -r data/requirements.txt
if [[ $OS == ubuntu* ]]
then
sudo apt-get update
sudo apt-get install libhackrf-dev librtlsdr-dev xvfb libxkbcommon-x11-0 x11-utils libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-randr0 libxcb-render-util0 libxcb-xinerama0
pip install PyVirtualDisplay==0.2.5
elif [[ $OS == windows* ]]
then
pip install pywin32 pipwin
pipwin install pyaudio
elif [[ $OS == mac* ]]
then
brew tap pothosware/homebrew-pothos
brew install airspy hackrf librtlsdr libbladerf limesuite portaudio uhd
wget -nv https://github.com/analogdevicesinc/libiio/releases/download/v0.23/macOS-10.15.pkg
sudo installer -pkg macOS-10.15.pkg -target /
sudo cp /Library/Frameworks/iio.framework/iio /usr/local/lib/libiio.dylib
sudo install_name_tool -id "/usr/local/lib/libiio.dylib" /usr/local/lib/libiio.dylib
file /usr/local/lib/libiio.dylib
otool -L /usr/local/lib/libiio.dylib
sudo cp /Library/Frameworks/iio.framework/Versions/0.23/Headers/iio.h /usr/local/include
wget -nv https://www.sdrplay.com/software/SDRplay_RSP_API-MacOSX-2.13.2.pkg
sudo installer -pkg SDRplay_RSP_API-MacOSX-2.13.2.pkg -target /
pip install pyaudio
pip install pillow
fi
pip install twine setuptools pytest pytest-xvfb pytest-cov pytest-faulthandler six appdirs packaging pyinstaller
python -c "import tempfile, os; open(os.path.join(tempfile.gettempdir(), 'urh_releasing'), 'w').close()"
shell: bash
env:
OS: ${{ matrix.os }}
- name: Build Cython Extensions
run: python src/urh/cythonext/build.py
- name: Create sdist
if: ${{ matrix.python-version == '3.9' && startsWith(matrix.os, 'ubuntu') }}
run: python setup.py sdist
- run: python setup.py bdist_wheel
if: ${{ !startsWith(matrix.os, 'ubuntu') }}
- name: Build manylinux2014
if: startsWith(matrix.os, 'ubuntu')
run: |
docker run --rm \
-e PYVER=$(python -c "import sys; print('%s%s' % (sys.version_info.major, sys.version_info.minor))") \
-v `pwd`:/io jopohl/urh_manylinux2014 /io/data/make_manylinux2014_wheels.sh
- name: Check wheel
if: startsWith(matrix.os, 'ubuntu')
run: |
pip install dist/*.whl
urh --version
xvfb-run urh autoclose
python data/check_native_backends.py
- name: Build .exe Installer
if: startsWith(matrix.os, 'windows')
run: |
python data/pyinstaller_helper.py
for /f %%i in ('python src/urh/version.py') do set URHVERSION=%%i
iscc /dMyAppVersion=%URHVERSION% /dArch=%PYARCH% data/inno.iss
shell: cmd
env:
PYARCH: ${{ matrix.architecture }}
- name: Check urh_debug.exe
if: startsWith(matrix.os, 'windows')
run: |
cd pyinstaller\urh
urh_debug.exe autoclose
shell: cmd
- name: Build DMG
if: startsWith(matrix.os, 'macos')
run: |
cp data/pyinstaller_macos.spec urh.spec
pyinstaller --clean --distpath ./pyinstaller --workpath ./urh_build urh.spec
mkdir -p dist
cat pyinstaller/main.app/Contents/Info.plist
hdiutil create -volname Universal.Radio.Hacker \
-srcfolder pyinstaller/main.app \
-ov -format UDZO \
dist/Universal.Radio.Hacker-"$(python src/urh/version.py)".dmg
- name: Upload artifacts
uses: actions/upload-artifact@v2
with:
name: dist-${{ matrix.os }}
path: dist
- name: Run pytest with coverage
if: ${{ startsWith(matrix.os, 'ubuntu') && matrix.python-version == '3.9' }}
run: |
touch tests/show_gui
cp tests/.coveragerc .
pytest -s -v --junitxml=junit/test-results.xml --cov=src --cov-config=.coveragerc tests
coverage xml
coverage html
- name: Run pytest without coverage
if: ${{ !startsWith(matrix.os, 'ubuntu') || matrix.python-version != '3.9' }}
run: pytest -s -v --junitxml=junit/test-results.xml tests
- uses: ncipollo/release-action@v1
if: startsWith(github.ref, 'refs/tags/')
with:
artifacts: "dist/*.exe,dist/*.dmg"
token: ${{ secrets.GITHUB_TOKEN }}
allowUpdates: true
generateReleaseNotes: true
omitBodyDuringUpdate: true
omitNameDuringUpdate: true
- name: Upload to PyPi
if: startsWith(github.ref, 'refs/tags/')
run: |
if [[ $OS == ubuntu* ]]
then
twine upload --skip-existing dist/*
else
twine upload --skip-existing dist/*.whl
fi
shell: bash
env:
TWINE_USERNAME: ${{ secrets.TWINE_USERNAME }}
TWINE_PASSWORD: ${{ secrets.TWINE_PASSWORD }}
TWINE_REPOSITORY_URL: "https://upload.pypi.org/legacy/"

View File

@ -1,56 +0,0 @@
# C extensions
*.so
.coverage
.pytest_cache
# Pycharm
.idea/
venv/
src/__pycache__/
src/urh/__pycache__/
__pycache__/
build/
src/urh/awre/__pycache__/
src/urh/awre/components/__pycache__/
src/urh/controller/__pycache__/
src/urh/cythonext/__pycache__/
src/urh/dev/__pycache__/
src/urh/dev/gr/__pycache__/
*.pyc
src/urh/dev/native/__pycache__/
src/urh/dev/native/lib/__pycache__/
src/urh/models/__pycache__/
src/urh/plugins/MessageBreak/__pycache__/
src/urh/plugins/ZeroHide/__pycache__/
src/urh/plugins/__pycache__/
src/urh/signalprocessing/__pycache__/
src/urh/ui/__pycache__/
src/urh/ui/actions/__pycache__/
src/urh/ui/delegates/__pycache__/
src/urh/ui/views/__pycache__/
src/urh/util/__pycache__/
tmp/
dist/
src/urh.egg-info/
.cache/
tests/data/URHProject.xml
src/urh/cythonext/*.html
src/urh/cythonext/*.c
src/urh/cythonext/*.cpp
src/urh/dev/native/lib/*.html
src/urh/dev/native/lib/*.c
src/urh/dev/native/lib/*.cpp
/tests/show_gui
src/urh/*.txt
src/urh/URHProject.xml
.coverage*
src/urh/dev/gr/scripts/top_block.py
misc/*

View File

@ -1,674 +0,0 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. 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
them 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 prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. 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.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey 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;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If 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 convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU 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 that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
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.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
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.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
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
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
Universal Radio Hacker: investigate wireless protocols like a boss
Copyright (C) 2022 Johannes Pohl and Andreas Noack
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 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, see <http://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
Universal Radio Hacker Copyright (C) 2022 Johannes Pohl and Andreas Noack
This program 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, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<http://www.gnu.org/licenses/>.
The GNU 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 Lesser General
Public License instead of this License. But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.

View File

@ -1,195 +0,0 @@
![URH image](https://raw.githubusercontent.com/jopohl/urh/master/data/icons/banner.png)
[![CI](https://github.com/jopohl/urh/actions/workflows/ci.yml/badge.svg)](https://github.com/jopohl/urh/actions/workflows/ci.yml)
[![PyPI version](https://badge.fury.io/py/urh.svg)](https://badge.fury.io/py/urh)
[![Packaging status](https://repology.org/badge/tiny-repos/urh.svg)](https://repology.org/project/urh/versions)
[![Blackhat Arsenal 2017](https://rawgit.com/toolswatch/badges/master/arsenal/usa/2017.svg)](http://www.toolswatch.org/2017/06/the-black-hat-arsenal-usa-2017-phenomenal-line-up-announced/)
[![Blackhat Arsenal 2018](https://rawgit.com/toolswatch/badges/master/arsenal/europe/2018.svg)](http://www.toolswatch.org/2018/09/black-hat-arsenal-europe-2018-lineup-announced/)
The Universal Radio Hacker (URH) is a complete suite for wireless protocol investigation with native support for [many](https://github.com/jopohl/urh/wiki/Supported-devices) common __Software Defined Radios__.
URH allows __easy demodulation__ of signals combined with an [automatic](https://dl.acm.org/doi/10.1145/3375894.3375896) detection of modulation parameters making it a breeze to identify the bits and bytes that fly over the air.
As data often gets _encoded_ before transmission, URH offers __customizable decodings__ to crack even sophisticated encodings like CC1101 data whitening.
When it comes to __protocol reverse-engineering__, URH is helpful in two ways. You can either manually assign protocol fields and message types or let URH __automatically infer protocol fields__ with a [rule-based intelligence](https://www.usenix.org/conference/woot19/presentation/pohl).
Finally, URH entails a __fuzzing component__ aimed at stateless protocols and a __simulation environment__ for stateful attacks.
### Getting started
In order to get started
- view the [installation instructions](#Installation) on this page,
- download the [official userguide (PDF)](https://github.com/jopohl/urh/releases/download/v2.0.0/userguide.pdf),
- watch the [demonstration videos (YouTube)](https://www.youtube.com/watch?v=kuubkTDAxwA&index=1&list=PLlKjreY6G-1EKKBs9sucMdk8PwzcFuIPB),
- check out the [wiki](https://github.com/jopohl/urh/wiki) for more information such as supported devices or
- read some [articles about URH](#Articles) for inspiration.
If you like URH, please :star: this repository and [join our Slack channel](https://join.slack.com/t/stralsundsecurity/shared_invite/enQtMjEwOTIxNzMzODc3LTk3NmE4MGVjYjEyYTMzYTdmN2RlNzUzYzg0NTNjNTQ2ODBkMzI3MDZlOWY3MjE4YjBkNTM4ZjJlNTJlZmJhNDg). We appreciate your support!
### Citing URH
We encourage researchers working with URH to cite [this](https://www.usenix.org/conference/woot18/presentation/pohl) WOOT'18 paper or directly use the following BibTeX entry.
<details>
<summary> <b>URH BibTeX entry for your research paper</b> </summary>
```bibtex
@inproceedings {220562,
author = {Johannes Pohl and Andreas Noack},
title = {Universal Radio Hacker: A Suite for Analyzing and Attacking Stateful Wireless Protocols},
booktitle = {12th {USENIX} Workshop on Offensive Technologies ({WOOT} 18)},
year = {2018},
address = {Baltimore, MD},
url = {https://www.usenix.org/conference/woot18/presentation/pohl},
publisher = {{USENIX} Association},
}
```
</details>
## Installation
URH runs on Windows, Linux and macOS. Click on your operating system below to view installation instructions.
<details>
<summary><b>Windows</b></summary><br/>
On Windows, URH can be installed with its [Installer](https://github.com/jopohl/urh/releases). No further dependencies are required.
If you get an error about missing ```api-ms-win-crt-runtime-l1-1-0.dll```, run Windows Update or directly install [KB2999226](https://support.microsoft.com/en-us/help/2999226/update-for-universal-c-runtime-in-windows).
</details>
<details>
<summary><b>Linux</b></summary>
<details open>
<summary><i>Generic Installation with pip (recommended)</i></summary><br/>
URH is available on [PyPi](https://pypi.org/project/urh/) so you can install it with
```bash
# IMPORTANT: Make sure your pip is up to date
sudo python3 -m pip install --upgrade pip # Update your pip installation
sudo python3 -m pip install urh # Install URH
```
This is the recommended way to install URH on Linux because it comes with __all native extensions__ precompiled.
In order to access your SDR as non-root user, install the according __udev rules__. You can find them [in the wiki](https://github.com/jopohl/urh/wiki/SDR-udev-rules).
</details>
<details>
<summary><i>Install via Package Manager</i></summary><br/>
URH is included in the repositories of many linux distributions such as __Arch Linux__, __Gentoo__, __Fedora__, __openSUSE__ or __NixOS__. There is also a package for __FreeBSD__. If available, simply use your package manager to install URH.
__Note__: For native support, you must install the according ```-dev``` package(s) of your SDR(s) such as ```hackrf-dev``` __before__ installing URH.
</details>
<details>
<summary><i>Snap</i></summary><br/>
URH is available as a snap: https://snapcraft.io/urh
</details>
<details>
<summary><i>Docker Image</i></summary><br/>
The official URH docker image is available [here](https://hub.docker.com/r/jopohl/urh/). It has all native backends included and ready to operate.
</details>
</details>
<details>
<summary><b>macOS</b></summary>
<details open>
<summary><i>Using DMG</i></summary><br/>
It is recommended to use __at least macOS 10.14__ when using the DMG available [here](https://github.com/jopohl/urh/releases).
</details>
<details>
<summary><i>With pip</i></summary><br/>
1. Install [Python 3 for Mac OS X](https://www.python.org/downloads/mac-osx/).
_If you experience issues with preinstalled Python, make sure you update to a recent version using the given link._
2. (Optional) Install desired native libs e.g. ```brew install librtlsdr``` for
corresponding native device support.
3. In a terminal, type: ```pip3 install urh```.
4. Type ```urh``` in a terminal to get it started.
</details>
</details>
<details>
<summary><b>Update your installation</b></summary><br/>
If you installed URH via pip you can keep it up to date with ``` python3 -m pip install --upgrade urh ```.
</details>
<details>
<summary><b>Running from source</b></summary>
<details>
<summary><i>Without installation</i></summary><br/>
To execute the Universal Radio Hacker without installation, just run:
```bash
git clone https://github.com/jopohl/urh/
cd urh/src/urh
./main.py
```
Note, before first usage the C++ extensions will be built.
</details>
<details>
<summary><i>Installing from source</i></summary><br/>
To install URH from source you need to have ```python-setuptools``` installed. You can get them with ```python3 -m pip install setuptools```.
Once the setuptools are installed execute:
```bash
git clone https://github.com/jopohl/urh/
cd urh
python setup.py install
```
And start the application by typing ```urh``` in a terminal.
</details>
</details>
## Articles
### Hacking stuff with URH
* [Hacking Burger Pagers](https://www.rtl-sdr.com/using-a-hackrf-to-reverse-engineer-and-control-restaurant-pagers/)
* [Reverse-engineer and Clone a Remote Control](https://www.rtl-sdr.com/video-tutorial-using-universal-radio-hacker-an-rtl-sdr-and-a-microcontroller-to-clone-433-mhz-remotes/)
* [Reverse-engineering Weather Station RF Signals](https://www.rtl-sdr.com/tag/universal-radio-hacker/)
* [Reverse-engineering Wireless Blinds](https://www.rtl-sdr.com/reverse-engineering-wireless-blinds-with-an-rtl-sdr-and-controlling-them-with-amazon-alexa/)
* [Attacking Logitech Wireless Presenters (German Article)](https://www.heise.de/security/meldung/Wireless-Presenter-von-Logitech-und-Inateck-anfaellig-fuer-Angriffe-ueber-Funk-4439795.html)
* [Attacking Wireless Keyboards](https://threatpost.com/fujitsu-wireless-keyboard-unpatched-flaws/149477/)
* [Reverse-engineering a 433MHz Remote-controlled Power Socket for use with Arduino](http://www.ignorantofthings.com/2018/11/reverse-engineering-433mhz-remote.html)
### General presentations and tutorials on URH
* [Hackaday Article](https://hackaday.com/2017/02/23/universal-radio-hacker/)
* [RTL-SDR.com Article](https://www.rtl-sdr.com/reverse-engineering-signals-universal-radio-hacker-software/)
* [Short Tutorial on URH with LimeSDR Mini](https://www.crowdsupply.com/lime-micro/limesdr-mini/updates/investigating-wireless-protocols-with-universal-radio-hacker)
* [Brute-forcing a RF Device: a Step-by-step Guide](https://pandwarf.com/news/brute-forcing-a-new-device-a-step-by-step-guide/)
* [Hacking wireless sockets like a NOOB](https://olof-astrand.medium.com/hacking-wireless-sockets-like-a-noob-b57d4b4812d5)
## External decodings
See [wiki](https://github.com/jopohl/urh/wiki/External-decodings) for a list of external decodings provided by our community! Thanks for that!
## Screenshots
### Get the data out of raw signals
![Interpretation phase](http://i.imgur.com/Wy17Zv3.png)
### Keep an overview even on complex protocols
![Analysis phase](http://i.imgur.com/ubAL3pE.png)
### Record and send signals
![Record](http://i.imgur.com/BfQpg23.png)

View File

@ -1,389 +0,0 @@
# Changelog
__This changelog file will not be updated anymore__.
Instead, the recent changes can be found at the releases page: https://github.com/jopohl/urh/releases
## v2.5.3 (19/12/2018)
### Bugfixes
- fix crash when using spectrum analyzer with GNU Radio backend [#588](https://github.com/jopohl/urh/pull/588)
## v2.5.2 (10/12/2018)
### Bugfixes
- certain windows (e.g. decoding) can't be closed on OSX
- prevent crash in substitution encoding
- consider alignment offset when showing selected labels
### Adjustments
- remove ```Save and Close``` of fuzzing dialog, as closing means saving here anyway
### New features
- make application __font size__ configurable in ``` Options ``` -> ``` View ```
## v2.5.1 (25/11/2018)
### Bugfixes
- improve stability when capturing with SoundCard
- fix bug making the docker container crash at startup
- stop simulation instantly after finishing
## v2.5.0 (19/11/2018)
### New features
- Add native support for PlutoSDR [#574](https://github.com/jopohl/urh/pull/574)
### Bugfixes
- do not add URH to autostart on windows [#569](https://github.com/jopohl/urh/pull/569)
- save button was not shown when change on saved signal was undone [#571](https://github.com/jopohl/urh/pull/571)
- y scale got falsely reset on save [#573](https://github.com/jopohl/urh/pull/573)
## v2.4.2 (11/11/2018)
### New features
- enhance settings for RTL-SDR [#561](https://github.com/jopohl/urh/pull/561) + [#566](https://github.com/jopohl/urh/pull/566)
- ergonomic improvements [#564](https://github.com/jopohl/urh/pull/564)
### Bugfixes
- fix problem with set reference message shortcut [#559](https://github.com/jopohl/urh/pull/559)
- fix loading decodings and centralized place for decodings [#563](https://github.com/jopohl/urh/pull/563)
## v2.4.1 (23/10/2018)
### New features
- Add an option to disable automatic detection of interpretation parameters for newly loaded signals to the ``` Edit ``` menu [#555](https://github.com/jopohl/urh/pull/555)
### Bugfixes
- fix off by one error when creating a new label in analysis
- fix crash when opening a project with saved dc correction setting
## v2.4.0 (19/10/2018)
### New features
- added __font size zoom__ to table views (analysis/generator/simulator); more details in [#546](https://github.com/jopohl/urh/pull/546)
- greatly enhance __accuracy of automatic interpretation__ [#550](https://github.com/jopohl/urh/pull/550)
- added __DC correction__ option to recording dialogs and as a new filter type in Interpretation [#552](https://github.com/jopohl/urh/pull/552)
### Improvements
- ignore case when searching for hex values in analysis [#544](https://github.com/jopohl/urh/pull/544)
- RSSI is now given in dBm [#549](https://github.com/jopohl/urh/pull/549)
### Bugfixes
- Fix display of RSSI indicator in Interpretation [#547](https://github.com/jopohl/urh/pull/547)
## v2.3.0 (28/09/2018)
### New features
- added native support for BladeRF [#524](https://github.com/jopohl/urh/pull/524)
- added backward compatibility for SDRPlay < 2.13 [#528](https://github.com/jopohl/urh/pull/528)
- improved UI for message type and label configuration in analysis [#532](https://github.com/jopohl/urh/pull/532)
- rename __close all__ action to __close all files__ for more clarity [#532](https://github.com/jopohl/urh/pull/532)
- added a __close project__ action [#532](https://github.com/jopohl/urh/pull/532)
## v2.2.4 (30/08/2018)
### Bugfixes
- fix scaling of modulated preview in modulation dialog [#523](https://github.com/jopohl/urh/pull/523)
- improve default parameters for PSK modulation in modulation dialog [#523](https://github.com/jopohl/urh/pull/523)
## v2.2.3 (28/07/2018)
### New features
- allow save and load of binary protocols (``` .bin ``` files) [#488](https://github.com/jopohl/urh/pull/488)
- improve bootstrap of simulator messages [#500](https://github.com/jopohl/urh/pull/500)
- auto assign destination when dropping messages to simulator
- show participant address in participant legend if present
- auto assign participant address when clicking analyze button in analysis based on SRC address label
- consider API changes of SDRPlay 2.13 [#508](https://github.com/jopohl/urh/pull/508) thanks [@mehdideveloper](https://github.com/mehdideveloper)
- also consider participant address (next to RSSI) when auto assigning participants in analysis [#512](https://github.com/jopohl/urh/pull/512)
- Clear button stays enabled during operation so e.g. recordings can be cleared live [#514](https://github.com/jopohl/urh/pull/514)
### Bugfixes
- antenna selection is not saved when reopening dialog [#494](https://github.com/jopohl/urh/pull/494)
- hiding multiple rows at once in analysis not working properly [#499](https://github.com/jopohl/urh/pull/499)
## v2.2.2 (01/07/2018)
This release removes the ``` config.pxi ``` requirement which caused problems on Arch Linux and Gentoo during installation. More details in PR [#484](https://github.com/jopohl/urh/pull/484).
## v2.2.1 (30/06/2018)
This is a hotfix release which targets issue [#481](https://github.com/jopohl/urh/issues/481), so if you had problems with a missing ``` config.pxi ``` make sure to use this version.
## v2.2.0 (29/06/2018)
__Import announcement if you build URH manually__: Cython is now a __required__ dependency to build URH. If you install URH from PyPi (with ``` pip ```) or use the ``` .msi ``` installer you will not notice any difference. However, if you run URH from source you need to install cython which is as easy as ``` python3 -m pip install cython ```.
- [#478](https://github.com/jopohl/urh/pull/478) - make message pause configurable in simulator
- [#476](https://github.com/jopohl/urh/pull/476) - add padding when sending very short messages with soundcard
- [#473](https://github.com/jopohl/urh/pull/473) - move ``` .desktop ``` file to ``` data ``` folder. __Important if you build a package of URH__
- [#471](https://github.com/jopohl/urh/pull/471) - make relative external programs paths relative to project path
- [#470](https://github.com/jopohl/urh/pull/470) - improve conditional compiling of native device extensions
- [#469](https://github.com/jopohl/urh/pull/469) - improve device selection in options, use a table instead of a list view
- [#468](https://github.com/jopohl/urh/pull/468) - improve python2 interpreter settings for GNU Radio backend with empty ``` urh.ini ```
- [#458](https://github.com/jopohl/urh/pull/458) - add alignment action to analysis
![alignment image](https://i.imgur.com/xQt7H7Y.png)
## v2.1.1 (17/06/2018)
This release updates the bundled SDR drivers on Windows.
__Furthermore, this release adds native device support for 32 bit windows__.
Bugfix:
- a bug was fixed where sample rate of a signal was not written correctly to wav file when exporting as wav
## v2.1.0 (01/06/2018)
The highlight of this release is a __Command Line Interface__ (CLI) for the Universal Radio Hacker.
Learn more about this new feature [in the wiki](https://github.com/jopohl/urh/wiki/Command-Line-Interface).
Moreover, these two features were added:
- Add export features #437
- make refin and refout configurable for CRC #439
These bugs were fixed:
- fix #441 (Reference signal is not kept when disabling and re-enabling "Mark diffs in protocol")
- fix #442 (consider hidden zeros for show selection in interpretation)
- fix #444 (Message Break error box popping up too early)
- fix #448 (Include pyaudio in windows package for soundcard support)
## v2.0.4 (06/05/2018)
This version fixes a bug when importing 24 bit wav files on windows.
## v2.0.3 (06/05/2018)
- Improve external program behaviour in Simulator #417
- fix #421
- Improve simulator useability #422
- Improve transcript for external programs #425
- make endianness selectable in order column #428
- UI improvements #430
- add support for soundcards as new SDR device #433
- Multi device support #432
- add support for 24bit wav #434
## v2.0.2 (22/04/2018)
- Improve external program behaviour in Simulator #417
- fix #421
- Improve simulator useability #422
- Improve transcript for external programs #425
- make endianness selectable in order column #428
- UI improvements #430
## v2.0.1 (23/03/2018)
Changes:
- improve appearance of splitters
- add adaptive noise feature for protocol sniffer and simulator (#401)
- improve native device rebuild button in options + added a new button to view the build log there (only visible after hitting the rebuild button) (#402)
- improve performance of CRC calculation (#412)
- save number of sending repeats when changed in send dialog (#415)
## v2.0.0 (28/02/2018)
URH 2.0 is here! This release adds a new tab to the main interface. This __Simulator__ tab enables you to simulate certain devices and crack even sophisticated security mechanisms like challenge response procedures. Learn more about this new feature [on this wiki page](https://github.com/jopohl/urh/wiki/Simulator).
Moreover, the overall performance and stability of URH increases with 2.0. The most notable changes are:
- improve accuracy when sending messages with short pauses
- improve accuracy of protocol sniffer
- allow setting lower frequencies for HackRF (#396)
- consider latest changes of LimeSuite API (#397)
- add timestamp to protocol sniffer output (#392)
- improve performance of modulations
- improve performance of filtering in analysis
- improve performance when starting sending
- improve send accuracy of HackRF
- improve performance when filtering messages in Analysis
## v1.9.2 (19/01/2018)
- Add BCD (Binary Coded Decimal) as new display format #386
- Make bit order configurable in analysis view table #390
- Improved loading of protocol files
## v1.9.1 (17/12/2017)
This is a hotfix release that fixes an error with HackRF receiving (#379).
## v1.9.0 (15/12/2017)
- added native support for SDRplay (#378)
- improved performance for continuous send mode
- added collapsable comboboxes to device dialog
## v1.8.17 (04/12/2017)
Changes:
- show warning at bottom if no project loaded (#374)
- if no project is opened an new project is created, add currently opnened files to new project (#374)
- add --version flag to command line script #375 (thanks to @Funcan for the initial work)
- Enable specifying a custom python 2 interpreter on Windows (#372)
## v1.8.16 (30/11/2017)
This release fixes an issue on Windows where processes ended with an error (#370).
Furthermore, the NetworkSDR can now be used in continuous send mode (#369).
## v1.8.15 (27/11/2017)
This release fixes a problem with GNU Radio backend on Windows mentioned in #366 and #368.
## v1.8.14 (26/11/2017)
This release fixes an overflow error (#364) when modulating very long messages in Generator.
The highlight of this release is an enhanced spectrum analyzer (#365) with __increased performance__ and a __waterfall plot__ to have a different, time based perspective on the spectrum.
![spectrum](https://user-images.githubusercontent.com/18219846/33239754-03bb62f6-d2a9-11e7-80aa-059df7b0b133.png)
## v1.8.13 (18/11/2017)
This release enhances the stability for sending and receiving with all SDRs. Especially, it fixes nasty bug #360 which affected HackRF users under Windows.
Furthermore, the WAV file support was greatly enhanced. Now, you can use WAV files from SDR# (fix #359).
## v1.8.12 (16/11/2017)
This release fixes the following issues:
- fix #355 - added a CSV import wizard for generic support of USB oscilloscopes
- fix #358 - MSI version of URH did not start on Windows
__So if you had trouble to install the previous version on Windows make sure you use this one.__
## v1.8.11 (13/11/2017)
The following issues were fixed in this release:
- fix #343 - crash when entering bits on empty position in Analysis / Generation
- fix #344 - bandpass filter can now also work with negative frequencies
- fix #346 - bandpass filter operations now run in a separate process and can be canceled with the ESC button
- fix #349 - added a csv import to work with USB oscilloscopes
- fix #352 - added a advanced modulation menu in Interpretation where a minimum message length for ASK can be configured
## v1.8.10 (21/10/2017)
This release fixes a crash when pressing the replay button in interpretation tab.
## (21/10/2017)
## v1.8.8 (16/10/2017)
These issues were fixed in this release:
- fix #339 - keep tree in analysis collapsed if check box toggled
- fix #338 - make pause threshold configurable in interpretation
- fix #333 - keep search string if search fails in analysis
## v1.8.7 (18/09/2017)
This release fixes the following issues:
- [#330](https://github.com/jopohl/urh/pull/330) - Improve modulation for large protocols
- [#329](https://github.com/jopohl/urh/pull/329) - Improve handling of protocol files
- [#324](https://github.com/jopohl/urh/issues/324) - LimeSDR: Failed to receive stream
- [#297](https://github.com/jopohl/urh/issues/297) - LimeSDR RX antenna always LNA_L
## v1.8.6 (06/09/2017)
This release fixes two crashes as described in #327.
## v1.8.5 (30/08/2017)
This release fixes #323 .
## v1.8.4 (28/08/2017)
This is a hotfix release that fixes native device extensions on Windows when conflicting SDR software is installed.
Furthermore, a health check button for native device extensions was added to options.
Details can be found in this PR: #321
## Version 1.8.0 (24/08/2017)
This release adds two highly demanded features to URH: __Spectrogram View__ and __Channel Separation__. Learn more about them in the [wiki](https://github.com/jopohl/urh/wiki/Spectrogram) and keep hacking like a boss!
## Version 1.7.1 (19/07/2017)
This release adds installers for Windows. If you use the new installer and should get an error about missing ``` api-ms-win-crt-runtime-l1-1-0.dll ```, run Windows Update or directly install [KB2999226](https://support.microsoft.com/en-us/help/2999226/update-for-universal-c-runtime-in-windows).
__It is recommended to use the 64 bit version (amd64) of URH on Windows__, because 32 bit version has no native device support.
This release also fixes some bugs:
- Fix exhaustive fuzzing mode
- Fix a rare crash in Generator tab when performing undo
- fix checksum assignment to fuzzed messages when sending/generating data
- refresh estimated time in generator if pause was edited
## Version 1.7.0 (14/07/2017)
The highlight of this release is support for __generic checksums__. You can define custom CRC polynomials or use predefined ones.
Learn more about this feature [in the wiki](https://github.com/jopohl/urh/wiki/Checksums).
Other fixes/features include:
- "Edit all" action in pause menu of generator tab
- Open Project now additionally possible by opening the project file
- bootstrapping of modulation when dropping first protocol to generator table
- new icons and improved UI
- improved auto detection of carrier frequency for modulation
- improved ASK demodulation algorithm
- fix a bug with relative paths on OS X
- fix selection behavior when extending selection with shift
- fix #306
- fix #308
- fix #310
- fix #311
## Hotfix for Windows wheels (11/06/2017)
This is a hotfix release that fixes dependencies in the precompiled wheels for Windows which were introduced in the previous release.
## Version 1.6.5 (11/06/2017)
This release brings the following changes:
- fix #278: added a __repeat button__ to fuzzing dialog, next to the table with fuzzing values
- fix #284: fixed behaviour: "Your selection is empty!" sometimes pops up when creating a new signal from signal
- fix #285: fixed a rare crash when undoing a crop action
- fix #281: Optimized performance of protocol synchronization in Interpretation
- fix #286: improved context menu in Analysis
- fix #288: UI improvements: remove unneeded borders and increase visibility of splitter handle
- fix #290: fixed a crash occurring when pressing Analysis button in certain circumstances
- fix #291: created precompiled wheels for windows on PyPI, so no C++ compiler needed anymore.
- improved visual appearance of comboboxes in protocol label list view
## Add filter to Interpretation (28/05/2017)
This release brings a filter button to the Interpretation phase:
![bildschirmfoto_2017-05-28_12-29-58](https://cloud.githubusercontent.com/assets/18219846/26528462/a20c36ce-43ac-11e7-815e-0d929aa20cb8.png)
This way, you can smooth your signals right inside URH or unlock the full power of DSP fir filters by defining custom filters through the menu!

View File

@ -1,40 +0,0 @@
FROM ubuntu:18.04
LABEL maintainer="Johannes.Pohl90@gmail.com"
ENV TZ=Europe/Berlin
# Debug QT plugins by exporting QT_DEBUG_PLUGINS=1 before running URH
# To allow docker to connect to X run xhost +local:docker
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone \
&& apt-get -qq update \
&& apt-get -qq install software-properties-common \
&& add-apt-repository -y ppa:myriadrf/drivers && apt-get -qq update \
&& apt-get -qq install wget gcc g++ git \
python3 python3-pip python3-pyaudio python3-pyqt5 python3-numpy python3-psutil \
fonts-dejavu-core libgles2-mesa libusb-1.0-0 \
gr-osmosdr \
libhackrf-dev liblimesuite-dev libbladerf-dev librtlsdr-dev libairspy-dev libuhd-dev libiio-dev \
&& python3 -m pip install setuptools cython \
&& mkdir /tmp/sdrplay \
&& wget http://www.sdrplay.com/software/SDRplay_RSP_API-Linux-2.13.1.run -O /tmp/sdrplay/sdrplay.run \
&& cd /tmp/sdrplay && bash sdrplay.run --tar xf \
&& cp mirsdrapi-rsp.h /usr/local/include \
&& cp x86_64/libmirsdrapi-rsp.so.2.13 /usr/lib/x86_64-linux-gnu/ \
&& ln -s /usr/lib/x86_64-linux-gnu/libmirsdrapi-rsp.so.2.13 /usr/lib/x86_64-linux-gnu/libmirsdrapi-rsp.so \
&& rm -rf /tmp/sdrplay \
\
&& cd /tmp && git clone --depth=1 https://github.com/jopohl/urh \
&& cd /tmp/urh \
&& python3 setup.py install \
&& rm -rf /tmp/urh \
\
&& apt-get -qq remove wget gcc g++ git ttf-bitstream-vera \
&& apt-get -qq autoremove \
&& dbus-uuidgen > /var/lib/dbus/machine-id \
&& apt-get -qq clean all \
&& mkdir /tmp/runtime-root \
&& chmod 0700 /tmp/runtime-root
CMD XDG_RUNTIME_DIR=/tmp/runtime-root urh

View File

@ -1,89 +0,0 @@
# Build Qt Resource File from custom Icon Theme for Windows
import os
import shutil
import xml.etree.ElementTree as ET
from subprocess import call
OXYGEN_PATH = "/usr/share/icons/oxygen/base"
def get_python_files():
python_files = []
code_dir = os.path.join(os.curdir, "..", "src")
assert os.path.isdir(code_dir)
for path, subdirs, files in os.walk(code_dir):
for name in files:
if name.endswith(".py"):
python_files.append(os.path.join(path, name))
return python_files
def get_used_icon_names():
icons = set()
for sourcefile in get_python_files():
with open(sourcefile, "r") as f:
for line in f:
if "QIcon.fromTheme" in line:
icon = line[line.find("QIcon.fromTheme"):]
icon = icon.replace('"', "'")
start = icon.find("'") + 1
end = icon.find("'", start)
icons.add(icon[start:end])
return icons
def copy_icons(icon_names: set):
target_dir = "/tmp/oxy"
sizes = [s for s in os.listdir(OXYGEN_PATH) if os.path.isdir(os.path.join(OXYGEN_PATH, s))] # 8x8, 22x22 ...
for size in sizes:
target_size_dir = os.path.join(target_dir, size)
os.makedirs(target_size_dir, exist_ok=True)
oxy_dir = os.path.join(OXYGEN_PATH, size)
for icon_name in icon_names:
for path, subdirs, files in os.walk(oxy_dir):
for f in files:
if os.path.splitext(f)[0] == icon_name:
src = os.path.join(path, f)
shutil.copyfile(src, os.path.join(target_size_dir, f))
break
# Create theme file
with open(os.path.join(target_dir, "index.theme"), "w") as f:
f.write("[Icon Theme]\n")
f.write("Name=oxy\n")
f.write("Comment=Subset of oxygen icons\n")
f.write("Inherits=default\n")
f.write("Directories=" + ",".join(sizes) + "\n")
for size in sizes:
f.write("\n")
f.write("[" + size + "]\n")
f.write("Size=" + size[:size.index("x")] + "\n")
f.write("\n")
root = ET.Element("RCC")
root.set("version", "1.0")
res = ET.SubElement(root, "qresource")
res.set("prefix", "icons/oxy")
relpath = os.path.relpath(os.path.join(target_dir, "index.theme"), "/tmp")
ET.SubElement(res, "file", alias="index.theme").text = relpath
for size in sizes:
size_dir = os.path.join(target_dir, size)
for icon in os.listdir(size_dir):
relpath = os.path.relpath(os.path.join(size_dir, icon), "/tmp")
ET.SubElement(res, "file", alias=size + "/" + icon).text = relpath
tree = ET.ElementTree(root)
tree.write("/tmp/xtra_icons.qrc")
call(["pyrcc5", "/tmp/xtra_icons.qrc", "-o", "/tmp/xtra_icons_rc.py"])
tar_path = os.path.dirname(os.path.join(os.path.dirname(__file__), "..", ".."))
tar_path = os.path.join(tar_path, "src/urh/ui")
shutil.copy("/tmp/xtra_icons_rc.py", tar_path)
if __name__ == "__main__":
icons = get_used_icon_names()
print(icons)
copy_icons(icons)

View File

@ -1,26 +0,0 @@
#!/bin/bash
DIR=$(dirname "$(readlink -f "$0")")
echo "Copy snapcraft.yaml to base directory"
cd $DIR
cp snapcraft.yaml ..
cd ..
sed -i "s/version\: git/version\: $(python3 src/urh/version.py)/" snapcraft.yaml
mkdir -p snap/gui
cp data/icons/appicon.png snap/gui/urh.png
echo "Create desktop entry for snap"
echo "[Desktop Entry]" > snap/gui/urh.desktop
echo "Type=Application" >> snap/gui/urh.desktop
echo "Name=Universal Radio Hacker" >> snap/gui/urh.desktop
echo "Comment=Investigate Wireless Protocols Like A Boss" >> snap/gui/urh.desktop
echo "Exec=urh" >> snap/gui/urh.desktop
echo "Icon=\${SNAP}/meta/gui/urh.png" >> snap/gui/urh.desktop
echo "Terminal=false" >> snap/gui/urh.desktop
SNAPCRAFT_BUILD_ENVIRONMENT_CPU=8 SNAPCRAFT_BUILD_ENVIRONMENT_MEMORY=24G snapcraft
#sudo snap install --dangerous urh*.snap
#urh

View File

@ -1,23 +0,0 @@
#!/usr/bin/env python3
import importlib
import os
import sys
rc = 0
if sys.platform == "win32":
shared_lib_dir = os.path.realpath(os.path.join(os.path.dirname(__file__), "..", "src/urh/dev/native/lib/shared"))
print("Attempting to read", shared_lib_dir)
if os.path.isdir(shared_lib_dir):
os.environ["PATH"] = os.environ.get("PATH", "") + os.pathsep + shared_lib_dir
print("PATH updated")
for sdr in ("AirSpy", "BladeRF", "HackRF", "RTLSDR", "LimeSDR", "PlutoSDR", "SDRPlay", "USRP"):
try:
importlib.import_module('.{}'.format(sdr.lower()), 'urh.dev.native.lib')
print("{:<10} \033[92mSUCCESS\033[0m".format(sdr+":"))
except ImportError as e:
print("{:<10} \033[91mFAILURE\033[0m ({})".format(sdr+":", e))
rc = 1
sys.exit(rc)

View File

@ -1,54 +0,0 @@
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv)
{
int i, len = strlen(argv[2]);
if (argc>2)
{
if (argv[1][0]=='d')
for(i = 0; i < len; i++)
switch(i % 12)
{
case 0:
case 1:
case 2:
case 4:
case 5:
case 6:
case 8:
case 9:
putchar(argv[2][i]);
break;
default:
break;
}
else
for(i = 0; i < len; i++)
switch(i % 8)
{
case 0:
case 1:
case 3:
case 4:
case 6:
putchar(argv[2][i]);
break;
case 2:
case 5:
putchar(argv[2][i]);
if(argv[2][i] == '0') putchar('1');
else putchar('0');
break;
case 7:
putchar(argv[2][i]);
if(i < len - 1)
printf("01");
}
}
else printf("Usage: %s <d/e> <bit sequence>\n\td - decode\n\te - encode\n\tbit sequence as string of 0 and 1.\n", argv[0]);
return 0;
}

View File

@ -1,102 +0,0 @@
#include <stdio.h>
#include <string.h>
typedef unsigned char byte;
byte str2byte(char str[8])
{
int ret = 0, i;
for(i = 0; i < 8; i++)
if (str[i]=='1') ret |= (1<<(7-i));
return ret;
}
void print_binary(byte inpt)
{
int i;
for(i = 0; i < 8; i++)
if (inpt & (1<<(7-i))) putchar('1');
else putchar('0');
}
int main(int argc, char **argv)
{
int i, max, offset;
byte dec[256]={0}, enc[256]={0};
char string[2048]={0};
offset = 8; // Preamble + Sync
if (argc>2)
{
if (argv[1][0]=='d')
{
if (strlen(argv[2]) > 256*8 || strlen(argv[2]) < 4) return -1;
memcpy(string, argv[2], strlen(argv[2]));
for (i = 0; i < strlen(string)-3; i+=8)
enc[i/8] = str2byte(&string[i]);
max = i/8;
memcpy(&dec, &enc, 256);
/*
* byte[] Dec = new byte[Enc.Length];
* Dec[0] = Enc[0]; //Packet length
* Dec[1] = (byte)((~Enc[1]) ^ 0x89);
* int j;
* for (j = 2; j < Dec[0]; j++)
* Dec[j] = (byte)((Enc[j-1] + 0xdc) ^ Enc[j]);
* Dec[j] = (byte)(Enc[j] ^ Dec[2]);
*/
dec[offset+0] = enc[offset+0];
dec[offset+1] = (~enc[offset+1])^0x89;
for(i = offset + 2; i < max - 3; i++)
dec[i] = (enc[i-1]+0xdc) ^ enc[i];
dec[i] = enc[i] ^ dec[offset+2];
dec[max-1]=0; // Set CRC to 0x0000
dec[max-2]=0;
for(i = 0; i < max; i++)
print_binary(dec[i]);
}
else
{
if (strlen(argv[2]) > 256*8 || strlen(argv[2]) < 4) return -1;
memcpy(string, argv[2], strlen(argv[2]));
for (i = 0; i < strlen(string)-3; i+=8)
dec[i/8] = str2byte(&string[i]);
max = i/8;
memcpy(&enc, &dec, 256);
/*
* byte[] Dec = new byte[Enc.Length];
* Dec[0] = Enc[0]; //Packet length
* Dec[1] = (byte)((~Enc[1]) ^ 0x89);
* int j;
* for (j = 2; j < Dec[0]; j++)
* Dec[j] = (byte)((Enc[j-1] + 0xdc) ^ Enc[j]);
* Dec[j] = (byte)(Enc[j] ^ Dec[2]);
*/
enc[offset+0] = dec[offset+0];
enc[offset+1] = ~(dec[offset+1]^0x89);
for(i = offset + 2; i < max - 3; i++)
enc[i] = (enc[i-1]+0xdc) ^ dec[i];
enc[i] = dec[i] ^ dec[offset+2];
enc[max-1]=0; // Set CRC to 0x0000
enc[max-2]=0;
for(i = 0; i < max; i++)
print_binary(enc[i]);
}
}
else printf("Usage: %s <d/e> <bit sequence>\n\td - decode\n\te - encode\n\tbit sequence as string of 0 and 1.\n", argv[0]);
return 0;
}

View File

@ -1,239 +0,0 @@
#include <stdio.h>
#include <string.h>
#define SHORTEN_PREAMBLE_TO_32 0
typedef unsigned char byte;
typedef unsigned short uint16;
uint16 crc(byte *data, int len)
{
byte i, x, crcdata;
uint16 crcReg = 0xFFFF;
for (x = 0; x < len; x++)
{
crcdata = data[x];
for (i = 0; i < 8; i++)
{
if (((crcReg & 0x8000) >> 8) ^ (crcdata & 0x80))
crcReg = (crcReg << 1) ^ 0x8005;
else
crcReg = (crcReg << 1);
crcdata <<= 1;
}
}
return crcReg;
}
byte str2byte(char str[8])
{
int ret = 0, i;
for(i = 0; i < 8; i++)
if (str[i]=='1') ret |= (1<<(7-i));
return ret;
}
void print_binary(byte inpt)
{
int i;
for(i = 0; i < 8; i++)
if (inpt & (1<<(7-i))) putchar('1');
else putchar('0');
}
void print_preamble_nibbles(int count)
{
int i;
for (i = 0; i < count; i++)
printf("1010");
}
int find_preamble_start_in_bit(char *string, int len)
{
char homematic_sync[] = "11101001110010101110100111001010";
for(int i = 0, j = 0; i < len; i++)
{
if(string[i] == homematic_sync[j])
{
j++;
if(j == 32 && i>= 63) return i-63;
}
else j = 0;
}
return -1; //not found
}
void xor_lfsr(char *string)
{
int i, j, x, len = strlen(string);
byte polynomial[9] = {0, 0, 0, 1, 0, 0, 0, 0, 1};
byte lfsr_state[9];
byte first_bit;
// Init with 8x 1 Bit
memset(lfsr_state, 1, 9);
for(j = 0; j < 8; j++)
if(string[j]=='1')
string[j]='0';
else
string[j]='1';
for(x = 8; x < len-7; x += 8)
{
for(i = 0; i < 8; i++)
{
first_bit = 255;
for(j = 8; j >= 0; j--)
if(polynomial[j] && lfsr_state[j])
{
if(first_bit == 255)
first_bit = 1;
else
first_bit = (first_bit==1) ? 0 : 1;
}
if(first_bit == 255)
first_bit = 0;
// Clock
for(j = 8; j >= 0; j--)
lfsr_state[j] = lfsr_state[j-1];
lfsr_state[0] = first_bit;
}
// Xor
for(j = 0; j < 8; j++)
if(lfsr_state[j+1] == 1)
if(string[x+j]=='1')
string[x+j]='0';
else
string[x+j]='1';
}
}
int main(int argc, char **argv)
{
int i, j, max, offset, len, preamble_additional_length;
byte dec[1024]={0}, enc[1024]={0}, crc_ok;
char string[65536]={0};
uint16 crcvalue;
offset = 8; // Preamble + Sync
// Copy data (argv[2]) to string if length is ok, shorten to multiple of 8 bit
if (strlen(argv[2]) > 8192*8 || strlen(argv[2]) < 4) return -1;
len = strlen(argv[2]);
i = find_preamble_start_in_bit(argv[2], len);
if(i < 0) return 0; // preamble+sync not found or wrong length
preamble_additional_length = i;
len = (len-i)-(len-i)%8;
memcpy(string, argv[2]+i, len);
if (argc>2)
{
if (argv[1][0]=='d')
{
// Apply datawhitening
xor_lfsr(string+64);
// Pack to bytes
for (i = 0; i < strlen(string)-3; i+=8)
enc[i/8] = str2byte(&string[i]);
max = i/8;
memcpy(&dec, &enc, 1024);
// Check CRC
crcvalue = crc(&dec[8], max-2-8);
crc_ok = 0;
if( ((crcvalue >> 8) & 0xFF) == dec[max-2] && (crcvalue & 0xFF) == dec[max-1]) crc_ok = 1;
/*
* byte[] Dec = new byte[Enc.Length];
* Dec[0] = Enc[0]; //Packet length
* Dec[1] = (byte)((~Enc[1]) ^ 0x89);
* int j;
* for (j = 2; j < Dec[0]; j++)
* Dec[j] = (byte)((Enc[j-1] + 0xdc) ^ Enc[j]);
* Dec[j] = (byte)(Enc[j] ^ Dec[2]);
*/
// Decrypt
dec[offset+0] = enc[offset+0];
dec[offset+1] = (~enc[offset+1])^0x89;
for(i = offset + 2; i < max - 3; i++)
dec[i] = (enc[i-1]+0xdc) ^ enc[i];
dec[i] = enc[i] ^ dec[offset+2];
// Recompute CRC and overwrite with FAKE-CRC, if CRC was OK before
if(crc_ok)
{
crcvalue = crc(&dec[8], max-2-8);
dec[max-1] = crcvalue & 0xFF;
dec[max-2] = (crcvalue >> 8) & 0xFF;
}
else
{
dec[max-1] = 0x0F; // Set magic code for wrong CRC
dec[max-2] = 0xD0;
}
// Prepend preamble longer than 32 bits
if(0 == SHORTEN_PREAMBLE_TO_32 && preamble_additional_length > 0)
print_preamble_nibbles(preamble_additional_length/4);
for(i = 0; i < max; i++)
print_binary(dec[i]);
}
else
{
// Pack to bytes
for (i = 0; i < strlen(string)-3; i+=8)
dec[i/8] = str2byte(&string[i]);
max = i/8;
memcpy(&enc, &dec, 1024);
/*
* byte[] Dec = new byte[Enc.Length];
* Dec[0] = Enc[0]; //Packet length
* Dec[1] = (byte)((~Enc[1]) ^ 0x89);
* int j;
* for (j = 2; j < Dec[0]; j++)
* Dec[j] = (byte)((Enc[j-1] + 0xdc) ^ Enc[j]);
* Dec[j] = (byte)(Enc[j] ^ Dec[2]);
*/
// Encrypt
enc[offset+0] = dec[offset+0];
enc[offset+1] = ~(dec[offset+1])^0x89;
for(i = offset + 2; i < max - 3; i++)
enc[i] = (enc[i-1]+0xdc) ^ dec[i];
enc[i] = dec[i] ^ dec[offset+2];
// Overwrite with correct CRC
crcvalue = crc(&enc[8], max-2-8);
enc[max-1] = crcvalue & 0xFF;
enc[max-2] = (crcvalue >> 8) & 0xFF;
// Convert to string
memset(string, 0, 65536);
for(i = 0; i < max; i++)
{
for(j = 0; j < 8; j++)
if(enc[i] & (1<<(7-j))) string[i*8+j]='1';
else string[i*8+j]='0';
}
// Apply datawhitening
xor_lfsr(string+64);
// Prepend preamble longer than 32 bits
if(0 == SHORTEN_PREAMBLE_TO_32 && preamble_additional_length > 0) // Add preamble longer than 32 bits
print_preamble_nibbles(preamble_additional_length/4);
// Print bits and duplicate last bit
printf("%s%c\n", string, string[strlen(string)-1]);
}
}
else printf("Usage: %s <d/e> <bit sequence>\n\td - decode\n\te - encode\n\tbit sequence as string of 0 and 1.\n", argv[0]);
return 0;
}

Binary file not shown.

View File

@ -1,47 +0,0 @@
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv)
{
int i, count, what;
if(argc>2)
{
if(argv[1][0]=='d')
{
for(i = 0; i < strlen(argv[2]); i++)
if(argv[2][i] == '0') printf("000");
else printf("11");
}
else
{
count = 0;
what = -1;
for(i = 0; i < strlen(argv[2]); i++)
{
if(argv[2][i] == '0')
{
if(what == 1) count = 0;
what = 0;
count++;
if(count == 3)
{
putchar('0');
count = 0;
}
}
else
{
if(what == 0) count = 0;
what = 1;
count++;
if(count == 2)
{
putchar('1');
count = 0;
}
}
}
}
}
return 0;
}

View File

@ -1,2 +0,0 @@
#!/bin/bash
echo "$1$1"

View File

@ -1,72 +0,0 @@
import sys
import os
from subprocess import call
import fileinput
def gen(force=False):
if sys.platform == "win32":
bindir = r"c:\Python34\Lib\site-packages\PyQt5"
else:
bindir = "/usr/bin"
if sys.platform == "win32":
uic_path = os.path.join(bindir, "pyuic5.bat")
rcc_path = os.path.join(bindir, "pyrcc5.exe")
else:
uic_path = os.path.join(bindir, "pyuic5")
rcc_path = os.path.join(bindir, "pyrcc5")
file_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), "ui")
ui_path = file_dir
rc_path = file_dir
out_path = os.path.join(file_dir, "..", "..", "src", "urh", "ui")
ui_files = [f for f in os.listdir(ui_path) if f.endswith(".ui")]
rc_files = [f for f in os.listdir(rc_path) if f.endswith(".qrc")]
for f in ui_files:
file_path = os.path.join(ui_path, f)
outfile = "ui_" + f.replace(".ui", ".py")
out_file_path = os.path.join(out_path, outfile)
time_ui_file = os.path.getmtime(file_path)
try:
time_generated_file = os.path.getmtime(out_file_path)
except os.error:
time_generated_file = 0
if time_generated_file >= time_ui_file and not force:
# Generated file is already there and newer than ui file, no need to recompile it
continue
call([uic_path, "--from-imports", file_path, "-o", out_file_path])
# Remove Line: # Form implementation generated from reading ui file '/home/joe/GIT/urh/ui/fuzzing.ui'
# to avoid useless git updates when working on another computer
for line in fileinput.input(out_file_path, inplace=True):
if line.startswith("# Form implementation generated from reading ui file") or line.startswith(
"# Created by: "):
continue
if line.strip().startswith("QtCore.QMetaObject.connectSlotsByName("):
# disable auto slot connection, as we do not use it, and it causes crash on python 3.7
continue
print(line, end='')
for f in rc_files:
file_path = os.path.join(rc_path, f)
out_file = f.replace(".qrc", "_rc.py")
out_file_path = os.path.join(out_path, out_file)
time_rc_file = os.path.getmtime(file_path)
try:
time_generated_file = os.path.getmtime(out_file_path)
except os.error:
time_generated_file = 0
if time_generated_file < time_rc_file or force:
# Only create, when generated file is old than rc file to prevent unneeded git pushes
call([rcc_path, file_path, "-o", out_file_path])
if __name__ == "__main__":
gen()

Binary file not shown.

Before

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 85 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 516 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 138 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 523 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 98 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 521 KiB

View File

@ -1,63 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16px"
height="16px"
viewBox="0 0 16 16"
version="1.1"
id="SVGRoot"
inkscape:version="0.92.2 5c3e80d, 2017-08-06"
sodipodi:docname="collapse.svg">
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="16"
inkscape:cx="-25.75"
inkscape:cy="8"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1920"
inkscape:window-height="1141"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:grid-bbox="true" />
<defs
id="defs815" />
<metadata
id="metadata818">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:groupmode="layer"
inkscape:label="Ebene 1">
<path
id="path1447"
inkscape:label="Triangle"
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.0745703;stroke-opacity:1"
d="m 4,4 v 8 l 8,-4.0000001 z"
inkscape:connector-curvature="0" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -1,107 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16px"
height="16px"
viewBox="0 0 16 16"
version="1.1"
id="SVGRoot"
inkscape:version="0.92.1 r"
sodipodi:docname="decoding.svg"
inkscape:export-filename="/home/joe/GIT/urh/data/icons/decoding.svg.png"
inkscape:export-xdpi="94.889999"
inkscape:export-ydpi="94.889999">
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="16"
inkscape:cx="2.84375"
inkscape:cy="20.0625"
inkscape:document-units="px"
inkscape:current-layer="layer2"
showgrid="false"
inkscape:window-width="1920"
inkscape:window-height="1141"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:grid-bbox="true"
showguides="false" />
<defs
id="defs33" />
<metadata
id="metadata36">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:groupmode="layer"
inkscape:label="Ebene 1">
<rect
id="rect72"
width="16.1875"
height="2.125"
x="0"
y="7"
style="stroke-width:0.57454073" />
</g>
<g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="Ebene 2">
<g
aria-label="101"
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-size:8px;line-height:1.25;font-family:'Source Code Pro';-inkscape-font-specification:'Source Code Pro Semi-Bold';letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none"
id="text51">
<path
d="M 0.33433331,6.4375 H 4.6649998 V 5.1495 H 3.3956665 V 0.52016687 H 2.2196666 C 1.7529999,0.80016686 1.2863333,0.96816685 0.57699997,1.0988335 V 2.0881668 H 1.7903333 V 5.1495 H 0.33433331 Z"
style="font-style:normal;font-variant:normal;font-weight:900;font-stretch:normal;font-size:9.33333302px;font-family:'Source Code Pro';-inkscape-font-specification:'Source Code Pro Heavy';fill:#ff0000"
id="path4542" />
<path
d="m 8.0213539,6.5495 c 1.3906666,0 2.3333331,-1.0733333 2.3333331,-3.0986666 0,-2.0253332 -0.9426665,-3.04266653 -2.3333331,-3.04266653 -1.3906666,0 -2.3333332,1.01733333 -2.3333332,3.04266653 0,2.0253333 0.9426666,3.0986666 2.3333332,3.0986666 z m 0,-1.232 c -0.4946666,0 -0.9146666,-0.3919999 -0.9146666,-1.8666666 0,-1.4746666 0.42,-1.8106666 0.9146666,-1.8106666 0.4946667,0 0.9146666,0.336 0.9146666,1.8106666 0,1.4746667 -0.4199999,1.8666666 -0.9146666,1.8666666 z m 0,-1.1199999 c 0.4293333,0 0.7466667,-0.2986667 0.7466667,-0.7466667 0,-0.4479999 -0.3173334,-0.7466666 -0.7466667,-0.7466666 -0.4293333,0 -0.7466666,0.2986667 -0.7466666,0.7466666 0,0.448 0.3173333,0.7466667 0.7466666,0.7466667 z"
style="font-style:normal;font-variant:normal;font-weight:900;font-stretch:normal;font-size:9.33333302px;font-family:'Source Code Pro';-inkscape-font-specification:'Source Code Pro Heavy';fill:#ff0000"
id="path4544" />
<path
d="m 11.527041,6.4375 h 4.330667 V 5.1495 H 14.588375 V 0.52016687 h -1.176 C 12.945708,0.80016686 12.479041,0.96816685 11.769708,1.0988335 v 0.9893333 h 1.213333 V 5.1495 h -1.456 z"
style="font-style:normal;font-variant:normal;font-weight:900;font-stretch:normal;font-size:9.33333302px;font-family:'Source Code Pro';-inkscape-font-specification:'Source Code Pro Heavy';fill:#ff0000"
id="path4546" />
</g>
<g
aria-label="010"
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-size:9.33333302px;line-height:1.25;font-family:'Source Code Pro';-inkscape-font-specification:'Source Code Pro Semi-Bold';letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none"
id="text51-0">
<path
d="m 2.4780495,15.7097 c 1.3906666,0 2.3333332,-1.073333 2.3333332,-3.098666 0,-2.025334 -0.9426666,-3.042667 -2.3333332,-3.042667 -1.3906667,0 -2.33333328,1.017333 -2.33333328,3.042667 0,2.025333 0.94266658,3.098666 2.33333328,3.098666 z m 0,-1.232 c -0.4946667,0 -0.9146667,-0.392 -0.9146667,-1.866666 0,-1.474667 0.42,-1.810667 0.9146667,-1.810667 0.4946666,0 0.9146666,0.336 0.9146666,1.810667 0,1.474666 -0.42,1.866666 -0.9146666,1.866666 z m 0,-1.12 c 0.4293333,0 0.7466666,-0.298666 0.7466666,-0.746666 0,-0.448 -0.3173333,-0.746667 -0.7466666,-0.746667 -0.4293333,0 -0.7466667,0.298667 -0.7466667,0.746667 0,0.448 0.3173334,0.746666 0.7466667,0.746666 z"
style="font-style:normal;font-variant:normal;font-weight:900;font-stretch:normal;font-size:9.33333302px;font-family:'Source Code Pro';-inkscape-font-specification:'Source Code Pro Heavy';fill:#ff0000"
id="path4549" />
<path
d="m 5.9837369,15.5977 h 4.3306661 v -1.288 H 9.0450701 V 9.680367 H 7.8690702 c -0.4666667,0.28 -0.9333334,0.448 -1.6426667,0.578667 v 0.989333 H 7.4397368 V 14.3097 H 5.9837369 Z"
style="font-style:normal;font-variant:normal;font-weight:900;font-stretch:normal;font-size:9.33333302px;font-family:'Source Code Pro';-inkscape-font-specification:'Source Code Pro Heavy';fill:#ff0000"
id="path4551" />
<path
d="m 13.670757,15.7097 c 1.390667,0 2.333334,-1.073333 2.333334,-3.098666 0,-2.025334 -0.942667,-3.042667 -2.333334,-3.042667 -1.390666,0 -2.333333,1.017333 -2.333333,3.042667 0,2.025333 0.942667,3.098666 2.333333,3.098666 z m 0,-1.232 c -0.494666,0 -0.914666,-0.392 -0.914666,-1.866666 0,-1.474667 0.42,-1.810667 0.914666,-1.810667 0.494667,0 0.914667,0.336 0.914667,1.810667 0,1.474666 -0.42,1.866666 -0.914667,1.866666 z m 0,-1.12 c 0.429334,0 0.746667,-0.298666 0.746667,-0.746666 0,-0.448 -0.317333,-0.746667 -0.746667,-0.746667 -0.429333,0 -0.746666,0.298667 -0.746666,0.746667 0,0.448 0.317333,0.746666 0.746666,0.746666 z"
style="font-style:normal;font-variant:normal;font-weight:900;font-stretch:normal;font-size:9.33333302px;font-family:'Source Code Pro';-inkscape-font-specification:'Source Code Pro Heavy';fill:#ff0000"
id="path4553" />
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 6.6 KiB

View File

@ -1,77 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="32px"
height="32px"
viewBox="0 0 32 32"
version="1.1"
id="SVGRoot"
inkscape:version="0.92.1 r"
sodipodi:docname="equals.svg">
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="16"
inkscape:cx="-7.8340023"
inkscape:cy="9.8125"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1920"
inkscape:window-height="1141"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:grid-bbox="true" />
<defs
id="defs4485" />
<metadata
id="metadata4488">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:groupmode="layer"
inkscape:label="Ebene 1">
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8px;line-height:1.25;font-family:'Source Code Pro';-inkscape-font-specification:'Source Code Pro';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
x="8.375"
y="7.875"
id="text5091"><tspan
sodipodi:role="line"
id="tspan5089"
x="8.375"
y="14.875" /></text>
<g
transform="translate(-2.8046876,-0.0527343)"
aria-label=" ≟"
style="font-style:normal;font-variant:normal;font-weight:900;font-stretch:normal;font-size:40px;line-height:1.25;font-family:'Source Code Pro';-inkscape-font-specification:'Source Code Pro Heavy';letter-spacing:0px;word-spacing:0px;fill:#0055d4;fill-opacity:1;stroke:none"
id="text5046" />
<path
id="path5687"
style="fill:#0055d4;fill-opacity:1;stroke:none;stroke-width:0.94488192;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 3.1054687,18.119141 H 28.144531 v 4.628906 H 3.1054687 Z m 0,-8.886719 H 28.144531 v 4.589844 H 3.1054687 Z"
inkscape:connector-curvature="0" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.7 KiB

View File

@ -1,66 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="32px"
height="32px"
viewBox="0 0 32 32"
version="1.1"
id="SVGRoot"
inkscape:version="0.92.1 r"
sodipodi:docname="equals_qm.svg">
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="16"
inkscape:cx="20.384743"
inkscape:cy="14.953125"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1920"
inkscape:window-height="1141"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:grid-bbox="true" />
<defs
id="defs4485" />
<metadata
id="metadata4488">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:groupmode="layer"
inkscape:label="Ebene 1">
<g
aria-label=" ≟"
style="font-style:normal;font-variant:normal;font-weight:900;font-stretch:normal;font-size:40px;line-height:1.25;font-family:'Source Code Pro';-inkscape-font-specification:'Source Code Pro Heavy';letter-spacing:0px;word-spacing:0px;fill:#0055d4;fill-opacity:1;stroke:none"
id="text5046">
<path
d="M 3.9726563,17.472656 H 29.011719 V 22.0625 H 3.9726563 Z m 0,8.886719 H 29.011719 v 4.628906 H 3.9726563 Z M 17.585937,10.539063 h -3.535156 v -0.46875 q 0,-0.820313 0.3125,-1.4257817 0.332032,-0.625 1.367188,-1.5820313 l 0.625,-0.5664063 q 0.566406,-0.5078125 0.820312,-0.9570312 0.253906,-0.4492188 0.253906,-0.8984375 0,-0.6835937 -0.46875,-1.0546875 -0.46875,-0.390625 -1.308593,-0.390625 -0.800781,0 -1.71875,0.3320313 -0.917969,0.3125 -1.894531,0.9570312 V 1.4179687 Q 13.210938,1.0078125 14.1875,0.8125 q 0.976563,-0.1953125 1.875,-0.1953125 2.382812,0 3.632812,0.9765625 1.25,0.9765625 1.25,2.8320312 0,0.9570313 -0.371093,1.71875 Q 20.203125,6.90625 19.265625,7.765625 l -0.625,0.546875 q -0.664063,0.625 -0.859375,0.9960938 -0.195313,0.3515625 -0.195313,0.8007812 z m -3.535156,1.445312 h 3.535156 v 3.476563 h -3.535156 z"
style="fill:#0055d4;fill-opacity:1"
id="path5048" />
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

View File

@ -1,105 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16px"
height="16px"
viewBox="0 0 16 16"
version="1.1"
id="SVGRoot"
inkscape:version="0.92.1 r"
sodipodi:docname="lock.svg">
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="32"
inkscape:cx="2.438584"
inkscape:cy="8.4622059"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1440"
inkscape:window-height="844"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:grid-bbox="true" />
<defs
id="defs10" />
<metadata
id="metadata13">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:groupmode="layer"
id="layer3"
inkscape:label="Ebene 3" />
<g
id="layer1"
inkscape:groupmode="layer"
inkscape:label="Ebene 1">
<rect
style="fill:#0055d4;fill-opacity:1;stroke-width:1.29552507"
id="rect26"
width="13.1875"
height="9.4109621"
x="1.53125"
y="6.1827879"
ry="1.668939" />
<path
style="fill:none;fill-opacity:1;stroke:#0055d4;stroke-width:2.37899995;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path955"
sodipodi:type="arc"
sodipodi:cx="8.0946102"
sodipodi:cy="4.9240141"
sodipodi:rx="4.0718422"
sodipodi:ry="3.1146088"
sodipodi:start="3.1334605"
sodipodi:end="3.1328231"
d="M 4.0229027,4.9493423 A 4.0718422,3.1146088 0 0 1 8.0608489,1.8095124 4.0718422,3.1146088 0 0 1 12.166307,4.8976933 4.0718422,3.1146088 0 0 1 8.1296692,8.0385074 4.0718422,3.1146088 0 0 1 4.0229246,4.9513275"
sodipodi:open="true" />
</g>
<g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="Ebene 2">
<path
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.50427711;stroke-opacity:1"
id="path853"
sodipodi:type="arc"
sodipodi:cx="8.0742912"
sodipodi:cy="8.8435822"
sodipodi:rx="1.8158679"
sodipodi:ry="1.7158939"
sodipodi:start="3.1415927"
sodipodi:end="2.8204603"
d="M 6.2584233,8.8435821 A 1.8158679,1.7158939 0 0 1 7.9286644,7.1332151 1.8158679,1.7158939 0 0 1 9.8668015,8.56925 1.8158679,1.7158939 0 0 1 8.5074256,10.509948 1.8158679,1.7158939 0 0 1 6.351253,9.385189"
sodipodi:open="true" />
<rect
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.79365373;stroke-opacity:1"
id="rect1685"
width="1.2488354"
height="4.0842142"
x="7.4914622"
y="10.344006" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.3 KiB

View File

@ -1,68 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16px"
height="16px"
viewBox="0 0 16 16"
version="1.1"
id="SVGRoot"
inkscape:version="0.92.2 2405546, 2018-03-11"
sodipodi:docname="message_type.svg">
<sodipodi:namedview
id="base"
pagecolor="#000000"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="1"
inkscape:pageshadow="2"
inkscape:zoom="32"
inkscape:cx="4.9678955"
inkscape:cy="8.278417"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1920"
inkscape:window-height="1141"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:grid-bbox="true" />
<defs
id="defs815" />
<metadata
id="metadata818">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:groupmode="layer"
inkscape:label="Ebene 1">
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:900;font-stretch:normal;font-size:14.66666698px;line-height:1.25;font-family:'Source Sans Pro';-inkscape-font-specification:'Source Sans Pro Heavy';letter-spacing:0px;word-spacing:0px;fill:#008000;fill-opacity:1;stroke:none"
x="-0.75"
y="12.0625"
id="text1376"><tspan
sodipodi:role="line"
id="tspan1374"
x="-0.75"
y="12.0625"
style="font-style:normal;font-variant:normal;font-weight:900;font-stretch:normal;font-size:12.66666698px;line-height:1;font-family:'Source Sans Pro';-inkscape-font-specification:'Source Sans Pro Heavy';fill:#008000">MT</tspan></text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.3 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 70 KiB

View File

@ -1,76 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="32px"
height="32px"
viewBox="0 0 32 32"
version="1.1"
id="SVGRoot"
inkscape:version="0.92.1 r"
sodipodi:docname="plus.svg">
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="16"
inkscape:cx="20.384743"
inkscape:cy="17.390625"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1920"
inkscape:window-height="1141"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:grid-bbox="true" />
<defs
id="defs4485" />
<metadata
id="metadata4488">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:groupmode="layer"
inkscape:label="Ebene 1">
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8px;line-height:1.25;font-family:'Source Code Pro';-inkscape-font-specification:'Source Code Pro';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
x="8.375"
y="7.875"
id="text5091"><tspan
sodipodi:role="line"
id="tspan5089"
x="8.375"
y="14.875" /></text>
<g
aria-label="+"
style="font-style:normal;font-variant:normal;font-weight:900;font-stretch:normal;font-size:53.33333206px;line-height:1.25;font-family:'Source Code Pro';-inkscape-font-specification:'Source Code Pro Heavy';letter-spacing:0px;word-spacing:0px;fill:#0055d4;fill-opacity:1;stroke:none"
id="text5707">
<path
d="m 12.755833,28.8875 h 6.613333 v -9.6 h 9.28 v -6.4 h -9.28 V 3.2875007 H 12.755833 V 12.8875 H 3.4758333 v 6.4 h 9.2799997 z"
style=""
id="path5709" />
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.6 KiB

View File

@ -1,162 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16px"
height="16px"
viewBox="0 0 16 16"
version="1.1"
id="SVGRoot"
sodipodi:docname="sniffer.svg"
inkscape:version="0.92.1 r">
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="32"
inkscape:cx="2.7848469"
inkscape:cy="9.5734649"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1920"
inkscape:window-height="1141"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:grid-bbox="true" />
<defs
id="defs5036">
<linearGradient
id="linearGradient7079"
osb:paint="solid">
<stop
style="stop-color:#aaccff;stop-opacity:1;"
offset="0"
id="stop7077" />
</linearGradient>
<filter
style="color-interpolation-filters:sRGB;"
inkscape:label="Drop Shadow"
id="filter914">
<feFlood
flood-opacity="0.498039"
flood-color="rgb(0,0,0)"
result="flood"
id="feFlood904" />
<feComposite
in="flood"
in2="SourceGraphic"
operator="in"
result="composite1"
id="feComposite906" />
<feGaussianBlur
in="composite1"
stdDeviation="0.5"
result="blur"
id="feGaussianBlur908" />
<feOffset
dx="0.1"
dy="0.1"
result="offset"
id="feOffset910" />
<feComposite
in="SourceGraphic"
in2="offset"
operator="over"
result="composite2"
id="feComposite912" />
</filter>
<filter
style="color-interpolation-filters:sRGB;"
inkscape:label="Drop Shadow"
id="filter938">
<feFlood
flood-opacity="0.498039"
flood-color="rgb(0,0,0)"
result="flood"
id="feFlood928" />
<feComposite
in="flood"
in2="SourceGraphic"
operator="in"
result="composite1"
id="feComposite930" />
<feGaussianBlur
in="composite1"
stdDeviation="0.5"
result="blur"
id="feGaussianBlur932" />
<feOffset
dx="0.1"
dy="0.1"
result="offset"
id="feOffset934" />
<feComposite
in="SourceGraphic"
in2="offset"
operator="over"
result="composite2"
id="feComposite936" />
</filter>
</defs>
<metadata
id="metadata5039">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="Ebene 2">
<path
style="fill:none;stroke:#ff0000;stroke-width:1.88976378;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter938)"
d="m 11.303085,11.154756 3.83883,3.910488"
id="path5611"
inkscape:connector-curvature="0" />
</g>
<g
id="layer1"
inkscape:groupmode="layer"
inkscape:label="Ebene 1">
<circle
style="fill:#afc6e9;fill-opacity:0.78417263;stroke:#ff0000;stroke-width:1.19093943;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter914)"
id="path5605"
cx="6.8475037"
cy="6.8600025"
r="6.0412431" />
<g
aria-label="10"
style="font-style:normal;font-variant:normal;font-weight:900;font-stretch:normal;font-size:10.66666698px;line-height:1.25;font-family:'Source Code Pro';-inkscape-font-specification:'Source Code Pro Heavy';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
id="text5597"
transform="matrix(0.7643067,0,0,0.85162896,0.65422787,0.02035532)">
<path
d="M 2.4981667,11.1875 H 7.4475002 V 9.7155 H 5.9968335 V 4.4248331 H 4.6528334 c -0.5333333,0.32 -1.0666667,0.512 -1.8773334,0.6613334 V 6.2168332 H 4.1621667 V 9.7155 h -1.664 z"
id="path7117"
inkscape:connector-curvature="0"
style="fill:#000000;fill-opacity:1" />
<path
d="m 11.283334,11.3155 c 1.589333,0 2.666666,-1.226667 2.666666,-3.5413334 0,-2.3146668 -1.077333,-3.4773335 -2.666666,-3.4773335 -1.5893338,0 -2.6666672,1.1626667 -2.6666672,3.4773335 0,2.3146664 1.0773334,3.5413334 2.6666672,3.5413334 z m 0,-1.408 C 10.718,9.9075 10.238,9.4594999 10.238,7.7741666 c 0,-1.6853334 0.48,-2.0693334 1.045334,-2.0693334 0.565333,0 1.045333,0.384 1.045333,2.0693334 0,1.6853333 -0.48,2.1333334 -1.045333,2.1333334 z m 0,-1.2800001 c 0.490666,0 0.853333,-0.3413333 0.853333,-0.8533333 0,-0.5120001 -0.362667,-0.8533334 -0.853333,-0.8533334 -0.490667,0 -0.853334,0.3413333 -0.853334,0.8533334 0,0.512 0.362667,0.8533333 0.853334,0.8533333 z"
id="path7119"
inkscape:connector-curvature="0"
style="fill:#000000;fill-opacity:1" />
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 5.6 KiB

View File

@ -1,67 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16px"
height="16px"
viewBox="0 0 16 16"
version="1.1"
id="SVGRoot"
inkscape:version="0.92.1 r"
sodipodi:docname="spectrum.svg">
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="45.254834"
inkscape:cx="4.0007222"
inkscape:cy="7.9550105"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1920"
inkscape:window-height="1015"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:grid-bbox="true" />
<defs
id="defs5788" />
<metadata
id="metadata5791">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Ebene 2"
id="layer2"
inkscape:groupmode="layer" />
<g
id="layer1"
inkscape:groupmode="layer"
inkscape:label="Ebene 1">
<path
style="fill:#80b3ff;fill-rule:evenodd;stroke:#7d7d7d;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M -0.1767767,13.19367 C -0.15467961,13.061088 0.79549512,7.2716507 0.79549512,7.2716507 L 1.6130873,12.818019 2.9610096,8.4648934 4.0216698,13.326252 5.5021746,7.7135924 6.2755727,12.199301 8.2201163,0.50994206 10.341437,13.171573 l 1.635184,-5.1707185 0.861787,4.1542525 0.773397,-3.9995729 0.662913,4.8171649 1.038563,-5.5905629 0.795495,5.8115339"
id="path4631"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccccccccccc" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -1,75 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16mm"
height="8mm"
viewBox="0 0 16 8"
version="1.1"
id="svg8"
inkscape:version="0.92.1 r"
sodipodi:docname="splitter_handle_horizontal.svg">
<defs
id="defs2" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="11.2"
inkscape:cx="28.682636"
inkscape:cy="13.700107"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1920"
inkscape:window-height="1141"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Ebene 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-289)">
<circle
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.25;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4487"
cx="2.0135045"
cy="293.08649"
r="1.9135045" />
<circle
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.25;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4487-6"
cx="7.9135046"
cy="293.08649"
r="1.9135045" />
<circle
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.25;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4487-7"
cx="14.013505"
cy="293.08649"
r="1.9135045" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -1,78 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="8mm"
height="16mm"
viewBox="0 0 8 16"
version="1.1"
id="svg8"
inkscape:version="0.92.1 r"
sodipodi:docname="splitter_handle_vertical.svg">
<defs
id="defs2" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="11.2"
inkscape:cx="28.682636"
inkscape:cy="35.128679"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1920"
inkscape:window-height="1141"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Ebene 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-281)">
<circle
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.25;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4487"
cx="-294.98648"
cy="3.9135046"
r="1.9135045"
transform="rotate(-90)" />
<circle
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.25;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4487-6"
cx="-289.08649"
cy="3.9135046"
r="1.9135045"
transform="rotate(-90)" />
<circle
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.25;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4487-7"
cx="-282.98648"
cy="3.9135046"
r="1.9135045"
transform="rotate(-90)" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -1,63 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16px"
height="16px"
viewBox="0 0 16 16"
version="1.1"
id="SVGRoot"
inkscape:version="0.92.2 5c3e80d, 2017-08-06"
sodipodi:docname="uncollapse.svg">
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="16"
inkscape:cx="-8.875"
inkscape:cy="8"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1920"
inkscape:window-height="1141"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:grid-bbox="true" />
<defs
id="defs815" />
<metadata
id="metadata818">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:groupmode="layer"
inkscape:label="Ebene 1">
<path
id="path1447"
inkscape:label="Triangle"
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.0745703;stroke-opacity:1"
d="M 12,4 H 4 l 4.000001,8 z"
inkscape:connector-curvature="0" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -1,105 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16px"
height="16px"
viewBox="0 0 16 16"
version="1.1"
id="SVGRoot"
inkscape:version="0.92.1 r"
sodipodi:docname="unlock.svg">
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="32"
inkscape:cx="2.438584"
inkscape:cy="8.4622059"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1440"
inkscape:window-height="844"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:grid-bbox="true" />
<defs
id="defs10" />
<metadata
id="metadata13">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:groupmode="layer"
id="layer3"
inkscape:label="Ebene 3" />
<g
id="layer1"
inkscape:groupmode="layer"
inkscape:label="Ebene 1">
<rect
style="fill:#0055d4;fill-opacity:1;stroke-width:1.29552507"
id="rect26"
width="13.1875"
height="9.4109621"
x="1.53125"
y="6.1827879"
ry="1.668939" />
<path
style="fill:none;fill-opacity:1;stroke:#0055d4;stroke-width:2.37899995;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path955"
sodipodi:type="arc"
sodipodi:cx="8.0946102"
sodipodi:cy="4.9240141"
sodipodi:rx="4.0718422"
sodipodi:ry="3.1146088"
sodipodi:start="4.709543"
sodipodi:end="1.5424001"
d="M 8.0830218,1.8094179 A 4.0718422,3.1146088 0 0 1 12.165956,4.8753624 4.0718422,3.1146088 0 0 1 8.2102196,8.0373672"
sodipodi:open="true" />
</g>
<g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="Ebene 2">
<path
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.50427711;stroke-opacity:1"
id="path853"
sodipodi:type="arc"
sodipodi:cx="8.0742912"
sodipodi:cy="8.8435822"
sodipodi:rx="1.8158679"
sodipodi:ry="1.7158939"
sodipodi:start="3.1415927"
sodipodi:end="2.8204603"
d="M 6.2584233,8.8435821 A 1.8158679,1.7158939 0 0 1 7.9286644,7.1332151 1.8158679,1.7158939 0 0 1 9.8668015,8.56925 1.8158679,1.7158939 0 0 1 8.5074256,10.509948 1.8158679,1.7158939 0 0 1 6.351253,9.385189"
sodipodi:open="true" />
<rect
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.79365373;stroke-opacity:1"
id="rect1685"
width="1.2488354"
height="4.0842142"
x="7.4914622"
y="10.344006" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.3 KiB

View File

@ -1,38 +0,0 @@
[Setup]
; NOTE: The value of AppId uniquely identifies this application.
; Do not use the same AppId value in installers for other applications.
; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
AppId={{8A0E36A6-DE56-46B8-BCC3-C16D1BC759CC}
AppName=Universal Radio Hacker
AppVersion={#MyAppVersion}
VersionInfoVersion={#MyAppVersion}
ArchitecturesInstallIn64BitMode=x64
UninstallDisplayName=Universal Radio Hacker
AppPublisher=Johannes Pohl
AppPublisherURL=https://github.com/jopohl/urh
AppSupportURL=https://github.com/jopohl/urh
AppUpdatesURL=https://github.com/jopohl/urh
DefaultDirName={commonpf}\Universal Radio Hacker
DisableProgramGroupPage=yes
LicenseFile=..\LICENSE
OutputDir=..\dist
OutputBaseFilename=Universal.Radio.Hacker-{#MyAppVersion}-{#Arch}
Compression=lzma2/ultra
SolidCompression=yes
[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"
[Tasks]
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
[Files]
Source: "..\pyinstaller\urh\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
[Icons]
Name: "{commonprograms}\Universal Radio Hacker"; Filename: "{app}\urh.exe"
Name: "{commondesktop}\Universal Radio Hacker"; Filename: "{app}\urh.exe"; Tasks: desktopicon
[Run]
Filename: "{app}\urh.exe"; Description: "{cm:LaunchProgram,Universal Radio Hacker}"; Flags: nowait postinstall skipifsilent

View File

@ -1,22 +0,0 @@
#!/bin/bash
# for adapted jopohl/urh_manylinux
touch /tmp/urh_releasing
for PYBIN in /opt/python/*$PYVER*/bin; do # for all if PYVER not set
echo -e "\033[1mInstalling requirements for $PYBIN\033[0m"
"${PYBIN}/pip" install -r /io/data/requirements.txt
cd /io || return
echo -e "\033[1mBuilding extentions for $PYBIN\033[0m"
"${PYBIN}/python3" setup.py build_ext "-j$(nproc)"
echo -e "\033[1mBuilding wheel for $PYBIN\033[0m"
"${PYBIN}/pip" wheel --no-deps /io/ -w /wheelhouse/
done
# Bundle external libs into wheels
echo -e '\033[92mRepairing wheels...\033[0m'
for whl in /wheelhouse/*.whl; do
auditwheel repair "$whl" -w /io/dist/
done

View File

@ -1,80 +0,0 @@
#!/bin/bash
# for plain quay.io/pypa/manylinux2014_x86_64
AIRSPY_VERSION="1.0.9"
BLADERF_VERSION="2018.08"
LIMESUITE_VERSION="20.01.0"
SDRPLAY_VERSION="2.13"
RTLSDR_VERSION="0.6.0"
echo -e '\033[92mInstalling dependencies...\033[0m'
yum -y -q install wget cmake3 hackrf-devel uhd-devel\
https://github.com/analogdevicesinc/libiio/releases/download/v0.19/libiio-0.19.g5f5af2e-centos-7-x86_64.rpm
build_airspy() {
&> /dev/null
tar xf /tmp/airspy.tar.gz -C /tmp
cmake3 -Wno-dev -S /tmp/airspyone_host-$AIRSPY_VERSION -B /tmp/build_airspy > /dev/null
make --silent -C /tmp/build_airspy > /dev/null
make --silent -C /tmp/build_airspy install > /dev/null
}
build_bladerf() {
wget https://github.com/Nuand/bladeRF/archive/$BLADERF_VERSION.tar.gz -O /tmp/bladeRF.tar.gz &> /dev/null
tar xf /tmp/bladeRF.tar.gz -C /tmp
cmake3 -Wno-dev -S /tmp/bladeRF-$BLADERF_VERSION/host -B /tmp/build_blade > /dev/null
make --silent -C /tmp/build_blade > /dev/null
make --silent -C /tmp/build_blade install > /dev/null
}
build_limesdr() {
wget https://github.com/myriadrf/LimeSuite/archive/v$LIMESUITE_VERSION.tar.gz -O /tmp/lime.tar.gz &> /dev/null
tar xf /tmp/lime.tar.gz -C /tmp
cmake3 -Wno-dev -S /tmp/LimeSuite-$LIMESUITE_VERSION -B /tmp/build_lime > /dev/null
make --silent -C /tmp/build_lime > /dev/null
make --silent -C /tmp/build_lime install > /dev/null
}
build_rtlsdr() {
wget https://github.com/osmocom/rtl-sdr/archive/$RTLSDR_VERSION.tar.gz -O /tmp/rtlsdr.tar.gz &> /dev/null
tar xf /tmp/rtlsdr.tar.gz -C /tmp
cmake3 -Wno-dev -DDETACH_KERNEL_DRIVER=ON -S /tmp/rtl-sdr-$RTLSDR_VERSION -B /tmp/build_rtlsdr > /dev/null
make --silent -C /tmp/build_rtlsdr > /dev/null
make --silent -C /tmp/build_rtlsdr install > /dev/null
}
build_sdrplay() {
wget http://www.sdrplay.com/software/SDRplay_RSP_API-Linux-$SDRPLAY_VERSION.1.run -O /tmp/sdrplay.run &> /dev/null
bash /tmp/sdrplay.run --tar xf -C /tmp
mv /tmp/mirsdrapi-rsp.h /usr/include
mv /tmp/x86_64/* /usr/lib64
ln -s /usr/lib64/libmirsdrapi-rsp.so.$SDRPLAY_VERSION /usr/lib64/libmirsdrapi-rsp.so
}
echo -e '\033[92mCompiling SDR libs...\033[0m'
build_airspy &
build_bladerf &
build_limesdr &
build_rtlsdr &
build_sdrplay &
wait
touch /tmp/urh_releasing
for PYBIN in /opt/python/*/bin; do
echo -e "\033[1mInstalling requirements for $PYBIN\033[0m"
"${PYBIN}/pip" install -r /io/data/requirements.txt > /dev/null
cd /io || return
echo -e "\033[1mBuilding extentions for $PYBIN\033[0m"
"${PYBIN}/python3" setup.py build_ext "-j$(nproc)" | grep --color=always "Skipping"
echo -e "\033[1mBuilding wheel for $PYBIN\033[0m"
"${PYBIN}/pip" wheel --no-deps /io/ -w /wheelhouse/ > /dev/null
done
# Bundle external libs into wheels
echo -e '\033[92mRepairing wheels...\033[0m'
for whl in /wheelhouse/*.whl; do
auditwheel repair "$whl" -w /io/dist/
done

View File

@ -1,48 +0,0 @@
FROM quay.io/pypa/manylinux2014_x86_64
RUN export AIRSPY_VERSION="1.0.9" \
&& export BLADERF_VERSION="2018.08" \
&& export LIMESUITE_VERSION="20.01.0" \
&& export SDRPLAY_VERSION="2.13" \
&& export RTLSDR_VERSION="0.6.0" \
&& export UHD_VERSION="3.15.0.0" \
&& yum -y install wget cmake3 hackrf-devel boost169-devel https://github.com/analogdevicesinc/libiio/releases/download/v0.19/libiio-0.19.g5f5af2e-centos-7-x86_64.rpm \
# UHD
&& wget https://github.com/EttusResearch/uhd/archive/v$UHD_VERSION.tar.gz -O /tmp/uhd.tar.gz \
&& tar xf /tmp/uhd.tar.gz -C /tmp \
&& python3.9 -m pip install mako \
&& cmake3 -DBOOST_INCLUDEDIR=/usr/include/boost169/ -DBOOST_LIBRARYDIR=/usr/lib64/boost169/ -DENABLE_EXAMPLES=OFF -DENABLE_UTILS=OFF -DENABLE_C_API=ON -DENABLE_TESTS=OFF -DENABLE_MAN_PAGES=OFF -S /tmp/uhd-$UHD_VERSION/host -B /tmp/build_uhd \
&& make -j$(nproc) -C /tmp/build_uhd \
&& make -C /tmp/build_uhd install \
# AirSpy
&& wget https://github.com/airspy/airspyone_host/archive/v$AIRSPY_VERSION.tar.gz -O /tmp/airspy.tar.gz \
&& tar xf /tmp/airspy.tar.gz -C /tmp \
&& cmake3 -Wno-dev -S /tmp/airspyone_host-$AIRSPY_VERSION -B /tmp/build_airspy \
&& make -j$(nproc) -C /tmp/build_airspy \
&& make -C /tmp/build_airspy install \
# BladeRF
&& wget https://github.com/Nuand/bladeRF/archive/$BLADERF_VERSION.tar.gz -O /tmp/bladeRF.tar.gz \
&& tar xf /tmp/bladeRF.tar.gz -C /tmp \
&& cmake3 -Wno-dev -S /tmp/bladeRF-$BLADERF_VERSION/host -B /tmp/build_blade \
&& make -j$(nproc) -C /tmp/build_blade \
&& make -C /tmp/build_blade install \
&& wget https://github.com/myriadrf/LimeSuite/archive/v$LIMESUITE_VERSION.tar.gz -O /tmp/lime.tar.gz \
# Lime
&& tar xf /tmp/lime.tar.gz -C /tmp \
&& cmake3 -S /tmp/LimeSuite-$LIMESUITE_VERSION -B /tmp/build_lime \
&& make -j$(nproc) -C /tmp/build_lime \
&& make -C /tmp/build_lime install \
# RTLSDR
&& wget https://github.com/osmocom/rtl-sdr/archive/$RTLSDR_VERSION.tar.gz -O /tmp/rtlsdr.tar.gz \
&& tar xf /tmp/rtlsdr.tar.gz -C /tmp \
&& cmake3 -DDETACH_KERNEL_DRIVER=ON -S /tmp/rtl-sdr-$RTLSDR_VERSION -B /tmp/build_rtlsdr \
&& make -j$(nproc) -C /tmp/build_rtlsdr \
&& make -C /tmp/build_rtlsdr install \
# SDRPLAY
&& wget http://www.sdrplay.com/software/SDRplay_RSP_API-Linux-$SDRPLAY_VERSION.1.run -O /tmp/sdrplay.run \
&& bash /tmp/sdrplay.run --tar xf -C /tmp \
&& mv /tmp/mirsdrapi-rsp.h /usr/include \
&& mv /tmp/x86_64/* /usr/lib64 \
&& ln -s /usr/lib64/libmirsdrapi-rsp.so.$SDRPLAY_VERSION /usr/lib64/libmirsdrapi-rsp.so \
&& rm -rf /tmp/* \
&& yum clean all

View File

@ -1,74 +0,0 @@
import os
import shutil
import sys
HIDDEN_IMPORTS = ["packaging.specifiers", "packaging.requirements", "pkg_resources.py2_warn",
"numpy.core._methods", "numpy.core._dtype_ctypes",
"numpy.random.common", "numpy.random.entropy", "numpy.random.bounded_integers"]
DATA = [("src/urh/dev/native/lib/shared", "."), ("src/urh/plugins", "urh/plugins"), ]
EXCLUDE = ["matplotlib"]
def run_pyinstaller(cmd_list: list, env: list=None):
cmd = " ".join(cmd_list)
print(cmd, flush=True)
env = [] if env is None else env
if env:
os.system(" ".join(env) + " " + cmd)
else:
os.system(cmd)
if __name__ == '__main__':
cmd = ["pyinstaller", "--clean"]
if sys.platform == "darwin":
cmd.append("--onefile")
for hidden_import in HIDDEN_IMPORTS:
cmd.append("--hidden-import={}".format(hidden_import))
for src, dst in DATA:
cmd.append("--add-data")
cmd.append('"{}{}{}"'.format(src, os.pathsep, dst))
for exclude in EXCLUDE:
cmd.append("--exclude-module={}".format(exclude))
urh_path = os.path.realpath(os.path.join(os.path.dirname(__file__), ".."))
if sys.platform == "darwin":
cmd.append('--icon="{}"'.format(os.path.join(urh_path, "data/icons/appicon.icns")))
else:
cmd.append('--icon="{}"'.format(os.path.join(urh_path, "data/icons/appicon.ico")))
cmd.extend(["--distpath", "./pyinstaller"])
urh_cmd = cmd + ["--name=urh", "--windowed", "--workpath", "./urh_build",
os.path.join(urh_path, "src/urh/main.py")]
urh_debug_cmd = cmd + ["--name=urh_debug", "--workpath", "./urh_debug_build",
os.path.join(urh_path, "src/urh/main.py")]
cli_cmd = cmd + ["--workpath", "./urh_cli_build",
os.path.join(urh_path, "src/urh/cli/urh_cli.py")]
os.makedirs("./pyinstaller")
if sys.platform == "darwin":
run_pyinstaller(urh_cmd, env=["DYLD_LIBRARY_PATH=src/urh/dev/native/lib/shared"])
import plistlib
with open("pyinstaller/urh.app/Contents/Info.plist", "rb") as f:
p = plistlib.load(f)
p["NSHighResolutionCapable"] = True
p["NSRequiresAquaSystemAppearance"] = True
p["NSMicrophoneUsageDescription"] = "URH needs access to your microphone to capture signals via Soundcard."
with open("pyinstaller/urh.app/Contents/Info.plist", "wb") as f:
plistlib.dump(p, f)
else:
for cmd in [urh_cmd, cli_cmd, urh_debug_cmd]:
run_pyinstaller(cmd)
shutil.copy("./pyinstaller/urh_cli/urh_cli.exe", "./pyinstaller/urh/urh_cli.exe")
shutil.copy("./pyinstaller/urh_debug/urh_debug.exe", "./pyinstaller/urh/urh_debug.exe")

View File

@ -1,54 +0,0 @@
# -*- mode: python ; coding: utf-8 -*-
block_cipher = None
a = Analysis(['src/urh/main.py'],
pathex=[],
binaries=[],
datas=[('src/urh/plugins', 'urh/plugins')],
hiddenimports=[],
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=['matplotlib'],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,
cipher=block_cipher)
exe = EXE(pyz,
a.scripts,
[],
exclude_binaries=True,
name='main',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
console=False,
disable_windowed_traceback=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None , icon='data/icons/appicon.icns')
coll = COLLECT(exe,
a.binaries,
a.zipfiles,
a.datas,
strip=False,
upx=True,
upx_exclude=[],
name='main')
app = BUNDLE(coll,
name='main.app',
icon='./data/icons/appicon.icns',
bundle_identifier=None,
info_plist={
'NSRequiresAquaSystemAppearance': True,
'NSMicrophoneUsageDescription': 'URH needs access to your microphone to capture signals via Soundcard.',
'CFBundleDisplayName': 'URH',
'CFBundleName': 'URH'
},)

View File

@ -1,83 +0,0 @@
import fileinput
import os
import shutil
import sys
import tempfile
from subprocess import call, check_output
def cleanup():
"""
Remove all cache directories
:return:
"""
script_dir = os.path.dirname(__file__) if not os.path.islink(__file__) else os.path.dirname(os.readlink(__file__))
script_dir = os.path.realpath(os.path.join(script_dir, ".."))
shutil.rmtree(os.path.join(script_dir, "dist"), ignore_errors=True)
shutil.rmtree(os.path.join(script_dir, "tmp"), ignore_errors=True)
shutil.rmtree(os.path.join(script_dir, "urh.egg-info"), ignore_errors=True)
shutil.rmtree(os.path.join(script_dir, "src", "urh.egg-info"), ignore_errors=True)
shutil.rmtree(os.path.join(script_dir, "src", "urh", "tmp"), ignore_errors=True)
def release():
script_dir = os.path.dirname(__file__) if not os.path.islink(__file__) else os.path.dirname(os.readlink(__file__))
script_dir = os.path.realpath(os.path.join(script_dir, ".."))
os.chdir(script_dir)
current_branch = check_output(["git", "rev-parse", "--abbrev-ref", "HEAD"]).decode("UTF-8").strip()
if current_branch != "master":
print("You can only release from master!")
sys.exit(1)
open(os.path.join(tempfile.gettempdir(), "urh_releasing"), "w").close()
from src.urh import version
version_file = os.path.realpath(os.path.join(script_dir, "src", "urh", "version.py"))
cur_version = version.VERSION
numbers = cur_version.split(".")
numbers[-1] = str(int(numbers[-1]) + 1)
cur_version = ".".join(numbers)
for line in fileinput.input(version_file, inplace=True):
if line.startswith("VERSION"):
line = 'VERSION = "{0}" \n'.format(cur_version)
print(line, end='')
# Publish new version number
call(["git", "add", version_file])
call(["git", "commit", "-m", "version" + cur_version])
input("Pushing to GitHub now. Press a key to continue.")
call(["git", "push"])
os.chdir(script_dir)
# Remove local tags
call("git tag -l | xargs git tag -d", shell=True)
call(["git", "fetch", "--tags"])
# Push new tag
call(["git", "tag", "v" + cur_version, "-m", "version " + cur_version])
call(["git", "push", "origin", "--tags"]) # Creates tar package on https://github.com/jopohl/urh/tarball/va.b.c.d
os.remove(os.path.join(tempfile.gettempdir(), "urh_releasing"))
# region Build docker image and push to DockerHub
os.chdir(os.path.dirname(__file__))
call(["docker", "login"])
call(["docker", "build", "--no-cache",
"--tag", "jopohl/urh:latest",
"--tag", "jopohl/urh:{}".format(cur_version), "."])
call(["docker", "push", "jopohl/urh:latest"])
call(["docker", "push", "jopohl/urh:{}".format(cur_version)])
# endregion
if __name__ == "__main__":
cleanup()
input("Starting release. Hit a key to continue.")
release()
cleanup()

View File

@ -1,4 +0,0 @@
numpy
pyqt5
psutil
cython!=0.29.18

View File

@ -1,280 +0,0 @@
// Source: https://github.com/snapcore/snapcraft-preloads/blob/master/semaphores/preload-semaphores.c
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
/*
* $ gcc -Wall -fPIC -shared -o mylib.so ./lib.c -ldl
* $ LD_PRELOAD=./mylib.so ...
*/
#include <dlfcn.h>
#include <sys/types.h>
#include <stdio.h>
#include <semaphore.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdarg.h>
#include <limits.h>
static sem_t *(*original_sem_open) (const char *, int, ...);
static int (*original_sem_unlink) (const char *);
// Format is: 'sem.snap.SNAP_NAME.<something>'. So: 'sem.snap.' + '.' = 10
#define MAX_NAME_SIZE NAME_MAX - 10
#define SHM_DIR "/dev/shm"
void debug(char *s, ...)
{
if (secure_getenv("SEMWRAP_DEBUG")) {
va_list va;
va_start(va, s);
fprintf(stderr, "SEMWRAP: ");
vfprintf(stderr, s, va);
va_end(va);
fprintf(stderr, "\n");
}
}
const char *get_snap_name(void)
{
const char *snapname = getenv("SNAP_INSTANCE_NAME");
if (!snapname) {
snapname = getenv("SNAP_NAME");
}
if (!snapname) {
debug("SNAP_NAME and SNAP_INSTANCE_NAME not set");
}
return snapname;
}
int rewrite(const char *snapname, const char *name, char *rewritten,
size_t rmax)
{
if (strlen(snapname) + strlen(name) > MAX_NAME_SIZE) {
errno = ENAMETOOLONG;
return -1;
}
const char *tmp = name;
if (tmp[0] == '/') {
// If specified with leading '/', just strip it to avoid
// having to mkdir(), etc
tmp = &name[1];
}
int n = snprintf(rewritten, rmax, "snap.%s.%s", snapname, tmp);
if (n < 0 || n >= rmax) {
fprintf(stderr, "snprintf truncated\n");
return -1;
}
rewritten[rmax-1] = '\0';
return 0;
}
sem_t *sem_open(const char *name, int oflag, ...)
{
mode_t mode;
unsigned int value;
debug("sem_open()");
debug("requested name: %s", name);
// lookup the libc's sem_open() if we haven't already
if (!original_sem_open) {
dlerror();
original_sem_open = dlsym(RTLD_NEXT, "sem_open");
if (!original_sem_open) {
debug("could not find sem_open in libc");
return SEM_FAILED;
}
dlerror();
}
// mode and value must be set with O_CREAT
va_list argp;
va_start(argp, oflag);
if (oflag & O_CREAT) {
mode = va_arg(argp, mode_t);
value = va_arg(argp, unsigned int);
if (value > SEM_VALUE_MAX) {
errno = EINVAL;
return SEM_FAILED;
}
}
va_end(argp);
const char *snapname = get_snap_name();
// just call libc's sem_open() if snapname not set
if (!snapname) {
if (oflag & O_CREAT) {
return original_sem_open(name, oflag, mode, value);
}
return original_sem_open(name, oflag);
}
// Format the rewritten name
char rewritten[MAX_NAME_SIZE+1];
if (rewrite(snapname, name, rewritten, MAX_NAME_SIZE + 1) != 0) {
return SEM_FAILED;
}
debug("rewritten name: %s", rewritten);
if (oflag & O_CREAT) {
// glibc's sem_open with O_CREAT will create a file in /dev/shm
// by creating a tempfile, initializing it, hardlinking it and
// unlinking the tempfile. We:
// 1. create a temporary file in /dev/shm with rewritten path
// as the template and the specified mode
// 2. initializing a sem_t with sem_init
// 3. writing the initialized sem_t to the temporary file using
// sem_open()s declared value. We used '1' for pshared since
// that is how glibc sets up a named semaphore
// 4. close the temporary file
// 5. hard link the temporary file to the rewritten path. If
// O_EXCL is not specified, ignore EEXIST and just cleanup
// as per documented behavior in 'man sem_open'. If O_EXCL
// is specified and file exists, exit with error. If link is
// successful, cleanup.
// 6. call glibc's sem_open() without O_CREAT|O_EXCL
//
// See glibc's fbtl/sem_open.c for more details
// First, calculate the requested path
char path[PATH_MAX] = { 0 };
// /sem. + '/0' = 14
int max_path_size = strlen(SHM_DIR) + strlen(rewritten) + 6;
if (max_path_size >= PATH_MAX) {
// Should never happen since PATH_MAX should be much
// larger than NAME_MAX, but be defensive.
errno = ENAMETOOLONG;
return SEM_FAILED;
}
int n = snprintf(path, max_path_size, "%s/sem.%s", SHM_DIR,
rewritten);
if (n < 0 || n >= max_path_size) {
errno = ENAMETOOLONG;
return SEM_FAILED;
}
path[max_path_size-1] = '\0';
// Then calculate the template path
char tmp[PATH_MAX] = { 0 };
n = snprintf(tmp, PATH_MAX, "%s/%s.XXXXXX", SHM_DIR,
rewritten);
if (n < 0 || n >= PATH_MAX) {
errno = ENAMETOOLONG;
return SEM_FAILED;
}
tmp[PATH_MAX-1] = '\0';
// Next, create a temporary file
int fd = mkstemp(tmp);
if (fd < 0) {
return SEM_FAILED;
}
debug("tmp name: %s", tmp);
// Update the temporary file to have the requested mode
if (fchmod(fd, mode) < 0) {
close(fd);
unlink(tmp);
return SEM_FAILED;
}
// Then write out an empty semaphore and set the initial value.
// We use '1' for pshared since that is how glibc sets up the
// semaphore (see glibc's fbtl/sem_open.c)
sem_t initsem;
sem_init(&initsem, 1, value);
if (write(fd, &initsem, sizeof(sem_t)) < 0) {
close(fd);
unlink(tmp);
return SEM_FAILED;
}
close(fd);
// Then link the file into place. If the target exists and
// O_EXCL was not specified, just cleanup and proceed to open
// the existing file as per documented behavior in 'man
// sem_open'.
int existed = 0;
if (link(tmp, path) < 0) {
// Note: snapd initially didn't allow 'l' in its
// policy so we first try with link() since it is
// race-free but fallback to rename() if necessary.
if (errno == EACCES || errno == EPERM) {
fprintf(stderr, "sem_open() wrapper: hard linking tempfile denied. Falling back to rename()\n");
if (rename(tmp, path) < 0) {
unlink(tmp);
return SEM_FAILED;
}
} else if (oflag & O_EXCL || errno != EEXIST) {
unlink(tmp);
return SEM_FAILED;
}
existed = 1;
}
unlink(tmp);
// Then call sem_open() on the created file, stripping out the
// O_CREAT|O_EXCL since we just created it
sem_t *sem = original_sem_open(rewritten,
oflag & ~(O_CREAT | O_EXCL));
if (sem == SEM_FAILED) {
if (!existed) {
unlink(path);
}
return SEM_FAILED;
}
return sem;
} else {
// without O_CREAT, just call sem_open with rewritten
return original_sem_open(rewritten, oflag);
}
return SEM_FAILED;
}
// sem_unlink
int sem_unlink(const char *name)
{
debug("sem_unlink()");
debug("requested name: %s", name);
// lookup the libc's sem_unlink() if we haven't already
if (!original_sem_unlink) {
dlerror();
original_sem_unlink = dlsym(RTLD_NEXT, "sem_unlink");
if (!original_sem_unlink) {
debug("could not find sem_unlink in libc");
return -1;
}
dlerror();
}
const char *snapname = get_snap_name();
// just call libc's sem_unlink() if snapname not set
if (!snapname) {
return original_sem_unlink(name);
}
// Format the rewritten name
char rewritten[MAX_NAME_SIZE+1];
if (rewrite(snapname, name, rewritten, MAX_NAME_SIZE + 1) != 0) {
return -1;
}
debug("rewritten name: %s", rewritten);
return original_sem_unlink(rewritten);
}

View File

@ -1,207 +0,0 @@
name: urh
title: Universal Radio Hacker
version: git
summary: Investigate Wireless Protocols Like A Boss
description: |
The Universal Radio Hacker (URH) is a complete suite for wireless protocol investigation with native support for many common **Software Defined Radios**.
URH allows **easy demodulation** of signals combined with an automatic detection of modulation parameters making it a breeze to identify the bits and bytes that fly over the air.
As data often gets _encoded_ before transmission, URH offers **customizable decodings** to crack even sophisticated encodings like CC1101 data whitening.
When it comes to **protocol reverse-engineering**, URH is helpful in two ways. You can either manually assign protocol fields and message types or let URH **automatically infer protocol fields** with a rule-based intelligence.
Finally, URH entails a **fuzzing component** aimed at stateless protocols and a **simulation environment** to perform stateful attacks.
After installation, give URH access to your USB in order to access your USB based SDRs:
sudo snap connect urh:raw-usb
In order to access your SDR as non-root user, install the according **udev rules** available at https://github.com/jopohl/urh/wiki/SDR-udev-rules.
If you want to use your Soundcard as an SDR for receiving please execute:
sudo snap connect urh:audio-record
icon: data/icons/appicon.png
grade: stable # must be 'stable' to release into candidate/stable channels
confinement: strict # use 'strict' once you have the right plugs and slots
base: core18
plugs: # plugs for theming, font settings, cursor and to use gtk3 file chooser
gtk-3-themes:
interface: content
target: $SNAP/data-dir/themes
default-provider: gtk-common-themes:gtk-3-themes
icon-themes:
interface: content
target: $SNAP/data-dir/icons
default-provider: gtk-common-themes:icon-themes
sound-themes:
interface: content
target: $SNAP/data-dir/sounds
default-provider: gtk-common-themes:sounds-themes
apps:
urh:
adapter: full
command: snap/command-chain/alsa-launch desktop-launch $SNAP/bin/urh
plugs:
- desktop
- desktop-legacy
- wayland
- x11
- unity7
- gsettings
- home
- opengl
- raw-usb
- audio-playback
- audio-record
- network
environment:
QT_QPA_PLATFORMTHEME: gtk3
LD_PRELOAD: $SNAP/lib/semwraplib.so
BLADERF_SEARCH_DIR: $SNAP/bladefpgas
layout:
/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/alsa-lib:
bind: $SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/alsa-lib
parts:
alsa-mixin:
plugin: dump
source: https://github.com/diddlesnaps/snapcraft-alsa.git
source-subdir: snapcraft-assets
build-packages:
- libasound2-dev
semwraplib:
plugin: nil
source: data
override-build: |
snapcraftctl build
mkdir -p $SNAPCRAFT_PART_INSTALL/lib
gcc -g -O0 -Wall -Wstrict-prototypes -fPIC -shared semwraplib.c -o $SNAPCRAFT_PART_INSTALL/lib/semwraplib.so -ldl
build-packages:
- build-essential
desktop-qt5:
source: https://github.com/ubuntu/snapcraft-desktop-helpers.git
source-subdir: qt
plugin: make
make-parameters: ["FLAVOR=qt5"]
build-packages:
- build-essential
- qtbase5-dev
- dpkg-dev
stage-packages:
- libxkbcommon0
- ttf-ubuntu-font-family
- dmz-cursor-theme
- light-themes
- libgstreamer-plugins-base1.0-0
- adwaita-icon-theme
- gnome-themes-standard
- shared-mime-info
- libgomp1
- libqt5gui5
- libgdk-pixbuf2.0-0
- libqt5svg5 # for loading icon themes which are svg
- try: [appmenu-qt5] # not available on core18
- locales-all
- xdg-user-dirs
- fcitx-frontend-qt5
- libatk1.0-0
- libgtk2.0-0
- libxcomposite1
- libxcursor1
- libxinerama1
- libxrandr2
- libasyncns0
- libatk-bridge2.0-0
- libatspi2.0-0
- libcairo-gobject2
- libepoxy0
- libflac8
- libgtk-3-0
- libogg0
- libpulse0
- libsndfile1
- libvorbis0a
- libvorbisenc2
- libwayland-cursor0
- libwayland-egl1
- libodbc1
- libpq5
- libpulse-mainloop-glib0
- libspeechd2
- python3
- python3-pyqt5
- python3-pyaudio
- dbus
- qtwayland5
- qt5-gtk-platformtheme
- libqt5x11extras5
- locales
- libcanberra-gtk3-module
- libairspy-dev
- libhackrf-dev
- libiio-dev
- liblimesuite-dev
- librtlsdr-dev
- libuhd-dev
- libc-bin
- libasound2
- libasound2-plugins
- python3-distutils
urh:
after: [desktop-qt5, sdrplay, alsa-mixin]
plugin: python
requirements: [data/requirements.txt]
source: .
override-build: |
git clone https://github.com/Nuand/bladeRF.git
cd bladeRF/host
mkdir build
cmake -DCMAKE_INSTALL_PREFIX=$SNAPCRAFT_PART_INSTALL ..
make -j$(nproc)
make install
cmake -DCMAKE_INSTALL_PREFIX=/usr ..
make install
snapcraftctl build
build-packages:
- libairspy-dev
- libhackrf-dev
- libiio-dev
- liblimesuite-dev
- librtlsdr-dev
- libuhd-dev
- wget
- execstack
- build-essential
- cmake
- pkg-config
sdrplay:
plugin: dump
source: /lib
stage: [libmirsdrapi-rsp.so.2.13]
override-build: |
wget http://www.sdrplay.com/software/SDRplay_RSP_API-Linux-2.13.1.run -O sdrplay.run
bash sdrplay.run --tar xf
cp mirsdrapi-rsp.h /usr/include
cp x86_64/* /lib
cp x86_64/* .
ln -sf /lib/libmirsdrapi-rsp.so.2.13 /lib/libmirsdrapi-rsp.so
snapcraftctl build
bladerf-fpga:
plugin: dump
source: .
override-build: |
snapcraftctl build
wget https://www.nuand.com/fpga/v0.11.0/hostedxA4.rbf -P $SNAPCRAFT_PART_INSTALL/bladefpgas
wget https://www.nuand.com/fpga/v0.11.0/hostedxA9.rbf -P $SNAPCRAFT_PART_INSTALL/bladefpgas
wget https://www.nuand.com/fpga/v0.11.0/hostedx40.rbf -P $SNAPCRAFT_PART_INSTALL/bladefpgas
wget https://www.nuand.com/fpga/v0.11.0/hostedx115.rbf -P $SNAPCRAFT_PART_INSTALL/bladefpgas

View File

@ -1,141 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>DialogAdvancedModSettings</class>
<widget class="QDialog" name="DialogAdvancedModSettings">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>527</width>
<height>501</height>
</rect>
</property>
<property name="windowTitle">
<string>Advanced Modulation Settings</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Pause Threshold</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The pause threshold gives you control &lt;span style=&quot; font-weight:600;&quot;&gt;when to insert a message break.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;The pause threshold is the maximum length of consecutive zero bits represented by a pause before a new message begins.&lt;/p&gt;&lt;p&gt;Special value is 0 to disable message breaking completely.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="spinBoxPauseThreshold">
<property name="specialValueText">
<string>Disable</string>
</property>
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>999999999</number>
</property>
<property name="value">
<number>8</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>Message Length Divisor</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;With the message &lt;span style=&quot; font-weight:600;&quot;&gt;divisor length&lt;/span&gt; you can control the minimum message length in a flexible way. URH will try to demodulate signals in such a way, that the resulting message has a number of bits that is divisble by the configured divisor. &lt;br/&gt;&lt;br/&gt;&lt;span style=&quot; font-style:italic;&quot;&gt;How does the zero padding work? Remaining zero bits are taken from the pause behind the message if possible.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="spinBoxMessageLengthDivisor">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>999999999</number>
</property>
</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>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>DialogAdvancedModSettings</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>DialogAdvancedModSettings</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

File diff suppressed because it is too large Load Diff

View File

@ -1,305 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ChecksumOptions</class>
<widget class="QWidget" name="ChecksumOptions">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>775</width>
<height>836</height>
</rect>
</property>
<property name="windowTitle">
<string>Configure Checksum</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0" colspan="2">
<widget class="QScrollArea" name="scrollArea">
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>738</width>
<height>827</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<property name="leftMargin">
<number>11</number>
</property>
<property name="topMargin">
<number>11</number>
</property>
<property name="rightMargin">
<number>11</number>
</property>
<property name="bottomMargin">
<number>11</number>
</property>
<item>
<widget class="QLabel" name="label_4">
<property name="text">
<string>Checksum category:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="comboBoxCategory">
<item>
<property name="text">
<string>CRC</string>
</property>
</item>
<item>
<property name="text">
<string>Wireless Short Packet Checksum</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="QStackedWidget" name="stackedWidget">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="page_crc">
<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>
<item row="3" column="1">
<widget class="QLineEdit" name="lineEditFinalXOR"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>CRC polynomial (hex):</string>
</property>
</widget>
</item>
<item row="7" column="0" colspan="2">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Configure data ranges for CRC</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QTableView" name="tableViewDataRanges">
<attribute name="horizontalHeaderHighlightSections">
<bool>false</bool>
</attribute>
<attribute name="verticalHeaderCascadingSectionResizes">
<bool>false</bool>
</attribute>
<attribute name="verticalHeaderHighlightSections">
<bool>false</bool>
</attribute>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QToolButton" name="btnAddRange">
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset theme="list-add">
<normaloff>../../../</normaloff>../../../</iconset>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="btnRemoveRange">
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset theme="list-remove">
<normaloff>../../../</normaloff>../../../</iconset>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="lineEditStartValue"/>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>CRC function:</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Final XOR (hex):</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Start value (hex):</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="lineEditCRCPolynomial"/>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="comboBoxCRCFunction"/>
</item>
<item row="6" column="0" colspan="2">
<widget class="QLabel" name="label_crc_info">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Order=17&lt;/p&gt;&lt;p&gt;Length of checksum=16&lt;/p&gt;&lt;p&gt;start value length =16&lt;/p&gt;&lt;p&gt;final XOR length = 16&lt;/p&gt;&lt;p&gt;Polynomial = x&lt;span style=&quot; vertical-align:super;&quot;&gt;1&lt;/span&gt; + 4&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="4" column="0" colspan="2">
<widget class="QCheckBox" name="checkBoxRefIn">
<property name="text">
<string>RefIn (Reflect input)</string>
</property>
</widget>
</item>
<item row="5" column="0" colspan="2">
<widget class="QCheckBox" name="checkBoxRefOut">
<property name="text">
<string>RefOut (Reflect output)</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="page_wsp">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="label_6">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The Wireless Short Packet (WSP) standard uses three different checksums. URH can automatically detect the used checksum algorithm from the message. However, you can enforce the usage of a certain checksum if you need to.&lt;/p&gt;&lt;p&gt;With &lt;span style=&quot; font-weight:600;&quot;&gt;Automatic&lt;/span&gt; setting, checksums are chosen by these rules:&lt;/p&gt;&lt;p&gt;1) 4 Bit Checksum - For Switch Telegram (RORG=5 or 6 and STATUS = 0x20 or 0x30)&lt;/p&gt;&lt;p&gt;2) 8 Bit Checksum: STATUS bit 2&lt;span style=&quot; vertical-align:super;&quot;&gt;7&lt;/span&gt; = 0&lt;/p&gt;&lt;p&gt;3) 8 Bit CRC: STATUS bit 2&lt;span style=&quot; vertical-align:super;&quot;&gt;7&lt;/span&gt; = 1&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="alignment">
<set>Qt::AlignJustify|Qt::AlignVCenter</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="radioButtonWSPAuto">
<property name="text">
<string>Automatic (recommended)</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="radioButtonWSPChecksum4">
<property name="text">
<string>Force Checksum4</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="radioButtonWSPChecksum8">
<property name="text">
<string>Force Checksum8</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="radioButtonWSPCRC8">
<property name="text">
<string>Force CRC8</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>107</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<tabstops>
<tabstop>comboBoxCRCFunction</tabstop>
<tabstop>lineEditCRCPolynomial</tabstop>
<tabstop>lineEditStartValue</tabstop>
<tabstop>lineEditFinalXOR</tabstop>
<tabstop>tableViewDataRanges</tabstop>
<tabstop>btnAddRange</tabstop>
<tabstop>radioButtonWSPAuto</tabstop>
<tabstop>btnRemoveRange</tabstop>
<tabstop>radioButtonWSPChecksum4</tabstop>
<tabstop>radioButtonWSPChecksum8</tabstop>
<tabstop>radioButtonWSPCRC8</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>

View File

@ -1,108 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>DialogCosta</class>
<widget class="QDialog" name="DialogCosta">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Configure Costas Loop</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>URH uses a Costas loop for PSK demodulation. Configure the loop bandwidth below.</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="labelLoopBandwidth">
<property name="text">
<string>Loop Bandwidth:</string>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="doubleSpinBoxLoopBandwidth">
<property name="decimals">
<number>4</number>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>DialogCosta</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>DialogCosta</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -1,280 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>DialogCSVImport</class>
<widget class="QDialog" name="DialogCSVImport">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>635</width>
<height>674</height>
</rect>
</property>
<property name="windowTitle">
<string>CSV Import</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="2">
<widget class="QLabel" name="labelFileNotFound">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; color:#ff0000;&quot;&gt;Could not open the selected file.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
<item row="3" column="2">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QComboBox" name="comboBoxCSVSeparator">
<item>
<property name="text">
<string>,</string>
</property>
</item>
<item>
<property name="text">
<string>;</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="QToolButton" name="btnAddSeparator">
<property name="toolTip">
<string>Add a custom separator.</string>
</property>
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset theme="list-add">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="iconSize">
<size>
<width>16</width>
<height>16</height>
</size>
</property>
</widget>
</item>
</layout>
</item>
<item row="6" column="2">
<widget class="QSpinBox" name="spinBoxTimestampColumn">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt; If your dataset contains timestamps URH will calculate the sample rate from them. You can manually edit the sample rate after import in the signal details.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="specialValueText">
<string>Not present</string>
</property>
<property name="maximum">
<number>999999999</number>
</property>
</widget>
</item>
<item row="4" column="0" colspan="2">
<widget class="QLabel" name="label">
<property name="text">
<string>I Data Column:</string>
</property>
</widget>
</item>
<item row="5" column="2">
<widget class="QSpinBox" name="spinBoxQDataColumn">
<property name="specialValueText">
<string>Not present</string>
</property>
<property name="maximum">
<number>999999999</number>
</property>
</widget>
</item>
<item row="6" column="0" colspan="2">
<widget class="QLabel" name="label_3">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt; If your dataset contains timestamps URH will calculate the sample rate from them. You can manually edit the sample rate after import in the signal details.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Timestamp Column:</string>
</property>
</widget>
</item>
<item row="5" column="0" colspan="2">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Q Data Column:</string>
</property>
</widget>
</item>
<item row="7" column="0" colspan="3">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Preview</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QTableWidget" name="tableWidgetPreview">
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<attribute name="horizontalHeaderCascadingSectionResizes">
<bool>false</bool>
</attribute>
<attribute name="horizontalHeaderStretchLastSection">
<bool>false</bool>
</attribute>
<attribute name="verticalHeaderStretchLastSection">
<bool>false</bool>
</attribute>
<column>
<property name="text">
<string>Timestamp</string>
</property>
</column>
<column>
<property name="text">
<string>I</string>
</property>
</column>
<column>
<property name="text">
<string>Q</string>
</property>
</column>
</widget>
</item>
</layout>
</widget>
</item>
<item row="0" column="2">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLineEdit" name="lineEditFilename"/>
</item>
<item>
<widget class="QToolButton" name="btnChooseFile">
<property name="text">
<string>...</string>
</property>
<property name="toolButtonStyle">
<enum>Qt::ToolButtonTextOnly</enum>
</property>
</widget>
</item>
</layout>
</item>
<item row="4" column="2">
<widget class="QSpinBox" name="spinBoxIDataColumn">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>999999999</number>
</property>
<property name="value">
<number>1</number>
</property>
</widget>
</item>
<item row="3" column="0" colspan="2">
<widget class="QLabel" name="label_4">
<property name="text">
<string>CSV Separator:</string>
</property>
</widget>
</item>
<item row="9" column="2">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
<item row="2" column="0" colspan="3">
<widget class="QGroupBox" name="groupBoxFilePreview">
<property name="title">
<string>File Content (at most 100 rows)</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QPlainTextEdit" name="plainTextEditFilePreview">
<property name="undoRedoEnabled">
<bool>false</bool>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>File to import:</string>
</property>
</widget>
</item>
<item row="10" column="2">
<widget class="QPushButton" name="btnAutoDefault">
<property name="text">
<string>Prevent Dialog From Close with Enter</string>
</property>
<property name="default">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<tabstops>
<tabstop>lineEditFilename</tabstop>
<tabstop>btnChooseFile</tabstop>
<tabstop>plainTextEditFilePreview</tabstop>
<tabstop>comboBoxCSVSeparator</tabstop>
<tabstop>btnAddSeparator</tabstop>
<tabstop>spinBoxIDataColumn</tabstop>
<tabstop>spinBoxQDataColumn</tabstop>
<tabstop>spinBoxTimestampColumn</tabstop>
<tabstop>tableWidgetPreview</tabstop>
</tabstops>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>DialogCSVImport</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>375</x>
<y>641</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>DialogCSVImport</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>443</x>
<y>647</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -1,732 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Decoder</class>
<widget class="QDialog" name="Decoder">
<property name="windowModality">
<enum>Qt::WindowModal</enum>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>2200</width>
<height>1398</height>
</rect>
</property>
<property name="windowTitle">
<string>Decoding</string>
</property>
<property name="modal">
<bool>false</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QComboBox" name="combobox_decodings">
<item>
<property name="text">
<string>Non Return to Zero (NRZ)</string>
</property>
</item>
<item>
<property name="text">
<string>Empty</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="QPushButton" name="delete_decoding">
<property name="text">
<string>Delete</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="saveas">
<property name="text">
<string>Save as...</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<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>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="label_8">
<property name="text">
<string>Base Functions</string>
</property>
</widget>
</item>
<item>
<widget class="QListWidget" name="basefunctions">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="dragEnabled">
<bool>true</bool>
</property>
<property name="dragDropMode">
<enum>QAbstractItemView::DragOnly</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_9">
<property name="text">
<string>Additional Functions</string>
</property>
</widget>
</item>
<item>
<widget class="QListWidget" name="additionalfunctions">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="dragEnabled">
<bool>true</bool>
</property>
<property name="dragDropMode">
<enum>QAbstractItemView::DragOnly</enum>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label">
<property name="font">
<font>
<pointsize>11</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Your Decoding</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="ListWidget" name="decoderchain">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="acceptDrops">
<bool>true</bool>
</property>
<property name="dragEnabled">
<bool>true</bool>
</property>
<property name="dragDropMode">
<enum>QAbstractItemView::DragDrop</enum>
</property>
<property name="defaultDropAction">
<enum>Qt::MoveAction</enum>
</property>
<property name="textElideMode">
<enum>Qt::ElideMiddle</enum>
</property>
<property name="resizeMode">
<enum>QListView::Fixed</enum>
</property>
<property name="viewMode">
<enum>QListView::ListMode</enum>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QGroupBox" name="gb_infoandoptions">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Information and Options</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
<widget class="QLabel" name="info">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<italic>true</italic>
</font>
</property>
<property name="text">
<string>Please drag functions from the categories base and additional to the decoding process (Decoder). You can reorder functions by drag and drop and remove functions by dropping them outside the Decoder box. Click on every function for detailed information.</string>
</property>
<property name="textFormat">
<enum>Qt::PlainText</enum>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QStackedWidget" name="optionWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="currentIndex">
<number>5</number>
</property>
<widget class="QWidget" name="page_empty"/>
<widget class="QWidget" name="page_redundancy">
<widget class="QSpinBox" name="multiple">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>56</width>
<height>23</height>
</rect>
</property>
<property name="minimum">
<number>2</number>
</property>
</widget>
<widget class="QLabel" name="label_5">
<property name="geometry">
<rect>
<x>60</x>
<y>0</y>
<width>171</width>
<height>21</height>
</rect>
</property>
<property name="text">
<string>Number of redundant bits</string>
</property>
</widget>
</widget>
<widget class="QWidget" name="page_carrier">
<widget class="QLineEdit" name="carrier">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>113</width>
<height>23</height>
</rect>
</property>
</widget>
<widget class="QLabel" name="label_6">
<property name="geometry">
<rect>
<x>120</x>
<y>0</y>
<width>171</width>
<height>21</height>
</rect>
</property>
<property name="text">
<string>Carrier ('1_' -&gt; 1_1_1_...)</string>
</property>
</widget>
</widget>
<widget class="QWidget" name="page_substitution">
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QSpinBox" name="substitution_rows">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>1000</number>
</property>
<property name="value">
<number>4</number>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="label_10">
<property name="text">
<string>Rows</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="QTableWidget" name="substitution">
<property name="verticalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
<property name="horizontalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="page_external">
<layout class="QVBoxLayout" name="verticalLayout_6">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLabel" name="label_11">
<property name="text">
<string>Decoder</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="external_decoder"/>
</item>
<item>
<widget class="QToolButton" name="btnChooseDecoder">
<property name="text">
<string>...</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QLabel" name="label_12">
<property name="text">
<string>Encoder</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="external_encoder"/>
</item>
<item>
<widget class="QToolButton" name="btnChooseEncoder">
<property name="text">
<string>...</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>158</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<widget class="QWidget" name="page_data_whitening">
<widget class="QLineEdit" name="datawhitening_sync">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>171</width>
<height>23</height>
</rect>
</property>
</widget>
<widget class="QLabel" name="label_13">
<property name="geometry">
<rect>
<x>180</x>
<y>0</y>
<width>1461</width>
<height>20</height>
</rect>
</property>
<property name="text">
<string>Synchronization bytes (hex coded)</string>
</property>
</widget>
<widget class="QLineEdit" name="datawhitening_polynomial">
<property name="geometry">
<rect>
<x>0</x>
<y>30</y>
<width>171</width>
<height>23</height>
</rect>
</property>
</widget>
<widget class="QLabel" name="label_14">
<property name="geometry">
<rect>
<x>180</x>
<y>30</y>
<width>1461</width>
<height>21</height>
</rect>
</property>
<property name="text">
<string>Data whitening polynomial (LFSR, hex, w/o first bit)</string>
</property>
</widget>
<widget class="QCheckBox" name="datawhitening_overwrite_crc">
<property name="geometry">
<rect>
<x>0</x>
<y>60</y>
<width>1641</width>
<height>31</height>
</rect>
</property>
<property name="text">
<string>Overwrite CRC16 field with correct value when encoding</string>
</property>
</widget>
</widget>
<widget class="QWidget" name="page_cut">
<widget class="QLineEdit" name="cutmark">
<property name="geometry">
<rect>
<x>0</x>
<y>30</y>
<width>181</width>
<height>31</height>
</rect>
</property>
<property name="text">
<string>1010</string>
</property>
</widget>
<widget class="QLabel" name="label_15">
<property name="geometry">
<rect>
<x>190</x>
<y>30</y>
<width>121</width>
<height>31</height>
</rect>
</property>
<property name="text">
<string>Sequence</string>
</property>
</widget>
<widget class="QRadioButton" name="rB_delbefore">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>131</width>
<height>23</height>
</rect>
</property>
<property name="text">
<string>&amp;Cut before</string>
</property>
</widget>
<widget class="QRadioButton" name="rB_delafter">
<property name="geometry">
<rect>
<x>150</x>
<y>0</y>
<width>111</width>
<height>23</height>
</rect>
</property>
<property name="text">
<string>Cut afte&amp;r</string>
</property>
</widget>
<widget class="QRadioButton" name="rB_delbeforepos">
<property name="geometry">
<rect>
<x>0</x>
<y>70</y>
<width>111</width>
<height>23</height>
</rect>
</property>
<property name="text">
<string>Cut before</string>
</property>
</widget>
<widget class="QRadioButton" name="rB_delafterpos">
<property name="geometry">
<rect>
<x>150</x>
<y>70</y>
<width>111</width>
<height>23</height>
</rect>
</property>
<property name="text">
<string>Cut after</string>
</property>
</widget>
<widget class="QSpinBox" name="cutmark2">
<property name="geometry">
<rect>
<x>0</x>
<y>100</y>
<width>181</width>
<height>33</height>
</rect>
</property>
<property name="maximum">
<number>1000</number>
</property>
</widget>
<widget class="QLabel" name="label_16">
<property name="geometry">
<rect>
<x>190</x>
<y>100</y>
<width>121</width>
<height>31</height>
</rect>
</property>
<property name="text">
<string>Position (in bit)</string>
</property>
</widget>
</widget>
<widget class="QWidget" name="page_morse">
<widget class="QLabel" name="label_17">
<property name="geometry">
<rect>
<x>70</x>
<y>10</y>
<width>341</width>
<height>21</height>
</rect>
</property>
<property name="text">
<string>Maximum (&lt;=) length of 1-sequence for: Low (0)</string>
</property>
</widget>
<widget class="QSpinBox" name="morse_low">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>56</width>
<height>23</height>
</rect>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="value">
<number>1</number>
</property>
</widget>
<widget class="QLabel" name="label_18">
<property name="geometry">
<rect>
<x>70</x>
<y>40</y>
<width>351</width>
<height>21</height>
</rect>
</property>
<property name="text">
<string>Minimum (&gt;=) length of 1-sequence for: High (1)</string>
</property>
</widget>
<widget class="QSpinBox" name="morse_high">
<property name="geometry">
<rect>
<x>10</x>
<y>40</y>
<width>56</width>
<height>23</height>
</rect>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="value">
<number>3</number>
</property>
</widget>
<widget class="QLabel" name="label_19">
<property name="geometry">
<rect>
<x>70</x>
<y>70</y>
<width>371</width>
<height>21</height>
</rect>
</property>
<property name="text">
<string>Number of 0s between 1-sequences (just for encoding)</string>
</property>
</widget>
<widget class="QSpinBox" name="morse_wait">
<property name="geometry">
<rect>
<x>10</x>
<y>70</y>
<width>56</width>
<height>23</height>
</rect>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="value">
<number>1</number>
</property>
</widget>
</widget>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnAddtoYourDecoding">
<property name="text">
<string>Add to Your Decoding</string>
</property>
</widget>
</item>
</layout>
<zorder>optionWidget</zorder>
<zorder>info</zorder>
<zorder>btnAddtoYourDecoding</zorder>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="1">
<spacer name="horizontalSpacer_5">
<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 row="1" column="1">
<widget class="QLineEdit" name="inpt">
<property name="inputMethodHints">
<set>Qt::ImhDigitsOnly</set>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QComboBox" name="combobox_signals">
<item>
<property name="text">
<string>Test</string>
</property>
</item>
</widget>
</item>
<item row="4" column="0" colspan="2">
<widget class="ZoomableGraphicView" name="graphicsView_signal"/>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Signal {0,1}:</string>
</property>
</widget>
</item>
<item row="5" column="0" colspan="2">
<widget class="ZoomableGraphicView" name="graphicsView_decoded"/>
</item>
<item row="3" column="1">
<widget class="QLineEdit" name="output">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Decoded Bits:</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="decoding_errors_label">
<property name="text">
<string>[Decoding Errors = 0]</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>ZoomableGraphicView</class>
<extends>QGraphicsView</extends>
<header>urh.ui.views.ZoomableGraphicView.h</header>
</customwidget>
<customwidget>
<class>ListWidget</class>
<extends>QListWidget</extends>
<header>urh.ui.ListWidget.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View File

@ -1,268 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>DialogFilterBandwidth</class>
<widget class="QDialog" name="DialogFilterBandwidth">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>502</width>
<height>426</height>
</rect>
</property>
<property name="windowTitle">
<string>Configure Filter Bandwidth</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout" stretch="1,3,1">
<property name="spacing">
<number>7</number>
</property>
<item>
<widget class="QLabel" name="labelExplanation">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;To separate the frequency bands from each other a &lt;b&gt;bandpass&lt;/b&gt; filter is used. You can configure the &lt;b&gt;bandwidth&lt;/b&gt; of this filter here. The bandwidth determines the &lt;b&gt;length N&lt;/b&gt; of the&lt;b&gt; filter kernel&lt;/b&gt;. Decreasing the bandwidth will increase the accuracy of the filter, at cost of higher computation time.&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="alignment">
<set>Qt::AlignJustify|Qt::AlignTop</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="7" column="1">
<widget class="QDoubleSpinBox" name="doubleSpinBoxCustomBandwidth">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="decimals">
<number>4</number>
</property>
<property name="minimum">
<double>0.000100000000000</double>
</property>
<property name="maximum">
<double>0.500000000000000</double>
</property>
</widget>
</item>
<item row="7" column="2">
<widget class="QSpinBox" name="spinBoxCustomKernelLength">
<property name="minimum">
<number>8</number>
</property>
<property name="maximum">
<number>999999999</number>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QRadioButton" name="radioButtonCustom">
<property name="text">
<string>Custom</string>
</property>
</widget>
</item>
<item row="4" column="2">
<widget class="QLabel" name="labelMediumKernelLength">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QRadioButton" name="radioButtonWide">
<property name="text">
<string>Wide</string>
</property>
</widget>
</item>
<item row="6" column="2">
<widget class="QLabel" name="labelVeryWideKernelLength">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QRadioButton" name="radioButtonNarrow">
<property name="text">
<string>Narrow</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QLabel" name="labelWideBandwidth">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QLabel" name="labelVeryNarrowKernelLength">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="labelBandwidthCaption">
<property name="text">
<string>&lt;b&gt;Bandwidth (Hz)&lt;/b&gt;</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="labelNarrowBandwidth">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="QLabel" name="labelNarrowKernelLength">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="labelVeryNarrowBandwidth">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLabel" name="labelKernelLengthCaption">
<property name="text">
<string>&lt;b &gt;Kernel Length N&lt;/b&gt;</string>
</property>
</widget>
</item>
<item row="5" column="2">
<widget class="QLabel" name="labelWideKernelLength">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QRadioButton" name="radioButtonVery_Wide">
<property name="text">
<string>Very Wide</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QRadioButton" name="radioButtonVery_Narrow">
<property name="text">
<string>Very Narrow</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>&lt;b&gt;Choose &lt;/b&gt;</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QLabel" name="labelVeryWideBandwidth">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QRadioButton" name="radioButtonMedium">
<property name="text">
<string>Medium</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QLabel" name="labelMediumBandwidth">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="3">
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
<property name="centerButtons">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>DialogFilterBandwidth</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>DialogFilterBandwidth</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -1,175 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>FilterDialog</class>
<widget class="QDialog" name="FilterDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>528</width>
<height>485</height>
</rect>
</property>
<property name="windowTitle">
<string>Configure filter</string>
</property>
<property name="windowIcon">
<iconset theme="view-filter">
<normaloff>.</normaloff>.</iconset>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="9" column="0">
<widget class="QRadioButton" name="radioButtonCustomTaps">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Custom taps:</string>
</property>
</widget>
</item>
<item row="15" column="0" colspan="2">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
<property name="centerButtons">
<bool>true</bool>
</property>
</widget>
</item>
<item row="16" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="7" column="0" colspan="2">
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="8" column="0" colspan="2">
<widget class="QRadioButton" name="radioButtonMovingAverage">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Moving average</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="10" column="1">
<widget class="QSpinBox" name="spinBoxNumTaps">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>999999999</number>
</property>
<property name="value">
<number>10</number>
</property>
</widget>
</item>
<item row="6" column="0" colspan="2">
<widget class="QLabel" name="label_4">
<property name="font">
<font>
<italic>true</italic>
</font>
</property>
<property name="text">
<string>A DC correction filter will remove the DC component (mean value) of the signal and center it around zero.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="9" column="1">
<widget class="QLineEdit" name="lineEditCustomTaps">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;You can configure custom filter taps here either explicit using [0.1, 0.2, 0.3] or with &lt;span style=&quot; font-weight:600;&quot;&gt;python programming shortcuts&lt;/span&gt; like [0.1] * 3 + [0.2] * 4 will result in [0.1, 0.1, 0.1, 0.2, 0.2, 0.2, 0.2]&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>[0.1]*10</string>
</property>
</widget>
</item>
<item row="10" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Number of taps:</string>
</property>
</widget>
</item>
<item row="13" column="0" colspan="2">
<widget class="QLabel" name="label_3">
<property name="font">
<font>
<italic>true</italic>
</font>
</property>
<property name="text">
<string>You can imagine taps as weighting factors applied to n samples of the signal whereby n is the number of taps. By default we use 10 taps with each tap set to 0.1 producing a moving average filter.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="14" column="0" colspan="2">
<widget class="QLabel" name="label_2">
<property name="font">
<font>
<italic>true</italic>
</font>
</property>
<property name="text">
<string>These n weighted samples get summed up to produce the output of the filter. In DSP terms you configure the impulse response of the filter here.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="0" colspan="2">
<widget class="QRadioButton" name="radioButtonDCcorrection">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>DC correction</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -1,678 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>FuzzingDialog</class>
<widget class="QDialog" name="FuzzingDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>523</width>
<height>632</height>
</rect>
</property>
<property name="windowTitle">
<string>Fuzzing</string>
</property>
<layout class="QGridLayout" name="gridLayout_5">
<item row="2" column="1">
<widget class="QSpinBox" name="spinBoxFuzzMessage">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximum">
<number>999999999</number>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QComboBox" name="comboBoxStrategy">
<item>
<property name="text">
<string>Add Range of Values</string>
</property>
</item>
<item>
<property name="text">
<string>Add Boundaries</string>
</property>
</item>
<item>
<property name="text">
<string>Add Random Values from Range</string>
</property>
</item>
<item>
<property name="text">
<string>Add De Bruijn Sequence</string>
</property>
</item>
</widget>
</item>
<item row="9" column="1">
<widget class="QPushButton" name="btnAddFuzzingValues">
<property name="text">
<string>Add to Fuzzed Values</string>
</property>
</widget>
</item>
<item row="7" column="0" rowspan="2">
<widget class="QStackedWidget" name="stackedWidgetLabels">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="pageAddRangeLabel">
<layout class="QVBoxLayout" name="verticalLayout_3">
<property name="spacing">
<number>6</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="lStart">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Start (Decimal):</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lEnd">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>End (Decimal):</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lStep">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Step (Decimal):</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="pageAddBoundariesLabel">
<layout class="QVBoxLayout" name="verticalLayout_4">
<property name="spacing">
<number>6</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="QCheckBox" name="checkBoxLowerBound">
<property name="text">
<string>Lower Bound</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBoxUpperBound">
<property name="text">
<string>Upper Bound</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lNumberBoundaries">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Values per Boundary:</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="pageAddRandomLabel">
<layout class="QVBoxLayout" name="verticalLayout_6">
<property name="spacing">
<number>6</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="lRandomMin">
<property name="text">
<string>Range Minimum:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lRandomMax">
<property name="text">
<string>Range Maximum:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lNumRandom">
<property name="text">
<string>Number Values:</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
<item row="1" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="lPreBits">
<property name="text">
<string>1111</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lFuzzedBits">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>1010</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lPostBits">
<property name="text">
<string>010101</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<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>
</layout>
</item>
<item row="5" column="0" colspan="2">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="lFuzzedValues">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Fuzzed Values</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="chkBRemoveDuplicates">
<property name="text">
<string>Remove Duplicates</string>
</property>
</widget>
</item>
<item>
<layout class="QGridLayout" name="gridLayout_4">
<item row="1" column="1">
<widget class="QToolButton" name="btnDelRow">
<property name="toolTip">
<string>Remove selected values or last value if nothing is selected.</string>
</property>
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset theme="list-remove">
<normaloff>.</normaloff>.</iconset>
</property>
</widget>
</item>
<item row="0" column="0" rowspan="4">
<widget class="FuzzingTableView" name="tblFuzzingValues">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<property name="verticalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
<property name="horizontalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
<property name="showGrid">
<bool>false</bool>
</property>
<attribute name="horizontalHeaderHighlightSections">
<bool>false</bool>
</attribute>
<attribute name="verticalHeaderHighlightSections">
<bool>false</bool>
</attribute>
</widget>
</item>
<item row="3" column="1">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="1">
<widget class="QToolButton" name="btnAddRow">
<property name="toolTip">
<string>Add a new value.</string>
</property>
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset theme="list-add">
<normaloff>.</normaloff>.</iconset>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QToolButton" name="btnRepeatValues">
<property name="toolTip">
<string>Repeat selected values or all values if nothing is selected.</string>
</property>
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset theme="media-playlist-repeat">
<normaloff>.</normaloff>.</iconset>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item row="7" column="1" rowspan="2">
<widget class="QStackedWidget" name="stackedWidgetSpinboxes">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="pageAddRange">
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="spacing">
<number>6</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="QSpinBox" name="sBAddRangeStart"/>
</item>
<item>
<widget class="QSpinBox" name="sBAddRangeEnd"/>
</item>
<item>
<widget class="QSpinBox" name="sBAddRangeStep">
<property name="minimum">
<number>1</number>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="pageAddBoundaries">
<layout class="QVBoxLayout" name="verticalLayout_5">
<property name="spacing">
<number>6</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="QSpinBox" name="spinBoxLowerBound"/>
</item>
<item>
<widget class="QSpinBox" name="spinBoxUpperBound">
<property name="value">
<number>13</number>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="spinBoxBoundaryNumber">
<property name="minimum">
<number>1</number>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="pageAddRandom">
<layout class="QVBoxLayout" name="verticalLayout_7">
<property name="spacing">
<number>6</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="QSpinBox" name="spinBoxRandomMinimum"/>
</item>
<item>
<widget class="QSpinBox" name="spinBoxRandomMaximum">
<property name="value">
<number>42</number>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="spinBoxNumberRandom">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>999999999</number>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="lSourceBlock">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Source Message:</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="lFuzzingReferenceBlock">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Message to fuzz:</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="lFuzzingEnd">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Fuzzing Label End Index:</string>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="lStrategy">
<property name="text">
<string>Strategy:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="comboBoxFuzzingLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="editable">
<bool>true</bool>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QSpinBox" name="spinBoxFuzzingEnd">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>999999999</number>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QSpinBox" name="spinBoxFuzzingStart">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>999999999</number>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="lFuzzingStart">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Fuzzing Label Start Index:</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="lFuzzingLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Fuzzing Label:</string>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>FuzzingTableView</class>
<extends>QTableView</extends>
<header>urh.ui.views.FuzzingTableView.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections>
<connection>
<sender>comboBoxStrategy</sender>
<signal>currentIndexChanged(int)</signal>
<receiver>stackedWidgetLabels</receiver>
<slot>setCurrentIndex(int)</slot>
<hints>
<hint type="sourcelabel">
<x>201</x>
<y>593</y>
</hint>
<hint type="destinationlabel">
<x>100</x>
<y>614</y>
</hint>
</hints>
</connection>
<connection>
<sender>comboBoxStrategy</sender>
<signal>currentIndexChanged(int)</signal>
<receiver>stackedWidgetSpinboxes</receiver>
<slot>setCurrentIndex(int)</slot>
<hints>
<hint type="sourcelabel">
<x>444</x>
<y>591</y>
</hint>
<hint type="destinationlabel">
<x>809</x>
<y>616</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -1,769 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>GeneratorTab</class>
<widget class="QWidget" name="GeneratorTab">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1287</width>
<height>774</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<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="QScrollArea" name="scrollArea">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1287</width>
<height>774</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QSplitter" name="splitter">
<property name="styleSheet">
<string notr="true">QSplitter::handle:horizontal {
margin: 4px 0px;
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,
stop:0 rgba(255, 255, 255, 0),
stop:0.5 rgba(100, 100, 100, 100),
stop:1 rgba(255, 255, 255, 0));
image: url(:/icons/icons/splitter_handle_vertical.svg);
}</string>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="handleWidth">
<number>6</number>
</property>
<widget class="QWidget" name="layoutWidget_2">
<layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin">
<number>11</number>
</property>
<property name="topMargin">
<number>11</number>
</property>
<property name="rightMargin">
<number>11</number>
</property>
<property name="bottomMargin">
<number>11</number>
</property>
<item>
<widget class="QTabWidget" name="tabWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="styleSheet">
<string notr="true">QTabWidget::pane { border: 0; }</string>
</property>
<property name="tabPosition">
<enum>QTabWidget::North</enum>
</property>
<property name="tabShape">
<enum>QTabWidget::Rounded</enum>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="tab_proto">
<attribute name="title">
<string>Protocols</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_4">
<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="GeneratorTreeView" name="treeProtocols">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Drag&amp;amp;Drop Protocols to the table on the right to fill the generation table.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<attribute name="headerDefaultSectionSize">
<number>57</number>
</attribute>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_pauses">
<attribute name="title">
<string>Pauses</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_5">
<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" colspan="2">
<widget class="GeneratorListWidget" name="lWPauses">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The pauses will be added automatically when you drag a protocol from the tree above to the table on the right.&lt;br/&gt;&lt;/p&gt;&lt;p&gt;You can see the &lt;span style=&quot; font-weight:600;&quot;&gt;position&lt;/span&gt; of each pause by &lt;span style=&quot; font-weight:600;&quot;&gt;selecting it&lt;/span&gt;. There will be drawn a line in the table indicating the position of the pause.&lt;br/&gt;&lt;/p&gt;&lt;p&gt;Use context menu or double click to &lt;span style=&quot; font-weight:600;&quot;&gt;edit a pauses' length&lt;/span&gt;.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="editTriggers">
<set>QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed</set>
</property>
<property name="showDropIndicator" stdset="0">
<bool>false</bool>
</property>
<property name="dragDropMode">
<enum>QAbstractItemView::NoDragDrop</enum>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_fuzzing">
<attribute name="title">
<string>Fuzzing</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_9">
<property name="spacing">
<number>6</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="GeneratorListView" name="listViewProtoLabels">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="editTriggers">
<set>QAbstractItemView::EditKeyPressed</set>
</property>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Add fuzzing values to generated data</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_6">
<item>
<widget class="QStackedWidget" name="stackedWidgetFuzzing">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="pageFuzzingUI">
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QPushButton" name="btnFuzz">
<property name="text">
<string>Fuzz</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="rBSuccessive">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;For multiple labels per message the fuzzed values are inserted &lt;span style=&quot; font-weight:600;&quot;&gt;one-by-one&lt;/span&gt;.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>S&amp;uccessive</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="rbConcurrent">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;For multiple labels per message the labels are fuzzed &lt;span style=&quot; font-weight:600;&quot;&gt;at the same time&lt;/span&gt;.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>&amp;Concurrent</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="rBExhaustive">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;For multiple labels per message the fuzzed values are inserted in &lt;span style=&quot; font-weight:600;&quot;&gt;all possible combinations&lt;/span&gt;.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>E&amp;xhaustive</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="pageFuzzingProgressBar">
<layout class="QHBoxLayout" name="horizontalLayout_7">
<item>
<widget class="QProgressBar" name="progressBarFuzzing">
<property name="value">
<number>24</number>
</property>
<property name="format">
<string>%v/%m</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
<item>
<widget class="Line" name="line_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<layout class="QGridLayout" name="gridLayout_6">
<property name="leftMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<item row="0" column="0" colspan="3">
<layout class="QGridLayout" name="modulationLayout_2">
<item row="1" column="1">
<widget class="QLabel" name="lCarrierFreqValue">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QLabel" name="lModType">
<property name="text">
<string>Modulation Type:</string>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QLabel" name="lModTypeValue">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_carrier_phase">
<property name="text">
<string>Carrier Phase:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="lCarrierPhaseValue">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="lBitLength">
<property name="text">
<string>Symbol Length:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="lBitLenValue">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="lEncoding">
<property name="text">
<string>Encoding:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="lEncodingValue">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>-</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLabel" name="lSampleRate">
<property name="text">
<string>Sample Rate:</string>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QLabel" name="lSampleRateValue">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="lCarrierFrequency">
<property name="text">
<string>Carrier Frequency:</string>
</property>
</widget>
</item>
<item row="3" column="3">
<widget class="ElidedLabel" name="labelParameterValues">
<property name="text">
<string>0/100</string>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="QLabel" name="lParamCaption">
<property name="text">
<string>Amplitudes:</string>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QLabel" name="label">
<property name="text">
<string>Bits per Symbol:</string>
</property>
</widget>
</item>
<item row="2" column="3">
<widget class="QLabel" name="labelBitsPerSymbol">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0" colspan="3">
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="cBoxModulations">
<item>
<property name="text">
<string>MyModulation</string>
</property>
</item>
</widget>
</item>
<item row="5" column="0">
<widget class="QProgressBar" name="prBarGeneration">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="value">
<number>0</number>
</property>
<property name="format">
<string>Modulating %p%</string>
</property>
</widget>
</item>
<item row="5" column="2">
<widget class="QPushButton" name="btnSend">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Send data...</string>
</property>
<property name="icon">
<iconset theme="media-playback-start">
<normaloff>.</normaloff>.</iconset>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QPushButton" name="btnEditModulation">
<property name="text">
<string>Edit ...</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="lModulation">
<property name="text">
<string>Modulation:</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QPushButton" name="btnGenerate">
<property name="enabled">
<bool>false</bool>
</property>
<property name="toolTip">
<string>Generate the complex file of the modulated signal, after tuning all parameters above.</string>
</property>
<property name="text">
<string>Generate file...</string>
</property>
<property name="icon">
<iconset theme="document-new">
<normaloff>.</normaloff>.</iconset>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QWidget" name="layoutWidget">
<layout class="QGridLayout" name="gridLayout_2">
<property name="leftMargin">
<number>11</number>
</property>
<property name="topMargin">
<number>11</number>
</property>
<property name="rightMargin">
<number>11</number>
</property>
<property name="bottomMargin">
<number>11</number>
</property>
<item row="2" column="6">
<widget class="QComboBox" name="cbViewType">
<item>
<property name="text">
<string>Bit</string>
</property>
</item>
<item>
<property name="text">
<string>Hex</string>
</property>
</item>
<item>
<property name="text">
<string>ASCII</string>
</property>
</item>
</widget>
</item>
<item row="2" column="5">
<widget class="QLabel" name="lViewType">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Viewtype:</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="7">
<widget class="GeneratorTableView" name="tableMessages">
<property name="acceptDrops">
<bool>true</bool>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="dragEnabled">
<bool>false</bool>
</property>
<property name="dragDropOverwriteMode">
<bool>false</bool>
</property>
<property name="dragDropMode">
<enum>QAbstractItemView::DropOnly</enum>
</property>
<property name="defaultDropAction">
<enum>Qt::CopyAction</enum>
</property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectItems</enum>
</property>
<property name="verticalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
<property name="horizontalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
<property name="showGrid">
<bool>false</bool>
</property>
<attribute name="horizontalHeaderHighlightSections">
<bool>false</bool>
</attribute>
<attribute name="verticalHeaderHighlightSections">
<bool>false</bool>
</attribute>
</widget>
</item>
<item row="0" column="0" colspan="7">
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="topMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="labelGeneratedData">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Generated Data</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="btnSave">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Save current fuzz profile.</string>
</property>
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset theme="document-save">
<normaloff>.</normaloff>.</iconset>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="btnOpen">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Load a fuzz profile.</string>
</property>
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset theme="document-open">
<normaloff>.</normaloff>.</iconset>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="0">
<widget class="QPushButton" name="btnNetworkSDRSend">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Send encoded data to your external application via TCP.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Send via Network</string>
</property>
<property name="icon">
<iconset theme="network-wired">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QPushButton" name="btnRfCatSend">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Send encoded data via RfCat. &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-style:italic;&quot;&gt;Hit again for stopping the sending process. Note that you can set the number of repetitions (from 1 to infinite) in:&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-style:italic;&quot;&gt;Edit-&amp;gt;Options-&amp;gt;Device-&amp;gt;'Device sending repetitions'&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Send via RfCat</string>
</property>
<property name="icon">
<iconset theme="network-wireless">
<normaloff>.</normaloff>.</iconset>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QLabel" name="lEstimatedTime">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The estimated average time is based on the average number of bits per message and average sample rate, you set for the modulations.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Estimated Time: </string>
</property>
</widget>
</item>
<item row="2" column="3" colspan="2">
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>38</width>
<height>22</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>ElidedLabel</class>
<extends>QLabel</extends>
<header>urh.ui.ElidedLabel.h</header>
</customwidget>
<customwidget>
<class>GeneratorTreeView</class>
<extends>QTreeView</extends>
<header>urh.ui.views.GeneratorTreeView.h</header>
</customwidget>
<customwidget>
<class>GeneratorTableView</class>
<extends>QTableView</extends>
<header>urh.ui.views.GeneratorTableView.h</header>
</customwidget>
<customwidget>
<class>GeneratorListWidget</class>
<extends>QListWidget</extends>
<header>urh.ui.GeneratorListWidget.h</header>
</customwidget>
<customwidget>
<class>GeneratorListView</class>
<extends>QListView</extends>
<header>urh.ui.views.GeneratorListView.h</header>
</customwidget>
</customwidgets>
<resources>
<include location="urh.qrc"/>
</resources>
<connections/>
</ui>

View File

@ -1,837 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>798</width>
<height>469</height>
</rect>
</property>
<property name="windowTitle">
<string>Universal Radio Hacker</string>
</property>
<property name="windowIcon">
<iconset resource="urh.qrc">
<normaloff>:/icons/icons/appicon.png</normaloff>:/icons/icons/appicon.png</iconset>
</property>
<property name="tabShape">
<enum>QTabWidget::Rounded</enum>
</property>
<property name="dockNestingEnabled">
<bool>false</bool>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QVBoxLayout" name="verticalLayout_4" stretch="100,1">
<item>
<widget class="QSplitter" name="splitter">
<property name="styleSheet">
<string notr="true">QSplitter::handle:horizontal {
margin: 4px 0px;
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,
stop:0 rgba(255, 255, 255, 0),
stop:0.5 rgba(100, 100, 100, 100),
stop:1 rgba(255, 255, 255, 0));
image: url(:/icons/icons/splitter_handle_vertical.svg);
}</string>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="handleWidth">
<number>6</number>
</property>
<widget class="QWidget" name="layoutWidget">
<layout class="QVBoxLayout" name="verticalLayout_3">
<property name="spacing">
<number>7</number>
</property>
<property name="leftMargin">
<number>11</number>
</property>
<property name="topMargin">
<number>11</number>
</property>
<property name="rightMargin">
<number>11</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLineEdit" name="lnEdtTreeFilter">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="acceptDrops">
<bool>false</bool>
</property>
<property name="inputMethodHints">
<set>Qt::ImhDialableCharactersOnly</set>
</property>
<property name="placeholderText">
<string>Filter</string>
</property>
<property name="clearButtonEnabled">
<bool>true</bool>
</property>
</widget>
</item>
<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="QToolButton" name="btnFileTreeGoUp">
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset theme="go-up">
<normaloff>.</normaloff>.</iconset>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="DirectoryTreeView" name="fileTree">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Expanding">
<horstretch>10</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="autoScroll">
<bool>true</bool>
</property>
<property name="dragEnabled">
<bool>true</bool>
</property>
<property name="dragDropMode">
<enum>QAbstractItemView::DragOnly</enum>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::ExtendedSelection</enum>
</property>
<property name="sortingEnabled">
<bool>false</bool>
</property>
<attribute name="headerCascadingSectionResizes">
<bool>true</bool>
</attribute>
<attribute name="headerStretchLastSection">
<bool>false</bool>
</attribute>
</widget>
</item>
<item>
<widget class="QTabWidget" name="tabWidget_Project">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="styleSheet">
<string notr="true">QTabWidget::pane { border: 0; }</string>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="tabParticipants">
<attribute name="title">
<string>Participants</string>
</attribute>
<layout class="QHBoxLayout" name="horizontalLayout">
<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="QListView" name="listViewParticipants">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tabDescription">
<attribute name="title">
<string>Description</string>
</attribute>
<layout class="QHBoxLayout" name="horizontalLayout_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>
<item>
<widget class="QTextEdit" name="textEditProjectDescription"/>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<widget class="QTabWidget" name="tabWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="baseSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="tab_interpretation">
<attribute name="title">
<string>Interpretation</string>
</attribute>
<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>
</layout>
</widget>
<widget class="QWidget" name="tab_protocol">
<attribute name="title">
<string>Analysis</string>
</attribute>
<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>
</layout>
</widget>
<widget class="QWidget" name="tab_generator">
<attribute name="title">
<string>Generator</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_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>
</layout>
</widget>
<widget class="QWidget" name="tab_simulator">
<attribute name="title">
<string>Simulator</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_7">
<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>
</layout>
</widget>
</widget>
</widget>
</item>
<item>
<widget class="QLabel" name="labelNonProjectMode">
<property name="styleSheet">
<string notr="true">background: rgba(255,255,0,64)</string>
</property>
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Warning: You are running URH in non project mode. All your settings will be lost after closing the program. If you want to keep your settings create a project via File -&amp;gt; &lt;a href=&quot;open_new_project_dialog&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;New Project&lt;/span&gt;&lt;/a&gt;. &lt;a href=&quot;dont_show_non_project_again&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;Don't show this hint&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>798</width>
<height>27</height>
</rect>
</property>
<widget class="QMenu" name="menuFile">
<property name="title">
<string>Fi&amp;le</string>
</property>
<widget class="QMenu" name="menuImport">
<property name="title">
<string>Import</string>
</property>
<property name="icon">
<iconset theme="document-import">
<normaloff>.</normaloff>.</iconset>
</property>
<addaction name="actionSamples_from_csv"/>
</widget>
<addaction name="actionNew_Project"/>
<addaction name="actionProject_settings"/>
<addaction name="actionSave_project"/>
<addaction name="actionClose_project"/>
<addaction name="separator"/>
<addaction name="actionOpen"/>
<addaction name="actionOpen_directory"/>
<addaction name="menuImport"/>
<addaction name="separator"/>
<addaction name="actionSpectrum_Analyzer"/>
<addaction name="actionRecord"/>
<addaction name="actionSniff_protocol"/>
<addaction name="separator"/>
<addaction name="actionSaveAllSignals"/>
<addaction name="actionCloseAllFiles"/>
<addaction name="separator"/>
<addaction name="actionConvert_Folder_to_Project"/>
</widget>
<widget class="QMenu" name="menuEdit">
<property name="title">
<string>Edi&amp;t</string>
</property>
<widget class="QMenu" name="menuDefault_noise_threshold">
<property name="title">
<string>Default noise threshold</string>
</property>
<addaction name="actionAutomaticNoiseThreshold"/>
<addaction name="action1NoiseThreshold"/>
<addaction name="action5NoiseThreshold"/>
<addaction name="action10NoiseThreshold"/>
<addaction name="action100NoiseThreshold"/>
</widget>
<addaction name="actionDecoding"/>
<addaction name="actionOptions"/>
<addaction name="separator"/>
<addaction name="actionShowFileTree"/>
<addaction name="actionFullscreen_mode"/>
<addaction name="separator"/>
<addaction name="actionAuto_detect_new_signals"/>
<addaction name="menuDefault_noise_threshold"/>
</widget>
<widget class="QMenu" name="menuHelp">
<property name="title">
<string>Hel&amp;p</string>
</property>
<addaction name="actionAbout_AutomaticHacker"/>
<addaction name="actionAbout_Qt"/>
</widget>
<addaction name="menuFile"/>
<addaction name="menuEdit"/>
<addaction name="menuHelp"/>
</widget>
<action name="actionFSK">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Undo</string>
</property>
</action>
<action name="actionOOK">
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="text">
<string>Redo</string>
</property>
</action>
<action name="actionPSK">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>PSK</string>
</property>
</action>
<action name="actionNone">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>None (bei .bin)</string>
</property>
</action>
<action name="actionAuto_Fit_Y">
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="text">
<string>&amp;Auto Fit Y</string>
</property>
</action>
<action name="actionUndo">
<property name="icon">
<iconset theme="edit-undo">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>&amp;Undo</string>
</property>
</action>
<action name="actionRedo">
<property name="icon">
<iconset theme="edit-redo">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>&amp;Redo</string>
</property>
</action>
<action name="actionShow_Confirm_Close_Dialog">
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
<property name="text">
<string>&amp;Show Confirm Close Dialog</string>
</property>
</action>
<action name="actionTest">
<property name="text">
<string>test</string>
</property>
</action>
<action name="actionHold_Shift_to_Drag">
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
<property name="text">
<string>&amp;Hold Shift to Drag</string>
</property>
</action>
<action name="actionDocumentation">
<property name="icon">
<iconset theme="help-contents">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>&amp;Documentation</string>
</property>
<property name="iconVisibleInMenu">
<bool>true</bool>
</property>
</action>
<action name="actionAbout_AutomaticHacker">
<property name="icon">
<iconset theme="help-about">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>&amp;About Universal Radio Hacker...</string>
</property>
<property name="iconVisibleInMenu">
<bool>true</bool>
</property>
</action>
<action name="actionOpenSignal">
<property name="text">
<string>&amp;Signal</string>
</property>
</action>
<action name="actionOpenProtocol">
<property name="text">
<string>&amp;Protocol</string>
</property>
</action>
<action name="actionShow_Compare_Frame">
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="text">
<string>Show &amp;Compare Frame</string>
</property>
</action>
<action name="actionCloseAllFiles">
<property name="icon">
<iconset theme="window-close">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>&amp;Close all files</string>
</property>
<property name="iconVisibleInMenu">
<bool>true</bool>
</property>
</action>
<action name="actionSaveAllSignals">
<property name="icon">
<iconset theme="document-save">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>&amp;Save all signals</string>
</property>
<property name="iconVisibleInMenu">
<bool>true</bool>
</property>
</action>
<action name="actionSeperate_Protocols_in_Compare_Frame">
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="text">
<string>Separate &amp;Protocols in Compare Frame</string>
</property>
</action>
<action name="actionOpenArchive">
<property name="text">
<string>&amp;Archive</string>
</property>
</action>
<action name="actionOpen">
<property name="icon">
<iconset theme="document-open">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>&amp;Open...</string>
</property>
<property name="iconVisibleInMenu">
<bool>true</bool>
</property>
</action>
<action name="actionOpen_Folder">
<property name="icon">
<iconset theme="folder-open">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>Open &amp;Folder..</string>
</property>
</action>
<action name="actionShow_only_Compare_Frame">
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="text">
<string>Show Compare Frame only</string>
</property>
</action>
<action name="actionConfigurePlugins">
<property name="text">
<string>Configure...</string>
</property>
<property name="iconVisibleInMenu">
<bool>true</bool>
</property>
</action>
<action name="actionSort_Frames_by_Name">
<property name="text">
<string>Sort &amp;Frames by Name</string>
</property>
</action>
<action name="actionConvert_Folder_to_Project">
<property name="text">
<string>Conv&amp;ert Folder to Project</string>
</property>
<property name="iconVisibleInMenu">
<bool>true</bool>
</property>
</action>
<action name="actionDecoding">
<property name="icon">
<iconset resource="urh.qrc">
<normaloff>:/icons/icons/decoding.svg</normaloff>:/icons/icons/decoding.svg</iconset>
</property>
<property name="text">
<string>&amp;Decoding...</string>
</property>
</action>
<action name="actionRecord">
<property name="icon">
<iconset theme="media-record">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>&amp;Record signal...</string>
</property>
<property name="iconVisibleInMenu">
<bool>true</bool>
</property>
</action>
<action name="actionSpectrum_Analyzer">
<property name="icon">
<iconset resource="urh.qrc">
<normaloff>:/icons/icons/spectrum.svg</normaloff>:/icons/icons/spectrum.svg</iconset>
</property>
<property name="text">
<string>Spectrum &amp;Analyzer...</string>
</property>
<property name="iconVisibleInMenu">
<bool>true</bool>
</property>
</action>
<action name="actionOptions">
<property name="icon">
<iconset theme="configure">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>&amp;Options...</string>
</property>
<property name="iconVisibleInMenu">
<bool>true</bool>
</property>
</action>
<action name="actionNew_Project">
<property name="icon">
<iconset theme="folder-new">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>&amp;New Project..</string>
</property>
</action>
<action name="actionSniff_protocol">
<property name="icon">
<iconset resource="urh.qrc">
<normaloff>:/icons/icons/sniffer.svg</normaloff>:/icons/icons/sniffer.svg</iconset>
</property>
<property name="text">
<string>Sn&amp;iff protocol...</string>
</property>
</action>
<action name="actionProject_settings">
<property name="icon">
<iconset theme="configure">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>&amp;Project settings...</string>
</property>
</action>
<action name="actionSave_project">
<property name="icon">
<iconset theme="document-save">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>Sa&amp;ve project</string>
</property>
</action>
<action name="actionFullscreen_mode">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>&amp;Fullscreen mode</string>
</property>
</action>
<action name="actionOpen_directory">
<property name="icon">
<iconset theme="folder-open">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>Open &amp;folder...</string>
</property>
</action>
<action name="actionAbout_Qt">
<property name="text">
<string>About &amp;Qt</string>
</property>
</action>
<action name="actionShowFileTree">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>&amp;Show file tree</string>
</property>
</action>
<action name="actionSamples_from_csv">
<property name="icon">
<iconset theme="text-csv">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>IQ samples from csv</string>
</property>
</action>
<action name="actionClose_project">
<property name="icon">
<iconset theme="document-close">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>Close project</string>
</property>
</action>
<action name="actionAuto_detect_new_signals">
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="text">
<string>Auto detect signals on loading</string>
</property>
</action>
<action name="actionAutomaticNoiseThreshold">
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="text">
<string>Automatic</string>
</property>
</action>
<action name="action1NoiseThreshold">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>1%</string>
</property>
</action>
<action name="action5NoiseThreshold">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>5%</string>
</property>
</action>
<action name="action10NoiseThreshold">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>10%</string>
</property>
</action>
<action name="action100NoiseThreshold">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>100% (disables demodulation)</string>
</property>
</action>
</widget>
<customwidgets>
<customwidget>
<class>DirectoryTreeView</class>
<extends>QTreeView</extends>
<header>urh.ui.views.DirectoryTreeView.h</header>
</customwidget>
</customwidgets>
<resources>
<include location="urh.qrc"/>
</resources>
<connections/>
</ui>

View File

@ -1,109 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>DialogMessageType</class>
<widget class="QDialog" name="DialogMessageType">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>471</width>
<height>359</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0" colspan="2">
<widget class="QComboBox" name="cbRulesetMode">
<item>
<property name="text">
<string>All rules must apply (AND)</string>
</property>
</item>
<item>
<property name="text">
<string>At least one rule must apply (OR)</string>
</property>
</item>
<item>
<property name="text">
<string>No rule must apply (NOR)</string>
</property>
</item>
</widget>
</item>
<item row="2" column="0" rowspan="3" colspan="2">
<widget class="QTableView" name="tblViewRuleset">
<property name="showGrid">
<bool>false</bool>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="QToolButton" name="btnRemoveRule">
<property name="toolTip">
<string>Remove ruleset</string>
</property>
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset theme="list-remove">
<normaloff>.</normaloff>.</iconset>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QRadioButton" name="rbAssignManually">
<property name="text">
<string>Assi&amp;gn manually</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QRadioButton" name="rbAssignAutomatically">
<property name="text">
<string>Assign a&amp;utomatically</string>
</property>
</widget>
</item>
<item row="4" column="2">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>145</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="2">
<widget class="QToolButton" name="btnAddRule">
<property name="toolTip">
<string>Add ruleset</string>
</property>
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset theme="list-add">
<normaloff>.</normaloff>.</iconset>
</property>
</widget>
</item>
<item row="5" column="0" colspan="2">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

File diff suppressed because it is too large Load Diff

View File

@ -1,59 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>DialogModulationParameters</class>
<widget class="QDialog" name="DialogModulationParameters">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>303</width>
<height>286</height>
</rect>
</property>
<property name="windowTitle">
<string>Modulation Parameters</string>
</property>
<property name="modal">
<bool>true</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTableWidget" name="tblSymbolParameters">
<property name="showGrid">
<bool>false</bool>
</property>
<property name="rowCount">
<number>2</number>
</property>
<attribute name="horizontalHeaderVisible">
<bool>true</bool>
</attribute>
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
<row/>
<row/>
<column>
<property name="text">
<string>Symbol</string>
</property>
</column>
<column>
<property name="text">
<string>Amplitude</string>
</property>
</column>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -1,261 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ModulationSettings</class>
<widget class="QWidget" name="ModulationSettings">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>821</width>
<height>635</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<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="QGroupBox" name="groupBoxSniffSettings">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="styleSheet">
<string notr="true">QGroupBox
{
border: none;
}
QGroupBox::title {
subcontrol-origin: margin;
}
QGroupBox::indicator:unchecked {
image: url(:/icons/icons/collapse.svg)
}
QGroupBox::indicator:checked {
image: url(:/icons/icons/uncollapse.svg)
}</string>
</property>
<property name="title">
<string>Modulation settings</string>
</property>
<property name="flat">
<bool>true</bool>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<property name="topMargin">
<number>15</number>
</property>
<item row="0" column="0">
<widget class="QFrame" name="frame">
<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="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="labelModulationProfile">
<property name="text">
<string>Choose profile:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="comboBoxModulationProfiles"/>
</item>
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="1">
<widget class="QLabel" name="labelCarrierFrequencyValue">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QLabel" name="labelSampleRate">
<property name="text">
<string>Sample Rate:</string>
</property>
</widget>
</item>
<item row="0" column="5" rowspan="2">
<widget class="Line" name="line_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="labelCarrierFrequency">
<property name="text">
<string>Carrier Frequency:</string>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QLabel" name="labelSamplesPerSymbol">
<property name="text">
<string>Samples per Symbol:</string>
</property>
</widget>
</item>
<item row="1" column="4">
<widget class="QLabel" name="labelSampleRateValue">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="labelModulationType">
<property name="text">
<string>Modulation type:</string>
</property>
</widget>
</item>
<item row="0" column="2" rowspan="2">
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item row="0" column="4">
<widget class="QLabel" name="labelSamplesPerSymbolValue">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="labelModulationTypeValue">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="1" column="6">
<widget class="QLabel" name="labelParameters">
<property name="text">
<string>Amplitudes in %:</string>
</property>
</widget>
</item>
<item row="1" column="7">
<widget class="ElidedLabel" name="labelParameterValues">
<property name="text">
<string>0/100</string>
</property>
</widget>
</item>
<item row="0" column="6">
<widget class="QLabel" name="label">
<property name="text">
<string>Bits per Symbol:</string>
</property>
</widget>
</item>
<item row="0" column="7">
<widget class="QLabel" name="labelBitsPerSymbol">
<property name="text">
<string>1</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QPushButton" name="btnConfigurationDialog">
<property name="text">
<string>Open modulation configuration dialog...</string>
</property>
<property name="icon">
<iconset theme="configure">
<normaloff>.</normaloff>.</iconset>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>ElidedLabel</class>
<extends>QLabel</extends>
<header>urh.ui.ElidedLabel.h</header>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>groupBoxSniffSettings</tabstop>
<tabstop>comboBoxModulationProfiles</tabstop>
<tabstop>btnConfigurationDialog</tabstop>
</tabstops>
<resources>
<include location="urh.qrc"/>
</resources>
<connections>
<connection>
<sender>groupBoxSniffSettings</sender>
<signal>toggled(bool)</signal>
<receiver>frame</receiver>
<slot>setVisible(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>33</x>
<y>10</y>
</hint>
<hint type="destinationlabel">
<x>18</x>
<y>53</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -1,630 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>DialogOptions</class>
<widget class="QDialog" name="DialogOptions">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>814</width>
<height>822</height>
</rect>
</property>
<property name="windowTitle">
<string>Options</string>
</property>
<property name="windowIcon">
<iconset theme="configure">
<normaloff>.</normaloff>.</iconset>
</property>
<layout class="QVBoxLayout" name="verticalLayout_6">
<item>
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>4</number>
</property>
<widget class="QWidget" name="tabGeneration">
<attribute name="title">
<string>Generation</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_9">
<item>
<layout class="QGridLayout" name="gridLayout_4">
<item row="1" column="1">
<widget class="QLabel" name="labelFuzzingSamples">
<property name="text">
<string>Samples</string>
</property>
</widget>
</item>
<item row="0" column="0" colspan="2">
<widget class="QCheckBox" name="checkBoxDefaultFuzzingPause">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;If you disable the default pause, the pause of the fuzzed message will be used.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Use a default pause for fuzzed messages</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="KillerDoubleSpinBox" name="doubleSpinBoxFuzzingPause">
<property name="decimals">
<number>3</number>
</property>
<property name="maximum">
<double>999999999.000000000000000</double>
</property>
</widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="QCheckBox" name="checkBoxMultipleModulations">
<property name="text">
<string>Enable modulation profiles</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QGroupBox" name="groupBoxModulationAccuracy">
<property name="title">
<string>Modulation Accuracy</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_7">
<item>
<widget class="QRadioButton" name="radioButtonLowModulationAccuracy">
<property name="text">
<string>Low (2x8 bit) - Recommended for HackRF and RTL-SDR</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="radioButtonMediumModulationAccuracy">
<property name="text">
<string>Medium (2x16 bit) - Recommended for BladeRF, PlutoSDR and SDRPlay</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="radioButtonHighModulationAccuracy">
<property name="text">
<string>High (2x32 bit) - Recommended if you are not sure what to choose</string>
</property>
</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>500</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<widget class="QWidget" name="tabView">
<attribute name="title">
<string>View</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="label_7">
<property name="text">
<string>Default View:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="comboBoxDefaultView">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item>
<property name="text">
<string>Bit</string>
</property>
</item>
<item>
<property name="text">
<string>Hex</string>
</property>
</item>
<item>
<property name="text">
<string>ASCII</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QCheckBox" name="checkBoxShowConfirmCloseDialog">
<property name="text">
<string>Show &quot;confirm close&quot; dialog</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBoxHoldShiftToDrag">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;If checked, you need to &lt;span style=&quot; font-weight:600;&quot;&gt;hold the Shift key to drag&lt;/span&gt; with the mouse inside graphic views like the drawn signal in Interpretation tab, while making a selection with the mouse does not require holding any buttons.&lt;/p&gt;&lt;p&gt;If unchecked, this is inverted: Hold shift to make a selection, and drag by default.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Hold shift to drag</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBoxPauseTime">
<property name="text">
<string>Show pauses as time</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBoxAlignLabels">
<property name="text">
<string>Align on labels</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="labelFontSize">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Application font size (&lt;span style=&quot; font-weight:600;&quot;&gt;restart&lt;/span&gt; for full effect):&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="spinBoxFontSize">
<property name="suffix">
<string>pt</string>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>120</number>
</property>
<property name="value">
<number>10</number>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QLabel" name="label_9">
<property name="text">
<string>Choose application theme (requires restart):</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="comboBoxTheme">
<item>
<property name="text">
<string>native look (default)</string>
</property>
</item>
<item>
<property name="text">
<string>fallback theme</string>
</property>
</item>
<item>
<property name="text">
<string>fallback theme (dark)</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<widget class="QLabel" name="labelIconTheme">
<property name="text">
<string>Choose icon theme (requires restart):</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="comboBoxIconTheme">
<item>
<property name="text">
<string>bundled icons (default)</string>
</property>
</item>
<item>
<property name="text">
<string>native icon theme</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QGroupBox" name="groupBoxSpectrogramColormap">
<property name="title">
<string>Spectrogram Colormap</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QScrollArea" name="scrollAreaSpectrogramColormap">
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetSpectrogramColormapContents">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>762</width>
<height>397</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4"/>
</widget>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tabFieldtypes">
<attribute name="title">
<string>Fieldtypes</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QTableView" name="tblLabeltypes">
<property name="alternatingRowColors">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QToolButton" name="btnAddLabelType">
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset theme="list-add">
<normaloff>.</normaloff>.</iconset>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="btnRemoveLabeltype">
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset theme="list-remove">
<normaloff>.</normaloff>.</iconset>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_5">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer_4">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>203</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_plugins">
<attribute name="title">
<string>Plugins</string>
</attribute>
</widget>
<widget class="QWidget" name="tabDevices">
<attribute name="title">
<string>Device</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_8">
<item>
<widget class="QLabel" name="labelInfoDeviceTable">
<property name="font">
<font>
<italic>true</italic>
</font>
</property>
<property name="toolTip">
<string/>
</property>
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Use the checkboxes in the table below to choose device backends and enable or disable devices. Disabled devices will not show up in device related dialogs such as send or receive.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QTableView" name="tblDevices">
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<property name="showGrid">
<bool>false</bool>
</property>
<attribute name="horizontalHeaderDefaultSectionSize">
<number>200</number>
</attribute>
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
</widget>
</item>
<item>
<widget class="QLabel" name="labelDeviceMissingInfo">
<property name="font">
<font>
<italic>false</italic>
</font>
</property>
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Missing a native backend? Perform a &lt;a href=&quot;health_check&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;health check&lt;/span&gt;&lt;/a&gt;! If GNU Radio backend is not available double check the GNU Radio settings below.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBoxNativeOptions">
<property name="title">
<string>Native options</string>
</property>
<layout class="QGridLayout" name="gridLayout_5">
<item row="2" column="0">
<widget class="QLabel" name="labelLibDirs">
<property name="text">
<string>Library directories:</string>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="QLineEdit" name="lineEditIncludeDirs">
<property name="placeholderText">
<string>Comma separated list of additional include directories</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="3">
<widget class="QLabel" name="labelNativeRebuildInfo">
<property name="text">
<string>You can rebuild the native device extensions here. This is useful, when you installed a device driver afterwards or your drivers are stored in an unusual location.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QLineEdit" name="lineEditLibDirs">
<property name="placeholderText">
<string>Comma separated list of additional library directories</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="labelIncludeDirs">
<property name="text">
<string>Include directories:</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QPushButton" name="btnViewBuildLog">
<property name="text">
<string>View log</string>
</property>
<property name="icon">
<iconset theme="utilities-log-viewer">
<normaloff>.</normaloff>.</iconset>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QPushButton" name="btnRebuildNative">
<property name="enabled">
<bool>true</bool>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Rebuild the native device extensions. You need to restart URH after this, to use new extensions.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Rebuild</string>
</property>
<property name="icon">
<iconset theme="view-refresh">
<normaloff>.</normaloff>.</iconset>
</property>
</widget>
</item>
<item row="4" column="2">
<widget class="QLabel" name="labelRebuildNativeStatus">
<property name="text">
<string>Rebuild &lt;x&gt; new device extensions. Please restart URH to use them.</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="Line" name="line_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_3">
<property name="title">
<string>GNU Radio options (optional)</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Choose a python interpreter which has access to your GNU Radio installation, that is, you can do &lt;span style=&quot; font-weight:600;&quot;&gt;python -c &amp;quot;import gnuradio&amp;quot;&lt;/span&gt; with it on the command line.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Python Interpreter:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="lineEditGRPythonInterpreter">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Choose a python interpreter which has access to your GNU Radio installation, that is, you can do &lt;span style=&quot; font-weight:600;&quot;&gt;python -c &amp;quot;import gnuradio&amp;quot;&lt;/span&gt; with it on the command line.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="placeholderText">
<string>Enter python interpreter path e.g. /usr/bin/python</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QToolButton" name="btnChooseGRPythonInterpreter">
<property name="text">
<string>...</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="Line" name="line_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Default sending repititions:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QSpinBox" name="spinBoxNumSendingRepeats">
<property name="specialValueText">
<string>Infinite</string>
</property>
<property name="showGroupSeparator" stdset="0">
<bool>false</bool>
</property>
<property name="maximum">
<number>999999999</number>
</property>
<property name="displayIntegerBase">
<number>10</number>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Use this percentage of available RAM for buffer allocation:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QDoubleSpinBox" name="doubleSpinBoxRAMThreshold">
<property name="suffix">
<string>%</string>
</property>
<property name="minimum">
<double>1.000000000000000</double>
</property>
<property name="maximum">
<double>100.000000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>KillerDoubleSpinBox</class>
<extends>QDoubleSpinBox</extends>
<header>urh.ui.KillerDoubleSpinBox.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View File

@ -1,98 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>FramePlugins</class>
<widget class="QFrame" name="FramePlugins">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>806</width>
<height>683</height>
</rect>
</property>
<property name="windowTitle">
<string>Plugins</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Available Plugins</string>
</property>
</widget>
</item>
<item>
<widget class="QListView" name="listViewPlugins">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Description</string>
</property>
</widget>
</item>
<item>
<widget class="QTextEdit" name="txtEditPluginDescription">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
<property name="placeholderText">
<string/>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item>
<widget class="QGroupBox" name="groupBoxSettings">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="title">
<string>Settings</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -1,412 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ProjectDialog</class>
<widget class="QDialog" name="ProjectDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>803</width>
<height>936</height>
</rect>
</property>
<property name="windowTitle">
<string>Create a new project</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="lNewProject">
<property name="font">
<font>
<pointsize>16</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>New Project</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lblName">
<property name="text">
<string>&lt;Name&gt;</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>17</width>
<height>10</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="3" column="4" colspan="2">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Sps</string>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QLineEdit" name="lineEdit_Path">
<property name="statusTip">
<string/>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="QLabel" name="label_7">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QLabel" name="lblNewPath">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-style:italic;&quot;&gt;Note: A new directory will be created.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
<item row="15" column="4" colspan="2">
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>57</height>
</size>
</property>
</spacer>
</item>
<item row="10" column="3">
<widget class="QPlainTextEdit" name="txtEdDescription"/>
</item>
<item row="11" column="3" rowspan="5">
<widget class="ParticipantTableView" name="tblParticipants">
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::ExtendedSelection</enum>
</property>
<attribute name="horizontalHeaderCascadingSectionResizes">
<bool>false</bool>
</attribute>
<attribute name="horizontalHeaderDefaultSectionSize">
<number>100</number>
</attribute>
<attribute name="horizontalHeaderStretchLastSection">
<bool>true</bool>
</attribute>
<attribute name="verticalHeaderCascadingSectionResizes">
<bool>true</bool>
</attribute>
<attribute name="verticalHeaderStretchLastSection">
<bool>false</bool>
</attribute>
</widget>
</item>
<item row="5" column="3">
<widget class="KillerDoubleSpinBox" name="spinBoxBandwidth">
<property name="decimals">
<number>3</number>
</property>
<property name="minimum">
<double>1.000000000000000</double>
</property>
<property name="maximum">
<double>999999999999.000000000000000</double>
</property>
<property name="singleStep">
<double>0.001000000000000</double>
</property>
<property name="value">
<double>1000000.000000000000000</double>
</property>
</widget>
</item>
<item row="4" column="0" colspan="2">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Default frequency:</string>
</property>
</widget>
</item>
<item row="4" column="3">
<widget class="KillerDoubleSpinBox" name="spinBoxFreq">
<property name="decimals">
<number>3</number>
</property>
<property name="minimum">
<double>0.010000000000000</double>
</property>
<property name="maximum">
<double>1000000000000.000000000000000</double>
</property>
<property name="singleStep">
<double>0.001000000000000</double>
</property>
<property name="value">
<double>433920000.000000000000000</double>
</property>
</widget>
</item>
<item row="3" column="3">
<widget class="KillerDoubleSpinBox" name="spinBoxSampleRate">
<property name="decimals">
<number>3</number>
</property>
<property name="minimum">
<double>0.010000000000000</double>
</property>
<property name="maximum">
<double>1000000000000.000000000000000</double>
</property>
<property name="singleStep">
<double>0.001000000000000</double>
</property>
<property name="value">
<double>1000000.000000000000000</double>
</property>
</widget>
</item>
<item row="16" column="3">
<widget class="QLineEdit" name="lineEditBroadcastAddress">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Enter the broadcast address of your protocol in &lt;span style=&quot; font-weight:600;&quot;&gt;hex&lt;/span&gt;. If you do not know what to enter here, just leave the default.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="inputMask">
<string/>
</property>
<property name="text">
<string>ffff</string>
</property>
</widget>
</item>
<item row="9" column="0" colspan="6">
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="5" column="0" colspan="2">
<widget class="QLabel" name="label_10">
<property name="text">
<string>Default bandwidth:</string>
</property>
</widget>
</item>
<item row="11" column="4" colspan="2">
<widget class="QToolButton" name="btnAddParticipant">
<property name="toolTip">
<string>Add participant</string>
</property>
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset theme="list-add">
<normaloff>.</normaloff>.</iconset>
</property>
</widget>
</item>
<item row="0" column="4" colspan="2">
<widget class="QToolButton" name="btnSelectPath">
<property name="text">
<string>...</string>
</property>
</widget>
</item>
<item row="2" column="0" colspan="6">
<widget class="Line" name="line_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="4" column="4" colspan="2">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Hz</string>
</property>
</widget>
</item>
<item row="3" column="0" colspan="2">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Default sample rate:</string>
</property>
</widget>
</item>
<item row="0" column="0" colspan="2">
<widget class="QLabel" name="label">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Choose a path:</string>
</property>
</widget>
</item>
<item row="12" column="4" colspan="2">
<widget class="QToolButton" name="btnRemoveParticipant">
<property name="toolTip">
<string>Remove participant</string>
</property>
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset theme="list-remove">
<normaloff>.</normaloff>.</iconset>
</property>
</widget>
</item>
<item row="6" column="3">
<widget class="QSpinBox" name="spinBoxGain">
<property name="minimum">
<number>1</number>
</property>
<property name="value">
<number>20</number>
</property>
</widget>
</item>
<item row="16" column="0" colspan="2">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Broadcast address (hex):</string>
</property>
</widget>
</item>
<item row="10" column="0" colspan="2">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Description:</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="5" column="4" colspan="2">
<widget class="QLabel" name="label_12">
<property name="text">
<string>Hz</string>
</property>
</widget>
</item>
<item row="6" column="0" colspan="2">
<widget class="QLabel" name="label_11">
<property name="text">
<string>Default gain:</string>
</property>
</widget>
</item>
<item row="13" column="4">
<widget class="QToolButton" name="btnUp">
<property name="toolTip">
<string>Move selected participants up</string>
</property>
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset theme="go-up">
<normaloff>.</normaloff>.</iconset>
</property>
</widget>
</item>
<item row="8" column="0" colspan="4">
<widget class="QLabel" name="lOpenSpectrumAnalyzer">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Tip: Open &lt;a href=&quot;open_spectrum_analyzer&quot;&gt;spectrum analyzer&lt;/a&gt; to find these values.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="textFormat">
<enum>Qt::AutoText</enum>
</property>
<property name="openExternalLinks">
<bool>false</bool>
</property>
</widget>
</item>
<item row="11" column="0" rowspan="5" colspan="2">
<widget class="QLabel" name="label_9">
<property name="text">
<string>Participants:</string>
</property>
</widget>
</item>
<item row="14" column="4">
<widget class="QToolButton" name="btnDown">
<property name="toolTip">
<string>Move selected participants down</string>
</property>
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset theme="go-down">
<normaloff>.</normaloff>.</iconset>
</property>
</widget>
</item>
<item row="17" column="3">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>ParticipantTableView</class>
<extends>QTableView</extends>
<header>urh.ui.views.ParticipantTableView.h</header>
</customwidget>
<customwidget>
<class>KillerDoubleSpinBox</class>
<extends>QDoubleSpinBox</extends>
<header>urh.ui.KillerDoubleSpinBox.h</header>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>lineEdit_Path</tabstop>
<tabstop>btnSelectPath</tabstop>
<tabstop>spinBoxSampleRate</tabstop>
<tabstop>spinBoxFreq</tabstop>
<tabstop>spinBoxBandwidth</tabstop>
<tabstop>spinBoxGain</tabstop>
<tabstop>txtEdDescription</tabstop>
<tabstop>tblParticipants</tabstop>
<tabstop>btnAddParticipant</tabstop>
<tabstop>btnRemoveParticipant</tabstop>
<tabstop>lineEditBroadcastAddress</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>

View File

@ -1,144 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>DialogLabels</class>
<widget class="QDialog" name="DialogLabels">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>714</width>
<height>463</height>
</rect>
</property>
<property name="windowTitle">
<string>Manage Protocol Labels</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QSplitter" name="splitter">
<property name="styleSheet">
<string notr="true">QSplitter::handle:vertical {
margin: 4px 0px;
background-color: qlineargradient(x1:0, y1:0, x2:1, y2:0,
stop:0 rgba(255, 255, 255, 0),
stop:0.5 rgba(100, 100, 100, 100),
stop:1 rgba(255, 255, 255, 0));
image: url(:/icons/icons/splitter_handle_horizontal.svg);
}</string>
</property>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="handleWidth">
<number>6</number>
</property>
<property name="childrenCollapsible">
<bool>false</bool>
</property>
<widget class="QGroupBox" name="groupBoxSettings">
<property name="title">
<string>Protocol Label Settings</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="ProtocolLabelTableView" name="tblViewProtoLabels">
<property name="selectionMode">
<enum>QAbstractItemView::ExtendedSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectItems</enum>
</property>
<property name="verticalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
<property name="horizontalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
<property name="showGrid">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="label">
<property name="font">
<font>
<underline>false</underline>
</font>
</property>
<property name="text">
<string>Start/End values refer to view type:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="cbProtoView">
<item>
<property name="text">
<string>Bits</string>
</property>
</item>
<item>
<property name="text">
<string>Hex</string>
</property>
</item>
<item>
<property name="text">
<string>ASCII</string>
</property>
</item>
</widget>
</item>
<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>
</layout>
</item>
</layout>
</widget>
<widget class="QGroupBox" name="groupBoxAdvancedSettings">
<property name="title">
<string>Advanced Settings</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QTabWidget" name="tabWidgetAdvancedSettings"/>
</item>
</layout>
</widget>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnConfirm">
<property name="text">
<string>Confirm</string>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>ProtocolLabelTableView</class>
<extends>QTableView</extends>
<header>urh.ui.views.ProtocolLabelTableView.h</header>
</customwidget>
</customwidgets>
<resources>
<include location="urh.qrc"/>
</resources>
<connections/>
</ui>

View File

@ -1,610 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SendRecvDialog</class>
<widget class="QDialog" name="SendRecvDialog">
<property name="windowModality">
<enum>Qt::NonModal</enum>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1246</width>
<height>1123</height>
</rect>
</property>
<property name="mouseTracking">
<bool>false</bool>
</property>
<property name="windowTitle">
<string>Record Signal</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QSplitter" name="splitter">
<property name="styleSheet">
<string notr="true">QSplitter::handle:horizontal {
margin: 4px 0px;
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,
stop:0 rgba(255, 255, 255, 0),
stop:0.5 rgba(100, 100, 100, 100),
stop:1 rgba(255, 255, 255, 0));
image: url(:/icons/icons/splitter_handle_vertical.svg);
}</string>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<widget class="QScrollArea" name="scrollArea">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents_2">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>621</width>
<height>1101</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_8">
<item>
<widget class="QGroupBox" name="groupBox">
<property name="styleSheet">
<string notr="true">QGroupBox
{
border: none;
}</string>
</property>
<property name="title">
<string/>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<property name="topMargin">
<number>0</number>
</property>
<item row="19" column="0">
<widget class="QProgressBar" name="progressBarMessage">
<property name="value">
<number>0</number>
</property>
<property name="format">
<string>%v/%m</string>
</property>
</widget>
</item>
<item row="18" column="0">
<widget class="QLabel" name="labelCurrentMessage">
<property name="text">
<string>Current message:</string>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QLabel" name="lReceiveBufferFullText">
<property name="text">
<string>Receive buffer full:</string>
</property>
</widget>
</item>
<item row="21" column="0">
<widget class="QProgressBar" name="progressBarSample">
<property name="value">
<number>0</number>
</property>
<property name="format">
<string>%v/%m</string>
</property>
</widget>
</item>
<item row="20" column="0">
<widget class="QLabel" name="lSamplesSentText">
<property name="text">
<string>Current sample:</string>
</property>
</widget>
</item>
<item row="12" column="0">
<widget class="QLabel" name="lTimeText">
<property name="text">
<string>Time (in seconds):</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="lSamplesCapturedText">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Samples captured:</string>
</property>
</widget>
</item>
<item row="9" column="0">
<widget class="QLabel" name="lSignalSizeText">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Signal size (in MiB):</string>
</property>
</widget>
</item>
<item row="6" column="0" colspan="2">
<widget class="QLabel" name="lSamplesCaptured">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>0</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="15" column="0" colspan="2">
<widget class="QLabel" name="lTime">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>0</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="11" column="0" colspan="2">
<widget class="QLabel" name="lSignalSize">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>0</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="16" column="0">
<widget class="QLabel" name="lblRepeatText">
<property name="text">
<string>Current iteration:</string>
</property>
</widget>
</item>
<item row="17" column="0">
<widget class="QLabel" name="lblCurrentRepeatValue">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>0</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QLabel" name="labelReceiveBufferFull">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>0%</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<spacer name="horizontalSpacer_2">
<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="QToolButton" name="btnStart">
<property name="minimumSize">
<size>
<width>64</width>
<height>64</height>
</size>
</property>
<property name="toolTip">
<string>Record signal</string>
</property>
<property name="text">
<string>Start</string>
</property>
<property name="icon">
<iconset theme="media-record">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="iconSize">
<size>
<width>32</width>
<height>32</height>
</size>
</property>
<property name="toolButtonStyle">
<enum>Qt::ToolButtonTextUnderIcon</enum>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="btnStop">
<property name="minimumSize">
<size>
<width>64</width>
<height>64</height>
</size>
</property>
<property name="toolTip">
<string>Stop recording</string>
</property>
<property name="text">
<string>Stop</string>
</property>
<property name="icon">
<iconset theme="media-playback-stop">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="iconSize">
<size>
<width>32</width>
<height>32</height>
</size>
</property>
<property name="toolButtonStyle">
<enum>Qt::ToolButtonTextUnderIcon</enum>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="btnSave">
<property name="minimumSize">
<size>
<width>64</width>
<height>64</height>
</size>
</property>
<property name="text">
<string>Save...</string>
</property>
<property name="icon">
<iconset theme="document-save">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="iconSize">
<size>
<width>32</width>
<height>32</height>
</size>
</property>
<property name="toolButtonStyle">
<enum>Qt::ToolButtonTextUnderIcon</enum>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="btnClear">
<property name="minimumSize">
<size>
<width>64</width>
<height>64</height>
</size>
</property>
<property name="toolTip">
<string>Clear</string>
</property>
<property name="text">
<string>Clear</string>
</property>
<property name="icon">
<iconset theme="view-refresh">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="iconSize">
<size>
<width>32</width>
<height>32</height>
</size>
</property>
<property name="toolButtonStyle">
<enum>Qt::ToolButtonTextUnderIcon</enum>
</property>
</widget>
</item>
<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>
</layout>
</item>
<item row="2" column="0">
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>10</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QTextEdit" name="txtEditErrors">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<widget class="QWidget" name="layoutWidget">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QStackedWidget" name="stackedWidget">
<property name="currentIndex">
<number>4</number>
</property>
<widget class="QWidget" name="page_receive">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="LiveGraphicView" name="graphicsViewReceive">
<property name="verticalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAsNeeded</enum>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="page_send">
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="EditableGraphicView" name="graphicsViewSend">
<property name="mouseTracking">
<bool>true</bool>
</property>
<property name="renderHints">
<set>QPainter::Antialiasing|QPainter::TextAntialiasing</set>
</property>
<property name="transformationAnchor">
<enum>QGraphicsView::NoAnchor</enum>
</property>
<property name="resizeAnchor">
<enum>QGraphicsView::NoAnchor</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_7">
<property name="font">
<font>
<italic>true</italic>
</font>
</property>
<property name="text">
<string>Hint: You can edit the raw signal before sending.</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="page_continuous_send">
<layout class="QVBoxLayout" name="verticalLayout_6">
<item>
<widget class="LiveGraphicView" name="graphicsViewContinuousSend">
<property name="renderHints">
<set>QPainter::Antialiasing|QPainter::TextAntialiasing</set>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="page_spectrum">
<layout class="QVBoxLayout" name="verticalLayout_7" stretch="1,1">
<item>
<widget class="LiveGraphicView" name="graphicsViewFFT"/>
</item>
<item>
<widget class="QGraphicsView" name="graphicsViewSpectrogram">
<property name="verticalScrollBarPolicy">
<enum>Qt::ScrollBarAsNeeded</enum>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="renderHints">
<set>QPainter::SmoothPixmapTransform|QPainter::TextAntialiasing</set>
</property>
<property name="cacheMode">
<set>QGraphicsView::CacheNone</set>
</property>
<property name="viewportUpdateMode">
<enum>QGraphicsView::MinimalViewportUpdate</enum>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="page_sniff">
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="LiveGraphicView" name="graphicsView_sniff_Preview"/>
</item>
<item>
<widget class="QPlainTextEdit" name="txtEd_sniff_Preview">
<property name="lineWrapMode">
<enum>QPlainTextEdit::NoWrap</enum>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
<property name="maximumBlockCount">
<number>100</number>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnAccept">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Accept the sniffed data and load it into &lt;span style=&quot; font-weight:600;&quot;&gt;Analysis&lt;/span&gt; tab.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Accept data (Open in Analysis)</string>
</property>
<property name="autoDefault">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
<widget class="QLabel" name="label_y_scale">
<property name="text">
<string>Y-Scale</string>
</property>
</widget>
</item>
<item>
<widget class="QSlider" name="sliderYscale">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>1000</number>
</property>
<property name="value">
<number>1</number>
</property>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="tickInterval">
<number>1</number>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>LiveGraphicView</class>
<extends>QGraphicsView</extends>
<header>urh.ui.views.LiveGraphicView.h</header>
</customwidget>
<customwidget>
<class>EditableGraphicView</class>
<extends>QGraphicsView</extends>
<header>urh.ui.views.EditableGraphicView.h</header>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>btnStart</tabstop>
<tabstop>btnStop</tabstop>
<tabstop>btnSave</tabstop>
<tabstop>btnClear</tabstop>
<tabstop>txtEd_sniff_Preview</tabstop>
<tabstop>sliderYscale</tabstop>
<tabstop>txtEditErrors</tabstop>
<tabstop>graphicsViewSend</tabstop>
<tabstop>graphicsViewReceive</tabstop>
<tabstop>btnAccept</tabstop>
</tabstops>
<resources>
<include location="urh.qrc"/>
</resources>
<connections/>
</ui>

View File

@ -1,619 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>FormDeviceSettings</class>
<widget class="QWidget" name="FormDeviceSettings">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>859</width>
<height>741</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<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="QGroupBox" name="groupBoxDeviceSettings">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="styleSheet">
<string notr="true">QGroupBox
{
border: none;
}
QGroupBox::title {
subcontrol-origin: margin;
}
QGroupBox::indicator:unchecked {
image: url(:/icons/icons/collapse.svg)
}
QGroupBox::indicator:checked {
image: url(:/icons/icons/uncollapse.svg)
}</string>
</property>
<property name="title">
<string>Device settings</string>
</property>
<property name="flat">
<bool>true</bool>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<layout class="QGridLayout" name="gridLayout_6">
<property name="topMargin">
<number>15</number>
</property>
<item row="0" column="0">
<widget class="QFrame" name="frame_2">
<property name="font">
<font>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="4" column="0">
<widget class="QLabel" name="labelAntenna">
<property name="text">
<string>Antenna:</string>
</property>
</widget>
</item>
<item row="12" column="0">
<widget class="QLabel" name="labelBasebandGain">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The baseband gain is applied to the baseband signal in your software defined radio. The baseband signal is at low frequency and gathered from the RF signal by &lt;span style=&quot; font-weight:600;&quot;&gt;complex downsampling&lt;/span&gt;.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Baseband gain:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="lineEditSubdevice">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Configure the subdevice of your USRP. For example, &lt;span style=&quot; font-weight:600;&quot;&gt;B:0 &lt;/span&gt;to select a WBX on slot B. You can learn more at &lt;a href=&quot;http://files.ettus.com/manual/page_configuration.html#config_subdev&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#2980b9;&quot;&gt;http://files.ettus.com/manual/page_configuration.html#config_subdev.&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
<item row="9" column="1">
<widget class="KillerDoubleSpinBox" name="spinBoxBandwidth">
<property name="decimals">
<number>10</number>
</property>
<property name="minimum">
<double>0.001000000000000</double>
</property>
<property name="maximum">
<double>1000000000000.000000000000000</double>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="labelSubdevice">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Configure the subdevice of your USRP. For example, &lt;span style=&quot; font-weight:600;&quot;&gt;B:0 &lt;/span&gt;to select a WBX on slot B. You can learn more at &lt;a href=&quot;http://files.ettus.com/manual/page_configuration.html#config_subdev&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#2980b9;&quot;&gt;http://files.ettus.com/manual/page_configuration.html#config_subdev.&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Subdevice:&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="KillerDoubleSpinBox" name="spinBoxFreq">
<property name="decimals">
<number>10</number>
</property>
<property name="minimum">
<double>0.001000000000000</double>
</property>
<property name="maximum">
<double>1000000000000.000000000000000</double>
</property>
<property name="value">
<double>433920000.000000000000000</double>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QLineEdit" name="lineEditIP">
<property name="text">
<string>127.0.0.1</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QToolButton" name="btnRefreshDeviceIdentifier">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Automatically detect connected SDRs of the above configured type. There is &lt;span style=&quot; font-weight:600;&quot;&gt;no need&lt;/span&gt; to press this button if you have only one SDR of a certain type attached. &lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset theme="view-refresh">
<normaloff>.</normaloff>.</iconset>
</property>
</widget>
</item>
<item row="15" column="0">
<widget class="QLabel" name="labelDirectSampling">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Set the direct sampling mode. If you do not know what to choose here, just set it to disabled. The&lt;span style=&quot; font-weight:600;&quot;&gt; native backend&lt;/span&gt; is recommended, when using this setting.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Direct sampling:</string>
</property>
</widget>
</item>
<item row="9" column="0">
<widget class="QLabel" name="labelBandwidth">
<property name="text">
<string>Bandwidth (Hz):</string>
</property>
</widget>
</item>
<item row="10" column="1">
<layout class="QGridLayout" name="gridLayout_5">
<property name="sizeConstraint">
<enum>QLayout::SetDefaultConstraint</enum>
</property>
<item row="0" column="0">
<widget class="QSlider" name="sliderGain">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The gain (more exactly RF gain) is the gain applied to the RF signal. This amplifies the high frequent signal arriving at the antenna of your Software Defined Radio.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="maximum">
<number>100</number>
</property>
<property name="singleStep">
<number>1</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QSpinBox" name="spinBoxGain">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The gain (more exactly RF gain) is the gain applied to the RF signal. This amplifies the high frequent signal arriving at the antenna of your Software Defined Radio.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>99</number>
</property>
<property name="value">
<number>40</number>
</property>
</widget>
</item>
</layout>
</item>
<item row="8" column="0">
<widget class="QLabel" name="labelSampleRate">
<property name="text">
<string>Sample rate (Sps):</string>
</property>
</widget>
</item>
<item row="11" column="1">
<layout class="QGridLayout" name="gridLayout_7">
<item row="0" column="0">
<widget class="QSlider" name="sliderIFGain">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The IF Gain is applied to the Intermediate Frequency signal in your Software Defined Radio. An IF signal has a lower frequency than the high frequent RF signal, so signal processing can be applied more efficiently.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QSpinBox" name="spinBoxIFGain">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The IF Gain is applied to the Intermediate Frequency signal in your Software Defined Radio. An IF signal has a lower frequency than the high frequent RF signal, so signal processing can be applied more efficiently.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="13" column="0">
<widget class="QLabel" name="labelFreqCorrection">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Set the frequency correction in &lt;span style=&quot; font-weight:600;&quot;&gt;ppm&lt;/span&gt;. If you do not know what to enter here, just leave it to one.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Frequency correction:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="comboBoxDeviceIdentifier">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;You can enter a device identifier here if you have multiple SDRs of the same type attached to separate them. There is no need to configure this value otherwise. URH will &lt;span style=&quot; font-weight:600;&quot;&gt;automatically&lt;/span&gt; select an attached SDR of the configured type if you leave this value empty.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="editable">
<bool>true</bool>
</property>
<property name="insertPolicy">
<enum>QComboBox::NoInsert</enum>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="cbDevice">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item>
<property name="text">
<string>USRP</string>
</property>
</item>
<item>
<property name="text">
<string>HackRF</string>
</property>
</item>
</widget>
</item>
<item row="16" column="1">
<widget class="QSpinBox" name="spinBoxNRepeat">
<property name="specialValueText">
<string>Infinite</string>
</property>
<property name="maximum">
<number>999999999</number>
</property>
</widget>
</item>
<item row="12" column="1">
<layout class="QGridLayout" name="gridLayout_8">
<item row="0" column="0">
<widget class="QSlider" name="sliderBasebandGain">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The baseband gain is applied to the baseband signal in your software defined radio. The baseband signal is at low frequency and gathered from the RF signal by &lt;span style=&quot; font-weight:600;&quot;&gt;complex downsampling&lt;/span&gt;.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="sliderPosition">
<number>0</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="invertedAppearance">
<bool>false</bool>
</property>
<property name="invertedControls">
<bool>false</bool>
</property>
<property name="tickPosition">
<enum>QSlider::NoTicks</enum>
</property>
<property name="tickInterval">
<number>0</number>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QSpinBox" name="spinBoxBasebandGain">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The baseband gain is applied to the baseband signal in your software defined radio. The baseband signal is at low frequency and gathered from the RF signal by &lt;span style=&quot; font-weight:600;&quot;&gt;complex downsampling&lt;/span&gt;.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="6" column="0">
<widget class="QLabel" name="labelPort">
<property name="text">
<string>Port number:</string>
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="KillerDoubleSpinBox" name="spinBoxSampleRate">
<property name="decimals">
<number>10</number>
</property>
<property name="minimum">
<double>0.001000000000000</double>
</property>
<property name="maximum">
<double>1000000000000.000000000000000</double>
</property>
</widget>
</item>
<item row="10" column="0">
<widget class="QLabel" name="labelGain">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The gain (more exactly RF gain) is the gain applied to the RF signal. This amplifies the high frequent signal arriving at the antenna of your Software Defined Radio.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Gain:</string>
</property>
</widget>
</item>
<item row="17" column="1">
<widget class="QCheckBox" name="checkBoxDCCorrection">
<property name="toolTip">
<string>Apply DC correction during recording, that is, ensure the captured signal has a mean value of zero.</string>
</property>
<property name="text">
<string>Apply DC correction</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="labelDeviceIdentifier">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;You can enter a device identifier here if you have multiple SDRs of the same type attached to separate them. There is no need to configure this value otherwise. URH will &lt;span style=&quot; font-weight:600;&quot;&gt;automatically&lt;/span&gt; select an attached SDR of the configured type if you leave this value empty.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Device Identifier:</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QComboBox" name="comboBoxAntenna"/>
</item>
<item row="7" column="0">
<widget class="QLabel" name="labelFreq">
<property name="text">
<string>Frequency (Hz):</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QSpinBox" name="spinBoxPort">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>65535</number>
</property>
<property name="value">
<number>1234</number>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="labelIP">
<property name="text">
<string>IP address:</string>
</property>
</widget>
</item>
<item row="13" column="1">
<widget class="QSpinBox" name="spinBoxFreqCorrection">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Set the frequency correction in &lt;span style=&quot; font-weight:600;&quot;&gt;ppm&lt;/span&gt;. If you do not know what to enter here, just leave it to one.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="minimum">
<number>-1000</number>
</property>
<property name="maximum">
<number>1000</number>
</property>
<property name="value">
<number>1</number>
</property>
</widget>
</item>
<item row="16" column="0">
<widget class="QLabel" name="labelNRepeat">
<property name="text">
<string>Repeat:</string>
</property>
</widget>
</item>
<item row="15" column="1">
<widget class="QComboBox" name="comboBoxDirectSampling">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Set the direct sampling mode. If you do not know what to choose here, just set it to disabled. The&lt;span style=&quot; font-weight:600;&quot;&gt; native backend&lt;/span&gt; is recommended, when using this setting.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
<item row="17" column="0">
<widget class="QLabel" name="labelDCCorrection">
<property name="toolTip">
<string>Apply DC correction during recording, that is, ensure the captured signal has a mean value of zero.</string>
</property>
<property name="text">
<string>DC correction:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QComboBox" name="comboBoxChannel"/>
</item>
<item row="11" column="0">
<widget class="QLabel" name="labelIFGain">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The IF Gain is applied to the Intermediate Frequency signal in your Software Defined Radio. An IF signal has a lower frequency than the high frequent RF signal, so signal processing can be applied more efficiently.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>IF Gain:</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="labelChannel">
<property name="text">
<string>Channel:</string>
</property>
</widget>
</item>
<item row="8" column="2" rowspan="2">
<widget class="QToolButton" name="btnLockBWSR">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="urh.qrc">
<normaloff>:/icons/icons/lock.svg</normaloff>:/icons/icons/lock.svg</iconset>
</property>
<property name="iconSize">
<size>
<width>16</width>
<height>16</height>
</size>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Device:</string>
</property>
</widget>
</item>
<item row="14" column="0">
<widget class="QLabel" name="labelBiasTee">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Enable the bias tee of your SDR, if you have an external LNA connected. Leave this disabled if you have no external LNA attached.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Bias Tee:</string>
</property>
</widget>
</item>
<item row="14" column="1">
<widget class="QCheckBox" name="checkBoxBiasTee">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Enable the bias tee of your SDR, if you have an external LNA connected. Leave this disabled if you have no external LNA attached.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Enable Bias Tee</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>KillerDoubleSpinBox</class>
<extends>QDoubleSpinBox</extends>
<header>urh.ui.KillerDoubleSpinBox.h</header>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>groupBoxDeviceSettings</tabstop>
<tabstop>cbDevice</tabstop>
<tabstop>comboBoxDeviceIdentifier</tabstop>
<tabstop>btnRefreshDeviceIdentifier</tabstop>
<tabstop>lineEditSubdevice</tabstop>
<tabstop>comboBoxChannel</tabstop>
<tabstop>comboBoxAntenna</tabstop>
<tabstop>lineEditIP</tabstop>
<tabstop>spinBoxPort</tabstop>
<tabstop>spinBoxFreq</tabstop>
<tabstop>spinBoxSampleRate</tabstop>
<tabstop>btnLockBWSR</tabstop>
<tabstop>spinBoxBandwidth</tabstop>
<tabstop>sliderGain</tabstop>
<tabstop>spinBoxGain</tabstop>
<tabstop>sliderIFGain</tabstop>
<tabstop>spinBoxIFGain</tabstop>
<tabstop>sliderBasebandGain</tabstop>
<tabstop>spinBoxBasebandGain</tabstop>
<tabstop>spinBoxFreqCorrection</tabstop>
<tabstop>comboBoxDirectSampling</tabstop>
<tabstop>spinBoxNRepeat</tabstop>
<tabstop>checkBoxDCCorrection</tabstop>
</tabstops>
<resources>
<include location="urh.qrc"/>
</resources>
<connections>
<connection>
<sender>groupBoxDeviceSettings</sender>
<signal>toggled(bool)</signal>
<receiver>frame_2</receiver>
<slot>setVisible(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>115</x>
<y>17</y>
</hint>
<hint type="destinationlabel">
<x>140</x>
<y>31</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -1,397 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SniffSettings</class>
<widget class="QWidget" name="SniffSettings">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>482</width>
<height>510</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<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="QGroupBox" name="groupBoxSniffSettings">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="styleSheet">
<string notr="true">QGroupBox
{
border: none;
}
QGroupBox::title {
subcontrol-origin: margin;
}
QGroupBox::indicator:unchecked {
image: url(:/icons/icons/collapse.svg)
}
QGroupBox::indicator:checked {
image: url(:/icons/icons/uncollapse.svg)
}</string>
</property>
<property name="title">
<string>Sniff settings</string>
</property>
<property name="flat">
<bool>true</bool>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<property name="topMargin">
<number>15</number>
</property>
<item row="0" column="0">
<widget class="QFrame" name="frame">
<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="QGridLayout" name="gridLayout">
<item row="2" column="0">
<widget class="QLabel" name="label_sniff_Center">
<property name="text">
<string>Center:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QDoubleSpinBox" name="spinbox_sniff_Noise">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="decimals">
<number>4</number>
</property>
<property name="maximum">
<double>1.000000000000000</double>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBoxAdaptiveNoise">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;With adaptive noise URH will update the noise level automatically during RX. This is helpful in a dynamic environment where noise differs in time.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Adaptive</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_sniff_Modulation">
<property name="text">
<string>Modulation:</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_sniff_Signal">
<property name="text">
<string>Use values from:</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QSpinBox" name="spinbox_sniff_ErrorTolerance">
<property name="maximum">
<number>999999</number>
</property>
<property name="value">
<number>5</number>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QComboBox" name="combox_sniff_Modulation">
<item>
<property name="text">
<string>ASK</string>
</property>
</item>
<item>
<property name="text">
<string>FSK</string>
</property>
</item>
<item>
<property name="text">
<string>PSK</string>
</property>
</item>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_sniff_Tolerance">
<property name="text">
<string>Error Tolerance:</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QSpinBox" name="spinbox_sniff_SamplesPerSymbol">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>999999999</number>
</property>
</widget>
</item>
<item row="9" column="0">
<widget class="QLabel" name="label_sniff_viewtype">
<property name="text">
<string>View:</string>
</property>
</widget>
</item>
<item row="10" column="1">
<widget class="QLineEdit" name="lineEdit_sniff_OutputFile">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="readOnly">
<bool>false</bool>
</property>
<property name="placeholderText">
<string>None</string>
</property>
<property name="clearButtonEnabled">
<bool>true</bool>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_sniff_BitLength">
<property name="text">
<string>Samples per Symbol:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QDoubleSpinBox" name="spinBoxCenterSpacing">
<property name="decimals">
<number>4</number>
</property>
<property name="maximum">
<double>1.000000000000000</double>
</property>
</widget>
</item>
<item row="0" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QComboBox" name="comboBox_sniff_signal">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btn_sniff_use_signal">
<property name="text">
<string>Use</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="10" column="0">
<widget class="QLabel" name="label_sniff_OutputFile">
<property name="text">
<string>Write bitstream to file:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QDoubleSpinBox" name="spinbox_sniff_Center">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="decimals">
<number>4</number>
</property>
<property name="minimum">
<double>-3.140000000000000</double>
</property>
<property name="maximum">
<double>3.140000000000000</double>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBoxAutoCenter">
<property name="text">
<string>Automatic</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="8" column="0">
<widget class="QLabel" name="label_sniff_encoding">
<property name="text">
<string>Encoding:</string>
</property>
</widget>
</item>
<item row="9" column="1">
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="sizeConstraint">
<enum>QLayout::SetDefaultConstraint</enum>
</property>
<item>
<widget class="QComboBox" name="comboBox_sniff_viewtype">
<item>
<property name="text">
<string>Bit</string>
</property>
</item>
<item>
<property name="text">
<string>Hex</string>
</property>
</item>
<item>
<property name="text">
<string>ASCII</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBox_sniff_Timestamp">
<property name="text">
<string>Show Timestamp</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_sniff_Noise">
<property name="text">
<string>Noise:</string>
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QComboBox" name="comboBox_sniff_encoding">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="labelCenterSpacing">
<property name="text">
<string>Center Spacing:</string>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QLabel" name="labelBitsPerSymbol">
<property name="text">
<string>Bits per Symbol:</string>
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QSpinBox" name="spinBoxBitsPerSymbol">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>10</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<tabstops>
<tabstop>groupBoxSniffSettings</tabstop>
<tabstop>spinbox_sniff_Noise</tabstop>
<tabstop>spinbox_sniff_SamplesPerSymbol</tabstop>
<tabstop>spinbox_sniff_ErrorTolerance</tabstop>
<tabstop>combox_sniff_Modulation</tabstop>
<tabstop>comboBox_sniff_encoding</tabstop>
<tabstop>comboBox_sniff_viewtype</tabstop>
<tabstop>checkBox_sniff_Timestamp</tabstop>
<tabstop>lineEdit_sniff_OutputFile</tabstop>
</tabstops>
<resources>
<include location="urh.qrc"/>
</resources>
<connections>
<connection>
<sender>groupBoxSniffSettings</sender>
<signal>toggled(bool)</signal>
<receiver>frame</receiver>
<slot>setVisible(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>93</x>
<y>17</y>
</hint>
<hint type="destinationlabel">
<x>113</x>
<y>35</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -1,186 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SignalDetails</class>
<widget class="QDialog" name="SignalDetails">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>469</width>
<height>200</height>
</rect>
</property>
<property name="windowTitle">
<string>Signal details</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="2" column="2">
<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 row="5" column="1">
<widget class="KillerDoubleSpinBox" name="dsb_sample_rate">
<property name="wrapping">
<bool>false</bool>
</property>
<property name="showGroupSeparator" stdset="0">
<bool>false</bool>
</property>
<property name="minimum">
<double>0.010000000000000</double>
</property>
<property name="maximum">
<double>999999999999999945575230987042816.000000000000000</double>
</property>
<property name="value">
<double>1000000.000000000000000</double>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Name:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="lblFile">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>TextLabel</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>File:</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Samples:</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Sample Rate (Sps):</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QLabel" name="lblSamplesTotal">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>File size:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="lblName">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>TextLabel</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="lblFileSize">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>File created:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="lFileCreated">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Duration:</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QLabel" name="lDuration">
<property name="text">
<string>42s</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>135</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>KillerDoubleSpinBox</class>
<extends>QDoubleSpinBox</extends>
<header>urh.ui.KillerDoubleSpinBox.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

File diff suppressed because it is too large Load Diff

View File

@ -1,912 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SimulatorTab</class>
<widget class="QWidget" name="SimulatorTab">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>842</width>
<height>689</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_8">
<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="QScrollArea" name="scrollArea">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>842</width>
<height>689</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
<widget class="QSplitter" name="splitterLeftRight">
<property name="styleSheet">
<string notr="true">QSplitter::handle:horizontal {
margin: 4px 0px;
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,
stop:0 rgba(255, 255, 255, 0),
stop:0.5 rgba(100, 100, 100, 100),
stop:1 rgba(255, 255, 255, 0));
image: url(:/icons/icons/splitter_handle_vertical.svg);
}</string>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="handleWidth">
<number>6</number>
</property>
<widget class="QWidget" name="layoutWidget">
<layout class="QVBoxLayout" name="verticalLayout_3">
<property name="leftMargin">
<number>11</number>
</property>
<property name="topMargin">
<number>11</number>
</property>
<property name="rightMargin">
<number>11</number>
</property>
<property name="bottomMargin">
<number>11</number>
</property>
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Protocols (Drag&amp;Drop to Flow Graph):</string>
</property>
</widget>
</item>
<item>
<widget class="GeneratorTreeView" name="treeProtocols"/>
</item>
<item>
<widget class="QLabel" name="label_6">
<property name="text">
<string>Simulate these participants:</string>
</property>
</widget>
</item>
<item>
<widget class="QListView" name="listViewSimulate">
<property name="alternatingRowColors">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Repeat simulation this often:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QSpinBox" name="spinBoxNRepeat">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="specialValueText">
<string>Infinite</string>
</property>
<property name="maximum">
<number>9999999</number>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Timeout:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSpinBox" name="spinBoxTimeout">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="suffix">
<string>ms</string>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>9999999</number>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>In case of an overdue response:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="comboBoxError">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item>
<property name="text">
<string>Resend last message</string>
</property>
</item>
<item>
<property name="text">
<string>Stop simulation</string>
</property>
</item>
<item>
<property name="text">
<string>Restart simulation</string>
</property>
</item>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Maximum retries:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QSpinBox" name="spinBoxRetries">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>9999999</number>
</property>
<property name="value">
<number>10</number>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QPushButton" name="btnStartSim">
<property name="text">
<string>Simulate...</string>
</property>
<property name="icon">
<iconset theme="media-playback-start">
<normaloff>.</normaloff>.</iconset>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QSplitter" name="splitter">
<property name="styleSheet">
<string notr="true">QSplitter::handle:vertical {
margin: 4px 0px;
background-color: qlineargradient(x1:0, y1:0, x2:1, y2:0,
stop:0 rgba(255, 255, 255, 0),
stop:0.5 rgba(100, 100, 100, 100),
stop:1 rgba(255, 255, 255, 0));
image: url(:/icons/icons/splitter_handle_horizontal.svg);
}</string>
</property>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="handleWidth">
<number>6</number>
</property>
<widget class="QWidget" name="layoutWidget_2">
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="leftMargin">
<number>11</number>
</property>
<property name="topMargin">
<number>11</number>
</property>
<property name="rightMargin">
<number>11</number>
</property>
<property name="bottomMargin">
<number>11</number>
</property>
<item>
<widget class="QTabWidget" name="tabWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="styleSheet">
<string notr="true">QTabWidget::pane { border: 0; }</string>
</property>
<property name="tabPosition">
<enum>QTabWidget::North</enum>
</property>
<property name="tabShape">
<enum>QTabWidget::Rounded</enum>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="tab">
<attribute name="title">
<string>Flow Graph</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>7</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="SimulatorGraphicsView" name="gvSimulator">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_2">
<attribute name="title">
<string>Messages</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_6">
<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="SimulatorMessageTableView" name="tblViewMessage">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<property name="verticalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
<property name="horizontalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
<property name="showGrid">
<bool>false</bool>
</property>
<attribute name="horizontalHeaderHighlightSections">
<bool>false</bool>
</attribute>
<attribute name="verticalHeaderHighlightSections">
<bool>false</bool>
</attribute>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLabel" name="lNumSelectedColumns">
<property name="text">
<string>0</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lColumnsSelectedText">
<property name="text">
<string>column(s) selected</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>138</width>
<height>33</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label_5">
<property name="text">
<string>Viewtype:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="cbViewType">
<item>
<property name="text">
<string>Bit</string>
</property>
</item>
<item>
<property name="text">
<string>Hex</string>
</property>
</item>
<item>
<property name="text">
<string>ASCII</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QWidget" name="tabParticipants">
<attribute name="title">
<string>Participants</string>
</attribute>
<layout class="QHBoxLayout" name="horizontalLayout">
<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="ParticipantTableView" name="tableViewParticipants"/>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_9">
<item>
<widget class="QToolButton" name="btnAddParticipant">
<property name="toolTip">
<string>Add participant</string>
</property>
<property name="text">
<string>Add</string>
</property>
<property name="icon">
<iconset theme="list-add">
<normaloff>.</normaloff>.</iconset>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="btnRemoveParticipant">
<property name="toolTip">
<string>Remove participant</string>
</property>
<property name="text">
<string>Remove</string>
</property>
<property name="icon">
<iconset theme="list-remove">
<normaloff>.</normaloff>.</iconset>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="btnUp">
<property name="toolTip">
<string>Move selected participants up</string>
</property>
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset theme="go-up">
<normaloff>../../../../</normaloff>../../../../</iconset>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="btnDown">
<property name="toolTip">
<string>Move selected participants down</string>
</property>
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset theme="go-down">
<normaloff>../../../../</normaloff>../../../../</iconset>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="layoutWidget_3">
<layout class="QVBoxLayout" name="verticalLayout_4">
<property name="leftMargin">
<number>11</number>
</property>
<property name="topMargin">
<number>11</number>
</property>
<property name="rightMargin">
<number>11</number>
</property>
<property name="bottomMargin">
<number>11</number>
</property>
<item>
<widget class="QLabel" name="lblMsgFieldsValues">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Detail view for item</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QStackedWidget" name="detail_view_widget">
<property name="currentIndex">
<number>2</number>
</property>
<widget class="QWidget" name="page_empty"/>
<widget class="QWidget" name="page_goto_action">
<layout class="QGridLayout" name="verticalLayout_7">
<item row="0" column="0">
<widget class="QLabel" name="label_9">
<property name="text">
<string>Goto:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="goto_combobox"/>
</item>
<item row="0" column="2">
<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 row="1" column="0" colspan="3">
<spacer name="verticalSpacer_4">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<widget class="QWidget" name="page_message">
<layout class="QGridLayout" name="gridLayout_6">
<item row="1" column="0">
<widget class="QLabel" name="label_10">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Copies:</string>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="SimulatorLabelTableView" name="tblViewFieldValues">
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<property name="showGrid">
<bool>false</bool>
</property>
<attribute name="horizontalHeaderDefaultSectionSize">
<number>150</number>
</attribute>
<attribute name="horizontalHeaderStretchLastSection">
<bool>true</bool>
</attribute>
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_11">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Labels:</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QSpinBox" name="spinBoxRepeat">
<property name="minimum">
<number>1</number>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Coding:</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLabel" name="lblEncodingDecoding">
<property name="text">
<string>-</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="page_rule">
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="0">
<widget class="QLabel" name="label_12">
<property name="text">
<string>Condition:</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<spacer name="verticalSpacer_5">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="1">
<widget class="ExpressionLineEdit" name="ruleCondLineEdit">
<property name="placeholderText">
<string>not (item1.crc == 0b1010 and item2.length &gt;=3)</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="page_ext_prog_action">
<layout class="QGridLayout" name="gridLayout_9">
<item row="2" column="0" colspan="4">
<widget class="QCheckBox" name="checkBoxPassTranscriptSTDIN">
<property name="text">
<string>Pass transcript to STDIN</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_14">
<property name="text">
<string>Command:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="lineEditTriggerCommand">
<property name="readOnly">
<bool>false</bool>
</property>
<property name="placeholderText">
<string>Path [+arguments] to external command e.g. mail or sendsms</string>
</property>
</widget>
</item>
<item row="1" column="2" colspan="2">
<widget class="QToolButton" name="btnChooseCommand">
<property name="text">
<string>...</string>
</property>
</widget>
</item>
<item row="4" column="0" colspan="4">
<spacer name="verticalSpacer_6">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="3" column="0" colspan="4">
<widget class="QLabel" name="label_18">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;You can access the return code of this item in formulas and rules using the item identifier followed by &lt;span style=&quot; font-style:italic;&quot;&gt;.rc&lt;/span&gt; e.g.&lt;span style=&quot; font-style:italic;&quot;&gt; item5.rc&lt;/span&gt;.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="page_sleep">
<layout class="QVBoxLayout" name="verticalLayout_10">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="label_13">
<property name="text">
<string>Sleep for:</string>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="doubleSpinBoxSleep">
<property name="suffix">
<string>s</string>
</property>
<property name="decimals">
<number>6</number>
</property>
<property name="maximum">
<double>10000.000000000000000</double>
</property>
<property name="value">
<double>1.000000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>231</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<widget class="QWidget" name="page">
<layout class="QVBoxLayout" name="verticalLayout_11">
<item>
<layout class="QGridLayout" name="gridLayout_2">
<item row="2" column="1">
<widget class="QSpinBox" name="spinBoxCounterStep">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>999999</number>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_15">
<property name="text">
<string>Start:</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_16">
<property name="text">
<string>Step:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSpinBox" name="spinBoxCounterStart">
<property name="maximum">
<number>999999</number>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="label_17">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;This counter will increase by &lt;span style=&quot; font-weight:600;&quot;&gt;step&lt;/span&gt; each time it gets hit during simulation. It will preserve it's value during simulation repeats and retries. To reset all counters stop the simulation and start it again.&lt;/p&gt;&lt;p&gt;Access the value of this counter using item&amp;lt;Number&amp;gt;.counter_value in &lt;span style=&quot; font-weight:600;&quot;&gt;Formulas&lt;/span&gt; or as parameter in &lt;span style=&quot; font-weight:600;&quot;&gt;external programs&lt;/span&gt; e.g. &lt;span style=&quot; font-style:italic;&quot;&gt;external_py -c item5.counter_value&lt;/span&gt;. The value of this counter will be inserted during simulation time.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>36</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
</widget>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>ParticipantTableView</class>
<extends>QTableView</extends>
<header>urh.ui.views.ParticipantTableView.h</header>
</customwidget>
<customwidget>
<class>GeneratorTreeView</class>
<extends>QTreeView</extends>
<header>urh.ui.views.GeneratorTreeView.h</header>
</customwidget>
<customwidget>
<class>SimulatorGraphicsView</class>
<extends>QGraphicsView</extends>
<header>urh.ui.views.SimulatorGraphicsView.h</header>
</customwidget>
<customwidget>
<class>SimulatorMessageTableView</class>
<extends>QTableView</extends>
<header>urh.ui.views.SimulatorMessageTableView.h</header>
</customwidget>
<customwidget>
<class>ExpressionLineEdit</class>
<extends>QLineEdit</extends>
<header>urh.ui.ExpressionLineEdit.h</header>
</customwidget>
<customwidget>
<class>SimulatorLabelTableView</class>
<extends>QTableView</extends>
<header>urh.ui.views.SimulatorLabelTableView.h</header>
</customwidget>
</customwidgets>
<resources>
<include location="urh.qrc"/>
</resources>
<connections/>
</ui>

View File

@ -1,603 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>DialogSimulator</class>
<widget class="QDialog" name="DialogSimulator">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1088</width>
<height>823</height>
</rect>
</property>
<property name="windowTitle">
<string>Simulation</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QTabWidget" name="tabWidgetSimulatorSettings">
<property name="styleSheet">
<string notr="true">QTabWidget::pane { border: 0; }</string>
</property>
<property name="currentIndex">
<number>3</number>
</property>
<widget class="QWidget" name="tabLog">
<attribute name="title">
<string>Log settings</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_3">
<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="LoggingGraphicsView" name="gvSimulator">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="btnLogAll">
<property name="text">
<string>Log all</string>
</property>
<property name="autoDefault">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnLogNone">
<property name="text">
<string>Log none</string>
</property>
<property name="autoDefault">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnToggleLog">
<property name="text">
<string>Toggle selected</string>
</property>
<property name="autoDefault">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QWidget" name="tabRX">
<attribute name="title">
<string>RX settings</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_5">
<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="QScrollArea" name="scrollAreaRX">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContentsRX">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1066</width>
<height>766</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_6">
<item>
<widget class="QPushButton" name="btnTestSniffSettings">
<property name="text">
<string>Test sniffer settings</string>
</property>
<property name="icon">
<iconset resource="urh.qrc">
<normaloff>:/icons/icons/sniffer.svg</normaloff>:/icons/icons/sniffer.svg</iconset>
</property>
<property name="autoDefault">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tabTX">
<attribute name="title">
<string>TX settings</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_7">
<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="QScrollArea" name="scrollAreaTX">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContentsTX">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1066</width>
<height>766</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_8">
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tabSimulation">
<attribute name="title">
<string>Simulation</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_9">
<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="QTabWidget" name="tabWidget">
<property name="styleSheet">
<string notr="true">QTabWidget::pane { border: 0; }</string>
</property>
<property name="tabPosition">
<enum>QTabWidget::West</enum>
</property>
<property name="tabShape">
<enum>QTabWidget::Triangular</enum>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="tab_simulation">
<attribute name="title">
<string>Status</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_15">
<item>
<widget class="QGroupBox" name="groupBoxSimulationStatus">
<property name="styleSheet">
<string notr="true">QGroupBox
{
border: none;
}
QGroupBox::title {
subcontrol-origin: margin;
}
QGroupBox::indicator:unchecked {
image: url(:/icons/icons/collapse.svg)
}
QGroupBox::indicator:checked {
image: url(:/icons/icons/uncollapse.svg)
}</string>
</property>
<property name="title">
<string>Simulation Status</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout_12">
<property name="topMargin">
<number>15</number>
</property>
<item>
<widget class="QFrame" name="frame">
<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="QVBoxLayout" name="verticalLayout_11">
<item>
<widget class="QTextEdit" name="textEditSimulation">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Current iteration:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lblCurrentRepeatValue">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>0</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Current item:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lblCurrentItemValue">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>0</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="btnSaveLog">
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset theme="document-save">
<normaloff>.</normaloff>.</iconset>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBoxRXStatus">
<property name="styleSheet">
<string notr="true">QGroupBox
{
border: none;
}
QGroupBox::title {
subcontrol-origin: margin;
}
QGroupBox::indicator:unchecked {
image: url(:/icons/icons/collapse.svg)
}
QGroupBox::indicator:checked {
image: url(:/icons/icons/uncollapse.svg)
}</string>
</property>
<property name="title">
<string>RX Status</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout_14">
<property name="topMargin">
<number>15</number>
</property>
<item>
<widget class="QFrame" name="frame_2">
<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="QVBoxLayout" name="verticalLayout_13">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<widget class="QCheckBox" name="checkBoxCaptureFullRX">
<property name="text">
<string>Capture complete RX</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<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="QToolButton" name="btnSaveRX">
<property name="toolTip">
<string>Save current capture</string>
</property>
<property name="text">
<string>Save</string>
</property>
<property name="icon">
<iconset theme="document-save">
<normaloff>.</normaloff>.</iconset>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="LiveGraphicView" name="graphicsViewPreview"/>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab">
<attribute name="title">
<string>Messages</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTextEdit" name="textEditTranscript">
<property name="readOnly">
<bool>true</bool>
</property>
<property name="placeholderText">
<string>Here you will find all messages that were sent and received during simulation.</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QRadioButton" name="radioButtonTranscriptBit">
<property name="text">
<string>Bit &amp;view</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="radioButtonTranscriptHex">
<property name="text">
<string>Hex view</string>
</property>
</widget>
</item>
<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="btnOpenInAnalysis">
<property name="text">
<string>Open in Analysis</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="btnSaveTranscript">
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset theme="document-save">
<normaloff>.</normaloff>.</iconset>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_device">
<attribute name="title">
<string>Devices</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_10">
<item>
<widget class="QTextEdit" name="textEditDevices">
<property name="readOnly">
<bool>true</bool>
</property>
<property name="placeholderText">
<string>After simulation start you will see the log messages of your configured SDRs here.</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnStartStop">
<property name="text">
<string>Start</string>
</property>
<property name="icon">
<iconset theme="media-playback-start">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="default">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>LiveGraphicView</class>
<extends>QGraphicsView</extends>
<header>urh.ui.views.LiveGraphicView.h</header>
</customwidget>
<customwidget>
<class>LoggingGraphicsView</class>
<extends>QGraphicsView</extends>
<header>urh.ui.views.LoggingGraphicsView.h</header>
</customwidget>
</customwidgets>
<resources>
<include location="urh.qrc"/>
</resources>
<connections>
<connection>
<sender>groupBoxSimulationStatus</sender>
<signal>toggled(bool)</signal>
<receiver>frame</receiver>
<slot>setVisible(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>167</x>
<y>99</y>
</hint>
<hint type="destinationlabel">
<x>164</x>
<y>108</y>
</hint>
</hints>
</connection>
<connection>
<sender>groupBoxRXStatus</sender>
<signal>toggled(bool)</signal>
<receiver>frame_2</receiver>
<slot>setVisible(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>616</x>
<y>478</y>
</hint>
<hint type="destinationlabel">
<x>629</x>
<y>544</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -1,145 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Interpretation</class>
<widget class="QWidget" name="Interpretation">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>631</width>
<height>561</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<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="ScrollArea" name="scrollArea">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="acceptDrops">
<bool>true</bool>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
<property name="verticalScrollBarPolicy">
<enum>Qt::ScrollBarAsNeeded</enum>
</property>
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrlAreaSignals">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>631</width>
<height>561</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="autoFillBackground">
<bool>true</bool>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QSplitter" name="splitter">
<property name="styleSheet">
<string notr="true">QSplitter::handle:vertical {
margin: 4px 0px;
background-color: qlineargradient(x1:0, y1:0, x2:1, y2:0,
stop:0 rgba(255, 255, 255, 0),
stop:0.5 rgba(100, 100, 100, 100),
stop:1 rgba(255, 255, 255, 0));
image: url(:/icons/icons/splitter_handle_horizontal.svg);
}</string>
</property>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="handleWidth">
<number>6</number>
</property>
<widget class="QLabel" name="labelGettingStarted">
<property name="font">
<font>
<pointsize>32</pointsize>
</font>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Open a file or record a new signal using the &lt;b&gt;File menu&lt;/b&gt; to get started.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::NoTextInteraction</set>
</property>
</widget>
<widget class="QLabel" name="placeholderLabel">
<property name="text">
<string/>
</property>
</widget>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>ScrollArea</class>
<extends>QScrollArea</extends>
<header>urh.ui.ScrollArea.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources>
<include location="urh.qrc"/>
</resources>
<connections/>
</ui>

View File

@ -1,20 +0,0 @@
<RCC>
<qresource prefix="icons">
<file>../icons/appicon.ico</file>
<file>../icons/decoding.svg</file>
<file>../icons/equals_qm.svg</file>
<file>../icons/appicon.png</file>
<file>../icons/collapse.svg</file>
<file>../icons/uncollapse.svg</file>
<file>../icons/equals.svg</file>
<file>../icons/lock.svg</file>
<file>../icons/modulation.svg</file>
<file>../icons/plus.svg</file>
<file>../icons/sniffer.svg</file>
<file>../icons/spectrum.svg</file>
<file>../icons/splitter_handle_horizontal.svg</file>
<file>../icons/splitter_handle_vertical.svg</file>
<file>../icons/unlock.svg</file>
<file>../icons/message_type.svg</file>
</qresource>
</RCC>

View File

@ -1,8 +0,0 @@
[Desktop Entry]
Type=Application
Name=Universal Radio Hacker
Comment=investigate wireless protocols like a boss
Exec=/usr/bin/urh
Icon=urh
Terminal=false
Categories=HamRadio

View File

@ -1,146 +0,0 @@
import os
import sys
import tempfile
if sys.version_info < (3, 4):
print("You need at least Python 3.4 for this application!")
if sys.version_info[0] < 3:
print("try running with python3 {}".format(" ".join(sys.argv)))
sys.exit(1)
try:
from setuptools import setup, Extension
from setuptools.command.build_ext import build_ext as _build_ext
except ImportError:
print("Could not find setuptools")
print("Try installing them with pip install setuptools")
sys.exit(1)
from src.urh.dev.native import ExtensionHelper
from src.urh.dev.native.ExtensionHelper import COMPILER_DIRECTIVES
import src.urh.version as version
if sys.platform == "win32":
OPEN_MP_FLAG = "/openmp"
NO_NUMPY_WARNINGS_FLAG = ""
elif sys.platform == "darwin":
OPEN_MP_FLAG = "" # no OpenMP support in default Mac OSX compiler
NO_NUMPY_WARNINGS_FLAG = "-Wno-#warnings"
else:
OPEN_MP_FLAG = "-fopenmp"
NO_NUMPY_WARNINGS_FLAG = "-Wno-cpp"
UI_SUBDIRS = ("actions", "delegates", "views")
PLUGINS = [path for path in os.listdir("src/urh/plugins") if os.path.isdir(os.path.join("src/urh/plugins", path))]
URH_DIR = "urh"
IS_RELEASE = os.path.isfile(os.path.join(tempfile.gettempdir(), "urh_releasing"))
try:
from Cython.Build import cythonize
except ImportError:
print("You need Cython to build URH's extensions!\n"
"You can get it e.g. with python3 -m pip install cython.",
file=sys.stderr)
sys.exit(1)
class build_ext(_build_ext):
def finalize_options(self):
print("Finalizing options")
_build_ext.finalize_options(self)
# Prevent numpy from thinking it is still in its setup process:
__builtins__.__NUMPY_SETUP__ = False
import numpy
self.include_dirs.append(numpy.get_include())
def get_packages():
packages = [URH_DIR]
separator = os.path.normpath("/")
for dirpath, dirnames, filenames in os.walk(os.path.join("./src/", URH_DIR)):
package_path = os.path.relpath(dirpath, os.path.join("./src/", URH_DIR)).replace(separator, ".")
if len(package_path) > 1:
packages.append(URH_DIR + "." + package_path)
return packages
def get_package_data():
package_data = {"urh.cythonext": ["*.pyx", "*.pxd"]}
for plugin in PLUGINS:
package_data["urh.plugins." + plugin] = ['*.ui', "*.txt"]
package_data["urh.dev.native.lib"] = ["*.pyx", "*.pxd"]
if IS_RELEASE and sys.platform == "win32":
package_data["urh.dev.native.lib.shared"] = ["*.dll", "*.txt"]
return package_data
def get_extensions():
filenames = [os.path.splitext(f)[0] for f in os.listdir("src/urh/cythonext") if f.endswith(".pyx")]
extensions = [Extension("urh.cythonext." + f, ["src/urh/cythonext/" + f + ".pyx"],
extra_compile_args=[OPEN_MP_FLAG],
extra_link_args=[OPEN_MP_FLAG],
language="c++") for f in filenames]
ExtensionHelper.USE_RELATIVE_PATHS = True
device_extensions, device_extras = ExtensionHelper.get_device_extensions_and_extras()
extensions += device_extensions
if NO_NUMPY_WARNINGS_FLAG:
for extension in extensions:
extension.extra_compile_args.append(NO_NUMPY_WARNINGS_FLAG)
extensions = cythonize(extensions, compiler_directives=COMPILER_DIRECTIVES, compile_time_env=device_extras)
return extensions
def read_long_description():
try:
with open("README.md") as f:
text = f.read()
return text
except:
return ""
install_requires = ["numpy", "psutil", "cython"]
if IS_RELEASE:
install_requires.append("pyqt5")
else:
try:
import PyQt5
except ImportError:
install_requires.append("pyqt5")
if sys.version_info < (3, 4):
install_requires.append('enum34')
setup(
name="urh",
version=version.VERSION,
description="Universal Radio Hacker: investigate wireless protocols like a boss",
long_description=read_long_description(),
long_description_content_type="text/markdown",
author="Johannes Pohl",
author_email="Johannes.Pohl90@gmail.com",
package_dir={"": "src"},
package_data=get_package_data(),
url="https://github.com/jopohl/urh",
license="GNU General Public License (GPL)",
download_url="https://github.com/jopohl/urh/tarball/v" + str(version.VERSION),
install_requires=install_requires,
setup_requires=['numpy'],
packages=get_packages(),
ext_modules=get_extensions(),
cmdclass={'build_ext': build_ext},
zip_safe=False,
entry_points={
'console_scripts': [
'urh = urh.main:main',
'urh_cli = urh.cli.urh_cli:main',
]}
)

View File

@ -1,434 +0,0 @@
import fractions
import itertools
import math
import sys
from collections import Counter
import numpy as np
from urh.ainterpretation import Wavelet
from urh.cythonext import auto_interpretation as c_auto_interpretation
from urh.cythonext import signal_functions
from urh.cythonext import util
from urh.signalprocessing.IQArray import IQArray
def max_without_outliers(data: np.ndarray, z=3):
if len(data) == 0:
return None
return np.max(data[abs(data - np.mean(data)) <= z * np.std(data)])
def min_without_outliers(data: np.ndarray, z=2):
if len(data) == 0:
return None
return np.min(data[abs(data - np.mean(data)) <= z * np.std(data)])
def get_most_frequent_value(values: list):
"""
Return the most frequent value in list.
If there is no unique one, return the maximum of the most frequent values
:param values:
:return:
"""
if len(values) == 0:
return None
most_common = Counter(values).most_common()
result, max_count = most_common[0]
for value, count in most_common:
if count < max_count:
return result
else:
result = value
return result
def most_common(values: list):
"""
Return the most common value in a list. In case of ties, return the value that appears first in list
:param values:
:return:
"""
counter = Counter(values)
return max(values, key=counter.get)
def detect_noise_level(magnitudes):
if len(magnitudes) <= 3:
return 0
# 1% for best accuracy and performance for large signals
chunksize_percent = 1
chunksize = max(1, int(len(magnitudes) * chunksize_percent / 100))
chunks = [magnitudes[i - chunksize:i] for i in range(len(magnitudes), 0, -chunksize) if i - chunksize >= 0]
mean_values = np.fromiter((np.mean(chunk) for chunk in chunks), dtype=np.float32, count=len(chunks))
minimum, maximum = util.minmax(mean_values)
if maximum == 0 or minimum / maximum > 0.9:
# Mean values are very close to each other, so there is probably no noise in the signal
return 0
# Get all indices for values which are in range of 10% of minimum mean value
indices = np.nonzero(mean_values <= 1.1 * np.min(mean_values))[0]
try:
result = np.max([np.max(chunks[i]) for i in indices if len(chunks[i]) > 0])
except ValueError:
return 0
# Round up to fourth digit
return math.ceil(result * 10000) / 10000
def segment_messages_from_magnitudes(magnitudes: np.ndarray, noise_threshold: float):
"""
Get the list of start, end indices of messages
:param magnitudes: Magnitudes of samples
:param noise_threshold: Threshold for noise
:return:
"""
return c_auto_interpretation.segment_messages_from_magnitudes(magnitudes, noise_threshold)
def merge_message_segments_for_ook(segments: list):
if len(segments) <= 1:
return segments
result = []
# Get a array of pauses for comparison
pauses = np.fromiter(
(segments[i + 1][0] - segments[i][1] for i in range(len(segments) - 1)),
count=len(segments) - 1,
dtype=np.uint64
)
pulses = np.fromiter(
(segments[i][1] - segments[i][0] for i in range(len(segments))),
count=len(segments),
dtype=np.uint64
)
# Find relatively large pauses, these mark new messages
min_pulse_length = min_without_outliers(pulses, z=1)
large_pause_indices = np.nonzero(pauses >= 8 * min_pulse_length)[0]
# Merge Pulse Lengths between long pauses
for i in range(0, len(large_pause_indices) + 1):
if i == 0:
start, end = 0, large_pause_indices[i] + 1 if len(large_pause_indices) >= 1 else len(segments)
elif i == len(large_pause_indices):
start, end = large_pause_indices[i - 1] + 1, len(segments)
else:
start, end = large_pause_indices[i - 1] + 1, large_pause_indices[i] + 1
msg_begin = segments[start][0]
msg_length = sum(segments[j][1] - segments[j][0] for j in range(start, end))
msg_length += sum(segments[j][0] - segments[j - 1][1] for j in range(start + 1, end))
result.append((msg_begin, msg_begin + msg_length))
return result
def detect_modulation(data: np.ndarray, wavelet_scale=4, median_filter_order=11) -> str:
n_data = len(data)
data = data[np.abs(data) > 0]
if len(data) == 0:
return None
if n_data - len(data) > 3:
return "OOK"
data = data / np.abs(np.max(data))
mag_wavlt = np.abs(Wavelet.cwt_haar(data, scale=wavelet_scale))
if len(mag_wavlt) == 0:
return None
norm_mag_wavlt = np.abs(Wavelet.cwt_haar(data / np.abs(data), scale=wavelet_scale))
var_mag = np.var(mag_wavlt)
var_norm_mag = np.var(norm_mag_wavlt)
var_filtered_mag = np.var(c_auto_interpretation.median_filter(mag_wavlt, k=median_filter_order))
var_filtered_norm_mag = np.var(c_auto_interpretation.median_filter(norm_mag_wavlt, k=median_filter_order))
if all(v < 0.15 for v in (var_mag, var_norm_mag, var_filtered_mag, var_filtered_norm_mag)):
return "OOK"
if var_mag > 1.5 * var_norm_mag:
# ASK or QAM
# todo: consider qam, compare filtered mag and filtered norm mag
return "ASK"
else:
# FSK or PSK
if var_mag > 10 * var_filtered_mag:
return "PSK"
else:
# Now we either have a FSK signal or we a have OOK single pulse
# If we have an FSK, there should be at least two peaks in FFT
fft = np.fft.fft(data[0:2 ** int(np.log2(len(data)))])
fft = np.abs(np.fft.fftshift(fft))
ten_greatest_indices = np.argsort(fft)[::-1][0:10]
greatest_index = ten_greatest_indices[0]
min_distance = 10
min_freq = 100 # 100 seems to be magnitude of noise frequency
if any(abs(i - greatest_index) >= min_distance and fft[i] >= min_freq for i in ten_greatest_indices):
return "FSK"
else:
return "OOK"
def detect_modulation_for_messages(signal: IQArray, message_indices: list) -> str:
max_messages = 100
modulations_for_messages = []
complex = signal.as_complex64()
for start, end in message_indices[0:max_messages]:
mod = detect_modulation(complex[start:end])
if mod is not None:
modulations_for_messages.append(mod)
if len(modulations_for_messages) == 0:
return None
return most_common(modulations_for_messages)
def detect_center(rectangular_signal: np.ndarray, max_size=None):
rect = rectangular_signal[rectangular_signal > -4] # do not consider noise
# Ignore the first and last 5% of samples,
# because there tends to be an overshoot at start/end of rectangular signal
rect = rect[int(0.05*len(rect)):int(0.95*len(rect))]
if max_size is not None and len(rect) > max_size:
rect = rect[0:max_size]
hist_min, hist_max = util.minmax(rect)
# The step size of histogram is set to variance of the rectangular signal
# If a signal has low variance we need to be more accurate at center detection
hist_step = float(np.var(rect))
try:
y, x = np.histogram(rect, bins=np.arange(hist_min, hist_max + hist_step, hist_step))
except (ZeroDivisionError, ValueError):
# For a segment with zero variance (constant line) it is not possible to find a center
return None
num_values = 2
most_common_levels = []
window_size = max(2, int(0.05*len(y)) + 1)
def get_elem(arr, index: int, default):
if 0 <= index < len(arr):
return arr[index]
else:
return default
for index in np.argsort(y)[::-1]:
# check if we have a local maximum in histogram, if yes, append the value
if all(y[index] > get_elem(y, index+i, 0) and
y[index] > get_elem(y, index-i, 0)
for i in range(1, window_size)):
most_common_levels.append(x[index])
if len(most_common_levels) == num_values:
break
if len(most_common_levels) == 0:
return None
# todo if num values greater two return more centers
return np.mean(most_common_levels)
def estimate_tolerance_from_plateau_lengths(plateau_lengths, relative_max=0.05) -> int:
if len(plateau_lengths) <= 1:
return None
unique = np.unique(plateau_lengths)
maximum = max_without_outliers(unique, z=2)
limit = relative_max * maximum
# limit = np.mean(plateau_lengths) - 1 * np.std(plateau_lengths)
if unique[0] > 1 and unique[0] >= limit:
return 0
result = 0
for value in unique:
if value > 1 and value >= limit:
break
result = value
return result
def merge_plateau_lengths(plateau_lengths, tolerance=None) -> list:
if tolerance is None:
tolerance = estimate_tolerance_from_plateau_lengths(plateau_lengths)
if tolerance == 0 or tolerance is None:
return plateau_lengths
return c_auto_interpretation.merge_plateaus(plateau_lengths, tolerance, max_count=10000)
def round_plateau_lengths(plateau_lengths: list):
"""
Round plateau lengths to next divisible number of digit count e.g. 99 -> 100, 293 -> 300
:param plateau_lengths:
:return:
"""
# round to n_digits of most common value
digit_counts = [len(str(p)) for p in plateau_lengths]
n_digits = min(3, int(np.percentile(digit_counts, 50)))
f = 10 ** (n_digits - 1)
for i, plateau_len in enumerate(plateau_lengths):
plateau_lengths[i] = int(round(plateau_len / f)) * f
def get_tolerant_greatest_common_divisor(numbers):
"""
Get the greatest common divisor of the numbers in a tolerant manner:
Calculate each gcd of each pair of numbers and return the most common one
"""
gcd = math.gcd if sys.version_info >= (3, 5) else fractions.gcd
gcds = [gcd(x, y) for x, y in itertools.combinations(numbers, 2) if gcd(x, y) != 1]
if len(gcds) == 0:
return 1
return get_most_frequent_value(gcds)
def get_bit_length_from_plateau_lengths(merged_plateau_lengths) -> int:
if len(merged_plateau_lengths) == 0:
return 0
if len(merged_plateau_lengths) == 1:
return int(merged_plateau_lengths[0])
round_plateau_lengths(merged_plateau_lengths)
histogram = c_auto_interpretation.get_threshold_divisor_histogram(merged_plateau_lengths)
if len(histogram) == 0:
return 0
else:
# Can't return simply argmax, since this could be a multiple of result (e.g. 2 1s are transmitted often)
sorted_indices = np.argsort(histogram)[::-1]
max_count = histogram[sorted_indices[0]]
result = sorted_indices[0]
for i in range(1, len(sorted_indices)):
if histogram[sorted_indices[i]] < 0.25 * max_count:
break
if sorted_indices[i] <= 0.5 * result:
result = sorted_indices[i]
return int(result)
def estimate(iq_array: IQArray, noise: float = None, modulation: str = None) -> dict:
if isinstance(iq_array, np.ndarray):
iq_array = IQArray(iq_array)
magnitudes = iq_array.magnitudes
# find noise threshold
noise = detect_noise_level(magnitudes) if noise is None else noise
# segment messages
message_indices = segment_messages_from_magnitudes(magnitudes, noise_threshold=noise)
# detect modulation
modulation = detect_modulation_for_messages(iq_array, message_indices) if modulation is None else modulation
if modulation is None:
return None
if modulation == "OOK":
message_indices = merge_message_segments_for_ook(message_indices)
if modulation == "OOK" or modulation == "ASK":
data = signal_functions.afp_demod(iq_array.data, noise, "ASK", 2)
elif modulation == "FSK":
data = signal_functions.afp_demod(iq_array.data, noise, "FSK", 2)
elif modulation == "PSK":
data = signal_functions.afp_demod(iq_array.data, noise, "PSK", 2)
else:
raise ValueError("Unsupported Modulation")
centers = []
bit_lengths = []
tolerances = []
for start, end in message_indices:
msg_rect_data = data[start:end]
center = detect_center(msg_rect_data)
if center is None:
continue
plateau_lengths = c_auto_interpretation.get_plateau_lengths(msg_rect_data, center, percentage=25)
tolerance = estimate_tolerance_from_plateau_lengths(plateau_lengths)
if tolerance is None:
tolerance = 0
else:
tolerances.append(tolerance)
merged_lengths = merge_plateau_lengths(plateau_lengths, tolerance=tolerance)
if len(merged_lengths) < 2:
continue
bit_length = get_bit_length_from_plateau_lengths(merged_lengths)
min_bit_length = tolerance + 1
if bit_length > min_bit_length:
# only add to score if found bit length surpasses minimum bit length
centers.append(center)
bit_lengths.append(bit_length)
# Since we cannot have different centers per message (yet) we need to combine them to return a common center
if modulation == "OOK" or modulation == "ASK":
# for ask modulations the center tends to be the minimum of all found centers
center = min_without_outliers(np.array(centers), z=2)
if center is None:
# did not find any centers at all so we cannot return a valid estimation
return None
elif len(centers) > 0:
# for other modulations it is a better strategy to take the mean of found centers
center = np.mean(centers)
else:
# did not find any centers at all so we cannot return a valid estimation
return None
bit_length = get_most_frequent_value(bit_lengths)
if bit_length is None:
return None
try:
tolerance = np.percentile(tolerances, 50)
except IndexError:
# no tolerances found, default to 5% of bit length
tolerance = max(1, int(0.05 * bit_length))
result = {
"modulation_type": "ASK" if modulation == "OOK" else modulation,
"bit_length": bit_length,
"center": center,
"tolerance": int(tolerance),
"noise": noise
}
return result

View File

@ -1,134 +0,0 @@
import numpy as np
from urh.cythonext import auto_interpretation as cy_auto_interpretation
from urh.signalprocessing.Modulator import Modulator
def normalized_haar_wavelet(omega, scale):
omega_cpy = omega[:] / scale
omega_cpy[0] = 1.0 # first element always zero, so prevent division by zero later
result = (1j * np.square(-1 + np.exp(0.5j * omega))) / omega_cpy
return result
def cwt_haar(x: np.ndarray, scale=10):
"""
continuous haar wavelet transform based on the paper
"A practical guide to wavelet analysis" by Christopher Torrence and Gilbert P Compo
"""
next_power_two = 2 ** int(np.log2(len(x)))
x = x[0:next_power_two]
num_data = len(x)
# get FFT of x (eq. (3) in paper)
x_hat = np.fft.fft(x)
# Get omega (eq. (5) in paper)
f = (2.0 * np.pi / num_data)
omega = f * np.concatenate((np.arange(0, num_data // 2), np.arange(num_data // 2, num_data) * -1))
# get psi hat (eq. (6) in paper)
psi_hat = np.sqrt(2.0 * np.pi * scale) * normalized_haar_wavelet(scale * omega, scale)
# get W (eq. (4) in paper)
W = np.fft.ifft(x_hat * psi_hat)
return W[2 * scale:-2 * scale]
if __name__ == "__main__":
from matplotlib import pyplot as plt
# data = np.fromfile("/home/joe/GIT/urh/tests/data/fsk.complex", dtype=np.complex64)[5:15000]
# data = np.fromfile("/home/joe/GIT/urh/tests/data/ask.complex", dtype=np.complex64)[462:754]
# data = np.fromfile("/home/joe/GIT/urh/tests/data/enocean.complex", dtype=np.complex64)[9724:10228]
data = np.fromfile("/home/joe/GIT/publications/ainterpretation/experiments/signals/esaver_test4on.complex",
dtype=np.complex64)[86452:115541]
# data = np.fromfile("/home/joe/GIT/urh/tests/data/action_ook.complex", dtype=np.complex64)[3780:4300]
# data = np.fromfile("/home/joe/GIT/urh/tests/data/ask50.complex", dtype=np.complex64)
# Wavelet transform the data
# data = np.fromfile("/home/joe/GIT/urh/tests/data/ask.complex", dtype=np.complex64)[0:2 ** 13]
# data = np.fromfile("/tmp/generated.complex", dtype=np.complex64)
# data = np.fromfile("/tmp/psk.complex", dtype=np.complex64)
# data = np.fromfile("/home/joe/GIT/urh/tests/data/psk_generated.complex", dtype=np.complex64)[0:8000]
modulator = Modulator("")
modulator.modulation_type = "PSK"
modulator.parameters[0] = 0
modulator.parameters[1] = 180
modulator.carrier_freq_hz = 5e3
modulator.sample_rate = 200e3
# data = modulator.modulate("1010", pause=0)
# data = np.fromfile("/tmp/ask25.complex", dtype=np.complex64)
# data = np.fromfile("/tmp/ask1080.complex", dtype=np.complex64)
scale = 4
median_filter_order = 11
data = data[np.abs(data) > 0]
# Normalize with max of data to prevent increasing variance for signals with lower amplitude
data = data / np.abs(np.max(data))
mag_wvlt = np.abs(cwt_haar(data, scale=scale))
norm_mag_wvlt = np.abs(cwt_haar(data / np.abs(data), scale=scale))
median_filter = cy_auto_interpretation.median_filter
filtered_mag_wvlt = median_filter(mag_wvlt, k=median_filter_order)
filtered_mag_norm_wvlt = median_filter(norm_mag_wvlt, k=median_filter_order)
plt.subplot(421)
plt.title("Original data")
plt.plot(data)
plt.subplot(422)
plt.title("Amplitude normalized data")
plt.plot(data / np.abs(data))
plt.subplot(423)
plt.title("CWT ({0:.4f})".format(np.var(mag_wvlt)))
plt.plot(mag_wvlt)
plt.subplot(424)
plt.title("Filtered CWT ({0:.4f})".format(np.var(filtered_mag_wvlt)))
plt.plot(filtered_mag_wvlt)
plt.subplot(425)
plt.title("Norm CWT ({0:.4f})".format(np.var(norm_mag_wvlt)))
plt.plot(norm_mag_wvlt)
plt.subplot(426)
plt.title("Filtered Norm CWT ({0:.4f})".format(np.var(filtered_mag_norm_wvlt)))
plt.plot(filtered_mag_norm_wvlt)
plt.subplot(427)
plt.title("FFT magnitude")
fft = np.fft.fft(data)
fft = np.abs(fft)
ten_greatest_indices = np.argsort(fft)[::-1][0:10]
print(ten_greatest_indices)
print(fft[ten_greatest_indices])
plt.plot(np.fft.fftshift(fft))
plt.subplot(428)
fft = np.fft.fftshift(np.fft.fft(data))
fft[np.abs(fft) < 0.2 * np.max(np.abs(fft))] = 0
fft_phase = np.angle(fft)
ten_greatest_indices = np.argsort(np.abs(fft_phase))[::-1][0:10]
print("FFT phases:")
print(ten_greatest_indices)
print(fft_phase[ten_greatest_indices])
plt.title("FFT phase ({:.2f})".format(np.var(fft_phase)))
plt.plot(fft_phase)
plt.show()

View File

@ -1,65 +0,0 @@
import numpy as np
from urh.cythonext import util
from urh.signalprocessing.Message import Message
def auto_assign_participants(messages, participants):
"""
:type messages: list of Message
:type participants: list of Participant
:return:
"""
if len(participants) == 0:
return
if len(participants) == 1:
for message in messages: # type: Message
message.participant = participants[0]
return
# Try to assign participants based on SRC_ADDRESS label and participant address
for msg in filter(lambda m: m.participant is None, messages):
src_address = msg.get_src_address_from_data()
if src_address:
try:
msg.participant = next(p for p in participants if p.address_hex == src_address)
except StopIteration:
pass
# Assign remaining participants based on RSSI of messages
rssis = np.array([msg.rssi for msg in messages], dtype=np.float32)
min_rssi, max_rssi = util.minmax(rssis)
center_spacing = (max_rssi - min_rssi) / (len(participants) - 1)
centers = [min_rssi + i * center_spacing for i in range(0, len(participants))]
rssi_assigned_centers = []
for rssi in rssis:
center_index = np.argmin(np.abs(rssi - centers))
rssi_assigned_centers.append(int(center_index))
participants.sort(key=lambda participant: participant.relative_rssi)
for message, center_index in zip(messages, rssi_assigned_centers):
if message.participant is None:
message.participant = participants[center_index]
def auto_assign_participant_addresses(messages, participants):
"""
:type messages: list of Message
:type participants: list of Participant
:return:
"""
participants_without_address = [p for p in participants if not p.address_hex]
if len(participants_without_address) == 0:
return
for msg in messages:
if msg.participant in participants_without_address:
src_address = msg.get_src_address_from_data()
if src_address:
participants_without_address.remove(msg.participant)
msg.participant.address_hex = src_address

View File

@ -1,296 +0,0 @@
import copy
import itertools
import numpy as np
from urh.util import util
from urh.util.GenericCRC import GenericCRC
class CommonRange(object):
def __init__(self, start, length, value: np.ndarray = None, score=0, field_type="Generic", message_indices=None,
range_type="bit", byte_order="big"):
"""
:param start:
:param length:
:param value: Value for this common range as string
"""
self.start = start
self.length = length
self.__byte_order = byte_order
self.sync_end = 0
if isinstance(value, str):
value = np.array(list(map(lambda x: int(x, 16), value)), dtype=np.uint8)
self.values = [value] if value is not None else []
self.score = score
self.field_type = field_type # can also be length, address etc.
self.range_type = range_type.lower() # one of bit/hex/byte
self.message_indices = set() if message_indices is None else set(message_indices)
"""
Set of message indices, this range applies to
"""
@property
def end(self):
return self.start + self.length - 1
@property
def bit_start(self):
return self.__convert_number(self.start) + self.sync_end
@property
def bit_end(self):
return self.__convert_number(self.start) + self.__convert_number(self.length) - 1 + self.sync_end
@property
def length_in_bits(self):
return self.bit_end - self.bit_start - 1
@property
def value(self):
if len(self.values) == 0:
return None
elif len(self.values) == 1:
return self.values[0]
else:
raise ValueError("This range has multiple values!")
@value.setter
def value(self, val):
if len(self.values) == 0:
self.values = [val]
elif len(self.values) == 1:
self.values[0] = val
else:
raise ValueError("This range has multiple values!")
@property
def byte_order(self):
if self.byte_order_is_unknown:
return "big"
return self.__byte_order
@byte_order.setter
def byte_order(self, val: str):
self.__byte_order = val
@property
def byte_order_is_unknown(self) -> bool:
return self.__byte_order is None
def matches(self, start: int, value: np.ndarray):
return self.start == start and \
self.length == len(value) and \
self.value.tobytes() == value.tobytes()
def __convert_number(self, n):
if self.range_type == "bit":
return n
elif self.range_type == "hex":
return n * 4
elif self.range_type == "byte":
return n * 8
else:
raise ValueError("Unknown range type {}".format(self.range_type))
def __repr__(self):
result = "{} {}-{} ({} {})".format(self.field_type, self.bit_start,
self.bit_end, self.length, self.range_type)
result += " Values: " + " ".join(map(util.convert_numbers_to_hex_string, self.values))
if self.score is not None:
result += " Score: " + str(self.score)
result += " Message indices: {" + ",".join(map(str, sorted(self.message_indices))) + "}"
return result
def __eq__(self, other):
if not isinstance(other, CommonRange):
return False
return self.bit_start == other.bit_start and \
self.bit_end == other.bit_end and \
self.field_type == other.field_type
def __hash__(self):
return hash((self.start, self.length, self.field_type))
def __lt__(self, other):
return self.bit_start < other.bit_start
def overlaps_with(self, other) -> bool:
if not isinstance(other, CommonRange):
raise ValueError("Need another bit range to compare")
return any(i in range(self.bit_start, self.bit_end)
for i in range(other.bit_start, other.bit_end))
def ensure_not_overlaps(self, start: int, end: int):
"""
:param start:
:param end:
:rtype: list of CommonRange
"""
if end < self.start or start > self.end:
# Other range is right or left of our range -> no overlapping
return [copy.deepcopy(self)]
if start <= self.start < end < self.end:
# overlaps on the left
result = copy.deepcopy(self)
result.length -= end - result.start
result.start = end
result.value = result.value[result.start-self.start:(result.start-self.start)+result.length]
return [result]
if self.start < start <= self.end <= end:
# overlaps on the right
result = copy.deepcopy(self)
result.length -= self.end + 1 - start
result.value = result.value[:result.length]
return [result]
if self.start < start and self.end > end:
# overlaps in the middle
left = copy.deepcopy(self)
right = copy.deepcopy(self)
left.length -= (left.end + 1 - start)
left.value = self.value[:left.length]
right.start = end + 1
right.length = self.end - end
right.value = self.value[right.start-self.start:(right.start-self.start)+right.length]
return [left, right]
return []
class ChecksumRange(CommonRange):
def __init__(self, start, length, crc: GenericCRC, data_range_start, data_range_end, value: np.ndarray = None,
score=0, field_type="Generic", message_indices=None, range_type="bit"):
super().__init__(start, length, value, score, field_type, message_indices, range_type)
self.data_range_start = data_range_start
self.data_range_end = data_range_end
self.crc = crc
@property
def data_range_bit_start(self):
return self.data_range_start + self.sync_end
@property
def data_range_bit_end(self):
return self.data_range_end + self.sync_end
def __eq__(self, other):
return super().__eq__(other) \
and self.data_range_start == other.data_range_start \
and self.data_range_end == other.data_range_end \
and self.crc == other.crc
def __hash__(self):
return hash((self.start, self.length, self.data_range_start, self.data_range_end, self.crc))
def __repr__(self):
return super().__repr__() + " \t" + \
"{}".format(self.crc.caption) + \
" Datarange: {}-{} ".format(self.data_range_start, self.data_range_end)
class EmptyCommonRange(CommonRange):
"""
Empty Common Bit Range, to indicate, that no common Bit Range was found
"""
def __init__(self, field_type="Generic"):
super().__init__(0, 0, "")
self.field_type = field_type
def __eq__(self, other):
return isinstance(other, EmptyCommonRange) \
and other.field_type == self.field_type
def __repr__(self):
return "No " + self.field_type
def __hash__(self):
return hash(super)
class CommonRangeContainer(object):
"""
This is the raw equivalent of a Message Type:
A container of common ranges
"""
def __init__(self, ranges: list, message_indices: set = None):
assert isinstance(ranges, list)
self.__ranges = ranges # type: list[CommonRange]
self.__ranges.sort()
if message_indices is None:
self.update_message_indices()
else:
self.message_indices = message_indices
@property
def ranges_overlap(self) -> bool:
return self.has_overlapping_ranges(self.__ranges)
def update_message_indices(self):
if len(self) == 0:
self.message_indices = set()
else:
self.message_indices = set(self[0].message_indices)
for i in range(1, len(self)):
self.message_indices.intersection_update(self[i].message_indices)
def add_range(self, rng: CommonRange):
self.__ranges.append(rng)
self.__ranges.sort()
def add_ranges(self, ranges: list):
self.__ranges.extend(ranges)
self.__ranges.sort()
def has_same_ranges(self, ranges: list) -> bool:
return self.__ranges == ranges
def has_same_ranges_as_container(self, container):
if not isinstance(container, CommonRangeContainer):
return False
return self.__ranges == container.__ranges
@staticmethod
def has_overlapping_ranges(ranges: list) -> bool:
for rng1, rng2 in itertools.combinations(ranges, 2):
if rng1.overlaps_with(rng2):
return True
return False
def __len__(self):
return len(self.__ranges)
def __iter__(self):
return self.__ranges.__iter__()
def __getitem__(self, item):
return self.__ranges[item]
def __repr__(self):
from pprint import pformat
return pformat(self.__ranges)
def __eq__(self, other):
if not isinstance(other, CommonRangeContainer):
return False
return self.__ranges == other.__ranges and self.message_indices == other.message_indices

View File

@ -1,435 +0,0 @@
import copy
import math
from collections import defaultdict
import numpy as np
from urh.awre import AutoAssigner
from urh.awre.CommonRange import CommonRange, EmptyCommonRange, CommonRangeContainer, ChecksumRange
from urh.awre.Preprocessor import Preprocessor
from urh.awre.engines.AddressEngine import AddressEngine
from urh.awre.engines.ChecksumEngine import ChecksumEngine
from urh.awre.engines.LengthEngine import LengthEngine
from urh.awre.engines.SequenceNumberEngine import SequenceNumberEngine
from urh.cythonext import awre_util
from urh.signalprocessing.ChecksumLabel import ChecksumLabel
from urh.signalprocessing.FieldType import FieldType
from urh.signalprocessing.Message import Message
from urh.signalprocessing.MessageType import MessageType
from urh.signalprocessing.ProtocoLabel import ProtocolLabel
from urh.util.WSPChecksum import WSPChecksum
class FormatFinder(object):
MIN_MESSAGES_PER_CLUSTER = 2
def __init__(self, messages, participants=None, shortest_field_length=None):
"""
:type messages: list of Message
:param participants:
"""
if participants is not None:
AutoAssigner.auto_assign_participants(messages, participants)
existing_message_types_by_msg = {i: msg.message_type for i, msg in enumerate(messages)}
self.existing_message_types = defaultdict(list)
for i, message_type in existing_message_types_by_msg.items():
self.existing_message_types[message_type].append(i)
preprocessor = Preprocessor(self.get_bitvectors_from_messages(messages), existing_message_types_by_msg)
self.preamble_starts, self.preamble_lengths, sync_len = preprocessor.preprocess()
self.sync_ends = self.preamble_starts + self.preamble_lengths + sync_len
n = shortest_field_length
if n is None:
# 0 = no sync found
n = 8 if sync_len >= 8 else 4 if sync_len >= 4 else 1 if sync_len >= 1 else 0
for i, value in enumerate(self.sync_ends):
# In doubt it is better to under estimate the sync end
if n > 0:
self.sync_ends[i] = n * max(int(math.floor((value - self.preamble_starts[i]) / n)), 1) + \
self.preamble_starts[i]
else:
self.sync_ends[i] = self.preamble_starts[i]
if self.sync_ends[i] - self.preamble_starts[i] < self.preamble_lengths[i]:
self.preamble_lengths[i] = self.sync_ends[i] - self.preamble_starts[i]
self.bitvectors = self.get_bitvectors_from_messages(messages, self.sync_ends)
self.hexvectors = self.get_hexvectors(self.bitvectors)
self.current_iteration = 0
participants = list(sorted(set(msg.participant for msg in messages if msg.participant is not None)))
self.participant_indices = [participants.index(msg.participant) if msg.participant is not None else -1
for msg in messages]
self.known_participant_addresses = {
participants.index(p): np.array([int(h, 16) for h in p.address_hex], dtype=np.uint8)
for p in participants if p and p.address_hex
}
@property
def message_types(self):
"""
:rtype: list of MessageType
"""
return sorted(self.existing_message_types.keys(), key=lambda x: x.name)
def perform_iteration_for_message_type(self, message_type: MessageType):
"""
Perform a field inference iteration for messages of the given message type
This routine will return newly found fields as a set of Common Ranges
:param message_type:
:rtype: set of CommonRange
"""
indices = self.existing_message_types[message_type]
engines = []
# We can take an arbitrary sync end to correct the already labeled fields for this message type,
# because if the existing labels would have different sync positions,
# they would not belong to the same message type in the first place
sync_end = self.sync_ends[indices[0]] if indices else 0
already_labeled = [(lbl.start - sync_end, lbl.end - sync_end) for lbl in message_type if lbl.start >= sync_end]
if not message_type.get_first_label_with_type(FieldType.Function.LENGTH):
engines.append(LengthEngine([self.bitvectors[i] for i in indices], already_labeled=already_labeled))
if not message_type.get_first_label_with_type(FieldType.Function.SRC_ADDRESS):
engines.append(AddressEngine([self.hexvectors[i] for i in indices],
[self.participant_indices[i] for i in indices],
self.known_participant_addresses,
already_labeled=already_labeled))
elif not message_type.get_first_label_with_type(FieldType.Function.DST_ADDRESS):
engines.append(AddressEngine([self.hexvectors[i] for i in indices],
[self.participant_indices[i] for i in indices],
self.known_participant_addresses,
already_labeled=already_labeled,
src_field_present=True))
if not message_type.get_first_label_with_type(FieldType.Function.SEQUENCE_NUMBER):
engines.append(SequenceNumberEngine([self.bitvectors[i] for i in indices], already_labeled=already_labeled))
if not message_type.get_first_label_with_type(FieldType.Function.CHECKSUM):
# If checksum was not found in first iteration, it will also not be found in next one
if self.current_iteration == 0:
engines.append(ChecksumEngine([self.bitvectors[i] for i in indices], already_labeled=already_labeled))
result = set()
for engine in engines:
high_scored_ranges = engine.find() # type: list[CommonRange]
high_scored_ranges = self.retransform_message_indices(high_scored_ranges, indices, self.sync_ends)
merged_ranges = self.merge_common_ranges(high_scored_ranges)
result.update(merged_ranges)
return result
def perform_iteration(self) -> bool:
new_field_found = False
for message_type in self.existing_message_types.copy():
new_fields_for_message_type = self.perform_iteration_for_message_type(message_type)
new_fields_for_message_type.update(
self.get_preamble_and_sync(self.preamble_starts, self.preamble_lengths, self.sync_ends,
message_type_indices=self.existing_message_types[message_type])
)
self.remove_overlapping_fields(new_fields_for_message_type, message_type)
containers = self.create_common_range_containers(new_fields_for_message_type)
# Store addresses of participants if we found a SRC address field
participants_with_unknown_address = set(self.participant_indices) - set(self.known_participant_addresses)
participants_with_unknown_address.discard(-1)
if participants_with_unknown_address:
for container in containers:
src_range = next((rng for rng in container if rng.field_type == "source address"), None)
if src_range is None:
continue
for msg_index in src_range.message_indices:
if len(participants_with_unknown_address) == 0:
break
p = self.participant_indices[msg_index]
if p not in self.known_participant_addresses:
hex_vector = self.hexvectors[msg_index]
self.known_participant_addresses[p] = hex_vector[src_range.start:src_range.end + 1]
participants_with_unknown_address.discard(p)
new_field_found |= len(containers) > 0
if len(containers) == 1:
for rng in containers[0]:
self.add_range_to_message_type(rng, message_type)
elif len(containers) > 1:
del self.existing_message_types[message_type]
for i, container in enumerate(containers):
new_message_type = copy.deepcopy(message_type) # type: MessageType
if i > 0:
new_message_type.name = "Message Type {}.{}".format(self.current_iteration+1, i)
new_message_type.give_new_id()
for rng in container:
self.add_range_to_message_type(rng, new_message_type)
self.existing_message_types[new_message_type].extend(sorted(container.message_indices))
return new_field_found
def run(self, max_iterations=10):
self.current_iteration = 0
while self.perform_iteration() and self.current_iteration < max_iterations:
self.current_iteration += 1
if len(self.message_types) > 0:
messages_without_message_type = set(range(len(self.bitvectors))) - set(
i for l in self.existing_message_types.values() for i in l)
# add to default message type
self.existing_message_types[self.message_types[0]].extend(list(messages_without_message_type))
@staticmethod
def remove_overlapping_fields(common_ranges, message_type: MessageType):
"""
Remove all fields from a set of CommonRanges which overlap with fields of the existing message type
:type common_ranges: set of CommonRange
:param message_type:
:return:
"""
if len(message_type) == 0:
return
for rng in common_ranges.copy():
for lbl in message_type: # type: ProtocolLabel
if any(i in range(rng.bit_start, rng.bit_end) for i in range(lbl.start, lbl.end)):
common_ranges.discard(rng)
break
@staticmethod
def merge_common_ranges(common_ranges):
"""
Merge common ranges if possible
:type common_ranges: list of CommonRange
:rtype: list of CommonRange
"""
merged_ranges = []
for common_range in common_ranges:
assert isinstance(common_range, CommonRange)
try:
same_range = next(rng for rng in merged_ranges
if rng.bit_start == common_range.bit_start
and rng.bit_end == common_range.bit_end
and rng.field_type == common_range.field_type)
same_range.values.extend(common_range.values)
same_range.message_indices.update(common_range.message_indices)
except StopIteration:
merged_ranges.append(common_range)
return merged_ranges
@staticmethod
def add_range_to_message_type(common_range: CommonRange, message_type: MessageType):
field_type = FieldType.from_caption(common_range.field_type)
label = message_type.add_protocol_label(name=common_range.field_type,
start=common_range.bit_start, end=common_range.bit_end,
auto_created=True,
type=field_type
)
label.display_endianness = common_range.byte_order
if field_type.function == FieldType.Function.CHECKSUM:
assert isinstance(label, ChecksumLabel)
assert isinstance(common_range, ChecksumRange)
label.data_ranges = [[common_range.data_range_bit_start, common_range.data_range_bit_end]]
if isinstance(common_range.crc, WSPChecksum):
label.category = ChecksumLabel.Category.wsp
else:
label.checksum = copy.copy(common_range.crc)
@staticmethod
def get_hexvectors(bitvectors: list):
result = awre_util.get_hexvectors(bitvectors)
return result
@staticmethod
def get_bitvectors_from_messages(messages: list, sync_ends: np.ndarray = None):
if sync_ends is None:
sync_ends = defaultdict(lambda: None)
return [np.array(msg.decoded_bits[sync_ends[i]:], dtype=np.uint8, order="C") for i, msg in enumerate(messages)]
@staticmethod
def create_common_range_containers(label_set: set, num_messages: int = None):
"""
Create message types from set of labels.
Handle overlapping conflicts and create multiple message types if needed
:param label_set:
:param num_messages:
:return:
:rtype: list of CommonRangeContainer
"""
if num_messages is None:
message_indices = sorted(set(i for rng in label_set for i in rng.message_indices))
else:
message_indices = range(num_messages)
result = []
for i in message_indices:
labels = sorted(set(rng for rng in label_set if i in rng.message_indices
and not isinstance(rng, EmptyCommonRange)))
container = next((container for container in result if container.has_same_ranges(labels)), None)
if container is None:
result.append(CommonRangeContainer(labels, message_indices={i}))
else:
container.message_indices.add(i)
result = FormatFinder.handle_overlapping_conflict(result)
return result
@staticmethod
def handle_overlapping_conflict(containers):
"""
Handle overlapping conflicts for a list of CommonRangeContainers
:type containers: list of CommonRangeContainer
:return:
"""
result = []
for container in containers:
if container.ranges_overlap:
conflicted_handled = FormatFinder.__handle_container_overlapping_conflict(container)
else:
conflicted_handled = container
try:
same_rng_container = next(c for c in result if c.has_same_ranges_as_container(conflicted_handled))
same_rng_container.message_indices.update(conflicted_handled.message_indices)
except StopIteration:
result.append(conflicted_handled)
return result
@staticmethod
def __handle_container_overlapping_conflict(container: CommonRangeContainer):
"""
Handle overlapping conflict for a CommRangeContainer.
We can assert that all labels in the container share the same message indices
because we partitioned them in a step before.
If two or more labels overlap we have three ways to resolve the conflict:
1. Choose the range with the highest score
2. If multiple ranges overlap choose the ranges that maximize the overall (cumulated) score
3. If the overlapping is very small i.e. only 1 or 2 bits we can adjust the start/end of the conflicting ranges
The ranges inside the container _must_ be sorted i.e. the range with lowest start must be at front
:param container:
:return:
"""
partitions = [] # type: list[list[CommonRange]]
# partition the container into overlapping partitions
# results in something like [[A], [B,C], [D], [E,F,G]]] where B and C and E, F, G are overlapping
for cur_rng in container:
if len(partitions) == 0:
partitions.append([cur_rng])
continue
last_rng = partitions[-1][-1] # type: CommonRange
if cur_rng.overlaps_with(last_rng):
partitions[-1].append(cur_rng)
else:
partitions.append([cur_rng])
# Todo: Adjust start/end of conflicting ranges if overlapping is very small (i.e. 1 or 2 bits)
result = []
# Go through these partitions and handle overlapping conflicts
for partition in partitions:
possible_solutions = []
for i, rng in enumerate(partition):
# Append every range to this solution that does not overlap with current rng
solution = [rng] + [r for r in partition[i + 1:] if not rng.overlaps_with(r)]
possible_solutions.append(solution)
# Take solution that maximizes score. In case of tie, choose solution with shorter total length.
# if there is still a tie prefer solution that contains a length field as is is very likely to be correct
# if nothing else helps break tie by names of field types to prevent randomness
best_solution = max(possible_solutions,
key=lambda sol: (sum(r.score for r in sol),
-sum(r.length_in_bits for r in sol),
"length" in {r.field_type for r in sol},
"".join(r.field_type[0] for r in sol)))
result.extend(best_solution)
return CommonRangeContainer(result, message_indices=container.message_indices)
@staticmethod
def retransform_message_indices(common_ranges, message_type_indices: list, sync_ends) -> list:
"""
Retransform the found message indices of an engine to the original index space
based on the message indices of the message type.
Furthermore, set the sync_end of the common ranges so bit_start and bit_end
match the position in the original space
:type common_ranges: list of CommonRange
:param message_type_indices: Messages belonging to the message type the engine ran for
:type sync_ends: np.ndarray
:return:
"""
result = []
for common_range in common_ranges:
# Retransform message indices into original space
message_indices = np.fromiter((message_type_indices[i] for i in common_range.message_indices),
dtype=int, count=len(common_range.message_indices))
# If we have different sync_ends we need to create a new common range for each different sync_length
matching_sync_ends = sync_ends[message_indices]
for sync_end in np.unique(matching_sync_ends):
rng = copy.deepcopy(common_range)
rng.sync_end = sync_end
rng.message_indices = set(message_indices[np.nonzero(matching_sync_ends == sync_end)])
result.append(rng)
return result
@staticmethod
def get_preamble_and_sync(preamble_starts, preamble_lengths, sync_ends, message_type_indices):
"""
Get preamble and sync common ranges based on the data
:type preamble_starts: np.ndarray
:type preamble_lengths: np.ndarray
:type sync_ends: np.ndarray
:type message_type_indices: list
:rtype: set of CommonRange
"""
assert len(preamble_starts) == len(preamble_lengths) == len(sync_ends)
result = set() # type: set[CommonRange]
for i in message_type_indices:
preamble = CommonRange(preamble_starts[i], preamble_lengths[i], field_type="preamble", message_indices={i})
existing_preamble = next((rng for rng in result if preamble == rng), None)
if existing_preamble is not None:
existing_preamble.message_indices.add(i)
elif preamble_lengths[i] > 0:
result.add(preamble)
preamble_end = preamble_starts[i] + preamble_lengths[i]
sync_end = sync_ends[i]
sync = CommonRange(preamble_end, sync_end - preamble_end, field_type="synchronization", message_indices={i})
existing_sync = next((rng for rng in result if sync == rng), None)
if existing_sync is not None:
existing_sync.message_indices.add(i)
elif sync_end - preamble_end > 0:
result.add(sync)
return result

View File

@ -1,116 +0,0 @@
from collections import defaultdict
import numpy as np
from urh.awre.CommonRange import CommonRange
from urh.cythonext import awre_util
class Histogram(object):
"""
Create a histogram based on the equalness of vectors
"""
def __init__(self, vectors, indices=None, normalize=True, debug=False):
"""
:type vectors: list of np.ndarray
:param indices: Indices of vectors for which the Histogram shall be created.
This is useful for clustering.
If None Histogram will be created over all bitvectors
:type: list of int
:param normalize:
"""
self.__vectors = vectors # type: list[np.ndarray]
self.__active_indices = list(range(len(vectors))) if indices is None else indices
self.normalize = normalize
self.data = self.__create_histogram()
def __create_histogram(self):
return awre_util.create_difference_histogram(self.__vectors, self.__active_indices)
def __repr__(self):
return str(self.data.tolist())
def find_common_ranges(self, alpha=0.95, range_type="bit"):
"""
Find all common ranges where at least alpha percent of numbers are equal
:param range_type: on of bit/hex/byte
:param alpha:
:return:
"""
data_indices = np.argwhere(self.data >= alpha).flatten()
if len(data_indices) < 2:
return []
result = []
start, length = None, 0
for i in range(1, len(data_indices)):
if start is None:
start = data_indices[i - 1]
length = 1
if data_indices[i] - data_indices[i - 1] == 1:
length += 1
else:
if length >= 2:
value = self.__get_value_for_common_range(start, length)
result.append(CommonRange(start, length, value, message_indices=set(self.__active_indices),
range_type=range_type))
start, length = None, 0
if i == len(data_indices) - 1 and length >= 2:
value = self.__get_value_for_common_range(start, length)
result.append(CommonRange(start, length, value, message_indices=set(self.__active_indices),
range_type=range_type))
return result
def __get_value_for_common_range(self, start: int, length: int):
"""
Get the value for a range of common numbers. This is the value that appears most.
:param start: Start of the common bit range
:param length: Length of the common bit range
:return:
"""
values = defaultdict(list)
for i in self.__active_indices:
vector = self.__vectors[i]
values[vector[start:start + length].tostring()].append(i)
value = max(values, key=lambda x: len(x))
indices = values[value]
return self.__vectors[indices[0]][start:start + length]
def __vector_to_string(self, data_vector) -> str:
lut = {i: "{0:x}".format(i) for i in range(16)}
return "".join(lut[x] if x in lut else " {} ".format(x) for x in data_vector)
def plot(self):
import matplotlib.pyplot as plt
self.subplot_on(plt)
plt.show()
def subplot_on(self, plt):
plt.grid()
plt.plot(self.data)
plt.xticks(np.arange(4, len(self.data), 4))
plt.xlabel("Bit position")
if self.normalize:
plt.ylabel("Number common bits (normalized)")
else:
plt.ylabel("Number common bits")
plt.ylim(ymin=0)
if __name__ == "__main__":
bv1 = np.array([1, 0, 1, 0, 1, 1, 1, 1], dtype=np.int8)
bv2 = np.array([1, 0, 1, 0, 1, 0, 0, 0], dtype=np.int8)
bv3 = np.array([1, 0, 1, 0, 1, 1, 1, 1], dtype=np.int8)
bv4 = np.array([1, 0, 1, 0, 0, 0, 0, 0], dtype=np.int8)
h = Histogram([bv1, bv2, bv3, bv4])
h.plot()

View File

@ -1,55 +0,0 @@
from urh.signalprocessing.ChecksumLabel import ChecksumLabel
from urh.signalprocessing.FieldType import FieldType
from urh.signalprocessing.MessageType import MessageType
from urh.signalprocessing.ProtocoLabel import ProtocolLabel
class MessageTypeBuilder(object):
def __init__(self, name: str):
self.name = name
self.message_type = MessageType(name)
def add_label(self, label_type: FieldType.Function, length: int, name: str=None):
try:
start = self.message_type[-1].end
color_index = self.message_type[-1].color_index + 1
except IndexError:
start, color_index = 0, 0
if name is None:
name = label_type.value
lbl = ProtocolLabel(name, start, start+length-1, color_index, field_type=FieldType(label_type.name, label_type))
self.message_type.append(lbl)
def add_checksum_label(self, length, checksum, data_start=None, data_end=None, name: str=None):
label_type = FieldType.Function.CHECKSUM
try:
start = self.message_type[-1].end
color_index = self.message_type[-1].color_index + 1
except IndexError:
start, color_index = 0, 0
if name is None:
name = label_type.value
if data_start is None:
# End of sync or preamble
sync_label = self.message_type.get_first_label_with_type(FieldType.Function.SYNC)
if sync_label:
data_start = sync_label.end
else:
preamble_label = self.message_type.get_first_label_with_type(FieldType.Function.PREAMBLE)
if preamble_label:
data_start = preamble_label.end
else:
data_start = 0
if data_end is None:
data_end = start
lbl = ChecksumLabel(name, start, start+length-1, color_index, field_type=FieldType(label_type.name, label_type))
lbl.data_ranges = [(data_start, data_end)]
lbl.checksum = checksum
self.message_type.append(lbl)

View File

@ -1,271 +0,0 @@
import itertools
import math
import os
import time
from collections import defaultdict
import numpy as np
from urh.cythonext import awre_util
from urh.signalprocessing.FieldType import FieldType
class Preprocessor(object):
"""
This class preprocesses the messages in the following ways
1) Identify preamble / length of preamble
2) Identify sync word(s)
3) Align all given messages on the identified preamble information
"""
_DEBUG_ = False
def __init__(self, bitvectors: list, existing_message_types: dict = None):
self.bitvectors = bitvectors # type: list[np.ndarray]
self.existing_message_types = existing_message_types if existing_message_types is not None else dict()
def preprocess(self) -> (np.ndarray, int):
raw_preamble_positions = self.get_raw_preamble_positions()
existing_sync_words = self.__get_existing_sync_words()
if len(existing_sync_words) == 0:
sync_words = self.find_possible_syncs(raw_preamble_positions)
else:
# NOTE: This does not cover the case if protocol has multiple sync words and not all of them were labeled
sync_words = existing_sync_words
preamble_starts = raw_preamble_positions[:, 0]
preamble_lengths = self.get_preamble_lengths_from_sync_words(sync_words, preamble_starts=preamble_starts)
sync_len = len(sync_words[0]) if len(sync_words) > 0 else 0
return preamble_starts, preamble_lengths, sync_len
def get_preamble_lengths_from_sync_words(self, sync_words: list, preamble_starts: np.ndarray):
"""
Get the preamble lengths based on the found sync words for all messages.
If there should be more than one sync word in a message, use the first one.
:param sync_words:
:param preamble_starts:
:return:
"""
# If there should be varying sync word lengths we need to return an array of sync lengths per message
assert all(len(sync_word) == len(sync_words[0]) for sync_word in sync_words)
byte_sync_words = [bytes(map(int, sync_word)) for sync_word in sync_words]
result = np.zeros(len(self.bitvectors), dtype=np.uint32)
for i, bitvector in enumerate(self.bitvectors):
preamble_lengths = []
bits = bitvector.tobytes()
for sync_word in byte_sync_words:
sync_start = bits.find(sync_word)
if sync_start != -1:
if sync_start - preamble_starts[i] >= 2:
preamble_lengths.append(sync_start - preamble_starts[i])
# Consider case where sync word starts with preamble pattern
sync_start = bits.find(sync_word, sync_start + 1, sync_start + 2 * len(sync_word))
if sync_start != -1:
if sync_start - preamble_starts[i] >= 2:
preamble_lengths.append(sync_start - preamble_starts[i])
preamble_lengths.sort()
if len(preamble_lengths) == 0:
result[i] = 0
elif len(preamble_lengths) == 1:
result[i] = preamble_lengths[0]
else:
# consider all indices not more than one byte before first one
preamble_lengths = list(filter(lambda x: x < preamble_lengths[0] + 7, preamble_lengths))
# take the smallest preamble_length, but prefer a greater one if it is divisible by 8 (or 4)
preamble_length = next((pl for pl in preamble_lengths if pl % 8 == 0), None)
if preamble_length is None:
preamble_length = next((pl for pl in preamble_lengths if pl % 4 == 0), None)
if preamble_length is None:
preamble_length = preamble_lengths[0]
result[i] = preamble_length
return result
def find_possible_syncs(self, raw_preamble_positions=None):
difference_matrix = self.get_difference_matrix()
if raw_preamble_positions is None:
raw_preamble_positions = self.get_raw_preamble_positions()
return self.determine_sync_candidates(raw_preamble_positions, difference_matrix, n_gram_length=4)
@staticmethod
def merge_possible_sync_words(possible_sync_words: dict, n_gram_length: int):
"""
Merge possible sync words by looking for common prefixes
:param possible_sync_words: dict of possible sync words and their frequencies
:return:
"""
result = defaultdict(int)
if len(possible_sync_words) < 2:
return possible_sync_words.copy()
for sync1, sync2 in itertools.combinations(possible_sync_words, 2):
common_prefix = os.path.commonprefix([sync1, sync2])
if len(common_prefix) > n_gram_length:
result[common_prefix] += possible_sync_words[sync1] + possible_sync_words[sync2]
else:
result[sync1] += possible_sync_words[sync1]
result[sync2] += possible_sync_words[sync2]
return result
def determine_sync_candidates(self,
raw_preamble_positions: np.ndarray,
difference_matrix: np.ndarray,
n_gram_length=4) -> list:
possible_sync_words = awre_util.find_possible_sync_words(difference_matrix, raw_preamble_positions,
self.bitvectors, n_gram_length)
self.__debug("Possible sync words", possible_sync_words)
if len(possible_sync_words) == 0:
return []
possible_sync_words = self.merge_possible_sync_words(possible_sync_words, n_gram_length)
self.__debug("Merged sync words", possible_sync_words)
scores = self.__score_sync_lengths(possible_sync_words)
sorted_scores = sorted(scores, reverse=True, key=scores.get)
estimated_sync_length = sorted_scores[0]
if estimated_sync_length % 8 != 0:
for other in filter(lambda x: 0 < estimated_sync_length-x < 7, sorted_scores):
if other % 8 == 0:
estimated_sync_length = other
break
# Now we look at all possible sync words with this length
sync_words = {word: frequency for word, frequency in possible_sync_words.items()
if len(word) == estimated_sync_length}
self.__debug("Sync words", sync_words)
additional_syncs = self.__find_additional_sync_words(estimated_sync_length, sync_words, possible_sync_words)
if additional_syncs:
self.__debug("Found additional sync words", additional_syncs)
sync_words.update(additional_syncs)
result = []
for sync_word in sorted(sync_words, key=sync_words.get, reverse=True):
# Convert bytes back to string
result.append("".join(str(c) for c in sync_word))
return result
def __find_additional_sync_words(self, sync_length: int, present_sync_words, possible_sync_words) -> dict:
"""
Look for additional sync words, in case we had varying preamble lengths and multiple sync words
(see test_with_three_syncs_different_preamble_lengths for an example)
:param sync_length:
:type present_sync_words: dict
:type possible_sync_words: dict
:return:
"""
np_syn = [np.fromiter(map(int, sync_word), dtype=np.uint8, count=len(sync_word))
for sync_word in present_sync_words]
messages_without_sync = [i for i, bv in enumerate(self.bitvectors)
if not any(awre_util.find_occurrences(bv, s, return_after_first=True) for s in np_syn)]
result = dict()
if len(messages_without_sync) == 0:
return result
# Is there another sync word that applies to all messages without sync?
additional_candidates = {word: score for word, score in possible_sync_words.items()
if len(word) > sync_length and not any(s in word for s in present_sync_words)}
for sync in sorted(additional_candidates, key=additional_candidates.get, reverse=True):
if len(messages_without_sync) == 0:
break
score = additional_candidates[sync]
s = sync[:sync_length]
np_s = np.fromiter(s, dtype=np.uint8, count=len(s))
matching = [i for i in messages_without_sync
if awre_util.find_occurrences(self.bitvectors[i], np_s, return_after_first=True)]
if matching:
result[s] = score
for m in matching:
messages_without_sync.remove(m)
return result
def get_raw_preamble_positions(self) -> np.ndarray:
"""
Return a 2D numpy array where first column is the start of preamble
second and third columns are lower and upper bound for preamble length by message, respectively
"""
result = np.zeros((len(self.bitvectors), 3), dtype=np.uint32)
for i, bitvector in enumerate(self.bitvectors):
if i in self.existing_message_types:
preamble_label = self.existing_message_types[i].get_first_label_with_type(FieldType.Function.PREAMBLE)
else:
preamble_label = None
if preamble_label is None:
start, lower, upper = awre_util.get_raw_preamble_position(bitvector)
else:
# If this message is already labeled with a preamble we just use it's values
start, lower, upper = preamble_label.start, preamble_label.end, preamble_label.end
result[i, 0] = start
result[i, 1] = lower - start
result[i, 2] = upper - start
return result
def get_difference_matrix(self) -> np.ndarray:
"""
Return a matrix of the first difference index between all messages
:return:
"""
return awre_util.get_difference_matrix(self.bitvectors)
def __score_sync_lengths(self, possible_sync_words: dict):
sync_lengths = defaultdict(int)
for sync_word, score in possible_sync_words.items():
sync_lengths[len(sync_word)] += score
self.__debug("Sync lengths", sync_lengths)
return sync_lengths
def __get_existing_sync_words(self) -> list:
result = []
for i, bitvector in enumerate(self.bitvectors):
if i in self.existing_message_types:
sync_label = self.existing_message_types[i].get_first_label_with_type(FieldType.Function.SYNC)
else:
sync_label = None
if sync_label is not None:
result.append("".join(map(str, bitvector[sync_label.start:sync_label.end])))
return result
def __debug(self, *args):
if self._DEBUG_:
print("[PREPROCESSOR]", *args)
@staticmethod
def get_next_multiple_of_n(number: int, n: int):
return n * int(math.ceil(number / n))
@staticmethod
def lower_multiple_of_n(number: int, n: int):
return n * int(math.floor(number / n))
@staticmethod
def get_next_lower_multiple_of_two(number: int):
return number if number % 2 == 0 else number - 1

View File

@ -1,260 +0,0 @@
import math
import struct
from array import array
from collections import defaultdict
from urh.util import util
from urh.awre.MessageTypeBuilder import MessageTypeBuilder
from urh.signalprocessing.ChecksumLabel import ChecksumLabel
from urh.signalprocessing.FieldType import FieldType
from urh.signalprocessing.Message import Message
from urh.signalprocessing.MessageType import MessageType
from urh.signalprocessing.Participant import Participant
from urh.signalprocessing.ProtocoLabel import ProtocolLabel
from urh.signalprocessing.ProtocolAnalyzer import ProtocolAnalyzer
class ProtocolGenerator(object):
DEFAULT_PREAMBLE = "10101010"
DEFAULT_SYNC = "1001"
BROADCAST_ADDRESS = "0xffff"
def __init__(self, message_types: list, participants: list = None, preambles_by_mt=None,
syncs_by_mt=None, little_endian=False, length_in_bytes=True, sequence_numbers=None,
sequence_number_increment=1, message_type_codes=None):
"""
:param message_types:
:param participants:
:param preambles_by_mt:
:param syncs_by_mt:
:param byte_order:
:param length_in_bytes: If false length will be given in bit
"""
self.participants = participants if participants is not None else []
self.protocol = ProtocolAnalyzer(None)
self.protocol.message_types = message_types
self.length_in_bytes = length_in_bytes
self.little_endian = little_endian
preambles_by_mt = dict() if preambles_by_mt is None else preambles_by_mt
self.preambles_by_message_type = defaultdict(lambda: self.DEFAULT_PREAMBLE)
for mt, preamble in preambles_by_mt.items():
self.preambles_by_message_type[mt] = self.to_bits(preamble)
syncs_by_mt = dict() if syncs_by_mt is None else syncs_by_mt
self.syncs_by_message_type = defaultdict(lambda: self.DEFAULT_SYNC)
for mt, sync in syncs_by_mt.items():
self.syncs_by_message_type[mt] = self.to_bits(sync)
sequence_numbers = dict() if sequence_numbers is None else sequence_numbers
self.sequence_numbers = defaultdict(lambda: 0)
self.sequence_number_increment = sequence_number_increment
for mt, seq in sequence_numbers.items():
self.sequence_numbers[mt] = seq
if message_type_codes is None:
message_type_codes = dict()
for i, mt in enumerate(self.message_types):
message_type_codes[mt] = i
self.message_type_codes = message_type_codes
@property
def messages(self):
return self.protocol.messages
@property
def message_types(self):
return self.protocol.message_types
def __get_address_for_participant(self, participant: Participant):
if participant is None:
return self.to_bits(self.BROADCAST_ADDRESS)
address = "0x" + participant.address_hex if not participant.address_hex.startswith(
"0x") else participant.address_hex
return self.to_bits(address)
@staticmethod
def to_bits(bit_or_hex_str: str):
if bit_or_hex_str.startswith("0x"):
lut = {"{0:x}".format(i): "{0:04b}".format(i) for i in range(16)}
return "".join(lut[c] for c in bit_or_hex_str[2:])
else:
return bit_or_hex_str
def decimal_to_bits(self, number: int, num_bits: int) -> str:
len_formats = {8: "B", 16: "H", 32: "I", 64: "Q"}
if num_bits not in len_formats:
raise ValueError("Invalid length for length field: {} bits".format(num_bits))
struct_format = "<" if self.little_endian else ">"
struct_format += len_formats[num_bits]
byte_length = struct.pack(struct_format, number)
return "".join("{0:08b}".format(byte) for byte in byte_length)
def generate_message(self, message_type=None, data="0x00", source: Participant = None,
destination: Participant = None):
for participant in (source, destination):
if isinstance(participant, Participant) and participant not in self.participants:
self.participants.append(participant)
if isinstance(message_type, MessageType):
message_type_index = self.protocol.message_types.index(message_type)
elif isinstance(message_type, int):
message_type_index = message_type
else:
message_type_index = 0
data = self.to_bits(data)
mt = self.protocol.message_types[message_type_index] # type: MessageType
mt.sort()
bits = []
start = 0
data_label_present = mt.get_first_label_with_type(FieldType.Function.DATA) is not None
if data_label_present:
message_length = mt[-1].end - 1
else:
message_length = mt[-1].end - 1 + len(data)
checksum_labels = []
for lbl in mt: # type: ProtocolLabel
bits.append("0" * (lbl.start - start))
len_field = lbl.end - lbl.start # in bits
if isinstance(lbl, ChecksumLabel):
checksum_labels.append(lbl)
continue # processed last
if lbl.field_type.function == FieldType.Function.PREAMBLE:
preamble = self.preambles_by_message_type[mt]
assert len(preamble) == len_field
bits.append(preamble)
message_length -= len(preamble)
elif lbl.field_type.function == FieldType.Function.SYNC:
sync = self.syncs_by_message_type[mt]
assert len(sync) == len_field
bits.append(sync)
message_length -= len(sync)
elif lbl.field_type.function == FieldType.Function.LENGTH:
value = int(math.ceil(message_length / 8))
if not self.length_in_bytes:
value *= 8
bits.append(self.decimal_to_bits(value, len_field))
elif lbl.field_type.function == FieldType.Function.TYPE:
bits.append(self.decimal_to_bits(self.message_type_codes[mt] % (2 ** len_field), len_field))
elif lbl.field_type.function == FieldType.Function.SEQUENCE_NUMBER:
bits.append(self.decimal_to_bits(self.sequence_numbers[mt] % (2 ** len_field), len_field))
elif lbl.field_type.function == FieldType.Function.DST_ADDRESS:
dst_bits = self.__get_address_for_participant(destination)
if len(dst_bits) != len_field:
raise ValueError(
"Length of dst ({0} bits) != length dst field ({1} bits)".format(len(dst_bits), len_field))
bits.append(dst_bits)
elif lbl.field_type.function == FieldType.Function.SRC_ADDRESS:
src_bits = self.__get_address_for_participant(source)
if len(src_bits) != len_field:
raise ValueError(
"Length of src ({0} bits) != length src field ({1} bits)".format(len(src_bits), len_field))
bits.append(src_bits)
elif lbl.field_type.function == FieldType.Function.DATA:
if len(data) != len_field:
raise ValueError(
"Length of data ({} bits) != length data field ({} bits)".format(len(data), len_field))
bits.append(data)
start = lbl.end
if not data_label_present:
bits.append(data)
msg = Message.from_plain_bits_str("".join(bits))
msg.message_type = mt
msg.participant = source
self.sequence_numbers[mt] += self.sequence_number_increment
for checksum_label in checksum_labels:
msg[checksum_label.start:checksum_label.end] = checksum_label.calculate_checksum_for_message(msg, False)
self.protocol.messages.append(msg)
def to_file(self, filename: str):
self.protocol.to_xml_file(filename, [], self.participants, write_bits=True)
def export_to_latex(self, filename: str, number: int):
def export_message_type_to_latex(message_type, f):
f.write(" \\begin{itemize}\n")
for lbl in message_type: # type: ProtocolLabel
if lbl.field_type.function == FieldType.Function.SYNC:
sync = array("B", map(int, self.syncs_by_message_type[message_type]))
f.write(" \\item {}: \\texttt{{0x{}}}\n".format(lbl.name, util.bit2hex(sync)))
elif lbl.field_type.function == FieldType.Function.PREAMBLE:
preamble = array("B", map(int, self.preambles_by_message_type[message_type]))
f.write(" \\item {}: \\texttt{{0x{}}}\n".format(lbl.name, util.bit2hex(preamble)))
elif lbl.field_type.function == FieldType.Function.CHECKSUM:
f.write(" \\item {}: {}\n".format(lbl.name, lbl.checksum.caption))
elif lbl.field_type.function in (FieldType.Function.LENGTH, FieldType.Function.SEQUENCE_NUMBER) and lbl.length > 8:
f.write(" \\item {}: {} bit (\\textbf{{{} endian}})\n".format(lbl.name, lbl.length, "little" if self.little_endian else "big"))
elif lbl.field_type.function == FieldType.Function.DATA:
f.write(" \\item payload: {} byte\n".format(lbl.length // 8))
else:
f.write(" \\item {}: {} bit\n".format(lbl.name, lbl.length))
f.write(" \\end{itemize}\n")
with open(filename, "a") as f:
f.write("\\subsection{{Protocol {}}}\n".format(number))
if len(self.participants) > 1:
f.write("There were {} participants involved in communication: ".format(len(self.participants)))
f.write(", ".join("{} (\\texttt{{0x{}}})".format(p.name, p.address_hex) for p in self.participants[:-1]))
f.write(" and {} (\\texttt{{0x{}}})".format(self.participants[-1].name, self.participants[-1].address_hex))
f.write(".\n")
if len(self.message_types) == 1:
f.write("The protocol has one message type with the following fields:\n")
export_message_type_to_latex(self.message_types[0], f)
else:
f.write("The protocol has {} message types with the following fields:\n".format(len(self.message_types)))
f.write("\\begin{itemize}\n")
for mt in self.message_types:
f.write(" \\item \\textbf{{{}}}\n".format(mt.name))
export_message_type_to_latex(mt, f)
f.write("\\end{itemize}\n")
f.write("\n")
if __name__ == '__main__':
mb = MessageTypeBuilder("test")
mb.add_label(FieldType.Function.PREAMBLE, 8)
mb.add_label(FieldType.Function.SYNC, 4)
mb.add_label(FieldType.Function.LENGTH, 8)
mb.add_label(FieldType.Function.SEQUENCE_NUMBER, 16)
mb.add_label(FieldType.Function.SRC_ADDRESS, 16)
mb.add_label(FieldType.Function.DST_ADDRESS, 16)
pg = ProtocolGenerator([mb.message_type], [], little_endian=False)
pg.generate_message(data="1" * 8)
pg.generate_message(data="1" * 16)
pg.generate_message(data="0xab", source=Participant("Alice", "A", "1234"),
destination=Participant("Bob", "B", "4567"))
pg.to_file("/tmp/test.proto")

View File

@ -1,399 +0,0 @@
import itertools
import math
from array import array
from collections import defaultdict, Counter
import numpy as np
from urh.awre.CommonRange import CommonRange
from urh.awre.engines.Engine import Engine
from urh.cythonext import awre_util
from urh.util.Logger import logger
class AddressEngine(Engine):
def __init__(self, msg_vectors, participant_indices, known_participant_addresses: dict = None,
already_labeled: list = None, src_field_present=False):
"""
:param msg_vectors: Message data behind synchronization
:type msg_vectors: list of np.ndarray
:param participant_indices: list of participant indices
where ith position holds participants index for ith messages
:type participant_indices: list of int
"""
assert len(msg_vectors) == len(participant_indices)
self.minimum_score = 0.1
self.msg_vectors = msg_vectors
self.participant_indices = participant_indices
self.already_labeled = []
self.src_field_present = src_field_present
if already_labeled is not None:
for start, end in already_labeled:
# convert it to hex
self.already_labeled.append((int(math.ceil(start / 4)), int(math.ceil(end / 4))))
self.message_indices_by_participant = defaultdict(list)
for i, participant_index in enumerate(self.participant_indices):
self.message_indices_by_participant[participant_index].append(i)
if known_participant_addresses is None:
self.known_addresses_by_participant = dict() # type: dict[int, np.ndarray]
else:
self.known_addresses_by_participant = known_participant_addresses # type: dict[int, np.ndarray]
@staticmethod
def cross_swap_check(rng1: CommonRange, rng2: CommonRange):
return (rng1.start == rng2.start + rng1.length or rng1.start == rng2.start - rng1.length) \
and rng1.value.tobytes() == rng2.value.tobytes()
@staticmethod
def ack_check(rng1: CommonRange, rng2: CommonRange):
return rng1.start == rng2.start and rng1.length == rng2.length and rng1.value.tobytes() != rng2.value.tobytes()
def find(self):
addresses_by_participant = {p: [addr.tostring()] for p, addr in self.known_addresses_by_participant.items()}
addresses_by_participant.update(self.find_addresses())
self._debug("Addresses by participant", addresses_by_participant)
# Find the address candidates by participant in messages
ranges_by_participant = defaultdict(list) # type: dict[int, list[CommonRange]]
addresses = [np.array(np.frombuffer(a, dtype=np.uint8))
for address_list in addresses_by_participant.values()
for a in address_list]
already_labeled_cols = array("L", [e for rng in self.already_labeled for e in range(*rng)])
# Find occurrences of address candidates in messages and create common ranges over matching positions
for i, msg_vector in enumerate(self.msg_vectors):
participant = self.participant_indices[i]
for address in addresses:
for index in awre_util.find_occurrences(msg_vector, address, already_labeled_cols):
common_ranges = ranges_by_participant[participant]
rng = next((cr for cr in common_ranges if cr.matches(index, address)), None) # type: CommonRange
if rng is not None:
rng.message_indices.add(i)
else:
common_ranges.append(CommonRange(index, len(address), address,
message_indices={i},
range_type="hex"))
num_messages_by_participant = defaultdict(int)
for participant in self.participant_indices:
num_messages_by_participant[participant] += 1
# Look for cross swapped values between participant clusters
for p1, p2 in itertools.combinations(ranges_by_participant, 2):
ranges1_set, ranges2_set = set(ranges_by_participant[p1]), set(ranges_by_participant[p2])
for rng1, rng2 in itertools.product(ranges_by_participant[p1], ranges_by_participant[p2]):
if rng1 in ranges2_set and rng2 in ranges1_set:
if self.cross_swap_check(rng1, rng2):
rng1.score += len(rng2.message_indices) / num_messages_by_participant[p2]
rng2.score += len(rng1.message_indices) / num_messages_by_participant[p1]
elif self.ack_check(rng1, rng2):
# Add previous score in divisor to add bonus to ranges that apply to all messages
rng1.score += len(rng2.message_indices) / (num_messages_by_participant[p2] + rng1.score)
rng2.score += len(rng1.message_indices) / (num_messages_by_participant[p1] + rng2.score)
if len(ranges_by_participant) == 1 and not self.src_field_present:
for p, ranges in ranges_by_participant.items():
for rng in sorted(ranges):
try:
if np.array_equal(rng.value, self.known_addresses_by_participant[p]):
# Only one participant in this iteration and address already known -> Highscore
rng.score = 1
break # Take only the first (leftmost) range
except KeyError:
pass
high_scored_ranges_by_participant = defaultdict(list)
address_length = self.__estimate_address_length(ranges_by_participant)
# Get highscored ranges by participant
for participant, common_ranges in ranges_by_participant.items():
# Sort by negative score so ranges with highest score appear first
# Secondary sort by tuple to ensure order when ranges have same score
sorted_ranges = sorted(filter(lambda cr: cr.score > self.minimum_score, common_ranges),
key=lambda cr: (-cr.score, cr))
if len(sorted_ranges) == 0:
addresses_by_participant[participant] = dict()
continue
addresses_by_participant[participant] = {a for a in addresses_by_participant.get(participant, [])
if len(a) == address_length}
for rng in filter(lambda r: r.length == address_length, sorted_ranges):
rng.score = min(rng.score, 1.0)
high_scored_ranges_by_participant[participant].append(rng)
# Now we find the most probable address for all participants
self.__assign_participant_addresses(addresses_by_participant, high_scored_ranges_by_participant)
# Eliminate participants for which we could not assign an address
for participant, address in addresses_by_participant.copy().items():
if address is None:
del addresses_by_participant[participant]
# Now we can separate SRC and DST
for participant, ranges in high_scored_ranges_by_participant.items():
try:
address = addresses_by_participant[participant]
except KeyError:
high_scored_ranges_by_participant[participant] = []
continue
result = []
for rng in sorted(ranges, key=lambda r: r.score, reverse=True):
rng.field_type = "source address" if rng.value.tostring() == address else "destination address"
if len(result) == 0:
result.append(rng)
else:
subset = next((r for r in result if rng.message_indices.issubset(r.message_indices)), None)
if subset is not None:
if rng.field_type == subset.field_type:
# Avoid adding same address type twice
continue
if rng.length != subset.length or (rng.start != subset.end + 1 and rng.end + 1 != subset.start):
# Ensure addresses are next to each other
continue
result.append(rng)
high_scored_ranges_by_participant[participant] = result
self.__find_broadcast_fields(high_scored_ranges_by_participant, addresses_by_participant)
result = [rng for ranges in high_scored_ranges_by_participant.values() for rng in ranges]
# If we did not find a SRC address, lower the score a bit,
# so DST fields do not win later e.g. again length fields in case of tie
if not any(rng.field_type == "source address" for rng in result):
for rng in result:
rng.score *= 0.95
return result
def __estimate_address_length(self, ranges_by_participant: dict):
"""
Estimate the address length which is assumed to be the same for all participants
:param ranges_by_participant:
:return:
"""
address_lengths = []
for participant, common_ranges in ranges_by_participant.items():
sorted_ranges = sorted(filter(lambda cr: cr.score > self.minimum_score, common_ranges),
key=lambda cr: (-cr.score, cr))
max_scored = [r for r in sorted_ranges if r.score == sorted_ranges[0].score]
# Prevent overestimation of address length by looking for substrings
for rng in max_scored[:]:
same_message_rng = [r for r in sorted_ranges
if r not in max_scored and r.score > 0 and r.message_indices == rng.message_indices]
if len(same_message_rng) > 1 and all(
r.value.tobytes() in rng.value.tobytes() for r in same_message_rng):
# remove the longer range and add the smaller ones
max_scored.remove(rng)
max_scored.extend(same_message_rng)
possible_address_lengths = [r.length for r in max_scored]
# Count possible address lengths.
frequencies = Counter(possible_address_lengths)
# Take the most common one. On tie, take the shorter one
try:
addr_len = max(frequencies, key=lambda x: (frequencies[x], -x))
address_lengths.append(addr_len)
except ValueError: # max() arg is an empty sequence
pass
# Take most common address length of participants, to ensure they all have same address length
counted = Counter(address_lengths)
try:
address_length = max(counted, key=lambda x: (counted[x], -x))
return address_length
except ValueError: # max() arg is an empty sequence
return 0
def __assign_participant_addresses(self, addresses_by_participant, high_scored_ranges_by_participant):
scored_participants_addresses = dict()
for participant in addresses_by_participant:
scored_participants_addresses[participant] = defaultdict(int)
for participant, addresses in addresses_by_participant.items():
if participant in self.known_addresses_by_participant:
address = self.known_addresses_by_participant[participant].tostring()
scored_participants_addresses[participant][address] = 9999999999
continue
for i in self.message_indices_by_participant[participant]:
matching = [rng for rng in high_scored_ranges_by_participant[participant]
if i in rng.message_indices and rng.value.tostring() in addresses]
if len(matching) == 1:
address = matching[0].value.tostring()
# only one address, so probably a destination and not a source
scored_participants_addresses[participant][address] *= 0.9
# Since this is probably an ACK, the address is probably SRC of participant of previous message
if i > 0 and self.participant_indices[i - 1] != participant:
prev_participant = self.participant_indices[i - 1]
prev_matching = [rng for rng in high_scored_ranges_by_participant[prev_participant]
if i - 1 in rng.message_indices and rng.value.tostring() in addresses]
if len(prev_matching) > 1:
for prev_rng in filter(lambda r: r.value.tostring() == address, prev_matching):
scored_participants_addresses[prev_participant][address] += prev_rng.score
elif len(matching) > 1:
# more than one address, so there must be a source address included
for rng in matching:
scored_participants_addresses[participant][rng.value.tostring()] += rng.score
minimum_score = 0.5
taken_addresses = set()
self._debug("Scored addresses", scored_participants_addresses)
# If all participants have exactly one possible address and they all differ, we can assign them right away
if all(len(addresses) == 1 for addresses in scored_participants_addresses.values()):
all_addresses = [list(addresses)[0] for addresses in scored_participants_addresses.values()]
if len(all_addresses) == len(set(all_addresses)): # ensure all addresses are different
for p, addresses in scored_participants_addresses.items():
addresses_by_participant[p] = list(addresses)[0]
return
for participant, addresses in sorted(scored_participants_addresses.items()):
try:
# sort filtered results to prevent randomness for equal scores
found_address = max(sorted(
filter(lambda a: a not in taken_addresses and addresses[a] >= minimum_score, addresses),
reverse=True
), key=addresses.get)
except ValueError:
# Could not assign address for this participant
addresses_by_participant[participant] = None
continue
addresses_by_participant[participant] = found_address
taken_addresses.add(found_address)
def __find_broadcast_fields(self, high_scored_ranges_by_participant, addresses_by_participant: dict):
"""
Last we check for messages that were sent to broadcast
1. we search for messages that have a SRC address but no DST address
2. we look at other messages that have this SRC field and find the corresponding DST position
3. we evaluate the value of message without DST from 1 and compare these values with each other.
if they match, we found the broadcast address
:param high_scored_ranges_by_participant:
:return:
"""
if -1 in addresses_by_participant:
# broadcast address is already known
return
broadcast_bag = defaultdict(list) # type: dict[CommonRange, list[int]]
for common_ranges in high_scored_ranges_by_participant.values():
src_address_fields = sorted(filter(lambda r: r.field_type == "source address", common_ranges))
dst_address_fields = sorted(filter(lambda r: r.field_type == "destination address", common_ranges))
msg_with_dst = {i for dst_address_field in dst_address_fields for i in dst_address_field.message_indices}
for src_address_field in src_address_fields: # type: CommonRange
msg_without_dst = {i for i in src_address_field.message_indices if i not in msg_with_dst}
if len(msg_without_dst) == 0:
continue
try:
matching_dst = next(dst for dst in dst_address_fields
if all(i in dst.message_indices
for i in src_address_field.message_indices - msg_without_dst))
except StopIteration:
continue
for msg in msg_without_dst:
broadcast_bag[matching_dst].append(msg)
if len(broadcast_bag) == 0:
return
broadcast_address = None
for dst, messages in broadcast_bag.items():
for msg_index in messages:
value = self.msg_vectors[msg_index][dst.start:dst.end + 1]
if broadcast_address is None:
broadcast_address = value
elif value.tobytes() != broadcast_address.tobytes():
# Address is not common across messages so it can't be a broadcast address
return
addresses_by_participant[-1] = broadcast_address.tobytes()
for dst, messages in broadcast_bag.items():
dst.values.append(broadcast_address)
dst.message_indices.update(messages)
def find_addresses(self) -> dict:
already_assigned = list(self.known_addresses_by_participant.keys())
if len(already_assigned) == len(self.message_indices_by_participant):
self._debug("Skipping find addresses as already known.")
return dict()
common_ranges_by_participant = dict()
for participant, message_indices in self.message_indices_by_participant.items():
# Cluster by length
length_clusters = defaultdict(list)
for i in message_indices:
length_clusters[len(self.msg_vectors[i])].append(i)
common_ranges_by_length = self.find_common_ranges_by_cluster(self.msg_vectors, length_clusters, range_type="hex")
common_ranges_by_participant[participant] = []
for ranges in common_ranges_by_length.values():
common_ranges_by_participant[participant].extend(self.ignore_already_labeled(ranges,
self.already_labeled))
self._debug("Common ranges by participant:", common_ranges_by_participant)
result = defaultdict(set)
participants = sorted(common_ranges_by_participant) # type: list[int]
if len(participants) < 2:
return result
# If we already know the address length we do not need to bother with other candidates
if len(already_assigned) > 0:
addr_len = len(self.known_addresses_by_participant[already_assigned[0]])
if any(len(self.known_addresses_by_participant[i]) != addr_len for i in already_assigned):
logger.warning("Addresses do not have a common length. Assuming length of {}".format(addr_len))
else:
addr_len = None
for p1, p2 in itertools.combinations(participants, 2):
p1_already_assigned = p1 in already_assigned
p2_already_assigned = p2 in already_assigned
if p1_already_assigned and p2_already_assigned:
continue
# common ranges are not merged yet, so there is only one element in values
values1 = [cr.value for cr in common_ranges_by_participant[p1]]
values2 = [cr.value for cr in common_ranges_by_participant[p2]]
for seq1, seq2 in itertools.product(values1, values2):
lcs = self.find_longest_common_sub_sequences(seq1, seq2)
vals = lcs if len(lcs) > 0 else [seq1, seq2]
# Address candidate must be at least 2 values long
for val in filter(lambda v: len(v) >= 2, vals):
if addr_len is not None and len(val) != addr_len:
continue
if not p1_already_assigned and not p2_already_assigned:
result[p1].add(val.tostring())
result[p2].add(val.tostring())
elif p1_already_assigned and val.tostring() != self.known_addresses_by_participant[p1].tostring():
result[p2].add(val.tostring())
elif p2_already_assigned and val.tostring() != self.known_addresses_by_participant[p2].tostring():
result[p1].add(val.tostring())
return result

View File

@ -1,121 +0,0 @@
import copy
import math
from collections import defaultdict
import numpy as np
from urh.util.WSPChecksum import WSPChecksum
from urh.awre.CommonRange import ChecksumRange
from urh.awre.engines.Engine import Engine
from urh.cythonext import awre_util
from urh.util.GenericCRC import GenericCRC
class ChecksumEngine(Engine):
def __init__(self, bitvectors, n_gram_length=8, minimum_score=0.9, already_labeled: list = None):
"""
:type bitvectors: list of np.ndarray
:param bitvectors: bitvectors behind the synchronization
"""
self.bitvectors = bitvectors
self.n_gram_length = n_gram_length
self.minimum_score = minimum_score
if already_labeled is None:
self.already_labeled_cols = set()
else:
self.already_labeled_cols = {e for rng in already_labeled for e in range(*rng)}
def find(self):
result = list()
bitvectors_by_n_gram_length = defaultdict(list)
for i, bitvector in enumerate(self.bitvectors):
bin_num = int(math.ceil(len(bitvector) / self.n_gram_length))
bitvectors_by_n_gram_length[bin_num].append(i)
crc = GenericCRC()
for length, message_indices in bitvectors_by_n_gram_length.items():
checksums_for_length = []
for index in message_indices:
bits = self.bitvectors[index]
data_start, data_stop, crc_start, crc_stop = WSPChecksum.search_for_wsp_checksum(bits)
if (data_start, data_stop, crc_start, crc_stop) != (0, 0, 0, 0):
checksum_range = ChecksumRange(start=crc_start, length=crc_stop-crc_start,
data_range_start=data_start, data_range_end=data_stop,
crc=WSPChecksum(), score=1/len(message_indices),
field_type="checksum", message_indices={index})
try:
present = next(c for c in checksums_for_length if c == checksum_range)
present.message_indices.add(index)
except StopIteration:
checksums_for_length.append(checksum_range)
continue
crc_object, data_start, data_stop, crc_start, crc_stop = crc.guess_all(bits,
ignore_positions=self.already_labeled_cols)
if (crc_object, data_start, data_stop, crc_start, crc_stop) != (0, 0, 0, 0, 0):
checksum_range = ChecksumRange(start=crc_start, length=crc_stop - crc_start,
data_range_start=data_start, data_range_end=data_stop,
crc=copy.copy(crc_object), score=1 / len(message_indices),
field_type="checksum", message_indices={index}
)
try:
present = next(rng for rng in checksums_for_length if rng == checksum_range)
present.message_indices.add(index)
continue
except StopIteration:
pass
checksums_for_length.append(checksum_range)
matching = awre_util.check_crc_for_messages(message_indices, self.bitvectors,
data_start, data_stop,
crc_start, crc_stop,
*crc_object.get_parameters())
checksum_range.message_indices.update(matching)
# Score ranges
for rng in checksums_for_length:
rng.score = len(rng.message_indices) / len(message_indices)
try:
result.append(max(checksums_for_length, key=lambda x: x.score))
except ValueError:
pass # no checksums found for this length
self._debug("Found Checksums", result)
try:
max_scored = max(filter(lambda x: len(x.message_indices) >= 2 and x.score >= self.minimum_score, result),
key=lambda x: x.score)
except ValueError:
return []
result = list(filter(lambda x: x.crc == max_scored.crc, result))
self._debug("Filtered Checksums", result)
return result
@staticmethod
def calc_score(diff_frequencies: dict) -> float:
"""
Calculate the score based on the distribution of differences
1. high if one constant (!= zero) dominates
2. Other constants (!= zero) should lower the score, zero means sequence number stays same for some messages
:param diff_frequencies: Frequencies of decimal differences between columns of subsequent messages
e.g. {-255: 3, 1: 1020} means -255 appeared 3 times and 1 appeared 1020 times
:return: a score between 0 and 1
"""
total = sum(diff_frequencies.values())
num_zeros = sum(v for k, v in diff_frequencies.items() if k == 0)
if num_zeros == total:
return 0
try:
most_frequent = ChecksumEngine.get_most_frequent(diff_frequencies)
except ValueError:
return 0
return diff_frequencies[most_frequent] / (total - num_zeros)

View File

@ -1,85 +0,0 @@
from urh.awre.CommonRange import CommonRange
from urh.awre.Histogram import Histogram
import numpy as np
from urh.cythonext import awre_util
import itertools
class Engine(object):
_DEBUG_ = False
def _debug(self, *args):
if self._DEBUG_:
print("[{}]".format(self.__class__.__name__), *args)
@staticmethod
def find_common_ranges_by_cluster(msg_vectors, clustered_bitvectors, alpha=0.95, range_type="bit"):
"""
:param alpha: How many percent of values must be equal per range?
:param range_type: Describes what kind of range this is: bit, hex or byte.
Needed for conversion of range start / end later
:type msg_vectors: list of np.ndarray
:type clustered_bitvectors: dict
:rtype: dict[int, list of CommonRange]
"""
histograms = {
cluster: Histogram(msg_vectors, message_indices)
for cluster, message_indices in clustered_bitvectors.items()
}
common_ranges_by_cluster = {
cluster: histogram.find_common_ranges(alpha=alpha, range_type=range_type)
for cluster, histogram in histograms.items()
}
return common_ranges_by_cluster
@staticmethod
def find_common_ranges_exhaustive(msg_vectors, msg_indices, range_type="bit") -> list:
result = []
for i, j in itertools.combinations(msg_indices, 2):
for rng in Histogram(msg_vectors, indices=[i, j]).find_common_ranges(alpha=1, range_type=range_type):
try:
common_range = next(cr for cr in result if cr.start == rng.start and cr.value.tobytes() == rng.value.tobytes())
common_range.message_indices.update({i, j})
except StopIteration:
result.append(rng)
return result
@staticmethod
def ignore_already_labeled(common_ranges, already_labeled):
"""
Shrink the common ranges so that they not overlap with already labeled ranges.
Empty common ranges are removed after shrinking
:type common_ranges: list of CommonRange
:type already_labeled: list of tuple
:return: list of CommonRange
"""
result = []
for common_range in common_ranges:
range_result = [common_range]
for start, end in already_labeled:
for rng in range_result[:]:
range_result.remove(rng)
range_result.extend(rng.ensure_not_overlaps(start, end))
result.extend(range_result)
return result
@staticmethod
def find_longest_common_sub_sequences(seq1, seq2) -> list:
result = []
if seq1 is None or seq2 is None:
return result
indices = awre_util.find_longest_common_sub_sequence_indices(seq1, seq2)
for ind in indices:
s = seq1[slice(*ind)]
if len(s) > 0:
result.append(s)
return result

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