Compare commits
76 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
72faef14ff | ||
|
|
dcb888c027 | ||
|
|
99e0354b3d | ||
|
|
bf853a0278 | ||
|
|
a1000b5df9 | ||
|
|
38a3bb273b | ||
|
|
6925a043fe | ||
|
|
43539ba773 | ||
|
|
0b62fc2abe | ||
|
|
a9d29b6d34 | ||
|
|
6a75e41d87 | ||
|
|
ff96e9b41a | ||
|
|
11c00939ab | ||
|
|
de3c8bb4c9 | ||
|
|
be215a39c3 | ||
|
|
b7e4f5f2ef | ||
|
|
674ae06bdf | ||
|
|
924b00f892 | ||
|
|
b003324772 | ||
|
|
1c1469ba53 | ||
|
|
6b6c6e9870 | ||
|
|
fe4a1ce9f4 | ||
|
|
6497c21ff8 | ||
|
|
7e6dbcc1ae | ||
|
|
b89e761d0c | ||
|
|
244cf19065 | ||
|
|
fb6ddddd3a | ||
|
|
032966ef57 | ||
|
|
7ab8abe3f9 | ||
|
|
a40262cc8a | ||
|
|
73d9e4096f | ||
|
|
101ff3f0e2 | ||
|
|
72b129c83d | ||
|
|
be33fb01e5 | ||
|
|
870162aec8 | ||
|
|
cbcc8703e3 | ||
|
|
8cf2f0e84d | ||
|
|
31c8392d47 | ||
|
|
23ae6374e7 | ||
|
|
db017bdfac | ||
|
|
27f04ade85 | ||
|
|
02840e9d8a | ||
|
|
611e337acd | ||
|
|
9446783a5c | ||
|
|
2e7436b58e | ||
|
|
fecae48d14 | ||
|
|
1bfd9977bd | ||
|
|
60f4ba9357 | ||
|
|
70ccc91c9e | ||
|
|
f0a365f70c | ||
|
|
ea170b1378 | ||
|
|
5fa5489be9 | ||
|
|
0e9a7c138f | ||
|
|
ec8c20a995 | ||
|
|
2d8f7518b7 | ||
|
|
d4e12190ef | ||
|
|
00847ec8f3 | ||
|
|
df66b09b09 | ||
|
|
1285c57eaf | ||
|
|
1031f9814b | ||
|
|
eff8f91e27 | ||
|
|
0baa32ac2c | ||
|
|
d1e6493ee6 | ||
|
|
05326fac38 | ||
|
|
9f6100eb2e | ||
|
|
ff480c0158 | ||
|
|
911c06b199 | ||
|
|
f1f8507c73 | ||
|
|
9f99994136 | ||
|
|
8c8edaa99a | ||
|
|
c92f544b55 | ||
|
|
0c7323746a | ||
|
|
ba2d3fc297 | ||
|
|
27dd6efb23 | ||
|
|
81130f1498 | ||
|
|
99b8ab1ae6 |
48
.gitignore
vendored
|
|
@ -1,3 +1,51 @@
|
|||
.*
|
||||
!.gitignore
|
||||
!.travis.yml
|
||||
!.valgrind.supp
|
||||
|
||||
# Object files
|
||||
*.o
|
||||
*.ko
|
||||
*.obj
|
||||
*.elf
|
||||
build
|
||||
tg-timer.res
|
||||
|
||||
# Executables
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
*.i*86
|
||||
*.x86_64
|
||||
*.hex
|
||||
tg-timer
|
||||
tg-timer-dbg
|
||||
tg-timer-prf
|
||||
tg-timer-vlg
|
||||
|
||||
# autotools
|
||||
Makefile
|
||||
Makefile.in
|
||||
/autom4te.cache
|
||||
/aclocal.m4
|
||||
/compile
|
||||
/configure
|
||||
/depcomp
|
||||
/install-sh
|
||||
/missing
|
||||
/stamp-h1
|
||||
/config.*
|
||||
/libtool
|
||||
/ltmain.sh
|
||||
/test-driver
|
||||
/test-suite.log
|
||||
.libs
|
||||
.deps
|
||||
.dirstamp
|
||||
*.log
|
||||
*.trs
|
||||
*.tar.gz
|
||||
|
||||
# build directories
|
||||
/deb
|
||||
/msi
|
||||
|
|
|
|||
15
.travis.yml
|
|
@ -1,5 +1,8 @@
|
|||
language: c
|
||||
|
||||
sudo: false
|
||||
dist: trusty
|
||||
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
|
|
@ -15,7 +18,7 @@ env:
|
|||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- libgtk2.0-dev
|
||||
- libgtk-3-dev
|
||||
- libjack-jackd2-dev
|
||||
- portaudio19-dev
|
||||
- libfftw3-dev
|
||||
|
|
@ -23,7 +26,7 @@ addons:
|
|||
before_install:
|
||||
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
|
||||
brew update;
|
||||
brew install gtk+;
|
||||
brew install gtk+3;
|
||||
brew install portaudio;
|
||||
brew install fftw;
|
||||
fi
|
||||
|
|
@ -34,8 +37,10 @@ before_script:
|
|||
sh -e /etc/init.d/xvfb start;
|
||||
fi;
|
||||
if [[ "$TARGET" == "test" ]]; then
|
||||
mkdir ~/.config;
|
||||
fi
|
||||
mkdir -p ~/.config;
|
||||
fi;
|
||||
|
||||
script:
|
||||
make "$TARGET"
|
||||
./autogen.sh;
|
||||
./configure;
|
||||
make "$TARGET";
|
||||
|
|
|
|||
13
.valgrind.supp
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
libasound1
|
||||
Memcheck:Cond
|
||||
obj:/usr/lib/x86_64-linux-gnu/libasound.so.2.0.0
|
||||
}
|
||||
|
||||
{
|
||||
libasound2
|
||||
Memcheck:Param
|
||||
ioctl(generic)
|
||||
fun:ioctl
|
||||
obj:/usr/lib/x86_64-linux-gnu/libasound.so.2.0.0
|
||||
}
|
||||
81
Makefile
|
|
@ -1,81 +0,0 @@
|
|||
VERSION := $(shell cat version)
|
||||
|
||||
CC ?= gcc
|
||||
BUILDDIR ?= build
|
||||
PREFIX ?= /usr/local
|
||||
|
||||
ifneq ($(shell uname -s),Darwin)
|
||||
LDFLAGS += -Wl,--as-needed
|
||||
endif
|
||||
|
||||
PACKAGES := gtk+-2.0 gthread-2.0 portaudio-2.0 fftw3f
|
||||
CFLAGS += -Wall -O3 -ffast-math -DVERSION='"$(VERSION)"' `pkg-config --cflags $(PACKAGES)`
|
||||
LDFLAGS += -lm -lpthread `pkg-config --libs $(PACKAGES)`
|
||||
|
||||
SRCDIR := src
|
||||
CFILES := $(wildcard $(SRCDIR)/*.c)
|
||||
HFILES := $(wildcard $(SRCDIR)/*.h)
|
||||
|
||||
ifeq ($(OS),Windows_NT)
|
||||
LDFLAGS += -mwindows
|
||||
DEBUG_LDFLAGS := -mconsole
|
||||
EXT := .exe
|
||||
RESFILE := $(BUILDDIR)/tg-timer.res
|
||||
else
|
||||
DEBUG_FLAGS :=
|
||||
EXT :=
|
||||
RESFILE :=
|
||||
endif
|
||||
|
||||
all: $(BUILDDIR)/tg$(EXT) $(BUILDDIR)/tg-lt$(EXT)
|
||||
.PHONY: all
|
||||
|
||||
debug: $(BUILDDIR)/tg-dbg$(EXT) $(BUILDDIR)/tg-lt-dbg$(EXT)
|
||||
.PHONY: debug
|
||||
|
||||
profile: $(BUILDDIR)/tg-prf$(EXT) $(BUILDDIR)/tg-lt-prf$(EXT)
|
||||
.PHONY: profile
|
||||
|
||||
test: $(BUILDDIR)/tg-dbg$(EXT)
|
||||
$(BUILDDIR)/tg-dbg test
|
||||
.PHONY: test
|
||||
|
||||
$(BUILDDIR)/tg-timer.res: icons/tg-timer.rc icons/tg-timer.ico
|
||||
windres icons/tg-timer.rc -O coff -o $(BUILDDIR)/tg-timer.res
|
||||
|
||||
define TARGET
|
||||
$(BUILDDIR)/$(1)_%.o: $(SRCDIR)/%.c $(HFILES)
|
||||
$(CC) -c $(CFLAGS) -DPROGRAM_NAME='"$(1)"' $(2) $$< -o $$@
|
||||
|
||||
$(BUILDDIR)/$(1)$(EXT): $(patsubst $(SRCDIR)/%.c,$(BUILDDIR)/$(1)_%.o,$(CFILES)) $(RESFILE)
|
||||
$(CC) -o $(BUILDDIR)/$(1)$(EXT) $$^ $(LDFLAGS) $(3)
|
||||
ifeq ($(4),strip)
|
||||
strip $(BUILDDIR)/$(1)$(EXT)
|
||||
endif
|
||||
endef
|
||||
|
||||
$(eval $(call TARGET,tg,,,strip))
|
||||
$(eval $(call TARGET,tg-lt,-DLIGHT,,strip))
|
||||
$(eval $(call TARGET,tg-dbg,-ggdb -DDEBUG,$(DEBUG_LDFLAGS),))
|
||||
$(eval $(call TARGET,tg-lt-dbg,-ggdb -DDEBUG -DLIGHT,$(DEBUG_LDFLAGS),))
|
||||
$(eval $(call TARGET,tg-prf,-pg,,))
|
||||
$(eval $(call TARGET,tg-lt-prf,-DLIGHT -pg,,))
|
||||
|
||||
ICONSIZES := $(foreach SIZE, $(shell cat icons/sizes), $(SIZE)x$(SIZE))
|
||||
|
||||
$(ICONSIZES): %: icons/%/tg-timer.png
|
||||
install -D -m 0644 $< $(PREFIX)/share/icons/hicolor/$@/apps/tg-timer.png
|
||||
.PHONY: $(ICONSIZES)
|
||||
|
||||
install: all $(ICONSIZES)
|
||||
install -D -m 0755 $(BUILDDIR)/tg$(EXT) $(PREFIX)/bin/tg-timer$(EXT)
|
||||
install -D -m 0755 $(BUILDDIR)/tg-lt$(EXT) $(PREFIX)/bin/tg-timer-lt$(EXT)
|
||||
install -D -m 0644 icons/tg-timer.desktop $(PREFIX)/share/applications/tg-timer.desktop
|
||||
install -D -m 0644 icons/tg-timer-lt.desktop $(PREFIX)/share/applications/tg-timer-lt.desktop
|
||||
install -D -m 0644 docs/tg-timer.1.gz $(PREFIX)/share/man/man1/tg-timer.1.gz
|
||||
ln -s tg-timer.1.gz $(PREFIX)/share/man/man1/tg-timer-lt.1.gz
|
||||
.PHONY: install
|
||||
|
||||
clean:
|
||||
rm -rf $(BUILDDIR)/*
|
||||
.PHONY: clean
|
||||
77
Makefile.am
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
SUBDIRS = icons
|
||||
bin_PROGRAMS = tg-timer
|
||||
EXTRA_PROGRAMS = tg-timer-dbg \
|
||||
tg-timer-prf \
|
||||
tg-timer-vlg
|
||||
MOSTLYCLEANFILES = $(EXTRA_PROGRAMS)
|
||||
|
||||
tg_timer_SOURCES = src/algo.c \
|
||||
src/audio.c \
|
||||
src/computer.c \
|
||||
src/config.c \
|
||||
src/interface.c \
|
||||
src/output_panel.c \
|
||||
src/serializer.c \
|
||||
src/tg.h
|
||||
|
||||
tg_timer_dbg_SOURCES = $(tg_timer_SOURCES)
|
||||
tg_timer_prf_SOURCES = $(tg_timer_SOURCES)
|
||||
tg_timer_vlg_SOURCES = $(tg_timer_SOURCES)
|
||||
|
||||
LIBS = $(GTK_LIBS) \
|
||||
$(GTHREAD_LIBS) \
|
||||
$(PORTAUDIO_LIBS) \
|
||||
$(FFTW_LIBS) \
|
||||
-lpthread \
|
||||
-lm
|
||||
|
||||
AM_CPPFLAGS = -DPROGRAM_NAME=\"Tg\" -DVERSION=\"$(PACKAGE_VERSION)\"
|
||||
tg_timer_dbg_CPPFLAGS = $(AM_CPPFLAGS) -DDEBUG
|
||||
|
||||
AM_CFLAGS = $(GTK_CFLAGS) \
|
||||
$(GTHREAD_CFLAGS) \
|
||||
$(PORTAUDIO_CFLAGS) \
|
||||
$(FFTW_CFLAGS)
|
||||
tg_timer_dbg_CFLAGS = $(AM_CFLAGS) -ggdb
|
||||
tg_timer_prf_CFLAGS = $(AM_CFLAGS) -pg
|
||||
tg_timer_vlg_CFLAGS = $(AM_CFLAGS) -g
|
||||
|
||||
tg_timer_LDFLAGS = $(AM_LDFLAGS)
|
||||
tg_timer_dbg_LDFLAGS = $(AM_LDFLAGS)
|
||||
tg_timer_prf_LDFLAGS = $(AM_LDFLAGS)
|
||||
tg_timer_vlg_LDFLAGS = $(AM_LDFLAGS)
|
||||
|
||||
if BE_WINDOWS
|
||||
if HAVE_WINDRES
|
||||
tg_timer_SOURCES += icons/tg-timer.rc
|
||||
endif
|
||||
tg_timer_LDFLAGS += -mwindows
|
||||
tg_timer_dbg_LDFLAGS += -mconsole
|
||||
tg_timer_prf_LDFLAGS += -mconsole
|
||||
tg_timer_vlg_LDFLAGS += -mconsole
|
||||
endif
|
||||
|
||||
desktopdir = $(datadir)/applications
|
||||
dist_desktop_DATA = icons/tg-timer.desktop
|
||||
|
||||
mimedir = $(datadir)/mime/packages
|
||||
dist_mime_DATA = icons/tg-timer.xml
|
||||
|
||||
dist_man_MANS = docs/tg-timer.1
|
||||
|
||||
EXTRA_DIST = autogen.sh \
|
||||
icons \
|
||||
packaging \
|
||||
LICENSE \
|
||||
README.md
|
||||
|
||||
.rc.o:
|
||||
$(WINDRES) $< -O coff -o $@
|
||||
|
||||
test: tg-timer-dbg
|
||||
./tg-timer-dbg test
|
||||
.PHONY: test
|
||||
|
||||
valgrind: tg-timer-vlg
|
||||
valgrind --leak-check=full -v --num-callers=99 --suppressions=.valgrind.supp ./$^
|
||||
.PHONY: valgrind
|
||||
65
README.md
|
|
@ -1,8 +1,9 @@
|
|||
# A program for timing mechanical watches [](https://travis-ci.org/vacaboja/tg)
|
||||
|
||||
The program tg is copyright (C) 2015 by Marcello Mamino, and it is
|
||||
distributed under the GNU GPL license version 2. The full source code of
|
||||
tg is available at https://github.com/vacaboja/tg
|
||||
The program tg is distributed under the GNU GPL license version 2. The full
|
||||
source code of tg is available at
|
||||
[https://github.com/vacaboja/tg](https://github.com/vacaboja/tg) and its
|
||||
copyright belongs to the respective contributors.
|
||||
|
||||
Tg is in development, and there is still no manual. Some info can be found
|
||||
in this
|
||||
|
|
@ -43,20 +44,66 @@ You can now launch tg by typing
|
|||
|
||||
Binary .deb packages can be downloaded from https://tg.ciovil.li
|
||||
|
||||
### Compiling from sources
|
||||
## Compiling from sources
|
||||
|
||||
The source code of tg can probably be built by any C99 compiler, however
|
||||
only gcc and clang have been tested. You need the following libraries:
|
||||
gtk2, portaudio2, fftw3 (all available as open-source).
|
||||
gtk+3, portaudio2, fftw3 (all available as open-source).
|
||||
|
||||
Release build:
|
||||
```sh
|
||||
git clone https://github.com/vacaboja/tg.git
|
||||
cd tg
|
||||
./autogen.sh
|
||||
./configure
|
||||
make
|
||||
```
|
||||
|
||||
Debug build:
|
||||
```sh
|
||||
make tg-timer-dbg
|
||||
```
|
||||
|
||||
### Compiling on Windows
|
||||
|
||||
It is suggested to use the msys2 platform. First install msys2 according
|
||||
to the instructions at [http://www.msys2.org](http://www.msys2.org). Then
|
||||
issue the following commands.
|
||||
|
||||
```sh
|
||||
pacman -S mingw-w64-x86_64-gcc make pkg-config mingw-w64-x86_64-gtk3 mingw-w64-x86_64-portaudio mingw-w64-x86_64-fftw git autoconf automake libtool
|
||||
git clone https://github.com/vacaboja/tg.git
|
||||
cd tg
|
||||
./autogen.sh
|
||||
./configure
|
||||
make
|
||||
```
|
||||
|
||||
### Compiling on Debian
|
||||
|
||||
To compile tg on Debian
|
||||
|
||||
sudo apt-get install libgtk2.0-dev libjack-jackd2-dev portaudio19-dev libfftw3-dev git
|
||||
git clone https://github.com/vacaboja/tg.git
|
||||
cd tg
|
||||
make
|
||||
```sh
|
||||
sudo apt-get install libgtk-3-dev libjack-jackd2-dev portaudio19-dev libfftw3-dev git autoconf automake libtool
|
||||
git clone https://github.com/vacaboja/tg.git
|
||||
cd tg
|
||||
./autogen.sh
|
||||
./configure
|
||||
make
|
||||
```
|
||||
|
||||
The package libjack-jackd2-dev is not necessary, it only works around a
|
||||
known bug (https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=718221).
|
||||
|
||||
### Compiling on Fedora
|
||||
|
||||
To compile tg on Fedora
|
||||
|
||||
```sh
|
||||
sudo dnf install fftw-devel portaudio-devel gtk3-devel autoconf automake libtool
|
||||
git clone https://github.com/vacaboja/tg.git
|
||||
cd tg
|
||||
./autogen.sh
|
||||
./configure
|
||||
make
|
||||
```
|
||||
|
|
|
|||
1580
autogen.sh
Executable file
2
build/.gitignore
vendored
|
|
@ -1,2 +0,0 @@
|
|||
*
|
||||
!.gitignore
|
||||
34
configure.ac
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
define([tg_version], m4_normalize(m4_include([version])))
|
||||
AC_CONFIG_MACRO_DIRS([m4])
|
||||
|
||||
AC_INIT([Tg], [tg_version], [vacaboja@gmail.com], [tg-timer], [https://github.com/vacaboja/tg])
|
||||
AM_INIT_AUTOMAKE([-Wall foreign subdir-objects])
|
||||
|
||||
AC_PROG_CC
|
||||
AC_CHECK_LIB([pthread], [pthread_mutex_init], [], [AC_MSG_ERROR([pthread not found])])
|
||||
AC_CHECK_LIB([m], [sqrt], [], [AC_MSG_ERROR([libm not found])])
|
||||
PKG_CHECK_MODULES([GTK], [gtk+-3.0 glib-2.0])
|
||||
PKG_CHECK_MODULES([PORTAUDIO], [portaudio-2.0])
|
||||
PKG_CHECK_MODULES([FFTW], [fftw3f])
|
||||
|
||||
AC_CHECK_TOOL([WINDRES], [windres])
|
||||
AM_CONDITIONAL([HAVE_WINDRES], [test x$WINDRES != x])
|
||||
|
||||
AM_CONDITIONAL([BE_WINDOWS], [test x$OS = xWindows_NT])
|
||||
AM_COND_IF([BE_WINDOWS], [AC_CONFIG_LINKS([icons/tg-timer.ico:icons/tg-timer.ico])])
|
||||
|
||||
CC_CHECK_LDFLAGS([-Wl,--as-needed], [AC_SUBST([AM_LDFLAGS], [-Wl,--as-needed])], [])
|
||||
CC_CHECK_CFLAGS_APPEND([-Wall -Wextra], [], [])
|
||||
|
||||
AC_OUTPUT([Makefile icons/Makefile])
|
||||
|
||||
AC_MSG_RESULT([
|
||||
$PACKAGE_NAME $VERSION
|
||||
=====
|
||||
|
||||
prefix: ${prefix}
|
||||
|
||||
compiler: ${CC}
|
||||
cflags: ${CFLAGS} ${AM_CFLAGS}
|
||||
ldflags: ${LDFLAGS} ${AM_LDFLAGS}
|
||||
])
|
||||
|
|
@ -4,7 +4,6 @@ tg \- a program for timing mechanincal watches
|
|||
.SH SYNOPSIS
|
||||
.nf
|
||||
.B tg-timer
|
||||
.B tg-timer-lt
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
Tg (tg-timer) is a program to evaluate the performance of mechanical watch
|
||||
|
|
|
|||
BIN
icons/128x128/apps/tg-timer.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
icons/128x128/mimetypes/application-x-tg-timer-data.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 15 KiB |
BIN
icons/16x16/apps/tg-timer.png
Normal file
|
After Width: | Height: | Size: 989 B |
BIN
icons/16x16/mimetypes/application-x-tg-timer-data.png
Normal file
|
After Width: | Height: | Size: 708 B |
|
Before Width: | Height: | Size: 975 B |
BIN
icons/22x22/apps/tg-timer.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
icons/22x22/mimetypes/application-x-tg-timer-data.png
Normal file
|
After Width: | Height: | Size: 1 KiB |
|
Before Width: | Height: | Size: 1.4 KiB |
BIN
icons/256x256/apps/tg-timer.png
Normal file
|
After Width: | Height: | Size: 35 KiB |
BIN
icons/256x256/mimetypes/application-x-tg-timer-data.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 37 KiB |
BIN
icons/32x32/apps/tg-timer.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
icons/32x32/mimetypes/application-x-tg-timer-data.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
BIN
icons/48x48/apps/tg-timer.png
Normal file
|
After Width: | Height: | Size: 3.9 KiB |
BIN
icons/48x48/mimetypes/application-x-tg-timer-data.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 3.9 KiB |
BIN
icons/64x64/apps/tg-timer.png
Normal file
|
After Width: | Height: | Size: 5.9 KiB |
BIN
icons/64x64/mimetypes/application-x-tg-timer-data.png
Normal file
|
After Width: | Height: | Size: 4 KiB |
|
Before Width: | Height: | Size: 5.8 KiB |
|
Before Width: | Height: | Size: 471 B |
19
icons/Makefile.am
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
iconsdir = $(datadir)/icons/hicolor
|
||||
nobase_dist_icons_DATA = \
|
||||
16x16/apps/tg-timer.png \
|
||||
22x22/apps/tg-timer.png \
|
||||
32x32/apps/tg-timer.png \
|
||||
48x48/apps/tg-timer.png \
|
||||
64x64/apps/tg-timer.png \
|
||||
128x128/apps/tg-timer.png \
|
||||
256x256/apps/tg-timer.png \
|
||||
scalable/apps/tg-timer.svg \
|
||||
16x16/mimetypes/application-x-tg-timer-data.png \
|
||||
22x22/mimetypes/application-x-tg-timer-data.png \
|
||||
32x32/mimetypes/application-x-tg-timer-data.png \
|
||||
48x48/mimetypes/application-x-tg-timer-data.png \
|
||||
64x64/mimetypes/application-x-tg-timer-data.png \
|
||||
128x128/mimetypes/application-x-tg-timer-data.png \
|
||||
256x256/mimetypes/application-x-tg-timer-data.png \
|
||||
scalable/mimetypes/application-x-tg-timer-data.svg
|
||||
|
||||
|
|
@ -2,9 +2,10 @@
|
|||
|
||||
for A in `cat sizes`;
|
||||
do
|
||||
if test ! -d $[A]x$[A]
|
||||
then
|
||||
mkdir $[A]x$[A]
|
||||
fi
|
||||
inkscape -z -e $[A]x$[A]/tg-timer.png -w $A -h $A scalable/tg-timer.svg
|
||||
mkdir -p ${A}x${A}/apps
|
||||
mkdir -p ${A}x${A}/mimetypes
|
||||
inkscape -z -e ${A}x${A}/apps/tg-timer.png -w $A -h $A scalable/apps/tg-timer.svg &>/dev/null
|
||||
optipng -quiet ${A}x${A}/apps/tg-timer.png
|
||||
inkscape -z -e ${A}x${A}/mimetypes/application-x-tg-timer-data.png -w $A -h $A scalable/application-x-tg-timer-data.svg &>/dev/null
|
||||
optipng -quiet ${A}x${A}/mimetypes/application-x-tg-timer-data.png
|
||||
done
|
||||
|
|
|
|||
|
|
@ -2,6 +2,10 @@
|
|||
|
||||
SIZES=`cat sizes`
|
||||
|
||||
PNGS=`for A in $SIZES; do echo $[A]x$[A]/tg-timer.png; done`
|
||||
PNGS=`for A in $SIZES; do echo ${A}x${A}/apps/tg-timer.png; done`
|
||||
|
||||
icotool -c -o tg-timer.ico $PNGS
|
||||
|
||||
PNGS=`for A in $SIZES; do echo ${A}x${A}/mimetypes/application-x-tg-timer-data.png; done`
|
||||
|
||||
icotool -c -o tg-document.ico $PNGS
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
279
icons/scalable/mimetypes/application-x-tg-timer-data.svg
Normal file
|
|
@ -0,0 +1,279 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<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:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
id="svg144"
|
||||
version="1.1"
|
||||
width="48px"
|
||||
height="48px"
|
||||
sodipodi:docname="tg-document.svg"
|
||||
inkscape:version="0.92.1 r15371">
|
||||
<sodipodi:namedview
|
||||
pagecolor="#000000"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1020"
|
||||
id="namedview47"
|
||||
showgrid="false"
|
||||
showborder="false"
|
||||
inkscape:zoom="6.9532168"
|
||||
inkscape:cx="25.922372"
|
||||
inkscape:cy="22.442674"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="31"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg144" />
|
||||
<metadata
|
||||
id="metadata148">
|
||||
<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>
|
||||
<defs
|
||||
id="defs104">
|
||||
<radialGradient
|
||||
r="15.82"
|
||||
gradientTransform="matrix(1.076,0,0,0.285,56.929661,32.427119)"
|
||||
cx="24.31"
|
||||
cy="42.1"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="b">
|
||||
<stop
|
||||
id="stop79"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop81"
|
||||
offset="1"
|
||||
stop-opacity="0" />
|
||||
</radialGradient>
|
||||
<radialGradient
|
||||
xlink:href="#linearGradient2222"
|
||||
r="86.699997"
|
||||
gradientTransform="scale(0.961,1.041)"
|
||||
cx="33.970001"
|
||||
cy="35.740002"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="f">
|
||||
<stop
|
||||
id="stop84"
|
||||
offset="0"
|
||||
stop-color="#fafafa" />
|
||||
<stop
|
||||
id="stop86"
|
||||
offset="1"
|
||||
stop-color="#bbb" />
|
||||
</radialGradient>
|
||||
<radialGradient
|
||||
r="37.75"
|
||||
gradientTransform="matrix(.968 0 0 1.033 3.35.65)"
|
||||
cx="8.82"
|
||||
cy="3.76"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="g">
|
||||
<stop
|
||||
id="stop89"
|
||||
offset="0"
|
||||
stop-color="#a3a3a3" />
|
||||
<stop
|
||||
id="stop91"
|
||||
offset="1"
|
||||
stop-color="#4c4c4c" />
|
||||
</radialGradient>
|
||||
<radialGradient
|
||||
r="38.2"
|
||||
gradientTransform="matrix(.968 0 0 1.033 3.35.65)"
|
||||
cx="8.14"
|
||||
cy="7.27"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="e">
|
||||
<stop
|
||||
id="stop94"
|
||||
offset="0"
|
||||
stop-color="#fff" />
|
||||
<stop
|
||||
id="stop96"
|
||||
offset="1"
|
||||
stop-color="#f8f8f8" />
|
||||
</radialGradient>
|
||||
<radialGradient
|
||||
r="1.21"
|
||||
cx="10.1"
|
||||
cy="18.82"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="c">
|
||||
<stop
|
||||
id="stop99"
|
||||
offset="0"
|
||||
stop-color="#f0f0f0" />
|
||||
<stop
|
||||
id="stop101"
|
||||
offset="1"
|
||||
stop-color="#9a9a9a" />
|
||||
</radialGradient>
|
||||
<linearGradient
|
||||
id="linearGradient2180">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#ffffff;stop-opacity:1"
|
||||
id="stop2182" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#ffffff;stop-opacity:0"
|
||||
id="stop2184" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient2222">
|
||||
<stop
|
||||
offset="0"
|
||||
style="stop-color:#5187d6;stop-opacity:1"
|
||||
id="stop2224" />
|
||||
<stop
|
||||
offset="1"
|
||||
style="stop-color:#1e4580;stop-opacity:1"
|
||||
id="stop2227" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(-1.531667,1.4182182,-1.8951832,-2.046786,20.931759,20.852827)"
|
||||
r="17.940001"
|
||||
fy="10.45207"
|
||||
fx="0.77357841"
|
||||
cy="10.45207"
|
||||
cx="0.77357841"
|
||||
id="radialGradient4858"
|
||||
xlink:href="#linearGradient2222" />
|
||||
<linearGradient
|
||||
y2="24.238262"
|
||||
x2="12.499243"
|
||||
y1="12.53757"
|
||||
x1="8.8207808"
|
||||
gradientTransform="matrix(2.8905003,0,0,1.7995248,-3.3500053,-18.415934)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient3845-7"
|
||||
xlink:href="#linearGradient2180" />
|
||||
<radialGradient
|
||||
r="37.75"
|
||||
gradientTransform="matrix(0.968,0,0,1.033,3.3500009,0.65000099)"
|
||||
cx="8.8199997"
|
||||
cy="3.76"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="g-7">
|
||||
<stop
|
||||
id="stop89-8"
|
||||
offset="0"
|
||||
stop-color="#a3a3a3" />
|
||||
<stop
|
||||
id="stop91-4"
|
||||
offset="1"
|
||||
stop-color="#4c4c4c" />
|
||||
</radialGradient>
|
||||
</defs>
|
||||
<rect
|
||||
style="fill-opacity:1;fill:url(#radialGradient4858);stroke:none"
|
||||
id="rect108"
|
||||
x="6.6"
|
||||
y="3.65"
|
||||
width="34.88"
|
||||
height="41"
|
||||
rx="1.2"
|
||||
stroke="url(#g)"
|
||||
fill="url(#f)" />
|
||||
<g
|
||||
style="stroke-width:1.06454599"
|
||||
transform="matrix(0.94000018,0,0,0.93873543,-52.813919,-10.009373)"
|
||||
id="g5030">
|
||||
<path
|
||||
style="fill:#ecffd9;fill-opacity:1;fill-rule:evenodd;stroke:#c3ea9b;stroke-width:1.06454599;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:0.41618497"
|
||||
d="m 69.689357,47.100885 h -6.16187 v 1.245308 h 7.898291 l 1.438618,-6.050635 3.543037,14.016067 3.283344,-11.071321 2.961859,6.049287 3.977354,-3.593643 H 99.633964 V 45.588404 H 86.178659 l -3.243941,3.212614 -3.351636,-6.814017 -3.07983,8.365012 -3.344545,-13.162931 z"
|
||||
id="path2188-3" />
|
||||
<path
|
||||
id="path3088-6"
|
||||
d="m 68.794008,46.156452 h -5.266521 v 3.119652 l 8.79364,-0.127907 0.671176,-3.113401 2.898722,11.18944 1.134847,0.197791 3.048626,-10.116651 2.578138,5.542056 4.361075,-4.20413 12.620253,-0.127907 -0.76744,-4.000458 -12.687865,-0.127907 -3.116034,3.246745 -3.479543,-7.971582 -2.696109,7.100014 -3.600359,-12.55597 z"
|
||||
style="opacity:0.38068183;fill:#ecffd9;fill-opacity:1;fill-rule:evenodd;stroke:#c3ea9b;stroke-width:1.06454635;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.41618497" />
|
||||
</g>
|
||||
<rect
|
||||
style="stroke:#d3d7cf;stroke-opacity:1"
|
||||
id="rect110"
|
||||
fill="none"
|
||||
x="7.66"
|
||||
y="4.58"
|
||||
stroke="url(#e)"
|
||||
width="32.78"
|
||||
height="39"
|
||||
rx=".2" />
|
||||
<rect
|
||||
style="fill:none;fill-opacity:1;stroke:#888a85;stroke-opacity:1"
|
||||
id="rect108-5"
|
||||
x="6.5999999"
|
||||
y="3.6500001"
|
||||
width="34.880001"
|
||||
height="41"
|
||||
rx="1.2"
|
||||
ry="1.2" />
|
||||
<g
|
||||
id="g4564"
|
||||
transform="translate(58.000001)">
|
||||
<ellipse
|
||||
ry="12"
|
||||
rx="12.000001"
|
||||
cy="18"
|
||||
cx="-31"
|
||||
id="path4540"
|
||||
style="opacity:1;fill:#d3d7cf;fill-opacity:1;fill-rule:evenodd;stroke:#d3d7cf;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
|
||||
<ellipse
|
||||
ry="10.999999"
|
||||
rx="11"
|
||||
cy="18.000002"
|
||||
cx="-31"
|
||||
id="path4540-6"
|
||||
style="opacity:1;fill:#888a85;fill-opacity:1;fill-rule:evenodd;stroke:#888a85;stroke-width:1.99999988;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
|
||||
<g
|
||||
style="stroke-width:1.07276595"
|
||||
transform="matrix(0.93221519,0,0,0.93212416,-56.170349,1.2244571)"
|
||||
id="g4523">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path5018"
|
||||
d="m 27.000001,6.1961087 c -6.515886,0 -11.803181,5.2884593 -11.799271,11.8015803 -0.0033,6.512582 5.283777,11.800426 11.799271,11.800426 6.515885,0 11.804337,-5.28846 11.800426,-11.801582 0.0036,-6.512582 -5.284931,-11.8004243 -11.800426,-11.8004243 z"
|
||||
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#f0dd5b;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.07276595;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
|
||||
<circle
|
||||
r="1.7750911"
|
||||
id="path4239-2"
|
||||
style="fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1.27121437"
|
||||
cx="27.000338"
|
||||
cy="17.996984" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4241-97"
|
||||
d="m 33.485556,10.292916 a 1.1835124,1.1835124 0 0 0 -0.813583,0.358254 l -6.508669,6.508666 a 1.1835124,1.1835124 0 1 0 1.673393,1.673394 l 6.508666,-6.508667 a 1.1835124,1.1835124 0 0 0 -0.859807,-2.031647 z"
|
||||
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#888a85;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4.29106379;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4241-9-3"
|
||||
d="m 22.846565,12.659704 a 1.1835124,1.1835124 0 0 0 -0.82514,2.031647 l 4.141879,4.141879 a 1.1835124,1.1835124 0 1 0 1.673393,-1.673394 l -4.141879,-4.141878 a 1.1835124,1.1835124 0 0 0 -0.848253,-0.358254 z"
|
||||
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#888a85;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4.29106379;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
|
||||
</g>
|
||||
</g>
|
||||
<path
|
||||
id="rect2178-1"
|
||||
d="M 27.370146,4.9981407 A 13.000134,12.995402 0 0 0 14.556207,14.187934 c 2.633113,0.620371 5.525529,0.979998 8.561116,0.979998 5.921411,0 11.304067,-1.300023 15.273176,-3.420748 A 13.000134,12.995402 0 0 0 27.370146,4.9981407 Z"
|
||||
style="opacity:0.43181817;fill:url(#linearGradient3845-7);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 13 KiB |
BIN
icons/tg-document.ico
Normal file
|
After Width: | Height: | Size: 363 KiB |
|
|
@ -1,8 +0,0 @@
|
|||
[Desktop Entry]
|
||||
Type=Application
|
||||
Name=Tg-lt
|
||||
Comment=Software-based timegrapher (light)
|
||||
Exec=tg-timer-lt
|
||||
Icon=tg-timer
|
||||
Terminal=false
|
||||
Categories=Utility;
|
||||
|
|
@ -2,7 +2,8 @@
|
|||
Type=Application
|
||||
Name=Tg
|
||||
Comment=Software-based timegrapher
|
||||
Exec=tg-timer
|
||||
Exec=tg-timer %F
|
||||
Icon=tg-timer
|
||||
Terminal=false
|
||||
Categories=Utility;
|
||||
Categories=Utility
|
||||
MimeType=application/x-tg-timer-data
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 363 KiB After Width: | Height: | Size: 363 KiB |
10
icons/tg-timer.xml
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0"?>
|
||||
<mime-info xmlns='http://www.freedesktop.org/standards/shared-mime-info'>
|
||||
<mime-type type="application/x-tg-timer-data">
|
||||
<comment>Watch timing data</comment>
|
||||
<magic>
|
||||
<match type="string" offset="0" value="Ltg-timer-version;"/>
|
||||
</magic>
|
||||
<glob pattern="*.tgj"/>
|
||||
</mime-type>
|
||||
</mime-info>
|
||||
311
m4/attributes.m4
Normal file
|
|
@ -0,0 +1,311 @@
|
|||
dnl Macros to check the presence of generic (non-typed) symbols.
|
||||
dnl Copyright (c) 2006-2008 Diego Pettenò <flameeyes@gmail.com>
|
||||
dnl Copyright (c) 2006-2008 xine project
|
||||
dnl
|
||||
dnl This program is free software; you can redistribute it and/or modify
|
||||
dnl it under the terms of the GNU General Public License as published by
|
||||
dnl the Free Software Foundation; either version 2, or (at your option)
|
||||
dnl any later version.
|
||||
dnl
|
||||
dnl This program is distributed in the hope that it will be useful,
|
||||
dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
dnl GNU General Public License for more details.
|
||||
dnl
|
||||
dnl You should have received a copy of the GNU General Public License
|
||||
dnl along with this program; if not, write to the Free Software
|
||||
dnl Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
dnl 02110-1301, USA.
|
||||
dnl
|
||||
dnl As a special exception, the copyright owners of the
|
||||
dnl macro gives unlimited permission to copy, distribute and modify the
|
||||
dnl configure scripts that are the output of Autoconf when processing the
|
||||
dnl Macro. You need not follow the terms of the GNU General Public
|
||||
dnl License when using or distributing such scripts, even though portions
|
||||
dnl of the text of the Macro appear in them. The GNU General Public
|
||||
dnl License (GPL) does govern all other use of the material that
|
||||
dnl constitutes the Autoconf Macro.
|
||||
dnl
|
||||
dnl This special exception to the GPL applies to versions of the
|
||||
dnl Autoconf Macro released by this project. When you make and
|
||||
dnl distribute a modified version of the Autoconf Macro, you may extend
|
||||
dnl this special exception to the GPL to apply to your modified version as
|
||||
dnl well.
|
||||
|
||||
dnl Check if the flag is supported by compiler
|
||||
dnl CC_CHECK_CFLAGS_SILENT([FLAG], [ACTION-IF-FOUND],[ACTION-IF-NOT-FOUND])
|
||||
|
||||
AC_DEFUN([CC_CHECK_CFLAGS_SILENT], [
|
||||
AC_CACHE_VAL(AS_TR_SH([cc_cv_cflags_$1]),
|
||||
[ac_save_CFLAGS="$CFLAGS"
|
||||
CFLAGS="$CFLAGS $1"
|
||||
AC_COMPILE_IFELSE([int a;],
|
||||
[eval "AS_TR_SH([cc_cv_cflags_$1])='yes'"],
|
||||
[eval "AS_TR_SH([cc_cv_cflags_$1])='no'"])
|
||||
CFLAGS="$ac_save_CFLAGS"
|
||||
])
|
||||
|
||||
AS_IF([eval test x$]AS_TR_SH([cc_cv_cflags_$1])[ = xyes],
|
||||
[$2], [$3])
|
||||
])
|
||||
|
||||
dnl Check if the flag is supported by compiler (cacheable)
|
||||
dnl CC_CHECK_CFLAGS([FLAG], [ACTION-IF-FOUND],[ACTION-IF-NOT-FOUND])
|
||||
|
||||
AC_DEFUN([CC_CHECK_CFLAGS], [
|
||||
AC_CACHE_CHECK([if $CC supports $1 flag],
|
||||
AS_TR_SH([cc_cv_cflags_$1]),
|
||||
CC_CHECK_CFLAGS_SILENT([$1]) dnl Don't execute actions here!
|
||||
)
|
||||
|
||||
AS_IF([eval test x$]AS_TR_SH([cc_cv_cflags_$1])[ = xyes],
|
||||
[$2], [$3])
|
||||
])
|
||||
|
||||
dnl CC_CHECK_CFLAG_APPEND(FLAG, [action-if-found], [action-if-not-found])
|
||||
dnl Check for CFLAG and appends them to CFLAGS if supported
|
||||
AC_DEFUN([CC_CHECK_CFLAG_APPEND], [
|
||||
AC_CACHE_CHECK([if $CC supports $1 flag],
|
||||
AS_TR_SH([cc_cv_cflags_$1]),
|
||||
CC_CHECK_CFLAGS_SILENT([$1]) dnl Don't execute actions here!
|
||||
)
|
||||
|
||||
AS_IF([eval test x$]AS_TR_SH([cc_cv_cflags_$1])[ = xyes],
|
||||
[CFLAGS="$CFLAGS $1"; DEBUG_CFLAGS="$DEBUG_CFLAGS $1"; $2], [$3])
|
||||
])
|
||||
|
||||
dnl CC_CHECK_CFLAGS_APPEND([FLAG1 FLAG2], [action-if-found], [action-if-not])
|
||||
AC_DEFUN([CC_CHECK_CFLAGS_APPEND], [
|
||||
for flag in $1; do
|
||||
CC_CHECK_CFLAG_APPEND($flag, [$2], [$3])
|
||||
done
|
||||
])
|
||||
|
||||
dnl Check if the flag is supported by linker (cacheable)
|
||||
dnl CC_CHECK_LDFLAGS([FLAG], [ACTION-IF-FOUND],[ACTION-IF-NOT-FOUND])
|
||||
|
||||
AC_DEFUN([CC_CHECK_LDFLAGS], [
|
||||
AC_CACHE_CHECK([if $CC supports $1 flag],
|
||||
AS_TR_SH([cc_cv_ldflags_$1]),
|
||||
[ac_save_LDFLAGS="$LDFLAGS"
|
||||
LDFLAGS="$LDFLAGS $1"
|
||||
AC_LINK_IFELSE([int main() { return 1; }],
|
||||
[eval "AS_TR_SH([cc_cv_ldflags_$1])='yes'"],
|
||||
[eval "AS_TR_SH([cc_cv_ldflags_$1])="])
|
||||
LDFLAGS="$ac_save_LDFLAGS"
|
||||
])
|
||||
|
||||
AS_IF([eval test x$]AS_TR_SH([cc_cv_ldflags_$1])[ = xyes],
|
||||
[$2], [$3])
|
||||
])
|
||||
|
||||
dnl define the LDFLAGS_NOUNDEFINED variable with the correct value for
|
||||
dnl the current linker to avoid undefined references in a shared object.
|
||||
AC_DEFUN([CC_NOUNDEFINED], [
|
||||
dnl We check $host for which systems to enable this for.
|
||||
AC_REQUIRE([AC_CANONICAL_HOST])
|
||||
|
||||
case $host in
|
||||
dnl FreeBSD (et al.) does not complete linking for shared objects when pthreads
|
||||
dnl are requested, as different implementations are present; to avoid problems
|
||||
dnl use -Wl,-z,defs only for those platform not behaving this way.
|
||||
*-freebsd* | *-openbsd*) ;;
|
||||
*)
|
||||
dnl First of all check for the --no-undefined variant of GNU ld. This allows
|
||||
dnl for a much more readable commandline, so that people can understand what
|
||||
dnl it does without going to look for what the heck -z defs does.
|
||||
for possible_flags in "-Wl,--no-undefined" "-Wl,-z,defs"; do
|
||||
CC_CHECK_LDFLAGS([$possible_flags], [LDFLAGS_NOUNDEFINED="$possible_flags"])
|
||||
break
|
||||
done
|
||||
;;
|
||||
esac
|
||||
|
||||
AC_SUBST([LDFLAGS_NOUNDEFINED])
|
||||
])
|
||||
|
||||
dnl Check for a -Werror flag or equivalent. -Werror is the GCC
|
||||
dnl and ICC flag that tells the compiler to treat all the warnings
|
||||
dnl as fatal. We usually need this option to make sure that some
|
||||
dnl constructs (like attributes) are not simply ignored.
|
||||
dnl
|
||||
dnl Other compilers don't support -Werror per se, but they support
|
||||
dnl an equivalent flag:
|
||||
dnl - Sun Studio compiler supports -errwarn=%all
|
||||
AC_DEFUN([CC_CHECK_WERROR], [
|
||||
AC_CACHE_CHECK(
|
||||
[for $CC way to treat warnings as errors],
|
||||
[cc_cv_werror],
|
||||
[CC_CHECK_CFLAGS_SILENT([-Werror], [cc_cv_werror=-Werror],
|
||||
[CC_CHECK_CFLAGS_SILENT([-errwarn=%all], [cc_cv_werror=-errwarn=%all])])
|
||||
])
|
||||
])
|
||||
|
||||
AC_DEFUN([CC_CHECK_ATTRIBUTE], [
|
||||
AC_REQUIRE([CC_CHECK_WERROR])
|
||||
AC_CACHE_CHECK([if $CC supports __attribute__(( ifelse([$2], , [$1], [$2]) ))],
|
||||
AS_TR_SH([cc_cv_attribute_$1]),
|
||||
[ac_save_CFLAGS="$CFLAGS"
|
||||
CFLAGS="$CFLAGS $cc_cv_werror"
|
||||
AC_COMPILE_IFELSE([$3],
|
||||
[eval "AS_TR_SH([cc_cv_attribute_$1])='yes'"],
|
||||
[eval "AS_TR_SH([cc_cv_attribute_$1])='no'"])
|
||||
CFLAGS="$ac_save_CFLAGS"
|
||||
])
|
||||
|
||||
AS_IF([eval test x$]AS_TR_SH([cc_cv_attribute_$1])[ = xyes],
|
||||
[AC_DEFINE(
|
||||
AS_TR_CPP([SUPPORT_ATTRIBUTE_$1]), 1,
|
||||
[Define this if the compiler supports __attribute__(( ifelse([$2], , [$1], [$2]) ))]
|
||||
)
|
||||
$4],
|
||||
[$5])
|
||||
])
|
||||
|
||||
AC_DEFUN([CC_ATTRIBUTE_CONSTRUCTOR], [
|
||||
CC_CHECK_ATTRIBUTE(
|
||||
[constructor],,
|
||||
[void __attribute__((constructor)) ctor() { int a; }],
|
||||
[$1], [$2])
|
||||
])
|
||||
|
||||
AC_DEFUN([CC_ATTRIBUTE_FORMAT], [
|
||||
CC_CHECK_ATTRIBUTE(
|
||||
[format], [format(printf, n, n)],
|
||||
[void __attribute__((format(printf, 1, 2))) printflike(const char *fmt, ...) { fmt = (void *)0; }],
|
||||
[$1], [$2])
|
||||
])
|
||||
|
||||
AC_DEFUN([CC_ATTRIBUTE_FORMAT_ARG], [
|
||||
CC_CHECK_ATTRIBUTE(
|
||||
[format_arg], [format_arg(printf)],
|
||||
[char *__attribute__((format_arg(1))) gettextlike(const char *fmt) { fmt = (void *)0; }],
|
||||
[$1], [$2])
|
||||
])
|
||||
|
||||
AC_DEFUN([CC_ATTRIBUTE_VISIBILITY], [
|
||||
CC_CHECK_ATTRIBUTE(
|
||||
[visibility_$1], [visibility("$1")],
|
||||
[void __attribute__((visibility("$1"))) $1_function() { }],
|
||||
[$2], [$3])
|
||||
])
|
||||
|
||||
AC_DEFUN([CC_ATTRIBUTE_NONNULL], [
|
||||
CC_CHECK_ATTRIBUTE(
|
||||
[nonnull], [nonnull()],
|
||||
[void __attribute__((nonnull())) some_function(void *foo, void *bar) { foo = (void*)0; bar = (void*)0; }],
|
||||
[$1], [$2])
|
||||
])
|
||||
|
||||
AC_DEFUN([CC_ATTRIBUTE_UNUSED], [
|
||||
CC_CHECK_ATTRIBUTE(
|
||||
[unused], ,
|
||||
[void some_function(void *foo, __attribute__((unused)) void *bar);],
|
||||
[$1], [$2])
|
||||
])
|
||||
|
||||
AC_DEFUN([CC_ATTRIBUTE_SENTINEL], [
|
||||
CC_CHECK_ATTRIBUTE(
|
||||
[sentinel], ,
|
||||
[void some_function(void *foo, ...) __attribute__((sentinel));],
|
||||
[$1], [$2])
|
||||
])
|
||||
|
||||
AC_DEFUN([CC_ATTRIBUTE_DEPRECATED], [
|
||||
CC_CHECK_ATTRIBUTE(
|
||||
[deprecated], ,
|
||||
[void some_function(void *foo, ...) __attribute__((deprecated));],
|
||||
[$1], [$2])
|
||||
])
|
||||
|
||||
AC_DEFUN([CC_ATTRIBUTE_ALIAS], [
|
||||
CC_CHECK_ATTRIBUTE(
|
||||
[alias], [weak, alias],
|
||||
[void other_function(void *foo) { }
|
||||
void some_function(void *foo) __attribute__((weak, alias("other_function")));],
|
||||
[$1], [$2])
|
||||
])
|
||||
|
||||
AC_DEFUN([CC_ATTRIBUTE_MALLOC], [
|
||||
CC_CHECK_ATTRIBUTE(
|
||||
[malloc], ,
|
||||
[void * __attribute__((malloc)) my_alloc(int n);],
|
||||
[$1], [$2])
|
||||
])
|
||||
|
||||
AC_DEFUN([CC_ATTRIBUTE_PACKED], [
|
||||
CC_CHECK_ATTRIBUTE(
|
||||
[packed], ,
|
||||
[struct astructure { char a; int b; long c; void *d; } __attribute__((packed));],
|
||||
[$1], [$2])
|
||||
])
|
||||
|
||||
AC_DEFUN([CC_ATTRIBUTE_CONST], [
|
||||
CC_CHECK_ATTRIBUTE(
|
||||
[const], ,
|
||||
[int __attribute__((const)) twopow(int n) { return 1 << n; } ],
|
||||
[$1], [$2])
|
||||
])
|
||||
|
||||
AC_DEFUN([CC_FLAG_VISIBILITY], [
|
||||
AC_REQUIRE([CC_CHECK_WERROR])
|
||||
AC_CACHE_CHECK([if $CC supports -fvisibility=hidden],
|
||||
[cc_cv_flag_visibility],
|
||||
[cc_flag_visibility_save_CFLAGS="$CFLAGS"
|
||||
CFLAGS="$CFLAGS $cc_cv_werror"
|
||||
CC_CHECK_CFLAGS_SILENT([-fvisibility=hidden],
|
||||
cc_cv_flag_visibility='yes',
|
||||
cc_cv_flag_visibility='no')
|
||||
CFLAGS="$cc_flag_visibility_save_CFLAGS"])
|
||||
|
||||
AS_IF([test "x$cc_cv_flag_visibility" = "xyes"],
|
||||
[AC_DEFINE([SUPPORT_FLAG_VISIBILITY], 1,
|
||||
[Define this if the compiler supports the -fvisibility flag])
|
||||
$1],
|
||||
[$2])
|
||||
])
|
||||
|
||||
AC_DEFUN([CC_FUNC_EXPECT], [
|
||||
AC_REQUIRE([CC_CHECK_WERROR])
|
||||
AC_CACHE_CHECK([if compiler has __builtin_expect function],
|
||||
[cc_cv_func_expect],
|
||||
[ac_save_CFLAGS="$CFLAGS"
|
||||
CFLAGS="$CFLAGS $cc_cv_werror"
|
||||
AC_COMPILE_IFELSE(
|
||||
[int some_function() {
|
||||
int a = 3;
|
||||
return (int)__builtin_expect(a, 3);
|
||||
}],
|
||||
[cc_cv_func_expect=yes],
|
||||
[cc_cv_func_expect=no])
|
||||
CFLAGS="$ac_save_CFLAGS"
|
||||
])
|
||||
|
||||
AS_IF([test "x$cc_cv_func_expect" = "xyes"],
|
||||
[AC_DEFINE([SUPPORT__BUILTIN_EXPECT], 1,
|
||||
[Define this if the compiler supports __builtin_expect() function])
|
||||
$1],
|
||||
[$2])
|
||||
])
|
||||
|
||||
AC_DEFUN([CC_ATTRIBUTE_ALIGNED], [
|
||||
AC_REQUIRE([CC_CHECK_WERROR])
|
||||
AC_CACHE_CHECK([highest __attribute__ ((aligned ())) supported],
|
||||
[cc_cv_attribute_aligned],
|
||||
[ac_save_CFLAGS="$CFLAGS"
|
||||
CFLAGS="$CFLAGS $cc_cv_werror"
|
||||
for cc_attribute_align_try in 64 32 16 8 4 2; do
|
||||
AC_COMPILE_IFELSE([
|
||||
int main() {
|
||||
static char c __attribute__ ((aligned($cc_attribute_align_try))) = 0;
|
||||
return c;
|
||||
}], [cc_cv_attribute_aligned=$cc_attribute_align_try; break])
|
||||
done
|
||||
CFLAGS="$ac_save_CFLAGS"
|
||||
])
|
||||
|
||||
if test "x$cc_cv_attribute_aligned" != "x"; then
|
||||
AC_DEFINE_UNQUOTED([ATTRIBUTE_ALIGNED_MAX], [$cc_cv_attribute_aligned],
|
||||
[Define the highest alignment supported])
|
||||
fi
|
||||
])
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
tg-timer (0.4.0-1) UNRELEASED; urgency=medium
|
||||
tg-timer (0.5.0-1) UNRELEASED; urgency=medium
|
||||
|
||||
* We don't keep a changelog.
|
||||
|
||||
-- Marcello Mamino <vacaboja@gmail.com> Thu, 20 Oct 2016 00:29:29 +0200
|
||||
-- Marcello Mamino <vacaboja@gmail.com> Sat, 24 Jun 2017 16:24:08 +0200
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ Maintainer: Marcello Mamino <vacaboja@gmail.com>
|
|||
Section: misc
|
||||
Priority: optional
|
||||
Standards-Version: 3.9.8
|
||||
Build-Depends: debhelper (>= 9), libgtk2.0-dev (>= 2.24), portaudio19-dev (>=19), libfftw3-dev (>=3.3)
|
||||
Build-Depends: debhelper (>= 9), libgtk-3-dev (>= 3.14), portaudio19-dev (>=19), libfftw3-dev (>=3.3)
|
||||
|
||||
Package: tg-timer
|
||||
Architecture: any
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
override_dh_auto_test:
|
||||
|
||||
override_dh_auto_install:
|
||||
PREFIX=$$(pwd)/debian/tg-timer/usr $(MAKE) install
|
||||
$(MAKE) DESTDIR=$$(pwd)/debian/tg-timer prefix=/usr install
|
||||
|
||||
%:
|
||||
dh $@
|
||||
|
|
|
|||
|
|
@ -7,10 +7,13 @@ cd "$DIR"/..
|
|||
|
||||
VERSION=`cat version`
|
||||
|
||||
cd build
|
||||
./autogen.sh
|
||||
./configure
|
||||
make dist
|
||||
|
||||
rm -rf deb
|
||||
mkdir deb
|
||||
cp tg-timer_"$VERSION".tar.gz deb/tg-timer_"$VERSION".orig.tar.gz
|
||||
cp tg-timer-"$VERSION".tar.gz deb/tg-timer_"$VERSION".orig.tar.gz
|
||||
|
||||
cd deb
|
||||
|
||||
|
|
|
|||
|
|
@ -2,35 +2,36 @@
|
|||
|
||||
if test ! -d "$1"
|
||||
then
|
||||
echo Usage: $0 dll-dir
|
||||
echo Usage: $0 resources-dir
|
||||
exit 1
|
||||
fi
|
||||
|
||||
DIR=`dirname "${BASH_SOURCE[0]}"`
|
||||
ABSDIR=`cd "$DIR"; pwd`
|
||||
|
||||
DLLS=`cd "$1"; pwd`
|
||||
RESOURCES=`cd "$1"; pwd`
|
||||
|
||||
TARGET="$ABSDIR/../build/msi"
|
||||
TARGET="$ABSDIR/../msi"
|
||||
|
||||
cd "$ABSDIR"/..
|
||||
|
||||
VERSION=`cat version`
|
||||
|
||||
make
|
||||
|
||||
rm -rf "$TARGET"
|
||||
mkdir -p "$TARGET"
|
||||
|
||||
cd "$TARGET"
|
||||
../configure
|
||||
make
|
||||
|
||||
mv "$TARGET/tg-timer.exe" "$TARGET/tg.exe"
|
||||
cp "$ABSDIR/tg-timer.wxs" "$TARGET"
|
||||
cp "$ABSDIR/LICENSE.rtf" "$TARGET"
|
||||
cp "$ABSDIR/../README.md" "$TARGET"
|
||||
cp "$ABSDIR/../LICENSE" "$TARGET"
|
||||
cp "$ABSDIR/../build/tg.exe" "$TARGET"
|
||||
cp "$ABSDIR/../build/tg-lt.exe" "$TARGET"
|
||||
cp "$DLLS"/* "$TARGET"
|
||||
heat dir "$DLLS" -srd -gg -sreg -dr INSTALLDIR -cg Dlls -out "$TARGET/Dlls.wxs"
|
||||
cp "$ABSDIR/../icons/tg-document.ico" "$TARGET"
|
||||
cp -r "$RESOURCES"/* "$TARGET"
|
||||
heat dir "$RESOURCES" -srd -gg -sreg -dr INSTALLDIR -cg Resources -out "$TARGET/Resources.wxs"
|
||||
|
||||
cd "$TARGET"
|
||||
|
||||
candle tg-timer.wxs Dlls.wxs
|
||||
light -out tg-timer_${VERSION}.msi -ext WixUIExtension tg-timer.wixobj Dlls.wixobj
|
||||
candle tg-timer.wxs Resources.wxs
|
||||
light -out tg-timer_${VERSION}.msi -ext WixUIExtension tg-timer.wixobj Resources.wixobj
|
||||
|
|
|
|||
|
|
@ -1,10 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
DIR=`dirname "${BASH_SOURCE[0]}"`
|
||||
ABSDIR=`cd "$DIR"; pwd`
|
||||
|
||||
cd "$DIR"/..
|
||||
|
||||
VERSION=`cat version`
|
||||
|
||||
tar czf build/tg-timer_"$VERSION".tar.gz * --exclude=".*" --exclude="build/*" --exclude="packaging" --xform="s|\\(.*\\)|tg-timer-$VERSION/\1|"
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
if test ! -d "$1"
|
||||
then
|
||||
echo Usage: $0 dll-dir
|
||||
exit 1
|
||||
fi
|
||||
|
||||
DIR=`dirname "${BASH_SOURCE[0]}"`
|
||||
ABSDIR=`cd "$DIR"; pwd`
|
||||
|
||||
DLLS=`cd "$1"; pwd`
|
||||
|
||||
cd "$ABSDIR"/..
|
||||
|
||||
VERSION=`cat version`
|
||||
NAME="tg-timer_$VERSION"
|
||||
TARGET="$ABSDIR/../build/$NAME"
|
||||
|
||||
make
|
||||
|
||||
rm -rf "$TARGET"
|
||||
mkdir -p "$TARGET"
|
||||
cp "$ABSDIR/../README.md" "$TARGET"
|
||||
cp "$ABSDIR/../LICENSE" "$TARGET"
|
||||
cp "$ABSDIR/../build/tg.exe" "$TARGET"
|
||||
cp "$ABSDIR/../build/tg-lt.exe" "$TARGET"
|
||||
cp "$DLLS"/* "$TARGET"
|
||||
|
||||
cd build
|
||||
rm -f "${NAME}.zip"
|
||||
7z a -tzip "${NAME}.zip" "${NAME}"/*
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
<?xml version='1.0' encoding='windows-1252'?>
|
||||
<Wix xmlns='http://schemas.microsoft.com/wix/2006/wi'>
|
||||
<Product Name='Tg' Id='f4b9cf89-06fc-4c90-bdc8-24d2bcc77ef9' UpgradeCode='088fdac7-fc91-4881-a2db-eed04425a207'
|
||||
Language='1033' Codepage='1252' Version='0.4.0' Manufacturer='Marcello Mamino'>
|
||||
<Product Name='Tg' Id='e725c262-348c-4e31-86ff-234893330f82' UpgradeCode='088fdac7-fc91-4881-a2db-eed04425a207'
|
||||
Language='1033' Codepage='1252' Version='0.5.0' Manufacturer='Marcello Mamino'>
|
||||
|
||||
<Package Id='*' Keywords='Installer'
|
||||
Description='Tg 0.4.0 Installer'
|
||||
Description='Tg 0.5.0 Installer'
|
||||
Manufacturer='Marcello Mamino'
|
||||
InstallerVersion='100' Languages='1033' Compressed='yes' SummaryCodepage='1252' />
|
||||
|
||||
|
|
@ -17,25 +17,24 @@
|
|||
<Directory Id='ProgramFilesFolder' Name='PFiles'>
|
||||
<Directory Id='INSTALLDIR' Name='tg-timer'>
|
||||
|
||||
<Component Id='MainExecutable' Guid='fa5c0b97-a6ce-44a3-a917-90a644ea0f84'>
|
||||
<Component Id='MainExecutable' Guid='c8210ac7-1900-4339-9825-a6d0694ecc6b'>
|
||||
<File Id='TgEXE' Name='tg.exe' DiskId='1' Source='tg.exe' KeyPath='yes'>
|
||||
<Shortcut Id='startmenuTg' Directory='ProgramMenuDir' Name='Tg 0.4.0' WorkingDirectory='INSTALLDIR' Icon='tg.exe' IconIndex='0' Advertise='yes' />
|
||||
<Shortcut Id='desktopTg' Directory='DesktopFolder' Name='Tg 0.4.0' WorkingDirectory='INSTALLDIR' Icon='tg.exe' IconIndex='0' Advertise='yes' />
|
||||
<Shortcut Id='startmenuTg' Directory='ProgramMenuDir' Name='Tg 0.5.0' WorkingDirectory='INSTALLDIR' Icon='tg.exe' IconIndex='0' Advertise='yes' />
|
||||
<Shortcut Id='desktopTg' Directory='DesktopFolder' Name='Tg 0.5.0' WorkingDirectory='INSTALLDIR' Icon='tg.exe' IconIndex='0' Advertise='yes' />
|
||||
</File>
|
||||
<File Id='TgDocumentICO' Name='tg-document.ico' Source='tg-document.ico' />
|
||||
<ProgId Id='TgjFile' Description='Tg data file' Icon='TgDocumentICO'>
|
||||
<Extension Id='tgj' ContentType='application/x-tg-timer-data'>
|
||||
<Verb Id='open' Command='Open' TargetFile='TgEXE' Argument='"%1"' />
|
||||
</Extension>
|
||||
</ProgId>
|
||||
</Component>
|
||||
|
||||
<Component Id='LightExecutable' Guid='de7b2b2b-f7ed-434d-b182-a6d915783e2f'>
|
||||
<File Id='TgLtEXE' Name='tg-lt.exe' DiskId='1' Source='tg-lt.exe' KeyPath='yes'>
|
||||
<Shortcut Id='startmenuTgLt' Directory='ProgramMenuDir' Name='Tg lt 0.4.0' WorkingDirectory='INSTALLDIR' Icon='tg.exe' IconIndex='0' Advertise='yes' />
|
||||
<Shortcut Id='desktopTgLt' Directory='DesktopFolder' Name='Tg lt 0.4.0' WorkingDirectory='INSTALLDIR' Icon='tg.exe' IconIndex='0' Advertise='yes' />
|
||||
</File>
|
||||
</Component>
|
||||
|
||||
<Component Id='License' Guid='49fcd7cf-94ba-4192-a0ca-501a72b4ac33'>
|
||||
<Component Id='License' Guid='bae8c647-10b0-43b2-9373-7ce83d066062'>
|
||||
<File Id='License' Name='LICENSE' DiskId='1' Source='LICENSE' KeyPath='yes' />
|
||||
</Component>
|
||||
|
||||
<Component Id='Readme' Guid='542ed91a-6411-4183-9926-301416309136'>
|
||||
<Component Id='Readme' Guid='6e6ae226-5a2b-4604-97fa-c931ccedab73'>
|
||||
<File Id='Readme' Name='README.md' DiskId='1' Source='README.md' KeyPath='yes' />
|
||||
</Component>
|
||||
|
||||
|
|
@ -43,8 +42,8 @@
|
|||
</Directory>
|
||||
|
||||
<Directory Id='ProgramMenuFolder' Name='Programs'>
|
||||
<Directory Id='ProgramMenuDir' Name='Tg 0.4.0'>
|
||||
<Component Id='ProgramMenuDir' Guid='9f8a890f-71f7-4f4c-b596-4ec402c0dfe5'>
|
||||
<Directory Id='ProgramMenuDir' Name='Tg 0.5.0'>
|
||||
<Component Id='ProgramMenuDir' Guid='1c065e58-79d8-4bb7-a3b6-364e597137fd'>
|
||||
<RemoveFolder Id='ProgramMenuDir' On='uninstall' />
|
||||
<RegistryValue Root='HKCU' Key='Software\[Manufacturer]\[ProductName]' Type='string' Value='' KeyPath='yes' />
|
||||
</Component>
|
||||
|
|
@ -56,10 +55,9 @@
|
|||
|
||||
<Feature Id='Complete' Level='1' ConfigurableDirectory='INSTALLDIR'>
|
||||
<ComponentRef Id='MainExecutable' />
|
||||
<ComponentRef Id='LightExecutable' />
|
||||
<ComponentRef Id='License' />
|
||||
<ComponentRef Id='Readme' />
|
||||
<ComponentGroupRef Id='Dlls' />
|
||||
<ComponentGroupRef Id='Resources' />
|
||||
<ComponentRef Id='ProgramMenuDir' />
|
||||
</Feature>
|
||||
|
||||
|
|
|
|||
|
|
@ -22,13 +22,12 @@
|
|||
<Shortcut Id='startmenuTg' Directory='ProgramMenuDir' Name='Tg #VERSION#' WorkingDirectory='INSTALLDIR' Icon='tg.exe' IconIndex='0' Advertise='yes' />
|
||||
<Shortcut Id='desktopTg' Directory='DesktopFolder' Name='Tg #VERSION#' WorkingDirectory='INSTALLDIR' Icon='tg.exe' IconIndex='0' Advertise='yes' />
|
||||
</File>
|
||||
</Component>
|
||||
|
||||
<Component Id='LightExecutable' Guid='#UUID#'>
|
||||
<File Id='TgLtEXE' Name='tg-lt.exe' DiskId='1' Source='tg-lt.exe' KeyPath='yes'>
|
||||
<Shortcut Id='startmenuTgLt' Directory='ProgramMenuDir' Name='Tg lt #VERSION#' WorkingDirectory='INSTALLDIR' Icon='tg.exe' IconIndex='0' Advertise='yes' />
|
||||
<Shortcut Id='desktopTgLt' Directory='DesktopFolder' Name='Tg lt #VERSION#' WorkingDirectory='INSTALLDIR' Icon='tg.exe' IconIndex='0' Advertise='yes' />
|
||||
</File>
|
||||
<File Id='TgDocumentICO' Name='tg-document.ico' Source='tg-document.ico' />
|
||||
<ProgId Id='TgjFile' Description='Tg data file' Icon='TgDocumentICO'>
|
||||
<Extension Id='tgj' ContentType='application/x-tg-timer-data'>
|
||||
<Verb Id='open' Command='Open' TargetFile='TgEXE' Argument='"%1"' />
|
||||
</Extension>
|
||||
</ProgId>
|
||||
</Component>
|
||||
|
||||
<Component Id='License' Guid='#UUID#'>
|
||||
|
|
@ -56,10 +55,9 @@
|
|||
|
||||
<Feature Id='Complete' Level='1' ConfigurableDirectory='INSTALLDIR'>
|
||||
<ComponentRef Id='MainExecutable' />
|
||||
<ComponentRef Id='LightExecutable' />
|
||||
<ComponentRef Id='License' />
|
||||
<ComponentRef Id='Readme' />
|
||||
<ComponentGroupRef Id='Dlls' />
|
||||
<ComponentGroupRef Id='Resources' />
|
||||
<ComponentRef Id='ProgramMenuDir' />
|
||||
</Feature>
|
||||
|
||||
|
|
|
|||
127
src/algo.c
|
|
@ -22,21 +22,21 @@ struct filter {
|
|||
double a0,a1,a2,b1,b2;
|
||||
};
|
||||
|
||||
int fl_cmp(const void *a, const void *b)
|
||||
static int fl_cmp(const void *a, const void *b)
|
||||
{
|
||||
float x = *(float*)a;
|
||||
float y = *(float*)b;
|
||||
return x<y ? -1 : x>y ? 1 : 0;
|
||||
}
|
||||
|
||||
int int_cmp(const void *a, const void *b)
|
||||
static int int_cmp(const void *a, const void *b)
|
||||
{
|
||||
int x = *(int*)a;
|
||||
int y = *(int*)b;
|
||||
return x<y ? -1 : x>y ? 1 : 0;
|
||||
}
|
||||
|
||||
void make_hp(struct filter *f, double freq)
|
||||
static void make_hp(struct filter *f, double freq)
|
||||
{
|
||||
double K = tan(M_PI * freq);
|
||||
double norm = 1 / (1 + K * sqrt(2) + K * K);
|
||||
|
|
@ -47,7 +47,7 @@ void make_hp(struct filter *f, double freq)
|
|||
f->b2 = (1 - K * sqrt(2) + K * K) * norm;
|
||||
}
|
||||
|
||||
void make_lp(struct filter *f, double freq)
|
||||
static void make_lp(struct filter *f, double freq)
|
||||
{
|
||||
double K = tan(M_PI * freq);
|
||||
double norm = 1 / (1 + K * sqrt(2) + K * K);
|
||||
|
|
@ -58,7 +58,7 @@ void make_lp(struct filter *f, double freq)
|
|||
f->b2 = (1 - K * sqrt(2) + K * K) * norm;
|
||||
}
|
||||
|
||||
void run_filter(struct filter *f, float *buff, int size)
|
||||
static void run_filter(struct filter *f, float *buff, int size)
|
||||
{
|
||||
int i;
|
||||
double z1 = 0, z2 = 0;
|
||||
|
|
@ -98,25 +98,61 @@ void setup_buffers(struct processing_buffers *b)
|
|||
b->events = malloc(EVENTS_MAX * sizeof(uint64_t));
|
||||
b->ready = 0;
|
||||
#ifdef DEBUG
|
||||
b->debug = fftwf_malloc(b->sample_count * sizeof(float));
|
||||
b->debug_size = b->sample_count;
|
||||
b->debug = fftwf_malloc(b->debug_size * sizeof(float));
|
||||
#endif
|
||||
}
|
||||
|
||||
void pb_destroy(struct processing_buffers *b)
|
||||
{
|
||||
fftwf_free(b->samples);
|
||||
free(b->samples_sc);
|
||||
free(b->waveform);
|
||||
free(b->waveform_sc);
|
||||
fftwf_free(b->fft);
|
||||
fftwf_free(b->sc_fft);
|
||||
fftwf_free(b->tic_wf);
|
||||
fftwf_free(b->slice_wf);
|
||||
fftwf_free(b->tic_fft);
|
||||
fftwf_free(b->slice_fft);
|
||||
free(b->tic_c);
|
||||
fftwf_destroy_plan(b->plan_a);
|
||||
fftwf_destroy_plan(b->plan_b);
|
||||
fftwf_destroy_plan(b->plan_c);
|
||||
fftwf_destroy_plan(b->plan_d);
|
||||
fftwf_destroy_plan(b->plan_e);
|
||||
fftwf_destroy_plan(b->plan_f);
|
||||
fftwf_destroy_plan(b->plan_g);
|
||||
free(b->hpf);
|
||||
free(b->lpf);
|
||||
free(b->events);
|
||||
#ifdef DEBUG
|
||||
fftwf_free(b->debug);
|
||||
#endif
|
||||
}
|
||||
|
||||
struct processing_buffers *pb_clone(struct processing_buffers *p)
|
||||
{
|
||||
struct processing_buffers *new = malloc(sizeof(struct processing_buffers));
|
||||
new->sample_rate = p->sample_rate;
|
||||
new->waveform = malloc(new->sample_rate * sizeof(float));
|
||||
memcpy(new->waveform, p->waveform, new->sample_rate * sizeof(float));
|
||||
new->events = malloc(EVENTS_MAX * sizeof(uint64_t));
|
||||
memcpy(new->events, p->events, EVENTS_MAX * sizeof(uint64_t));
|
||||
new->sample_count = ceil(p->period);
|
||||
new->waveform = malloc(new->sample_count * sizeof(float));
|
||||
memcpy(new->waveform, p->waveform, new->sample_count * sizeof(float));
|
||||
if(p->events) {
|
||||
new->events = malloc(EVENTS_MAX * sizeof(uint64_t));
|
||||
memcpy(new->events, p->events, EVENTS_MAX * sizeof(uint64_t));
|
||||
} else
|
||||
new->events = NULL;
|
||||
|
||||
#ifdef DEBUG
|
||||
new->debug = malloc(p->sample_count * sizeof(float));
|
||||
memcpy(new->debug, p->debug, p->sample_count * sizeof(float));
|
||||
new->debug_size = p->debug_size;
|
||||
if(p->debug) {
|
||||
new->debug = malloc(new->debug_size * sizeof(float));
|
||||
memcpy(new->debug, p->debug, new->debug_size * sizeof(float));
|
||||
} else
|
||||
new->debug = NULL;
|
||||
#endif
|
||||
|
||||
new->sample_count = p->sample_count;
|
||||
new->sample_rate = p->sample_rate;
|
||||
new->period = p->period;
|
||||
new->sigma = p->sigma;
|
||||
new->be = p->be;
|
||||
|
|
@ -141,7 +177,7 @@ void pb_destroy_clone(struct processing_buffers *p)
|
|||
free(p);
|
||||
}
|
||||
|
||||
float vmax(float *v, int a, int b, int *i_max)
|
||||
static float vmax(float *v, int a, int b, int *i_max)
|
||||
{
|
||||
float max = v[a];
|
||||
if(i_max) *i_max = a;
|
||||
|
|
@ -155,7 +191,7 @@ float vmax(float *v, int a, int b, int *i_max)
|
|||
return max;
|
||||
}
|
||||
|
||||
void noise_suppressor(struct processing_buffers *p)
|
||||
static void noise_suppressor(struct processing_buffers *p)
|
||||
{
|
||||
float *a = p->samples_sc;
|
||||
float *b = p->samples_sc + p->sample_count;
|
||||
|
|
@ -189,15 +225,13 @@ void noise_suppressor(struct processing_buffers *p)
|
|||
}
|
||||
}
|
||||
|
||||
void prepare_data(struct processing_buffers *b, int run_noise_suppressor)
|
||||
static void prepare_data(struct processing_buffers *b, int run_noise_suppressor)
|
||||
{
|
||||
int i;
|
||||
|
||||
memset(b->samples + b->sample_count, 0, b->sample_count * sizeof(float));
|
||||
run_filter(b->hpf, b->samples, b->sample_count);
|
||||
#ifndef LIGHT
|
||||
if(run_noise_suppressor) noise_suppressor(b);
|
||||
#endif
|
||||
|
||||
for(i=0; i < b->sample_count; i++)
|
||||
b->samples[i] = fabs(b->samples[i]);
|
||||
|
|
@ -227,7 +261,7 @@ void prepare_data(struct processing_buffers *b, int run_noise_suppressor)
|
|||
#endif
|
||||
}
|
||||
|
||||
int peak_detector(float *buff, int a, int b)
|
||||
static int peak_detector(float *buff, int a, int b)
|
||||
{
|
||||
int i_max;
|
||||
double max = vmax(buff, a, b+1, &i_max);
|
||||
|
|
@ -262,7 +296,7 @@ int peak_detector(float *buff, int a, int b)
|
|||
return i_max;
|
||||
}
|
||||
|
||||
double estimate_period(struct processing_buffers *p)
|
||||
static double estimate_period(struct processing_buffers *p)
|
||||
{
|
||||
int first_estimate;
|
||||
vmax(p->samples_sc, p->sample_rate / 12, p->sample_rate, &first_estimate);
|
||||
|
|
@ -301,7 +335,7 @@ double estimate_period(struct processing_buffers *p)
|
|||
} else return estimate;
|
||||
}
|
||||
|
||||
int compute_period(struct processing_buffers *b, int bph)
|
||||
static int compute_period(struct processing_buffers *b, int bph)
|
||||
{
|
||||
double estimate;
|
||||
if(bph)
|
||||
|
|
@ -352,7 +386,7 @@ int compute_period(struct processing_buffers *b, int bph)
|
|||
return 0;
|
||||
}
|
||||
|
||||
float tmean(float *x, int n)
|
||||
static float tmean(float *x, int n)
|
||||
{
|
||||
if(n>16) {
|
||||
qsort(x,16,sizeof(float),fl_cmp);
|
||||
|
|
@ -378,7 +412,7 @@ float tmean(float *x, int n)
|
|||
return sum/(n*4/5);
|
||||
}
|
||||
|
||||
void compute_phase(struct processing_buffers *p, double period)
|
||||
static void compute_phase(struct processing_buffers *p, double period)
|
||||
{
|
||||
int i;
|
||||
double x = 0, y = 0;
|
||||
|
|
@ -400,7 +434,7 @@ void compute_phase(struct processing_buffers *p, double period)
|
|||
p->phase = period * (M_PI + atan2(y,x)) / (2 * M_PI);
|
||||
}
|
||||
|
||||
void compute_waveform(struct processing_buffers *p, int wf_size)
|
||||
static void compute_waveform(struct processing_buffers *p, int wf_size)
|
||||
{
|
||||
int i;
|
||||
for(i=0; i<2*p->sample_rate; i++)
|
||||
|
|
@ -428,7 +462,7 @@ void compute_waveform(struct processing_buffers *p, int wf_size)
|
|||
p->waveform_max = vmax(p->waveform, 0, wf_size, &p->waveform_max_i);
|
||||
}
|
||||
|
||||
void prepare_waveform(struct processing_buffers *p)
|
||||
static void prepare_waveform(struct processing_buffers *p)
|
||||
{
|
||||
compute_phase(p,p->period/2);
|
||||
compute_waveform(p,ceil(p->period));
|
||||
|
|
@ -440,13 +474,13 @@ void prepare_waveform(struct processing_buffers *p)
|
|||
fftwf_execute(p->plan_d);
|
||||
}
|
||||
|
||||
void prepare_waveform_cal(struct processing_buffers *p)
|
||||
static void prepare_waveform_cal(struct processing_buffers *p)
|
||||
{
|
||||
compute_phase(p,p->sample_rate);
|
||||
compute_waveform(p,p->sample_rate);
|
||||
}
|
||||
|
||||
void smooth(float *in, float *out, int window, int size)
|
||||
static void smooth(float *in, float *out, int window, int size)
|
||||
{
|
||||
int i;
|
||||
double k = 1 - (1. / window);
|
||||
|
|
@ -471,7 +505,7 @@ void smooth(float *in, float *out, int window, int size)
|
|||
}
|
||||
}
|
||||
|
||||
int compute_parameters(struct processing_buffers *p)
|
||||
static int compute_parameters(struct processing_buffers *p)
|
||||
{
|
||||
int tic_to_toc = peak_detector(p->waveform_sc,
|
||||
floor(p->period/2)-p->sample_rate/50,
|
||||
|
|
@ -518,7 +552,7 @@ int compute_parameters(struct processing_buffers *p)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void do_locate_events(int *events, struct processing_buffers *p, float *waveform, int last, int offset, int count)
|
||||
static void do_locate_events(int *events, struct processing_buffers *p, float *waveform, int last, int offset, int count)
|
||||
{
|
||||
int i;
|
||||
memset(p->tic_wf, 0, p->sample_rate * sizeof(float));
|
||||
|
|
@ -552,7 +586,7 @@ void do_locate_events(int *events, struct processing_buffers *p, float *waveform
|
|||
}
|
||||
}
|
||||
|
||||
void locate_events(struct processing_buffers *p)
|
||||
static void locate_events(struct processing_buffers *p)
|
||||
{
|
||||
int count = 1 + ceil((p->timestamp - p->events_from) / p->period);
|
||||
if(count <= 0 || 2*count >= EVENTS_MAX) {
|
||||
|
|
@ -580,7 +614,7 @@ void locate_events(struct processing_buffers *p)
|
|||
p->events[j] = 0;
|
||||
}
|
||||
|
||||
void compute_amplitude(struct processing_buffers *p, double la)
|
||||
static void compute_amplitude(struct processing_buffers *p, double la)
|
||||
{
|
||||
int i,j,k;
|
||||
|
||||
|
|
@ -630,15 +664,17 @@ void compute_amplitude(struct processing_buffers *p, double la)
|
|||
} else
|
||||
goto next_threshold;
|
||||
}
|
||||
double tic_amp = la * .5 / sin(M_PI * tic_pulse / p->period);
|
||||
double toc_amp = la * .5 / sin(M_PI * toc_pulse / p->period);
|
||||
double tic_amp_abs = .5 / sin(M_PI * tic_pulse / p->period);
|
||||
double toc_amp_abs = .5 / sin(M_PI * toc_pulse / p->period);
|
||||
double tic_amp = la * tic_amp_abs;
|
||||
double toc_amp = la * toc_amp_abs;
|
||||
if(135 < tic_amp && tic_amp < 360 && 135 < toc_amp && toc_amp < 360 && fabs(tic_amp - toc_amp) < 60) {
|
||||
p->amp = (tic_amp + toc_amp) / 2;
|
||||
p->amp = (tic_amp_abs + toc_amp_abs) / 2;
|
||||
p->tic_pulse = tic_pulse;
|
||||
p->toc_pulse = toc_pulse;
|
||||
p->be = p->period/2 - fabs(p->toc - p->tic + p->tic_pulse - p->toc_pulse);
|
||||
debug("amp: be = %.1f\n",fabs(p->be)*1000/p->sample_rate);
|
||||
debug("amp = %f\n", p->amp);
|
||||
debug("amp = %f\n", la * p->amp);
|
||||
break;
|
||||
} else
|
||||
debug("amp rejected\n");
|
||||
|
|
@ -655,7 +691,14 @@ void setup_cal_data(struct calibration_data *cd)
|
|||
cd->events = malloc(cd->size * sizeof(uint64_t));
|
||||
}
|
||||
|
||||
int add_sample_cal(struct processing_buffers *p, struct calibration_data *cd)
|
||||
void cal_data_destroy(struct calibration_data *cd)
|
||||
{
|
||||
free(cd->times);
|
||||
free(cd->phases);
|
||||
free(cd->events);
|
||||
}
|
||||
|
||||
static int add_sample_cal(struct processing_buffers *p, struct calibration_data *cd)
|
||||
{
|
||||
int i;
|
||||
double phase = -1;
|
||||
|
|
@ -694,7 +737,7 @@ int add_sample_cal(struct processing_buffers *p, struct calibration_data *cd)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void compute_cal(struct calibration_data *cd, int sample_rate)
|
||||
static void compute_cal(struct calibration_data *cd)
|
||||
{
|
||||
int i;
|
||||
double x = 0, y = 0;
|
||||
|
|
@ -724,11 +767,11 @@ void compute_cal(struct calibration_data *cd, int sample_rate)
|
|||
cd->state = delta * 3600 * 24 < 0.1 ? 1 : -1;
|
||||
}
|
||||
|
||||
void process(struct processing_buffers *p, int bph, double la)
|
||||
void process(struct processing_buffers *p, int bph, double la, int light)
|
||||
{
|
||||
prepare_data(p,1);
|
||||
prepare_data(p, !light);
|
||||
p->ready = !compute_period(p,bph);
|
||||
if(p->period >= p->sample_rate / 2) {
|
||||
if(p->ready && p->period >= p->sample_rate / 2) {
|
||||
debug("Detected period too long\n");
|
||||
p->ready = 0;
|
||||
}
|
||||
|
|
@ -763,6 +806,6 @@ int process_cal(struct processing_buffers *p, struct calibration_data *cd)
|
|||
if(add_sample_cal(p,cd))
|
||||
return 1;
|
||||
if(cd->wp == cd->size && cd->state == 0)
|
||||
compute_cal(cd, p->sample_rate);
|
||||
compute_cal(cd);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
58
src/audio.c
|
|
@ -24,13 +24,16 @@ int write_pointer = 0;
|
|||
uint64_t timestamp = 0;
|
||||
pthread_mutex_t audio_mutex;
|
||||
|
||||
int paudio_callback(const void *input_buffer,
|
||||
void *output_buffer,
|
||||
unsigned long frame_count,
|
||||
const PaStreamCallbackTimeInfo *time_info,
|
||||
PaStreamCallbackFlags status_flags,
|
||||
void *data)
|
||||
static int paudio_callback(const void *input_buffer,
|
||||
void *output_buffer,
|
||||
unsigned long frame_count,
|
||||
const PaStreamCallbackTimeInfo *time_info,
|
||||
PaStreamCallbackFlags status_flags,
|
||||
void *data)
|
||||
{
|
||||
UNUSED(output_buffer);
|
||||
UNUSED(time_info);
|
||||
UNUSED(status_flags);
|
||||
unsigned long i;
|
||||
long channels = (long)data;
|
||||
int wp = write_pointer;
|
||||
|
|
@ -93,13 +96,8 @@ int start_portaudio(int *nominal_sample_rate, double *real_sample_rate)
|
|||
goto error;
|
||||
|
||||
const PaStreamInfo *info = Pa_GetStreamInfo(stream);
|
||||
#ifdef LIGHT
|
||||
*nominal_sample_rate = PA_SAMPLE_RATE / 2;
|
||||
*real_sample_rate = info->sampleRate / 2;
|
||||
#else
|
||||
*nominal_sample_rate = PA_SAMPLE_RATE;
|
||||
*real_sample_rate = info->sampleRate;
|
||||
#endif
|
||||
#ifdef DEBUG
|
||||
end:
|
||||
#endif
|
||||
|
|
@ -123,46 +121,36 @@ int terminate_portaudio()
|
|||
return 0;
|
||||
}
|
||||
|
||||
uint64_t get_timestamp()
|
||||
uint64_t get_timestamp(int light)
|
||||
{
|
||||
pthread_mutex_lock(&audio_mutex);
|
||||
#ifdef LIGHT
|
||||
uint64_t ts = timestamp / 2;
|
||||
#else
|
||||
uint64_t ts = timestamp;
|
||||
#endif
|
||||
uint64_t ts = light ? timestamp / 2 : timestamp;
|
||||
pthread_mutex_unlock(&audio_mutex);
|
||||
return ts;
|
||||
}
|
||||
|
||||
void fill_buffers(struct processing_buffers *p)
|
||||
static void fill_buffers(struct processing_buffers *p, int light)
|
||||
{
|
||||
pthread_mutex_lock(&audio_mutex);
|
||||
uint64_t ts = timestamp;
|
||||
int wp = write_pointer;
|
||||
pthread_mutex_unlock(&audio_mutex);
|
||||
if(wp < 0 || wp >= PA_BUFF_SIZE) wp = 0;
|
||||
#ifdef LIGHT
|
||||
if(wp % 2) wp--;
|
||||
ts /= 2;
|
||||
#endif
|
||||
if(light) {
|
||||
if(wp % 2) wp--;
|
||||
ts /= 2;
|
||||
}
|
||||
int i;
|
||||
for(i=0; i<NSTEPS; i++) {
|
||||
int j,k;
|
||||
p[i].timestamp = ts;
|
||||
#ifdef LIGHT
|
||||
k = wp - 2*p[i].sample_count;
|
||||
#else
|
||||
k = wp - p[i].sample_count;
|
||||
#endif
|
||||
if(light) k = wp - 2*p[i].sample_count;
|
||||
else k = wp - p[i].sample_count;
|
||||
|
||||
if(k < 0) k += PA_BUFF_SIZE;
|
||||
for(j=0; j < p[i].sample_count; j++) {
|
||||
p[i].samples[j] = pa_buffers[0][k] + pa_buffers[1][k];
|
||||
#ifdef LIGHT
|
||||
k += 2;
|
||||
#else
|
||||
k++;
|
||||
#endif
|
||||
k += light ? 2 : 1;
|
||||
if(k >= PA_BUFF_SIZE) k -= PA_BUFF_SIZE;
|
||||
}
|
||||
}
|
||||
|
|
@ -171,14 +159,14 @@ void fill_buffers(struct processing_buffers *p)
|
|||
int analyze_pa_data(struct processing_data *pd, int bph, double la, uint64_t events_from)
|
||||
{
|
||||
struct processing_buffers *p = pd->buffers;
|
||||
fill_buffers(p);
|
||||
fill_buffers(p, pd->is_light);
|
||||
|
||||
int i;
|
||||
debug("\nSTART OF COMPUTATION CYCLE\n\n");
|
||||
for(i=0; i<NSTEPS; i++) {
|
||||
p[i].last_tic = pd->last_tic;
|
||||
p[i].events_from = events_from;
|
||||
process(&p[i], bph, la);
|
||||
process(&p[i], bph, la, pd->is_light);
|
||||
if( !p[i].ready ) break;
|
||||
debug("step %d : %f +- %f\n",i,p[i].period/p[i].sample_rate,p[i].sigma/p[i].sample_rate);
|
||||
}
|
||||
|
|
@ -193,7 +181,7 @@ int analyze_pa_data(struct processing_data *pd, int bph, double la, uint64_t eve
|
|||
int analyze_pa_data_cal(struct processing_data *pd, struct calibration_data *cd)
|
||||
{
|
||||
struct processing_buffers *p = pd->buffers;
|
||||
fill_buffers(p);
|
||||
fill_buffers(p, pd->is_light);
|
||||
|
||||
int i,j;
|
||||
debug("\nSTART OF CALIBRATION CYCLE\n\n");
|
||||
|
|
|
|||
304
src/computer.c
Normal file
|
|
@ -0,0 +1,304 @@
|
|||
/*
|
||||
tg
|
||||
Copyright (C) 2015 Marcello Mamino
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License version 2 as
|
||||
published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "tg.h"
|
||||
|
||||
static int count_events(struct snapshot *s)
|
||||
{
|
||||
int i, cnt = 0;
|
||||
if(!s->events_count) return 0;
|
||||
for(i = s->events_wp; s->events[i];) {
|
||||
cnt++;
|
||||
if(--i < 0) i = s->events_count - 1;
|
||||
if(i == s->events_wp) break;
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
||||
struct snapshot *snapshot_clone(struct snapshot *s)
|
||||
{
|
||||
struct snapshot *t = malloc(sizeof(struct snapshot));
|
||||
memcpy(t,s,sizeof(struct snapshot));
|
||||
if(s->pb) t->pb = pb_clone(s->pb);
|
||||
t->events_count = count_events(s);
|
||||
if(t->events_count) {
|
||||
t->events_wp = t->events_count - 1;
|
||||
t->events = malloc(t->events_count * sizeof(uint64_t));
|
||||
int i, j;
|
||||
for(i = t->events_wp, j = s->events_wp; i >= 0; i--) {
|
||||
t->events[i] = s->events[j];
|
||||
if(--j < 0) j = s->events_count - 1;
|
||||
}
|
||||
} else {
|
||||
t->events_wp = 0;
|
||||
t->events = NULL;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
void snapshot_destroy(struct snapshot *s)
|
||||
{
|
||||
if(s->pb) pb_destroy_clone(s->pb);
|
||||
free(s->events);
|
||||
free(s);
|
||||
}
|
||||
|
||||
static int guess_bph(double period)
|
||||
{
|
||||
double bph = 7200 / period;
|
||||
double min = bph;
|
||||
int i,ret;
|
||||
|
||||
ret = 0;
|
||||
for(i=0; preset_bph[i]; i++) {
|
||||
double diff = fabs(bph - preset_bph[i]);
|
||||
if(diff < min) {
|
||||
min = diff;
|
||||
ret = i;
|
||||
}
|
||||
}
|
||||
|
||||
return preset_bph[ret];
|
||||
}
|
||||
|
||||
static void compute_update_cal(struct computer *c)
|
||||
{
|
||||
c->actv->signal = analyze_pa_data_cal(c->pdata, c->cdata);
|
||||
if(c->actv->pb) {
|
||||
pb_destroy_clone(c->actv->pb);
|
||||
c->actv->pb = NULL;
|
||||
}
|
||||
c->actv->cal_state = c->cdata->state;
|
||||
c->actv->cal_percent = 100*c->cdata->wp/c->cdata->size;
|
||||
if(c->cdata->state == 1)
|
||||
c->actv->cal_result = round(10 * c->cdata->calibration);
|
||||
}
|
||||
|
||||
static void compute_update(struct computer *c)
|
||||
{
|
||||
int signal = analyze_pa_data(c->pdata, c->actv->bph, c->actv->la, c->actv->events_from);
|
||||
struct processing_buffers *p = c->pdata->buffers;
|
||||
int i;
|
||||
for(i=0; i<NSTEPS && p[i].ready; i++);
|
||||
for(i--; i>=0 && p[i].sigma > p[i].period / 10000; i--);
|
||||
if(i>=0) {
|
||||
if(c->actv->pb) pb_destroy_clone(c->actv->pb);
|
||||
c->actv->pb = pb_clone(&p[i]);
|
||||
c->actv->is_old = 0;
|
||||
c->actv->signal = i == NSTEPS-1 && p[i].amp < 0 ? signal-1 : signal;
|
||||
} else {
|
||||
c->actv->is_old = 1;
|
||||
c->actv->signal = -signal;
|
||||
}
|
||||
}
|
||||
|
||||
static void compute_events_cal(struct computer *c)
|
||||
{
|
||||
struct calibration_data *d = c->cdata;
|
||||
struct snapshot *s = c->actv;
|
||||
int i;
|
||||
for(i=d->wp-1; i >= 0 &&
|
||||
d->events[i] > s->events[s->events_wp];
|
||||
i--);
|
||||
for(i++; i<d->wp; i++) {
|
||||
if(d->events[i] / s->nominal_sr <= s->events[s->events_wp] / s->nominal_sr)
|
||||
continue;
|
||||
if(++s->events_wp == s->events_count) s->events_wp = 0;
|
||||
s->events[s->events_wp] = d->events[i];
|
||||
debug("event at %llu\n",s->events[s->events_wp]);
|
||||
}
|
||||
s->events_from = get_timestamp(s->is_light);
|
||||
}
|
||||
|
||||
static void compute_events(struct computer *c)
|
||||
{
|
||||
struct snapshot *s = c->actv;
|
||||
struct processing_buffers *p = c->actv->pb;
|
||||
if(p && !s->is_old) {
|
||||
uint64_t last = s->events[s->events_wp];
|
||||
int i;
|
||||
for(i=0; i<EVENTS_MAX && p->events[i]; i++)
|
||||
if(p->events[i] > last + floor(p->period / 4)) {
|
||||
if(++s->events_wp == s->events_count) s->events_wp = 0;
|
||||
s->events[s->events_wp] = p->events[i];
|
||||
debug("event at %llu\n",s->events[s->events_wp]);
|
||||
}
|
||||
s->events_from = p->timestamp - ceil(p->period);
|
||||
} else {
|
||||
s->events_from = get_timestamp(s->is_light);
|
||||
}
|
||||
}
|
||||
|
||||
void compute_results(struct snapshot *s)
|
||||
{
|
||||
s->sample_rate = s->nominal_sr * (1 + (double) s->cal / (10 * 3600 * 24));
|
||||
if(s->pb) {
|
||||
s->guessed_bph = s->bph ? s->bph : guess_bph(s->pb->period / s->sample_rate);
|
||||
s->rate = (7200/(s->guessed_bph * s->pb->period / s->sample_rate) - 1)*24*3600;
|
||||
s->be = fabs(s->pb->be) * 1000 / s->sample_rate;
|
||||
s->amp = s->la * s->pb->amp; // 0 = not available
|
||||
if(s->amp < 135 || s->amp > 360)
|
||||
s->amp = 0;
|
||||
} else
|
||||
s->guessed_bph = s->bph ? s->bph : DEFAULT_BPH;
|
||||
}
|
||||
|
||||
static void *computing_thread(void *void_computer)
|
||||
{
|
||||
struct computer *c = void_computer;
|
||||
for(;;) {
|
||||
pthread_mutex_lock(&c->mutex);
|
||||
while(!c->recompute)
|
||||
pthread_cond_wait(&c->cond, &c->mutex);
|
||||
if(c->recompute > 0) c->recompute = 0;
|
||||
int calibrate = c->calibrate;
|
||||
c->actv->bph = c->bph;
|
||||
c->actv->la = c->la;
|
||||
void (*callback)(void *) = c->callback;
|
||||
void *callback_data = c->callback_data;
|
||||
pthread_mutex_unlock(&c->mutex);
|
||||
|
||||
if(c->recompute < 0) {
|
||||
if(callback) callback(callback_data);
|
||||
break;
|
||||
}
|
||||
|
||||
if(calibrate && !c->actv->calibrate) {
|
||||
c->cdata->wp = 0;
|
||||
c->cdata->state = 0;
|
||||
c->actv->cal_state = 0;
|
||||
c->actv->cal_percent = 0;
|
||||
}
|
||||
if(calibrate != c->actv->calibrate)
|
||||
memset(c->actv->events,0,c->actv->events_count*sizeof(uint64_t));
|
||||
c->actv->calibrate = calibrate;
|
||||
|
||||
if(c->actv->calibrate) {
|
||||
compute_update_cal(c);
|
||||
compute_events_cal(c);
|
||||
} else {
|
||||
compute_update(c);
|
||||
compute_events(c);
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&c->mutex);
|
||||
if(c->curr)
|
||||
snapshot_destroy(c->curr);
|
||||
if(c->clear_trace) {
|
||||
if(!calibrate)
|
||||
memset(c->actv->events,0,c->actv->events_count*sizeof(uint64_t));
|
||||
c->clear_trace = 0;
|
||||
}
|
||||
c->curr = snapshot_clone(c->actv);
|
||||
pthread_mutex_unlock(&c->mutex);
|
||||
|
||||
if(callback) callback(callback_data);
|
||||
}
|
||||
|
||||
debug("Terminating computation thread\n");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void computer_destroy(struct computer *c)
|
||||
{
|
||||
int i;
|
||||
for(i=0; i<NSTEPS; i++)
|
||||
pb_destroy(&c->pdata->buffers[i]);
|
||||
free(c->pdata->buffers);
|
||||
free(c->pdata);
|
||||
cal_data_destroy(c->cdata);
|
||||
free(c->cdata);
|
||||
snapshot_destroy(c->actv);
|
||||
if(c->curr)
|
||||
snapshot_destroy(c->curr);
|
||||
pthread_mutex_destroy(&c->mutex);
|
||||
pthread_cond_destroy(&c->cond);
|
||||
pthread_join(c->thread, NULL);
|
||||
free(c);
|
||||
}
|
||||
|
||||
struct computer *start_computer(int nominal_sr, int bph, double la, int cal, int light)
|
||||
{
|
||||
if(light) nominal_sr /= 2;
|
||||
|
||||
struct processing_buffers *p = malloc(NSTEPS * sizeof(struct processing_buffers));
|
||||
int first_step = light ? FIRST_STEP_LIGHT : FIRST_STEP;
|
||||
int i;
|
||||
for(i=0; i<NSTEPS; i++) {
|
||||
p[i].sample_rate = nominal_sr;
|
||||
p[i].sample_count = nominal_sr * (1<<(i+first_step));
|
||||
setup_buffers(&p[i]);
|
||||
}
|
||||
|
||||
struct processing_data *pd = malloc(sizeof(struct processing_data));
|
||||
pd->buffers = p;
|
||||
pd->last_tic = 0;
|
||||
pd->is_light = light;
|
||||
|
||||
struct calibration_data *cd = malloc(sizeof(struct calibration_data));
|
||||
setup_cal_data(cd);
|
||||
|
||||
struct snapshot *s = malloc(sizeof(struct snapshot));
|
||||
s->timestamp = 0;
|
||||
s->nominal_sr = nominal_sr;
|
||||
s->pb = NULL;
|
||||
s->is_old = 1;
|
||||
s->calibrate = 0;
|
||||
s->signal = 0;
|
||||
s->events_count = EVENTS_COUNT;
|
||||
s->events = malloc(EVENTS_COUNT * sizeof(uint64_t));
|
||||
memset(s->events,0,EVENTS_COUNT * sizeof(uint64_t));
|
||||
s->events_wp = 0;
|
||||
s->events_from = 0;
|
||||
s->trace_centering = 0;
|
||||
s->bph = bph;
|
||||
s->la = la;
|
||||
s->cal = cal;
|
||||
s->is_light = light;
|
||||
|
||||
struct computer *c = malloc(sizeof(struct computer));
|
||||
c->cdata = cd;
|
||||
c->pdata = pd;
|
||||
c->actv = s;
|
||||
c->curr = snapshot_clone(s);
|
||||
c->recompute = 0;
|
||||
c->calibrate = 0;
|
||||
c->clear_trace = 0;
|
||||
|
||||
if( pthread_mutex_init(&c->mutex, NULL)
|
||||
|| pthread_cond_init(&c->cond, NULL)
|
||||
|| pthread_create(&c->thread, NULL, computing_thread, c)) {
|
||||
error("Unable to initialize computing thread");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
void lock_computer(struct computer *c)
|
||||
{
|
||||
pthread_mutex_lock(&c->mutex);
|
||||
}
|
||||
|
||||
void unlock_computer(struct computer *c)
|
||||
{
|
||||
if(c->recompute)
|
||||
pthread_cond_signal(&c->cond);
|
||||
pthread_mutex_unlock(&c->mutex);
|
||||
}
|
||||
|
|
@ -19,7 +19,7 @@
|
|||
#include "tg.h"
|
||||
|
||||
#if !GLIB_CHECK_VERSION(2,40,0)
|
||||
gboolean
|
||||
static gboolean
|
||||
g_key_file_save_to_file (GKeyFile *key_file,
|
||||
const gchar *filename,
|
||||
GError **error)
|
||||
|
|
@ -113,3 +113,10 @@ void save_on_change(struct main_window *w)
|
|||
|
||||
CONFIG_FIELDS(CHANGED);
|
||||
}
|
||||
|
||||
void close_config(struct main_window *w)
|
||||
{
|
||||
g_key_file_free(w->config_file);
|
||||
g_free(w->config_file_name);
|
||||
free(w->conf_data);
|
||||
}
|
||||
|
|
|
|||
1867
src/interface.c
868
src/output_panel.c
Normal file
|
|
@ -0,0 +1,868 @@
|
|||
/*
|
||||
tg
|
||||
Copyright (C) 2015 Marcello Mamino
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License version 2 as
|
||||
published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "tg.h"
|
||||
|
||||
cairo_pattern_t *black,*white,*red,*green,*blue,*blueish,*yellow;
|
||||
|
||||
static void define_color(cairo_pattern_t **gc,double r,double g,double b)
|
||||
{
|
||||
*gc = cairo_pattern_create_rgb(r,g,b);
|
||||
}
|
||||
|
||||
void initialize_palette()
|
||||
{
|
||||
define_color(&black,0,0,0);
|
||||
define_color(&white,1,1,1);
|
||||
define_color(&red,1,0,0);
|
||||
define_color(&green,0,0.8,0);
|
||||
define_color(&blue,0,0,1);
|
||||
define_color(&blueish,0,0,.5);
|
||||
define_color(&yellow,1,1,0);
|
||||
}
|
||||
|
||||
static void draw_graph(double a, double b, cairo_t *c, struct processing_buffers *p, GtkWidget *da)
|
||||
{
|
||||
GtkAllocation temp;
|
||||
gtk_widget_get_allocation (da, &temp);
|
||||
int width = temp.width;
|
||||
int height = temp.height;
|
||||
|
||||
int n;
|
||||
|
||||
int first = 1;
|
||||
for(n=0; n<2*width; n++) {
|
||||
int i = n < width ? n : 2*width - 1 - n;
|
||||
double x = fmod(a + i * (b-a) / width, p->period);
|
||||
if(x < 0) x += p->period;
|
||||
int j = floor(x);
|
||||
double y;
|
||||
|
||||
if(p->waveform[j] <= 0) y = 0;
|
||||
else y = p->waveform[j] * 0.4 / p->waveform_max;
|
||||
|
||||
int k = round(y*height);
|
||||
if(n < width) k = -k;
|
||||
|
||||
if(first) {
|
||||
cairo_move_to(c,i+.5,height/2+k+.5);
|
||||
first = 0;
|
||||
} else
|
||||
cairo_line_to(c,i+.5,height/2+k+.5);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
static void draw_debug_graph(double a, double b, cairo_t *c, struct processing_buffers *p, GtkWidget *da)
|
||||
{
|
||||
if(!p->debug) return;
|
||||
|
||||
GtkAllocation temp;
|
||||
gtk_widget_get_allocation (da, &temp);
|
||||
int width = temp.width;
|
||||
int height = temp.height;
|
||||
|
||||
int i;
|
||||
float max = 0;
|
||||
|
||||
int ai = round(a);
|
||||
int bi = 1+round(b);
|
||||
if(ai < 0) ai = 0;
|
||||
if(bi > p->sample_count) bi = p->sample_count;
|
||||
for(i=ai; i<bi; i++)
|
||||
if(p->debug[i] > max)
|
||||
max = p->debug[i];
|
||||
|
||||
int first = 1;
|
||||
for(i=0; i<width; i++) {
|
||||
if( round(a + i*(b-a)/width) != round(a + (i+1)*(b-a)/width) ) {
|
||||
int j = round(a + i*(b-a)/width);
|
||||
if(j < 0) j = 0;
|
||||
if(j >= p->sample_count) j = p->sample_count-1;
|
||||
|
||||
int k = round((0.1+p->debug[j]/max)*0.8*height);
|
||||
|
||||
if(first) {
|
||||
cairo_move_to(c,i+.5,height-k-.5);
|
||||
first = 0;
|
||||
} else
|
||||
cairo_line_to(c,i+.5,height-k-.5);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static double amplitude_to_time(double lift_angle, double amp)
|
||||
{
|
||||
return asin(lift_angle / (2 * amp)) / M_PI;
|
||||
}
|
||||
|
||||
static double draw_watch_icon(cairo_t *c, int signal, int happy, int light)
|
||||
{
|
||||
happy = !!happy;
|
||||
cairo_set_line_width(c,3);
|
||||
cairo_set_source(c,happy?green:red);
|
||||
cairo_move_to(c, OUTPUT_WINDOW_HEIGHT * 0.5, OUTPUT_WINDOW_HEIGHT * 0.5);
|
||||
cairo_line_to(c, OUTPUT_WINDOW_HEIGHT * 0.75, OUTPUT_WINDOW_HEIGHT * (0.75 - 0.5*happy));
|
||||
cairo_move_to(c, OUTPUT_WINDOW_HEIGHT * 0.5, OUTPUT_WINDOW_HEIGHT * 0.5);
|
||||
cairo_line_to(c, OUTPUT_WINDOW_HEIGHT * 0.35, OUTPUT_WINDOW_HEIGHT * (0.65 - 0.3*happy));
|
||||
cairo_stroke(c);
|
||||
cairo_arc(c, OUTPUT_WINDOW_HEIGHT * 0.5, OUTPUT_WINDOW_HEIGHT * 0.5, OUTPUT_WINDOW_HEIGHT * 0.4, 0, 2*M_PI);
|
||||
cairo_stroke(c);
|
||||
int l = OUTPUT_WINDOW_HEIGHT * 0.8 / (2*NSTEPS - 1);
|
||||
int i;
|
||||
cairo_set_line_width(c,1);
|
||||
for(i = 0; i < signal; i++) {
|
||||
cairo_move_to(c, OUTPUT_WINDOW_HEIGHT + 0.5*l, OUTPUT_WINDOW_HEIGHT * 0.9 - 2*i*l);
|
||||
cairo_line_to(c, OUTPUT_WINDOW_HEIGHT + 1.5*l, OUTPUT_WINDOW_HEIGHT * 0.9 - 2*i*l);
|
||||
cairo_line_to(c, OUTPUT_WINDOW_HEIGHT + 1.5*l, OUTPUT_WINDOW_HEIGHT * 0.9 - (2*i+1)*l);
|
||||
cairo_line_to(c, OUTPUT_WINDOW_HEIGHT + 0.5*l, OUTPUT_WINDOW_HEIGHT * 0.9 - (2*i+1)*l);
|
||||
cairo_line_to(c, OUTPUT_WINDOW_HEIGHT + 0.5*l, OUTPUT_WINDOW_HEIGHT * 0.9 - 2*i*l);
|
||||
cairo_stroke_preserve(c);
|
||||
cairo_fill(c);
|
||||
}
|
||||
if(light) {
|
||||
int l = OUTPUT_WINDOW_HEIGHT * 0.15;
|
||||
cairo_set_line_width(c,2);
|
||||
cairo_move_to(c, OUTPUT_WINDOW_HEIGHT * 0.5 - 0.5*l, OUTPUT_WINDOW_HEIGHT * 0.2);
|
||||
cairo_line_to(c, OUTPUT_WINDOW_HEIGHT * 0.5 - 0.5*l, OUTPUT_WINDOW_HEIGHT * 0.2 + l);
|
||||
cairo_line_to(c, OUTPUT_WINDOW_HEIGHT * 0.5 , OUTPUT_WINDOW_HEIGHT * 0.2 + l);
|
||||
cairo_move_to(c, OUTPUT_WINDOW_HEIGHT * 0.5 - 0.2*l, OUTPUT_WINDOW_HEIGHT * 0.2 + 1);
|
||||
cairo_line_to(c, OUTPUT_WINDOW_HEIGHT * 0.5 + 0.8*l, OUTPUT_WINDOW_HEIGHT * 0.2 + 1);
|
||||
cairo_move_to(c, OUTPUT_WINDOW_HEIGHT * 0.5 + 0.3*l, OUTPUT_WINDOW_HEIGHT * 0.2 + 1);
|
||||
cairo_line_to(c, OUTPUT_WINDOW_HEIGHT * 0.5 + 0.3*l, OUTPUT_WINDOW_HEIGHT * 0.2 + l + 1);
|
||||
cairo_stroke(c);
|
||||
}
|
||||
return OUTPUT_WINDOW_HEIGHT + 3*l;
|
||||
}
|
||||
|
||||
static void cairo_init(cairo_t *c)
|
||||
{
|
||||
cairo_set_line_width(c,1);
|
||||
|
||||
cairo_set_source(c,black);
|
||||
cairo_paint(c);
|
||||
}
|
||||
|
||||
static double print_s(cairo_t *c, double x, double y, char *s)
|
||||
{
|
||||
cairo_text_extents_t extents;
|
||||
cairo_move_to(c,x,y);
|
||||
cairo_show_text(c,s);
|
||||
cairo_text_extents(c,s,&extents);
|
||||
x += extents.x_advance;
|
||||
return x;
|
||||
}
|
||||
|
||||
static double print_number(cairo_t *c, double x, double y, char *s)
|
||||
{
|
||||
cairo_text_extents_t extents;
|
||||
cairo_text_extents(c,"0",&extents);
|
||||
double z = extents.x_advance;
|
||||
char t[2];
|
||||
t[1] = 0;
|
||||
while((t[0] = *s++)) {
|
||||
cairo_text_extents(c,t,&extents);
|
||||
cairo_move_to(c, x + (z - extents.x_advance) / 2, y);
|
||||
cairo_show_text(c,t);
|
||||
x += z;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
static gboolean output_draw_event(GtkWidget *widget, cairo_t *c, struct output_panel *op)
|
||||
{
|
||||
UNUSED(widget);
|
||||
cairo_init(c);
|
||||
|
||||
struct snapshot *snst = op->snst;
|
||||
struct processing_buffers *p = snst->pb;
|
||||
int old = snst->is_old;
|
||||
|
||||
double x = draw_watch_icon(c,snst->signal,snst->calibrate ? snst->signal==NSTEPS : snst->signal, snst->is_light);
|
||||
|
||||
cairo_text_extents_t extents;
|
||||
|
||||
cairo_set_font_size(c, OUTPUT_FONT);
|
||||
cairo_text_extents(c,"0",&extents);
|
||||
double y = (double)OUTPUT_WINDOW_HEIGHT/2 - extents.y_bearing - extents.height/2;
|
||||
|
||||
if(snst->calibrate) {
|
||||
cairo_set_source(c, white);
|
||||
x = print_s(c,x,y,"cal");
|
||||
cairo_set_font_size(c, OUTPUT_FONT*2/3);
|
||||
x = print_s(c,x,y," (");
|
||||
cairo_move_to(c,x,y);
|
||||
{
|
||||
double a = 0;
|
||||
char *s[] = {"wait", "acq.", "done", "fail", NULL}, **t = s;
|
||||
for(;*t;t++) {
|
||||
cairo_text_extents(c,*t,&extents);
|
||||
if(a < extents.x_advance) a = extents.x_advance;
|
||||
}
|
||||
x += a;
|
||||
}
|
||||
switch(snst->cal_state) {
|
||||
case 1:
|
||||
cairo_set_source(c,green);
|
||||
cairo_show_text(c,"done");
|
||||
break;
|
||||
case 0:
|
||||
cairo_set_source(c, snst->signal == NSTEPS ? white : yellow);
|
||||
cairo_show_text(c, snst->signal == NSTEPS ? "acq." : "wait");
|
||||
break;
|
||||
case -1:
|
||||
cairo_set_source(c,red);
|
||||
cairo_show_text(c,"fail");
|
||||
break;
|
||||
}
|
||||
cairo_set_source(c, white);
|
||||
x = print_s(c,x,y,")");
|
||||
cairo_set_font_size(c, OUTPUT_FONT);
|
||||
char s[20];
|
||||
switch(snst->cal_state) {
|
||||
case 1:
|
||||
sprintf(s, " %s%d.%d",
|
||||
snst->cal_result < 0 ? "-" : "+",
|
||||
abs(snst->cal_result) / 10,
|
||||
abs(snst->cal_result) % 10 );
|
||||
x = print_s(c,x,y,s);
|
||||
cairo_set_font_size(c, OUTPUT_FONT*2/3);
|
||||
x = print_s(c,x,y," s/d");
|
||||
break;
|
||||
case 0:
|
||||
sprintf(s, " %d", snst->cal_percent);
|
||||
x = print_number(c,x,y,s);
|
||||
x = print_s(c,x,y," %");
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
char outputs[8][20];
|
||||
if(p) {
|
||||
int rate = round(snst->rate);
|
||||
double be = snst->be;
|
||||
char rates[20];
|
||||
sprintf(rates,"%s%d",rate > 0 ? "+" : rate < 0 ? "-" : "",abs(rate));
|
||||
sprintf(outputs[0],"%4s",rates);
|
||||
sprintf(outputs[2]," %4.1f",be);
|
||||
if(snst->amp > 0)
|
||||
sprintf(outputs[4]," %3.0f",snst->amp);
|
||||
else
|
||||
strcpy(outputs[4]," ---");
|
||||
} else {
|
||||
strcpy(outputs[0],"----");
|
||||
strcpy(outputs[2]," ----");
|
||||
strcpy(outputs[4]," ---");
|
||||
}
|
||||
sprintf(outputs[6]," %d",snst->guessed_bph);
|
||||
|
||||
strcpy(outputs[1]," s/d");
|
||||
strcpy(outputs[3]," ms");
|
||||
strcpy(outputs[5]," deg");
|
||||
strcpy(outputs[7]," bph");
|
||||
|
||||
int i;
|
||||
for(i=0; i<8; i++) {
|
||||
if(i%2) {
|
||||
cairo_set_source(c, white);
|
||||
cairo_set_font_size(c, OUTPUT_FONT*2/3);
|
||||
x = print_s(c,x,y,outputs[i]);
|
||||
} else {
|
||||
cairo_set_source(c, i > 4 || !p || !old ? white : yellow);
|
||||
cairo_set_font_size(c, OUTPUT_FONT);
|
||||
x = print_number(c,x,y,outputs[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG
|
||||
{
|
||||
static GTimer *timer = NULL;
|
||||
if (!timer) timer = g_timer_new();
|
||||
else {
|
||||
char s[100];
|
||||
sprintf(s," %.2f fps",1./g_timer_elapsed(timer, NULL));
|
||||
cairo_set_source(c, white);
|
||||
cairo_set_font_size(c, OUTPUT_FONT);
|
||||
x = print_s(c,x,y,s);
|
||||
g_timer_reset(timer);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void expose_waveform(
|
||||
struct output_panel *op,
|
||||
GtkWidget *da,
|
||||
cairo_t *c,
|
||||
int (*get_offset)(struct processing_buffers*),
|
||||
double (*get_pulse)(struct processing_buffers*))
|
||||
{
|
||||
cairo_init(c);
|
||||
|
||||
GtkAllocation temp;
|
||||
gtk_widget_get_allocation(da, &temp);
|
||||
|
||||
int width = temp.width;
|
||||
int height = temp.height;
|
||||
|
||||
gtk_widget_get_allocation(gtk_widget_get_toplevel(da), &temp);
|
||||
int font = temp.width / 90;
|
||||
if(font < 12)
|
||||
font = 12;
|
||||
int i;
|
||||
|
||||
cairo_set_font_size(c,font);
|
||||
|
||||
for(i = 1-NEGATIVE_SPAN; i < POSITIVE_SPAN; i++) {
|
||||
int x = (NEGATIVE_SPAN + i) * width / (POSITIVE_SPAN + NEGATIVE_SPAN);
|
||||
cairo_move_to(c, x + .5, height / 2 + .5);
|
||||
cairo_line_to(c, x + .5, height - .5);
|
||||
if(i%5)
|
||||
cairo_set_source(c,green);
|
||||
else
|
||||
cairo_set_source(c,red);
|
||||
cairo_stroke(c);
|
||||
}
|
||||
cairo_set_source(c,white);
|
||||
for(i = 1-NEGATIVE_SPAN; i < POSITIVE_SPAN; i++) {
|
||||
if(!(i%5)) {
|
||||
int x = (NEGATIVE_SPAN + i) * width / (POSITIVE_SPAN + NEGATIVE_SPAN);
|
||||
char s[10];
|
||||
sprintf(s,"%d",i);
|
||||
cairo_move_to(c,x+font/4,height-font/2);
|
||||
cairo_show_text(c,s);
|
||||
}
|
||||
}
|
||||
|
||||
cairo_text_extents_t extents;
|
||||
|
||||
cairo_text_extents(c,"ms",&extents);
|
||||
cairo_move_to(c,width - extents.x_advance - font/4,height-font/2);
|
||||
cairo_show_text(c,"ms");
|
||||
|
||||
struct snapshot *snst = op->snst;
|
||||
struct processing_buffers *p = snst->pb;
|
||||
int old = snst->is_old;
|
||||
double period = p ? p->period / snst->sample_rate : 7200. / snst->guessed_bph;
|
||||
|
||||
for(i = 10; i < 360; i+=10) {
|
||||
if(2*i < snst->la) continue;
|
||||
double t = period*amplitude_to_time(snst->la,i);
|
||||
if(t > .001 * NEGATIVE_SPAN) continue;
|
||||
int x = round(width * (NEGATIVE_SPAN - 1000*t) / (NEGATIVE_SPAN + POSITIVE_SPAN));
|
||||
cairo_move_to(c, x+.5, .5);
|
||||
cairo_line_to(c, x+.5, height / 2 + .5);
|
||||
if(i % 50)
|
||||
cairo_set_source(c,green);
|
||||
else
|
||||
cairo_set_source(c,red);
|
||||
cairo_stroke(c);
|
||||
}
|
||||
|
||||
double last_x = 0;
|
||||
cairo_set_source(c,white);
|
||||
for(i = 50; i < 360; i+=50) {
|
||||
double t = period*amplitude_to_time(snst->la,i);
|
||||
if(t > .001 * NEGATIVE_SPAN) continue;
|
||||
int x = round(width * (NEGATIVE_SPAN - 1000*t) / (NEGATIVE_SPAN + POSITIVE_SPAN));
|
||||
if(x > last_x) {
|
||||
char s[10];
|
||||
|
||||
sprintf(s,"%d",abs(i));
|
||||
cairo_move_to(c, x + font/4, font * 3 / 2);
|
||||
cairo_show_text(c,s);
|
||||
cairo_text_extents(c,s,&extents);
|
||||
last_x = x + font/4 + extents.x_advance;
|
||||
}
|
||||
}
|
||||
|
||||
cairo_text_extents(c,"deg",&extents);
|
||||
cairo_move_to(c,width - extents.x_advance - font/4,font * 3 / 2);
|
||||
cairo_show_text(c,"deg");
|
||||
|
||||
if(p) {
|
||||
double span = 0.001 * snst->sample_rate;
|
||||
int offset = get_offset(p);
|
||||
|
||||
double a = offset - span * NEGATIVE_SPAN;
|
||||
double b = offset + span * POSITIVE_SPAN;
|
||||
|
||||
draw_graph(a,b,c,p,da);
|
||||
|
||||
cairo_set_source(c,old?yellow:white);
|
||||
cairo_stroke_preserve(c);
|
||||
cairo_fill(c);
|
||||
|
||||
double pulse = get_pulse(p);
|
||||
if(pulse > 0) {
|
||||
int x = round((NEGATIVE_SPAN - pulse / span) * width / (POSITIVE_SPAN + NEGATIVE_SPAN));
|
||||
cairo_move_to(c, x, 1);
|
||||
cairo_line_to(c, x, height - 1);
|
||||
cairo_set_source(c,blue);
|
||||
cairo_set_line_width(c,2);
|
||||
cairo_stroke(c);
|
||||
}
|
||||
} else {
|
||||
cairo_move_to(c, .5, height / 2 + .5);
|
||||
cairo_line_to(c, width - .5, height / 2 + .5);
|
||||
cairo_set_source(c,yellow);
|
||||
cairo_stroke(c);
|
||||
}
|
||||
}
|
||||
|
||||
static int get_tic(struct processing_buffers *p)
|
||||
{
|
||||
return p->tic;
|
||||
}
|
||||
|
||||
static int get_toc(struct processing_buffers *p)
|
||||
{
|
||||
return p->toc;
|
||||
}
|
||||
|
||||
static double get_tic_pulse(struct processing_buffers *p)
|
||||
{
|
||||
return p->tic_pulse;
|
||||
}
|
||||
|
||||
static double get_toc_pulse(struct processing_buffers *p)
|
||||
{
|
||||
return p->toc_pulse;
|
||||
}
|
||||
|
||||
static gboolean tic_draw_event(GtkWidget *widget, cairo_t *c, struct output_panel *op)
|
||||
{
|
||||
UNUSED(widget);
|
||||
expose_waveform(op, op->tic_drawing_area, c, get_tic, get_tic_pulse);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean toc_draw_event(GtkWidget *widget, cairo_t *c, struct output_panel *op)
|
||||
{
|
||||
UNUSED(widget);
|
||||
expose_waveform(op, op->toc_drawing_area, c, get_toc, get_toc_pulse);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean period_draw_event(GtkWidget *widget, cairo_t *c, struct output_panel *op)
|
||||
{
|
||||
UNUSED(widget);
|
||||
cairo_init(c);
|
||||
|
||||
GtkAllocation temp;
|
||||
gtk_widget_get_allocation (op->period_drawing_area, &temp);
|
||||
|
||||
int width = temp.width;
|
||||
int height = temp.height;
|
||||
|
||||
struct snapshot *snst = op->snst;
|
||||
struct processing_buffers *p = snst->pb;
|
||||
int old = snst->is_old;
|
||||
|
||||
double toc,a=0,b=0;
|
||||
|
||||
if(p) {
|
||||
toc = p->tic < p->toc ? p->toc : p->toc + p->period;
|
||||
a = ((double)p->tic + toc)/2 - p->period/2;
|
||||
b = ((double)p->tic + toc)/2 + p->period/2;
|
||||
|
||||
cairo_move_to(c, (p->tic - a - NEGATIVE_SPAN*.001*snst->sample_rate) * width/p->period, 0);
|
||||
cairo_line_to(c, (p->tic - a - NEGATIVE_SPAN*.001*snst->sample_rate) * width/p->period, height);
|
||||
cairo_line_to(c, (p->tic - a + POSITIVE_SPAN*.001*snst->sample_rate) * width/p->period, height);
|
||||
cairo_line_to(c, (p->tic - a + POSITIVE_SPAN*.001*snst->sample_rate) * width/p->period, 0);
|
||||
cairo_set_source(c,blueish);
|
||||
cairo_fill(c);
|
||||
|
||||
cairo_move_to(c, (toc - a - NEGATIVE_SPAN*.001*snst->sample_rate) * width/p->period, 0);
|
||||
cairo_line_to(c, (toc - a - NEGATIVE_SPAN*.001*snst->sample_rate) * width/p->period, height);
|
||||
cairo_line_to(c, (toc - a + POSITIVE_SPAN*.001*snst->sample_rate) * width/p->period, height);
|
||||
cairo_line_to(c, (toc - a + POSITIVE_SPAN*.001*snst->sample_rate) * width/p->period, 0);
|
||||
cairo_set_source(c,blueish);
|
||||
cairo_fill(c);
|
||||
}
|
||||
|
||||
int i;
|
||||
for(i = 1; i < 16; i++) {
|
||||
int x = i * width / 16;
|
||||
cairo_move_to(c, x+.5, .5);
|
||||
cairo_line_to(c, x+.5, height - .5);
|
||||
if(i % 4)
|
||||
cairo_set_source(c,green);
|
||||
else
|
||||
cairo_set_source(c,red);
|
||||
cairo_stroke(c);
|
||||
}
|
||||
|
||||
if(p) {
|
||||
draw_graph(a,b,c,p,op->period_drawing_area);
|
||||
|
||||
cairo_set_source(c,old?yellow:white);
|
||||
cairo_stroke_preserve(c);
|
||||
cairo_fill(c);
|
||||
} else {
|
||||
cairo_move_to(c, .5, height / 2 + .5);
|
||||
cairo_line_to(c, width - .5, height / 2 + .5);
|
||||
cairo_set_source(c,yellow);
|
||||
cairo_stroke(c);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean paperstrip_draw_event(GtkWidget *widget, cairo_t *c, struct output_panel *op)
|
||||
{
|
||||
int i;
|
||||
struct snapshot *snst = op->snst;
|
||||
uint64_t time = snst->timestamp ? snst->timestamp : get_timestamp(snst->is_light);
|
||||
double sweep;
|
||||
int zoom_factor;
|
||||
double slope = 1000; // detected rate: 1000 -> do not display
|
||||
if(snst->calibrate) {
|
||||
sweep = snst->nominal_sr;
|
||||
zoom_factor = PAPERSTRIP_ZOOM_CAL;
|
||||
slope = (double) snst->cal * zoom_factor / (10 * 3600 * 24);
|
||||
} else {
|
||||
sweep = snst->sample_rate * 3600. / snst->guessed_bph;
|
||||
zoom_factor = PAPERSTRIP_ZOOM;
|
||||
if(snst->events_count && snst->events[snst->events_wp])
|
||||
slope = - snst->rate * zoom_factor / (3600. * 24.);
|
||||
}
|
||||
|
||||
cairo_init(c);
|
||||
|
||||
GtkAllocation temp;
|
||||
gtk_widget_get_allocation (op->paperstrip_drawing_area, &temp);
|
||||
|
||||
int width = temp.width;
|
||||
int height = temp.height;
|
||||
|
||||
int stopped = 0;
|
||||
if( snst->events_count &&
|
||||
snst->events[snst->events_wp] &&
|
||||
time > 5 * snst->nominal_sr + snst->events[snst->events_wp]) {
|
||||
time = 5 * snst->nominal_sr + snst->events[snst->events_wp];
|
||||
stopped = 1;
|
||||
}
|
||||
|
||||
int strip_width = round(width / (1 + PAPERSTRIP_MARGIN));
|
||||
|
||||
cairo_set_line_width(c,1.3);
|
||||
|
||||
slope *= strip_width;
|
||||
if(slope <= 2 && slope >= -2) {
|
||||
for(i=0; i<4; i++) {
|
||||
double y = 0;
|
||||
cairo_move_to(c, (double)width * (i+.5) / 4, 0);
|
||||
for(;;) {
|
||||
double x = y * slope + (double)width * (i+.5) / 4;
|
||||
x = fmod(x, width);
|
||||
if(x < 0) x += width;
|
||||
double nx = x + slope * (height - y);
|
||||
if(nx >= 0 && nx <= width) {
|
||||
cairo_line_to(c, nx, height);
|
||||
break;
|
||||
} else {
|
||||
double d = slope > 0 ? width - x : x;
|
||||
y += d / fabs(slope);
|
||||
cairo_line_to(c, slope > 0 ? width : 0, y);
|
||||
y += 1;
|
||||
if(y > height) break;
|
||||
cairo_move_to(c, slope > 0 ? 0 : width, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
cairo_set_source(c, blue);
|
||||
cairo_stroke(c);
|
||||
}
|
||||
|
||||
cairo_set_line_width(c,1);
|
||||
|
||||
int left_margin = (width - strip_width) / 2;
|
||||
int right_margin = (width + strip_width) / 2;
|
||||
cairo_move_to(c, left_margin + .5, .5);
|
||||
cairo_line_to(c, left_margin + .5, height - .5);
|
||||
cairo_move_to(c, right_margin + .5, .5);
|
||||
cairo_line_to(c, right_margin + .5, height - .5);
|
||||
cairo_set_source(c, green);
|
||||
cairo_stroke(c);
|
||||
|
||||
double now = sweep*ceil(time/sweep);
|
||||
double ten_s = snst->sample_rate * 10 / sweep;
|
||||
double last_line = fmod(now/sweep, ten_s);
|
||||
int last_tenth = floor(now/(sweep*ten_s));
|
||||
for(i=0;;i++) {
|
||||
double y = 0.5 + round(last_line + i*ten_s);
|
||||
if(y > height) break;
|
||||
cairo_move_to(c, .5, y);
|
||||
cairo_line_to(c, width-.5, y);
|
||||
cairo_set_source(c, (last_tenth-i)%6 ? green : red);
|
||||
cairo_stroke(c);
|
||||
}
|
||||
|
||||
cairo_set_source(c,stopped?yellow:white);
|
||||
for(i = snst->events_wp;;) {
|
||||
if(!snst->events_count || !snst->events[i]) break;
|
||||
double event = now - snst->events[i] + snst->trace_centering + sweep * PAPERSTRIP_MARGIN / (2 * zoom_factor);
|
||||
int column = floor(fmod(event, (sweep / zoom_factor)) * strip_width / (sweep / zoom_factor));
|
||||
int row = floor(event / sweep);
|
||||
if(row >= height) break;
|
||||
cairo_move_to(c,column,row);
|
||||
cairo_line_to(c,column+1,row);
|
||||
cairo_line_to(c,column+1,row+1);
|
||||
cairo_line_to(c,column,row+1);
|
||||
cairo_line_to(c,column,row);
|
||||
cairo_fill(c);
|
||||
if(column < width - strip_width && row > 0) {
|
||||
column += strip_width;
|
||||
row -= 1;
|
||||
cairo_move_to(c,column,row);
|
||||
cairo_line_to(c,column+1,row);
|
||||
cairo_line_to(c,column+1,row+1);
|
||||
cairo_line_to(c,column,row+1);
|
||||
cairo_line_to(c,column,row);
|
||||
cairo_fill(c);
|
||||
}
|
||||
if(--i < 0) i = snst->events_count - 1;
|
||||
if(i == snst->events_wp) break;
|
||||
}
|
||||
|
||||
cairo_set_source(c,white);
|
||||
cairo_set_line_width(c,2);
|
||||
cairo_move_to(c, left_margin + 3, height - 20.5);
|
||||
cairo_line_to(c, right_margin - 3, height - 20.5);
|
||||
cairo_stroke(c);
|
||||
cairo_set_line_width(c,1);
|
||||
cairo_move_to(c, left_margin + .5, height - 20.5);
|
||||
cairo_line_to(c, left_margin + 5.5, height - 15.5);
|
||||
cairo_line_to(c, left_margin + 5.5, height - 25.5);
|
||||
cairo_line_to(c, left_margin + .5, height - 20.5);
|
||||
cairo_fill(c);
|
||||
cairo_move_to(c, right_margin + .5, height - 20.5);
|
||||
cairo_line_to(c, right_margin - 4.5, height - 15.5);
|
||||
cairo_line_to(c, right_margin - 4.5, height - 25.5);
|
||||
cairo_line_to(c, right_margin + .5, height - 20.5);
|
||||
cairo_fill(c);
|
||||
|
||||
char s[100];
|
||||
cairo_text_extents_t extents;
|
||||
|
||||
gtk_widget_get_allocation(gtk_widget_get_toplevel(widget), &temp);
|
||||
int font = temp.width / 90;
|
||||
if(font < 12)
|
||||
font = 12;
|
||||
cairo_set_font_size(c,font);
|
||||
|
||||
sprintf(s, "%.1f ms", snst->calibrate ?
|
||||
1000. / zoom_factor :
|
||||
3600000. / (snst->guessed_bph * zoom_factor));
|
||||
cairo_text_extents(c,s,&extents);
|
||||
cairo_move_to(c, (width - extents.x_advance)/2, height - 30);
|
||||
cairo_show_text(c,s);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
static gboolean debug_draw_event(GtkWidget *widget, cairo_t *c, struct output_panel *op)
|
||||
{
|
||||
UNUSED(widget);
|
||||
cairo_init(c);
|
||||
|
||||
struct snapshot *snst = op->snst;
|
||||
struct processing_buffers *p;
|
||||
if(snst->calibrate)
|
||||
p = &op->computer->pdata->buffers[0];
|
||||
else
|
||||
p = snst->pb;
|
||||
|
||||
if(p) {
|
||||
double a = snst->nominal_sr / 10;
|
||||
double b = snst->nominal_sr * 2;
|
||||
|
||||
draw_debug_graph(a,b,c,p,op->debug_drawing_area);
|
||||
|
||||
cairo_set_source(c,snst->is_old?yellow:white);
|
||||
cairo_stroke(c);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void handle_clear_trace(GtkButton *b, struct output_panel *op)
|
||||
{
|
||||
UNUSED(b);
|
||||
if(op->computer) {
|
||||
lock_computer(op->computer);
|
||||
if(!op->snst->calibrate) {
|
||||
memset(op->snst->events,0,op->snst->events_count*sizeof(uint64_t));
|
||||
op->computer->clear_trace = 1;
|
||||
}
|
||||
unlock_computer(op->computer);
|
||||
gtk_widget_queue_draw(op->paperstrip_drawing_area);
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_center_trace(GtkButton *b, struct output_panel *op)
|
||||
{
|
||||
UNUSED(b);
|
||||
struct snapshot *snst = op->snst;
|
||||
uint64_t last_ev = snst->events[snst->events_wp];
|
||||
double new_centering;
|
||||
if(last_ev) {
|
||||
double sweep;
|
||||
if(snst->calibrate)
|
||||
sweep = (double) snst->nominal_sr / PAPERSTRIP_ZOOM_CAL;
|
||||
else
|
||||
sweep = snst->sample_rate * 3600. / (PAPERSTRIP_ZOOM * snst->guessed_bph);
|
||||
new_centering = fmod(last_ev + .5*sweep , sweep);
|
||||
} else
|
||||
new_centering = 0;
|
||||
snst->trace_centering = new_centering;
|
||||
gtk_widget_queue_draw(op->paperstrip_drawing_area);
|
||||
}
|
||||
|
||||
static void shift_trace(struct output_panel *op, double direction)
|
||||
{
|
||||
struct snapshot *snst = op->snst;
|
||||
double sweep;
|
||||
if(snst->calibrate)
|
||||
sweep = (double) snst->nominal_sr / PAPERSTRIP_ZOOM_CAL;
|
||||
else
|
||||
sweep = snst->sample_rate * 3600. / (PAPERSTRIP_ZOOM * snst->guessed_bph);
|
||||
snst->trace_centering = fmod(snst->trace_centering + sweep * (1.+.1*direction), sweep);
|
||||
gtk_widget_queue_draw(op->paperstrip_drawing_area);
|
||||
}
|
||||
|
||||
static void handle_left(GtkButton *b, struct output_panel *op)
|
||||
{
|
||||
UNUSED(b);
|
||||
shift_trace(op,-1);
|
||||
}
|
||||
|
||||
static void handle_right(GtkButton *b, struct output_panel *op)
|
||||
{
|
||||
UNUSED(b);
|
||||
shift_trace(op,1);
|
||||
}
|
||||
|
||||
void op_set_snapshot(struct output_panel *op, struct snapshot *snst)
|
||||
{
|
||||
op->snst = snst;
|
||||
gtk_widget_set_sensitive(op->clear_button, !snst->calibrate);
|
||||
}
|
||||
|
||||
void op_set_border(struct output_panel *op, int i)
|
||||
{
|
||||
gtk_container_set_border_width(GTK_CONTAINER(op->panel), i);
|
||||
}
|
||||
|
||||
void op_destroy(struct output_panel *op)
|
||||
{
|
||||
snapshot_destroy(op->snst);
|
||||
free(op);
|
||||
}
|
||||
|
||||
struct output_panel *init_output_panel(struct computer *comp, struct snapshot *snst, int border)
|
||||
{
|
||||
struct output_panel *op = malloc(sizeof(struct output_panel));
|
||||
|
||||
op->computer = comp;
|
||||
op->snst = snst;
|
||||
|
||||
op->panel = gtk_box_new(GTK_ORIENTATION_VERTICAL, 10);
|
||||
gtk_container_set_border_width(GTK_CONTAINER(op->panel), border);
|
||||
|
||||
// Info area on top
|
||||
op->output_drawing_area = gtk_drawing_area_new();
|
||||
gtk_widget_set_size_request(op->output_drawing_area, 0, OUTPUT_WINDOW_HEIGHT);
|
||||
gtk_box_pack_start(GTK_BOX(op->panel),op->output_drawing_area, FALSE, TRUE, 0);
|
||||
g_signal_connect (op->output_drawing_area, "draw", G_CALLBACK(output_draw_event), op);
|
||||
gtk_widget_set_events(op->output_drawing_area, GDK_EXPOSURE_MASK);
|
||||
|
||||
GtkWidget *hbox2 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 10);
|
||||
gtk_box_pack_start(GTK_BOX(op->panel), hbox2, TRUE, TRUE, 0);
|
||||
|
||||
GtkWidget *vbox2 = gtk_box_new(GTK_ORIENTATION_VERTICAL, 10);
|
||||
gtk_box_pack_start(GTK_BOX(hbox2), vbox2, FALSE, TRUE, 0);
|
||||
|
||||
// Paperstrip
|
||||
op->paperstrip_drawing_area = gtk_drawing_area_new();
|
||||
gtk_widget_set_size_request(op->paperstrip_drawing_area, 300, 0);
|
||||
gtk_box_pack_start(GTK_BOX(vbox2), op->paperstrip_drawing_area, TRUE, TRUE, 0);
|
||||
g_signal_connect (op->paperstrip_drawing_area, "draw", G_CALLBACK(paperstrip_draw_event), op);
|
||||
gtk_widget_set_events(op->paperstrip_drawing_area, GDK_EXPOSURE_MASK);
|
||||
|
||||
GtkWidget *hbox3 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 10);
|
||||
gtk_box_pack_start(GTK_BOX(vbox2), hbox3, FALSE, TRUE, 0);
|
||||
|
||||
// < button
|
||||
GtkWidget *left_button = gtk_button_new_with_label("<");
|
||||
gtk_box_pack_start(GTK_BOX(hbox3), left_button, TRUE, TRUE, 0);
|
||||
g_signal_connect (left_button, "clicked", G_CALLBACK(handle_left), op);
|
||||
|
||||
// CLEAR button
|
||||
if(comp) {
|
||||
op->clear_button = gtk_button_new_with_label("Clear");
|
||||
gtk_box_pack_start(GTK_BOX(hbox3), op->clear_button, TRUE, TRUE, 0);
|
||||
g_signal_connect (op->clear_button, "clicked", G_CALLBACK(handle_clear_trace), op);
|
||||
gtk_widget_set_sensitive(op->clear_button, !snst->calibrate);
|
||||
}
|
||||
|
||||
// CENTER button
|
||||
GtkWidget *center_button = gtk_button_new_with_label("Center");
|
||||
gtk_box_pack_start(GTK_BOX(hbox3), center_button, TRUE, TRUE, 0);
|
||||
g_signal_connect (center_button, "clicked", G_CALLBACK(handle_center_trace), op);
|
||||
|
||||
// > button
|
||||
GtkWidget *right_button = gtk_button_new_with_label(">");
|
||||
gtk_box_pack_start(GTK_BOX(hbox3), right_button, TRUE, TRUE, 0);
|
||||
g_signal_connect (right_button, "clicked", G_CALLBACK(handle_right), op);
|
||||
|
||||
GtkWidget *vbox3 = gtk_box_new(GTK_ORIENTATION_VERTICAL,10);
|
||||
gtk_box_pack_start(GTK_BOX(hbox2), vbox3, TRUE, TRUE, 0);
|
||||
|
||||
// Tic waveform area
|
||||
op->tic_drawing_area = gtk_drawing_area_new();
|
||||
gtk_box_pack_start(GTK_BOX(vbox3), op->tic_drawing_area, TRUE, TRUE, 0);
|
||||
g_signal_connect (op->tic_drawing_area, "draw", G_CALLBACK(tic_draw_event), op);
|
||||
gtk_widget_set_events(op->tic_drawing_area, GDK_EXPOSURE_MASK);
|
||||
|
||||
// Toc waveform area
|
||||
op->toc_drawing_area = gtk_drawing_area_new();
|
||||
gtk_box_pack_start(GTK_BOX(vbox3), op->toc_drawing_area, TRUE, TRUE, 0);
|
||||
g_signal_connect (op->toc_drawing_area, "draw", G_CALLBACK(toc_draw_event), op);
|
||||
gtk_widget_set_events(op->toc_drawing_area, GDK_EXPOSURE_MASK);
|
||||
|
||||
// Period waveform area
|
||||
op->period_drawing_area = gtk_drawing_area_new();
|
||||
gtk_box_pack_start(GTK_BOX(vbox3), op->period_drawing_area, TRUE, TRUE, 0);
|
||||
g_signal_connect (op->period_drawing_area, "draw", G_CALLBACK(period_draw_event), op);
|
||||
gtk_widget_set_events(op->period_drawing_area, GDK_EXPOSURE_MASK);
|
||||
|
||||
#ifdef DEBUG
|
||||
op->debug_drawing_area = gtk_drawing_area_new();
|
||||
gtk_box_pack_start(GTK_BOX(vbox3), op->debug_drawing_area, TRUE, TRUE, 0);
|
||||
g_signal_connect (op->debug_drawing_area, "draw", G_CALLBACK(debug_draw_event), op);
|
||||
gtk_widget_set_events(op->debug_drawing_area, GDK_EXPOSURE_MASK);
|
||||
#endif
|
||||
|
||||
return op;
|
||||
}
|
||||
568
src/serializer.c
Normal file
|
|
@ -0,0 +1,568 @@
|
|||
/*
|
||||
tg
|
||||
Copyright (C) 2015 Marcello Mamino
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License version 2 as
|
||||
published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "tg.h"
|
||||
#include <inttypes.h>
|
||||
|
||||
#define LABEL_SIZE 64
|
||||
|
||||
#define XSTR(X) STR(X)
|
||||
#define STR(X) #X
|
||||
#define LABEL_SIZE_STR XSTR(LABEL_SIZE)
|
||||
|
||||
#ifdef _WIN32
|
||||
// My own implementation of %a
|
||||
// because I'm sick of bugs in __mingw_fprintf()
|
||||
|
||||
static char hex_digit(uint64_t n)
|
||||
{
|
||||
if(n < 10) return (char)n+'0';
|
||||
else return (char)n-10+'a';
|
||||
}
|
||||
|
||||
static int write_hex_double(FILE *f, double d)
|
||||
{
|
||||
uint64_t bd = *(uint64_t *)&d;
|
||||
uint64_t mantissa = bd << 12;
|
||||
uint64_t exponent = (bd >> 52) & 0x7ff;
|
||||
uint64_t sign = bd >> 63;
|
||||
|
||||
// nan or inf = error
|
||||
if(exponent == 0x7ff) return 1;
|
||||
|
||||
if(sign && fprintf(f, "-") < 0) return 1;
|
||||
|
||||
if(exponent == 0) {
|
||||
if(mantissa) {
|
||||
exponent = 1;
|
||||
if(fprintf(f, "0x0") < 0) return 1;
|
||||
} else {
|
||||
return 0 > fprintf(f, "0x0p+0");
|
||||
}
|
||||
} else {
|
||||
if(fprintf(f, "0x1") < 0) return 1;
|
||||
}
|
||||
|
||||
if(mantissa && fprintf(f, ".") < 0) return 1;
|
||||
for(; mantissa; mantissa <<= 4)
|
||||
if(fprintf(f, "%c", hex_digit( mantissa >> 60 )) < 0) return 1;
|
||||
|
||||
int exp = (int)exponent - 1023;
|
||||
if(fprintf(f, "p%c", exp < 0 ? '-' : '+') < 0) return 1;
|
||||
return 0 > fprintf(f,"%d",abs(exp));
|
||||
}
|
||||
|
||||
static int parse_hex_digit(char c)
|
||||
{
|
||||
if('0' <= c && c <= '9') return c - '0';
|
||||
if('a' <= c && c <= 'f') return 10 + c - 'a';
|
||||
if('A' <= c && c <= 'F') return 10 + c - 'A';
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int parse_hex_double(FILE *f, double *d)
|
||||
{
|
||||
char s[64], *t = s;
|
||||
if(1 != fscanf(f, "%63[0-9a-fA-F.xXpP+-]", s)) return 1;
|
||||
double place = 1;
|
||||
if(*t == '+') t++;
|
||||
else if(*t == '-') {
|
||||
place = -1;
|
||||
t++;
|
||||
}
|
||||
if(*t != '0') return 1;
|
||||
if(*++t != 'x' && *t != 'X') return 1;
|
||||
int n = parse_hex_digit(*++t);
|
||||
if(n < 0) return 1;
|
||||
*d = place * n;
|
||||
if(!*++t) return 0;
|
||||
if(*t != '.') goto exponent;
|
||||
while(*++t && *t != 'p' && *t != 'P') {
|
||||
place /= 16;
|
||||
n = parse_hex_digit(*t);
|
||||
if(n < 0) return 1;
|
||||
*d += place * n;
|
||||
}
|
||||
exponent:
|
||||
if(*t) {
|
||||
long int radix = strtol(t+1, &t, 10);
|
||||
if(*t) return 1;
|
||||
*d *= pow(2, radix);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int serialize_uint64_t(FILE *f, uint64_t x)
|
||||
{
|
||||
return 0 > fprintf(f, "I%"PRIu64";\n", x);
|
||||
}
|
||||
|
||||
static int scan_uint64_t(FILE *f, uint64_t *x)
|
||||
{
|
||||
int n = 0;
|
||||
return 1 != fscanf(f, " I%"SCNu64";%n", x, &n) || !n;
|
||||
}
|
||||
|
||||
static int serialize_int64_t(FILE *f, int64_t x)
|
||||
{
|
||||
return 0 > fprintf(f, "I%"PRId64";\n", x);
|
||||
}
|
||||
|
||||
static int scan_int64_t(FILE *f, int64_t *x)
|
||||
{
|
||||
int n = 0;
|
||||
return 1 != fscanf(f, " I%"SCNd64";%n", x, &n) || !n;
|
||||
}
|
||||
|
||||
static int serialize_int(FILE *f, int x)
|
||||
{
|
||||
return serialize_int64_t(f, x);
|
||||
}
|
||||
|
||||
static int scan_int(FILE *f, int *x)
|
||||
{
|
||||
int64_t y;
|
||||
if(scan_int64_t(f, &y) || y < INT_MIN || y > INT_MAX) return 1;
|
||||
*x = y;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int serialize_double(FILE *f, double x)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if(fprintf(f, "I") < 0) return 1;
|
||||
if(write_hex_double(f, x)) return 1;
|
||||
return 0 > fprintf(f, ";\n");
|
||||
#else
|
||||
return 0 > fprintf(f, "I%a;\n", x);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int scan_double(FILE *f, double *x)
|
||||
{
|
||||
int n = 0;
|
||||
#ifdef _WIN32
|
||||
if( 0 != fscanf(f, " I%n", &n) || !n ) return 1;
|
||||
if( parse_hex_double(f,x) ) return 1;
|
||||
n = 0;
|
||||
if( 0 != fscanf(f, ";%n", &n) || !n ) return 1;
|
||||
return 0;
|
||||
#else
|
||||
return 1 != fscanf(f, " I%la;%n", x, &n) || !n;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int serialize_float(FILE *f, float x)
|
||||
{
|
||||
return serialize_double(f, x);
|
||||
}
|
||||
|
||||
static int scan_float(FILE *f, float *x)
|
||||
{
|
||||
double y;
|
||||
if(scan_double(f, &y)) return 1;
|
||||
*x = y;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int serialize_string(FILE *f, char *s)
|
||||
{
|
||||
if(0 > fprintf(f, "S%"PRIu64";", (uint64_t)strlen(s))) return 1;
|
||||
return 0 > fprintf(f, "%s;\n", s);
|
||||
}
|
||||
|
||||
static int scan_string(FILE *f, char **s, uint64_t max_l, uint64_t *len)
|
||||
{
|
||||
uint64_t l;
|
||||
int n = 0;
|
||||
if(1 != fscanf(f, " S%"SCNu64";%n", &l, &n) || !n) return 1;
|
||||
if(max_l && l >= max_l) return 1;
|
||||
if(!*s) *s = malloc(l+1);
|
||||
if(l+1 != fread(*s, 1, l+1, f)) return 1;
|
||||
if((*s)[l] != ';') return 1;
|
||||
(*s)[l] = 0;
|
||||
if(len) *len = l;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int serialize_uint64_t_array(FILE *f, uint64_t *a, uint64_t len)
|
||||
{
|
||||
uint64_t i;
|
||||
if(0 > fprintf(f, "A%"PRIu64";\n", len)) return 1;
|
||||
for(i = 0; i < len; i++)
|
||||
if(serialize_uint64_t(f, a[i])) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int scan_uint64_t_array(FILE *f, uint64_t **a, uint64_t max_l, uint64_t *len)
|
||||
{
|
||||
uint64_t l,i;
|
||||
int n = 0;
|
||||
if(1 != fscanf(f, " A%"SCNu64";%n", &l, &n) || !n) return 1;
|
||||
if(max_l && l > max_l) return 1;
|
||||
if(!*a) *a = malloc(l*sizeof(uint64_t));
|
||||
for(i = 0; i < l; i++)
|
||||
if(scan_uint64_t(f, *a+i)) return 1;
|
||||
if(len) *len = l;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int serialize_float_array(FILE *f, float *a, uint64_t len)
|
||||
{
|
||||
uint64_t i;
|
||||
if(0 > fprintf(f, "A%"PRIu64";\n", len)) return 1;
|
||||
for(i = 0; i < len; i++)
|
||||
if(serialize_float(f, a[i])) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int scan_float_array(FILE *f, float **a, uint64_t max_l, uint64_t *len)
|
||||
{
|
||||
uint64_t l,i;
|
||||
int n = 0;
|
||||
if(1 != fscanf(f, " A%"SCNu64";%n", &l, &n) || !n) return 1;
|
||||
if(max_l && l > max_l) return 1;
|
||||
if(!*a) *a = malloc(l*sizeof(float));
|
||||
for(i = 0; i < l; i++)
|
||||
if(scan_float(f, *a+i)) return 1;
|
||||
if(len) *len = l;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int make_label(FILE *f, char *l)
|
||||
{
|
||||
return 0 > fprintf(f, "L%s;\n", l);
|
||||
}
|
||||
|
||||
static int scan_label(FILE *f, char *l)
|
||||
{
|
||||
int n = 0;
|
||||
return 1 != fscanf(f, " L%" LABEL_SIZE_STR "[^;];%n", l, &n) || !n;
|
||||
}
|
||||
|
||||
static int eat_object(FILE *f)
|
||||
{
|
||||
char c;
|
||||
if(1 != fscanf(f, " %c", &c)) return 1;
|
||||
uint64_t l;
|
||||
int n = 0;
|
||||
switch(c) {
|
||||
case 'I':
|
||||
return 0 != fscanf(f, "%*[^;];%n", &n) || !n;
|
||||
case 'S':
|
||||
if(1 != fscanf(f, "%"SCNu64";%n", &l, &n) || !n) return 1;
|
||||
if(fseek(f, l, SEEK_CUR)) return 1;
|
||||
return 1 != fscanf(f, "%c", &c) || c != ';';
|
||||
case 'A':
|
||||
if(1 != fscanf(f, "%"SCNu64";%n", &l, &n) || !n) return 1;
|
||||
for(;l;l--) if(eat_object(f)) return 1;
|
||||
return 0;
|
||||
case 'T':
|
||||
if(1 != fscanf(f, "%c", &c)) return 1;
|
||||
if(c != ';') return 1;
|
||||
for(;;) {
|
||||
char b[LABEL_SIZE+1];
|
||||
if(scan_label(f, b)) return 1;
|
||||
if(!strcmp("__end__", b)) return 0;
|
||||
if(eat_object(f)) return 1;
|
||||
}
|
||||
case 'U':
|
||||
if(1 != fscanf(f, "%c", &c)) return 1;
|
||||
if(c != ';') return 1;
|
||||
char b[LABEL_SIZE+1];
|
||||
if(scan_label(f, b)) return 1;
|
||||
if(eat_object(f)) return 1;
|
||||
return 0;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
static int serialize_struct_begin(FILE *f)
|
||||
{
|
||||
return 0 > fprintf(f, "T;\n");
|
||||
}
|
||||
|
||||
static int serialize_struct_end(FILE *f)
|
||||
{
|
||||
return make_label(f, "__end__");
|
||||
}
|
||||
|
||||
static int serialize_union_begin(FILE *f, char *s)
|
||||
{
|
||||
if(fprintf(f, "U;\n") < 0) return 1;
|
||||
return make_label(f, s);
|
||||
}
|
||||
|
||||
#define SERIALIZE(T,A) { \
|
||||
if(make_label(f, #A)) return 1; \
|
||||
if(serialize_ ## T (f, s -> A)) return 1; \
|
||||
}
|
||||
|
||||
static int serialize_snapshot(FILE *f, struct snapshot *s, char *name)
|
||||
{
|
||||
if(serialize_union_begin(f, "realtime-snapshot")) return 1;
|
||||
if(serialize_struct_begin(f)) return 1;
|
||||
if(name) {
|
||||
if(make_label(f, "name")) return 1;
|
||||
if(serialize_string(f, name)) return 1;
|
||||
}
|
||||
if(make_label(f, "pb->waveform")) return 1;
|
||||
if(serialize_float_array(f, s->pb->waveform, s->pb->sample_count)) return 1;
|
||||
if(make_label(f, "events")) return 1;
|
||||
if(serialize_uint64_t_array(f, s->events, s->events_count)) return 1;
|
||||
SERIALIZE(int,pb->sample_rate);
|
||||
SERIALIZE(double,pb->period);
|
||||
SERIALIZE(double,pb->waveform_max);
|
||||
SERIALIZE(int,pb->tic);
|
||||
SERIALIZE(int,pb->toc);
|
||||
SERIALIZE(double,pb->tic_pulse);
|
||||
SERIALIZE(double,pb->toc_pulse);
|
||||
SERIALIZE(int,is_old);
|
||||
SERIALIZE(uint64_t,timestamp);
|
||||
SERIALIZE(int,nominal_sr);
|
||||
SERIALIZE(int,bph);
|
||||
SERIALIZE(double,la);
|
||||
SERIALIZE(int,cal);
|
||||
SERIALIZE(int,events_wp);
|
||||
SERIALIZE(int,signal);
|
||||
SERIALIZE(double,sample_rate);
|
||||
SERIALIZE(int,guessed_bph);
|
||||
SERIALIZE(double,rate);
|
||||
SERIALIZE(double,be);
|
||||
SERIALIZE(double,amp);
|
||||
SERIALIZE(double,trace_centering);
|
||||
SERIALIZE(int,is_light);
|
||||
return serialize_struct_end(f);
|
||||
}
|
||||
|
||||
#define SCAN(T,A) { \
|
||||
if(!strcmp( #A , l )) { \
|
||||
debug("serializer: scanning " #A "\n"); \
|
||||
if(scan_ ## T (f, &((*s) -> A))) goto error; \
|
||||
continue; \
|
||||
}}
|
||||
|
||||
static int scan_snapshot(FILE *f, struct snapshot **s, char **name)
|
||||
{
|
||||
char l[LABEL_SIZE+1];
|
||||
int n = 0;
|
||||
*s = NULL;
|
||||
*name = NULL;
|
||||
if(0 != fscanf(f, " U;%n", &n) || !n) return 1;
|
||||
if(scan_label(f,l)) return 1;
|
||||
if(strcmp("realtime-snapshot", l))
|
||||
return eat_object(f);
|
||||
|
||||
*s = malloc(sizeof(struct snapshot));
|
||||
memset(*s, 0, sizeof(struct snapshot));
|
||||
(*s)->pb = malloc(sizeof(struct processing_buffers));
|
||||
memset((*s)->pb, 0, sizeof(struct processing_buffers));
|
||||
*name = NULL;
|
||||
|
||||
n = 0;
|
||||
if(0 != fscanf(f, " T;%n", &n) || !n) goto error;
|
||||
for(;;) {
|
||||
if(scan_label(f,l)) goto error;
|
||||
if(!strcmp("__end__", l)) break;
|
||||
|
||||
if(!strcmp("name", l)) {
|
||||
debug("serializer: scanning name\n");
|
||||
if(scan_string(f, name, 0, NULL)) goto error;
|
||||
continue;
|
||||
}
|
||||
if(!strcmp("pb->waveform", l)) {
|
||||
debug("serializer: scanning pb->waveform\n");
|
||||
uint64_t x;
|
||||
if( (*s)->pb->waveform ||
|
||||
scan_float_array(f, &((*s)->pb->waveform), INT_MAX, &x)) goto error;
|
||||
(*s)->pb->sample_count = x;
|
||||
continue;
|
||||
}
|
||||
if(!strcmp("events", l)) {
|
||||
debug("serializer: scanning events\n");
|
||||
uint64_t x;
|
||||
if( (*s)->events ||
|
||||
scan_uint64_t_array(f, &((*s)->events), INT_MAX, &x)) goto error;
|
||||
(*s)->events_count = x;
|
||||
continue;
|
||||
}
|
||||
SCAN(int,pb->sample_rate);
|
||||
SCAN(double,pb->period);
|
||||
SCAN(double,pb->waveform_max);
|
||||
SCAN(int,pb->tic);
|
||||
SCAN(int,pb->toc);
|
||||
SCAN(double,pb->tic_pulse);
|
||||
SCAN(double,pb->toc_pulse);
|
||||
SCAN(int,is_old);
|
||||
SCAN(uint64_t,timestamp);
|
||||
SCAN(int,nominal_sr);
|
||||
SCAN(int,bph);
|
||||
SCAN(double,la);
|
||||
SCAN(int,cal);
|
||||
SCAN(int,events_wp);
|
||||
SCAN(int,signal);
|
||||
SCAN(double,sample_rate);
|
||||
SCAN(int,guessed_bph);
|
||||
SCAN(double,rate);
|
||||
SCAN(double,be);
|
||||
SCAN(double,amp);
|
||||
SCAN(double,trace_centering);
|
||||
SCAN(int,is_light);
|
||||
|
||||
if(eat_object(f)) goto error;
|
||||
}
|
||||
debug("serializer: checking period\n");
|
||||
if((*s)->pb->period <= 0 || (*s)->pb->sample_count < ceil((*s)->pb->period)) goto error;
|
||||
debug("serializer: checking timestamp\n");
|
||||
if(!(*s)->timestamp) goto error;
|
||||
debug("serializer: checking nominal_sr\n");
|
||||
if(!(*s)->nominal_sr) goto error;
|
||||
debug("serializer: checking bph\n");
|
||||
if((*s)->bph && ( (*s)->bph < MIN_BPH || (*s)->bph > MAX_BPH )) goto error;
|
||||
debug("serializer: checking la\n");
|
||||
if((*s)->la < MIN_LA || (*s)->la > MAX_LA ) goto error;
|
||||
debug("serializer: checking cal\n");
|
||||
if((*s)->cal < MIN_CAL || (*s)->cal > MAX_CAL) goto error;
|
||||
debug("serializer: checking events\n");
|
||||
if((*s)->events_count && (*s)->events_wp >= (*s)->events_count) goto error;
|
||||
if((*s)->signal > NSTEPS) (*s)->signal = NSTEPS;
|
||||
debug("serializer: checking sample_rate\n");
|
||||
if((*s)->sample_rate <= 0) goto error;
|
||||
debug("serializer: checking guessed_bph\n");
|
||||
if((*s)->guessed_bph < MIN_BPH || (*s)->guessed_bph > MAX_BPH) goto error;
|
||||
debug("serializer: checking rate\n");
|
||||
if((*s)->rate < -9999 || (*s)->rate > 9999) goto error;
|
||||
debug("serializer: checking beat error\n");
|
||||
if((*s)->be < 0 || (*s)->be > 99.9) goto error;
|
||||
debug("serializer: checking amplitude\n");
|
||||
if((*s)->amp < 0 || (*s)->amp > 360) goto error;
|
||||
(*s)->pb->events = NULL;
|
||||
#ifdef DEBUG
|
||||
(*s)->pb->debug = NULL;
|
||||
#endif
|
||||
return 0;
|
||||
|
||||
error:
|
||||
free(*name);
|
||||
free((*s)->pb->waveform);
|
||||
free((*s)->pb);
|
||||
free((*s)->events);
|
||||
free(*s);
|
||||
*s = NULL;
|
||||
*name = NULL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int scan_snapshot_list(FILE *f, struct snapshot ***s, char ***names, uint64_t *cnt)
|
||||
{
|
||||
debug("serializer: scanning snapshot list\n");
|
||||
uint64_t i;
|
||||
int n = 0;
|
||||
*s = NULL;
|
||||
*names = NULL;
|
||||
*cnt = 0;
|
||||
if(1 != fscanf(f, " A%"SCNu64";%n", &i, &n) || !n) goto error;
|
||||
*s = malloc(i*sizeof(struct snapshot *));
|
||||
*names = malloc(i*sizeof(char *));
|
||||
uint64_t j;
|
||||
for(j = 0; j < i; j++) {
|
||||
if(scan_snapshot(f, *s+*cnt, *names+*cnt)) goto error;
|
||||
*cnt += !!(*s)[*cnt];
|
||||
}
|
||||
*s = realloc(*s, *cnt*sizeof(struct snapshot *));
|
||||
*names = realloc(*names, *cnt*sizeof(char *));
|
||||
return 0;
|
||||
error:
|
||||
debug("serializer: error in snapshot list\n");
|
||||
for(; (*cnt)--;) {
|
||||
snapshot_destroy((*s)[*cnt]);
|
||||
free((*names)[*cnt]);
|
||||
}
|
||||
free(*s);
|
||||
free(*names);
|
||||
*s = NULL;
|
||||
*names = NULL;
|
||||
*cnt = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int write_file(FILE *f, struct snapshot **s, char **names, uint64_t cnt)
|
||||
{
|
||||
uint64_t i;
|
||||
if(make_label(f, "tg-timer-version")) return 1;
|
||||
if(serialize_string(f, VERSION)) return 1;
|
||||
if(make_label(f, "data")) return 1;
|
||||
if(serialize_struct_begin(f)) return 1;
|
||||
if(make_label(f, "snapshot-list")) return 1;
|
||||
if(0 > fprintf(f, "A%"PRIu64";\n", cnt)) return 1;
|
||||
for(i = 0; i < cnt; i++)
|
||||
if(serialize_snapshot(f, s[i], names[i])) return 1;
|
||||
if(serialize_struct_end(f)) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int read_file(FILE *f, struct snapshot ***s, char ***names, uint64_t *cnt)
|
||||
{
|
||||
debug("serializer: reading file\n");
|
||||
char lbl[LABEL_SIZE+1];
|
||||
char *l = lbl;
|
||||
if(scan_label(f, l) || strcmp("tg-timer-version",l)) return 1;
|
||||
if(scan_string(f, &l, LABEL_SIZE, NULL)) return 1;
|
||||
debug("serializer: read version %s\n",l);
|
||||
if(scan_label(f, l) || strcmp("data",l)) return 1;
|
||||
debug("serializer: found data structure\n",l);
|
||||
int n = 0;
|
||||
if(0 != fscanf(f, " T;%n", &n) || !n) return 1;
|
||||
*s = NULL;
|
||||
*names = NULL;
|
||||
for(;;) {
|
||||
if(scan_label(f,l)) goto error;
|
||||
if(!strcmp("__end__",l)) break;
|
||||
if(!strcmp("snapshot-list",l)) {
|
||||
if(*s || scan_snapshot_list(f, s, names, cnt)) goto error;
|
||||
else continue;
|
||||
}
|
||||
if(eat_object(f)) goto error;
|
||||
}
|
||||
debug("serializer: end of data structure\n",l);
|
||||
char c;
|
||||
if(*s && 1 != fscanf(f, " %c", &c)) return 0;
|
||||
#ifdef DEBUG
|
||||
if(*s) {
|
||||
debug("serializer: stray char %c (%d) after end\n", c, c);
|
||||
} else {
|
||||
debug("serializer: no snapshots\n");
|
||||
}
|
||||
#endif
|
||||
error:
|
||||
debug("serializer: read error\n");
|
||||
if(*s) {
|
||||
uint64_t i;
|
||||
for(i = 0; i < *cnt; i++) {
|
||||
snapshot_destroy((*s)[i]);
|
||||
free((*names)[i]);
|
||||
}
|
||||
free(*s);
|
||||
free(*names);
|
||||
*s = NULL;
|
||||
*names = NULL;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
165
src/tg.h
|
|
@ -27,17 +27,18 @@
|
|||
#include <gtk/gtk.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
#define _WIN32
|
||||
#endif
|
||||
|
||||
#define CONFIG_FILE_NAME "tg-timer.ini"
|
||||
|
||||
#define FILTER_CUTOFF 3000
|
||||
|
||||
#define CAL_DATA_SIZE 900
|
||||
|
||||
#ifdef LIGHT
|
||||
#define FIRST_STEP 0
|
||||
#else
|
||||
#define FIRST_STEP 1
|
||||
#endif
|
||||
#define FIRST_STEP_LIGHT 0
|
||||
|
||||
#define NSTEPS 4
|
||||
#define PA_SAMPLE_RATE 44100
|
||||
|
|
@ -69,9 +70,11 @@
|
|||
#ifdef DEBUG
|
||||
#define debug(...) print_debug(__VA_ARGS__)
|
||||
#else
|
||||
#define debug(...)
|
||||
#define debug(...) {}
|
||||
#endif
|
||||
|
||||
#define UNUSED(X) (void)(X)
|
||||
|
||||
/* algo.c */
|
||||
struct processing_buffers {
|
||||
int sample_rate;
|
||||
|
|
@ -88,6 +91,7 @@ struct processing_buffers {
|
|||
uint64_t timestamp, last_tic, last_toc, events_from;
|
||||
uint64_t *events;
|
||||
#ifdef DEBUG
|
||||
int debug_size;
|
||||
float *debug;
|
||||
#endif
|
||||
};
|
||||
|
|
@ -104,10 +108,12 @@ struct calibration_data {
|
|||
};
|
||||
|
||||
void setup_buffers(struct processing_buffers *b);
|
||||
void pb_destroy(struct processing_buffers *b);
|
||||
struct processing_buffers *pb_clone(struct processing_buffers *p);
|
||||
void pb_destroy_clone(struct processing_buffers *p);
|
||||
void process(struct processing_buffers *p, int bph, double la);
|
||||
void process(struct processing_buffers *p, int bph, double la, int light);
|
||||
void setup_cal_data(struct calibration_data *cd);
|
||||
void cal_data_destroy(struct calibration_data *cd);
|
||||
int test_cal(struct processing_buffers *p);
|
||||
int process_cal(struct processing_buffers *p, struct calibration_data *cd);
|
||||
|
||||
|
|
@ -115,62 +121,143 @@ int process_cal(struct processing_buffers *p, struct calibration_data *cd);
|
|||
struct processing_data {
|
||||
struct processing_buffers *buffers;
|
||||
uint64_t last_tic;
|
||||
int is_light;
|
||||
};
|
||||
|
||||
int start_portaudio(int *nominal_sample_rate, double *real_sample_rate);
|
||||
int terminate_portaudio();
|
||||
uint64_t get_timestamp();
|
||||
uint64_t get_timestamp(int light);
|
||||
int analyze_pa_data(struct processing_data *pd, int bph, double la, uint64_t events_from);
|
||||
int analyze_pa_data_cal(struct processing_data *pd, struct calibration_data *cd);
|
||||
|
||||
/* interface.c */
|
||||
struct main_window {
|
||||
GtkWidget *window;
|
||||
/* computer.c */
|
||||
struct snapshot {
|
||||
struct processing_buffers *pb;
|
||||
int is_old;
|
||||
uint64_t timestamp;
|
||||
int is_light;
|
||||
|
||||
int nominal_sr;
|
||||
int calibrate;
|
||||
int bph;
|
||||
double la; // deg
|
||||
int cal; // 0.1 s/d
|
||||
|
||||
int events_count;
|
||||
uint64_t *events; // used in cal+timegrapher mode
|
||||
int events_wp; // used in cal+timegrapher mode
|
||||
uint64_t events_from; // used only in timegrapher mode
|
||||
|
||||
int signal;
|
||||
|
||||
int cal_state;
|
||||
int cal_percent;
|
||||
int cal_result; // 0.1 s/d
|
||||
|
||||
// data dependent on bph, la, cal
|
||||
double sample_rate;
|
||||
int guessed_bph;
|
||||
double rate;
|
||||
double be;
|
||||
double amp;
|
||||
|
||||
double trace_centering;
|
||||
};
|
||||
|
||||
struct computer {
|
||||
pthread_t thread;
|
||||
pthread_mutex_t mutex;
|
||||
pthread_cond_t cond;
|
||||
|
||||
// controlled by interface
|
||||
int recompute;
|
||||
int calibrate;
|
||||
int bph;
|
||||
double la; // deg
|
||||
int clear_trace;
|
||||
void (*callback)(void *);
|
||||
void *callback_data;
|
||||
|
||||
struct processing_data *pdata;
|
||||
struct calibration_data *cdata;
|
||||
|
||||
struct snapshot *actv;
|
||||
struct snapshot *curr;
|
||||
};
|
||||
|
||||
struct snapshot *snapshot_clone(struct snapshot *s);
|
||||
void snapshot_destroy(struct snapshot *s);
|
||||
void computer_destroy(struct computer *c);
|
||||
struct computer *start_computer(int nominal_sr, int bph, double la, int cal, int light);
|
||||
void lock_computer(struct computer *c);
|
||||
void unlock_computer(struct computer *c);
|
||||
void compute_results(struct snapshot *s);
|
||||
|
||||
/* output_panel.c */
|
||||
struct output_panel {
|
||||
GtkWidget *panel;
|
||||
|
||||
GtkWidget *output_drawing_area;
|
||||
GtkWidget *tic_drawing_area;
|
||||
GtkWidget *toc_drawing_area;
|
||||
GtkWidget *period_drawing_area;
|
||||
GtkWidget *paperstrip_drawing_area;
|
||||
GtkWidget *cal_spin_button;
|
||||
GtkWidget *clear_button;
|
||||
#ifdef DEBUG
|
||||
GtkWidget *debug_drawing_area;
|
||||
#endif
|
||||
struct computer *computer;
|
||||
struct snapshot *snst;
|
||||
};
|
||||
|
||||
pthread_t computing_thread;
|
||||
pthread_mutex_t recompute_mutex;
|
||||
pthread_cond_t recompute_cond;
|
||||
int recompute;
|
||||
guint computer_kicker;
|
||||
void initialize_palette();
|
||||
struct output_panel *init_output_panel(struct computer *comp, struct snapshot *snst, int border);
|
||||
void redraw_op(struct output_panel *op);
|
||||
void op_set_snapshot(struct output_panel *op, struct snapshot *snst);
|
||||
void op_set_border(struct output_panel *op, int i);
|
||||
void op_destroy(struct output_panel *op);
|
||||
|
||||
/* interface.c */
|
||||
struct main_window {
|
||||
GtkApplication *app;
|
||||
|
||||
GtkWidget *window;
|
||||
GtkWidget *bph_combo_box;
|
||||
GtkWidget *la_spin_button;
|
||||
GtkWidget *cal_spin_button;
|
||||
GtkWidget *snapshot_button;
|
||||
GtkWidget *snapshot_name;
|
||||
GtkWidget *snapshot_name_entry;
|
||||
GtkWidget *cal_button;
|
||||
GtkWidget *notebook;
|
||||
GtkWidget *save_item;
|
||||
GtkWidget *save_all_item;
|
||||
GtkWidget *close_all_item;
|
||||
struct output_panel *active_panel;
|
||||
|
||||
struct computer *computer;
|
||||
struct snapshot *active_snapshot;
|
||||
int computer_timeout;
|
||||
|
||||
int is_light;
|
||||
int zombie;
|
||||
int controls_active;
|
||||
int calibrate;
|
||||
int calibrating;
|
||||
int cal_updated;
|
||||
|
||||
struct processing_data *pdata;
|
||||
struct processing_buffers *old;
|
||||
struct calibration_data *cdata;
|
||||
int is_old;
|
||||
|
||||
int bph;
|
||||
int guessed_bph;
|
||||
int last_bph;
|
||||
double la; // deg
|
||||
int cal; // 0.1 s/d
|
||||
double sample_rate;
|
||||
int nominal_sr;
|
||||
|
||||
uint64_t *events;
|
||||
int events_wp;
|
||||
uint64_t events_from;
|
||||
double trace_centering;
|
||||
|
||||
int signal;
|
||||
|
||||
GKeyFile *config_file;
|
||||
gchar *config_file_name;
|
||||
struct conf_data *conf_data;
|
||||
|
||||
guint kick_timeout;
|
||||
guint save_timeout;
|
||||
};
|
||||
|
||||
extern int preset_bph[];
|
||||
|
||||
#ifdef DEBUG
|
||||
extern int testing;
|
||||
#endif
|
||||
|
|
@ -178,11 +265,12 @@ extern int testing;
|
|||
void print_debug(char *format,...);
|
||||
void error(char *format,...);
|
||||
|
||||
// config.c
|
||||
/* config.c */
|
||||
#define CONFIG_FIELDS(OP) \
|
||||
OP(bph, bph, int) \
|
||||
OP(lift_angle, la, double) \
|
||||
OP(calibration, cal, int)
|
||||
OP(calibration, cal, int) \
|
||||
OP(light_algorithm, is_light, int)
|
||||
|
||||
struct conf_data {
|
||||
#define DEF(NAME,PLACE,TYPE) TYPE PLACE;
|
||||
|
|
@ -192,3 +280,8 @@ struct conf_data {
|
|||
void load_config(struct main_window *w);
|
||||
void save_config(struct main_window *w);
|
||||
void save_on_change(struct main_window *w);
|
||||
void close_config(struct main_window *w);
|
||||
|
||||
/* serializer.c */
|
||||
int write_file(FILE *f, struct snapshot **s, char **names, uint64_t cnt);
|
||||
int read_file(FILE *f, struct snapshot ***s, char ***names, uint64_t *cnt);
|
||||
|
|
|
|||
2
version
|
|
@ -1 +1 @@
|
|||
0.4.0
|
||||
0.5.0
|
||||
|
|
|
|||