pax_global_header00006660000000000000000000000064137257570420014526gustar00rootroot0000000000000052 comment=1ef6826bcdce14c6da3417328938ef9404aaab7c baresip-1.0.0/000077500000000000000000000000001372575704200131515ustar00rootroot00000000000000baresip-1.0.0/.gitignore000066400000000000000000000003711372575704200151420ustar00rootroot00000000000000# Object files *.o *.ko # Libraries *.lib *.a # Shared objects (inc. Windows DLLs) *.dll *.so *.so.* *.dylib # Executables *.exe *.out *.app baresip selftest # Generated files src/static.c build* *.pc # Backup files *~ *.bak *.old *.orig *.rej baresip-1.0.0/.travis.yml000066400000000000000000000042741372575704200152710ustar00rootroot00000000000000language: c os: - linux - osx compiler: - clang - gcc env: - LIBRE=re LIBREM=rem sudo: require jobs: include: - name: OpenSSL 1.0.2g os: linux dist: xenial addons: apt: update: false stage: openssl - name: OpenSSL 1.1.1f os: linux dist: focal addons: apt: update: false stage: openssl - name: macOS 10.15.5 os: osx osx_image: xcode12.0 stage: openssl - name: LibreSSL os: linux addons: apt: update: false dist: xenial script: - wget "https://github.com/baresip/ci/releases/download/v0.1/assets.tar.gz" - tar -xf assets.tar.gz - make EXTRA_CFLAGS="-Iassets/libressl/include -Werror" EXTRA_LFLAGS="-Lassets/libressl" CCACHE=; stage: openssl - name: OpenSSL 1.1.1g no-deprecated os: linux dist: xenial addons: apt: update: false script: - wget "https://github.com/baresip/ci/releases/download/v0.1/assets.tar.gz" - tar -xf assets.tar.gz - make EXTRA_CFLAGS="-Iassets/openssl/include -Werror" EXTRA_LFLAGS="-Lassets/openssl" CCACHE=; stage: openssl stages: - test - openssl addons: apt: packages: - libavcodec-dev - libavdevice-dev - libavformat-dev - libgtk2.0-dev - libjack-jackd2-dev - libmpg123-dev - libopus-dev - libpulse-dev - libsndfile1-dev - libspandsp-dev - libssl-dev homebrew: packages: - codec2 - fdk-aac - ffmpeg - jack - mpg123 - spandsp update: false install: - git clone https://github.com/baresip/re.git - git clone https://github.com/creytiv/rem.git - for p in ${LIBRE} ${LIBREM}; do cd $p && sudo PATH="$PATH" make install && cd - && sudo rm -Rf $p; done - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo ldconfig; fi script: - make V=1 CCACHE= EXTRA_CFLAGS=-Werror info test modules - make clean; make CCACHE= STATIC=yes - make ccheck baresip-1.0.0/CHANGELOG.md000066400000000000000000000146371372575704200147750ustar00rootroot00000000000000# Baresip Changelog All notable changes to baresip will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] ### Added - aac: add AAC_STREAMTYPE_AUDIO enum value - aac: add AAC_ prefix - Video mode param to call_answer(), ua_answer() and ua_hold_answer [#966] - video_stop_display() API function [#977] - module: add path to module_load() function - conf: add conf_configure_buf - test: add usage of g711.so module [#978] - JSON initial codec state command and response [#973] - account_set_video_codecs() API function [#981] - net: add fallback dns nameserver [#996] - gtk: show call_peername in notify title [#1006] - call: Added call_state() API function that returns enum state of the call [#1013] - account_set_stun_user() and account_set_stun_pass() API functions [#1015] - API functions account_stun_uri and account_set_stun_uri. [#1018] - ausine: Audio sine wave input module [#1021] - gtk/menu: replace spaces from uri [#1007] - jack: allowing jack client name to be specified in the config file [#1025] [#1020] - snapshot: Add snapshot_send and snapshot_recv commands [#1029] - webrtc_aec: 'extended_filter' config option [#1030] - avfilter: FFmpeg filter graphs integration [#1038] - reg: view proxy expiry value in reg_status [#1068] - account: add parameter rwait for re-register interval [#1069] - call, stream, menu: add cmd to set the direction of video stream [#1073] ### Changed - **Using [baresip/re](https://github.com/baresip/re) fork now** - audio: move calculation to audio_jb_current_value - avformat: clean up docs - gzrtp: update docs - account: increased size of audio codec list to 16 - video: make video_sdp_attr_decode public - config: Derive default audio driver from default audio device [#1009] - jack: modifying info message on jack client creation [#1019] - call: when video stream is disabled, stop also video display [#1023] - dtls_srtp: use tls_set_selfsigned_rsa with keysize 2048 [#1062] [#1056] - rst: use a min ptime of 20ms - aac: change ptime to 4ms ### Fixed - avcodec: fix H.264 interop with Firefox - winwave: waveInGetPosition is no longer supported for use as of Windows Vista [#960] - avcodec: call av_hwdevice_ctx_create before if-statement - account: use single quote instead of backtick - ice: fix segfault in connh [#980] - call: Update call->got_offer when re-INVITE or answer to re-INVITE is received [#986] - mk: Test also for /usr/lib64/libspeexdsp.so to cover Fedora/RHEL/CentOS [#992] - config: Allow distribution specific CA trust bundle locations (fixes [#993] - config: Allow distribution specific default audio device (fixes [#994] - mqtt: fix err is never read (found by clang static analyzer) - avcodec: fix err is never read (found by clang static analyzer) - gtk: notification buttons do not work on Systems [#1012] - gtk: fix dtmf_tone and add tones as feedback [#1010] - pulse: drain pulse buffers before freeing [#1016] - jack: jack_play connect all physical ports [#1028] - Makefile: do not try to install modules if build is static [#1031] - gzrtp: media_alloc function is missing [#1034] [#1022] - call: when updating video, check if video stream has been disabled [#1037] - amr: fix length check, fixes [#1011] - modules: fix search path for avdevice.h [#1043] - gtk: declare variables C89 style - config: init newly added member - menu: fix segfault in ua_event_handler [#1059] [#1061] - debug_cmd: fix OpenSSL no-deprecated [#1065] - aac: handle missing bitrate parameter in SDP format - av1: properly configure encoder ### Removed - ice: remove support for ICE-lite - ice: remove ice_debug, use log level DEBUG instead - ice: make stun server optional - config: remove ice_debug option (unused) ### Contributors (many thanks) - Alfred E. Heggestad - Alexander Gramner - Andrew Webster - Christian Spielberger - Christoph Huber - Davide Alberani - Ethan Funk - Juha Heinanen - mbattista - Michael Malone - Mikl Kurkov - ndilieto - Robert Scheck - Roger Sandholm - Sebastian Reimers [#966]: https://github.com/baresip/baresip/pull/966 [#977]: https://github.com/baresip/baresip/pull/977 [#978]: https://github.com/baresip/baresip/pull/978 [#973]: https://github.com/baresip/baresip/pull/973 [#981]: https://github.com/baresip/baresip/pull/981 [#996]: https://github.com/baresip/baresip/pull/996 [#1006]: https://github.com/baresip/baresip/pull/1006 [#1013]: https://github.com/baresip/baresip/pull/1013 [#1015]: https://github.com/baresip/baresip/pull/1015 [#1018]: https://github.com/baresip/baresip/pull/1018 [#1021]: https://github.com/baresip/baresip/pull/1021 [#1007]: https://github.com/baresip/baresip/pull/1007 [#1025]: https://github.com/baresip/baresip/pull/1025 [#1020]: https://github.com/baresip/baresip/pull/1020 [#1029]: https://github.com/baresip/baresip/pull/1029 [#1030]: https://github.com/baresip/baresip/pull/1030 [#1038]: https://github.com/baresip/baresip/pull/1038 [#1009]: https://github.com/baresip/baresip/pull/1009 [#1019]: https://github.com/baresip/baresip/pull/1019 [#1023]: https://github.com/baresip/baresip/pull/1023 [#1062]: https://github.com/baresip/baresip/pull/1062 [#1056]: https://github.com/baresip/baresip/pull/1056 [#960]: https://github.com/baresip/baresip/pull/960 [#980]: https://github.com/baresip/baresip/pull/980 [#986]: https://github.com/baresip/baresip/pull/986 [#992]: https://github.com/baresip/baresip/pull/992 [#993]: https://github.com/baresip/baresip/pull/993 [#994]: https://github.com/baresip/baresip/pull/994 [#1012]: https://github.com/baresip/baresip/pull/1012 [#1010]: https://github.com/baresip/baresip/pull/1010 [#1016]: https://github.com/baresip/baresip/pull/1016 [#1028]: https://github.com/baresip/baresip/pull/1028 [#1031]: https://github.com/baresip/baresip/pull/1031 [#1034]: https://github.com/baresip/baresip/pull/1034 [#1022]: https://github.com/baresip/baresip/pull/1022 [#1037]: https://github.com/baresip/baresip/pull/1037 [#1011]: https://github.com/baresip/baresip/pull/1011 [#1043]: https://github.com/baresip/baresip/pull/1043 [#1059]: https://github.com/baresip/baresip/pull/1059 [#1061]: https://github.com/baresip/baresip/pull/1061 [#1065]: https://github.com/baresip/baresip/pull/1065 [#1068]: https://github.com/baresip/baresip/pull/1068 [#1069]: https://github.com/baresip/baresip/pull/1069 [#1073]: https://github.com/baresip/baresip/pull/1073 [Unreleased]: https://github.com/baresip/baresip/compare/v0.6.6...HEAD baresip-1.0.0/Makefile000066400000000000000000000176031372575704200146200ustar00rootroot00000000000000# # Makefile # # Copyright (C) 2010 Creytiv.com # # # Internal features: # # USE_TLS Enable SIP over TLS transport # PROJECT := baresip VERSION := 1.0.0 DESCR := "Baresip is a modular SIP User-Agent with audio and video support" # Verbose and silent build modes ifeq ($(V),) HIDE=@ endif ifndef LIBRE_MK LIBRE_MK := $(shell [ -f ../re/mk/re.mk ] && \ echo "../re/mk/re.mk") ifeq ($(LIBRE_MK),) LIBRE_MK := $(shell [ -f ../re-$(VERSION)/mk/re.mk ] && \ echo "../re-$(VERSION)/mk/re.mk") endif ifeq ($(LIBRE_MK),) LIBRE_MK := $(shell [ -f /usr/share/re/re.mk ] && \ echo "/usr/share/re/re.mk") endif ifeq ($(LIBRE_MK),) LIBRE_MK := $(shell [ -f /usr/local/share/re/re.mk ] && \ echo "/usr/local/share/re/re.mk") endif endif ifeq ($(SYSROOT_LOCAL),) SYSROOT_LOCAL := $(shell [ -d /usr/local/include ] && echo "/usr/local") endif include $(LIBRE_MK) include mk/modules.mk ifndef LIBREM_PATH LIBREM_PATH := $(shell [ -d ../rem ] && echo "../rem") endif CFLAGS += -I. -Iinclude -I$(LIBRE_INC) ifneq ($(LIBREM_PATH),) CFLAGS += -I$(LIBREM_PATH)/include endif CFLAGS += -I$(SYSROOT)/local/include/rem -I$(SYSROOT)/include/rem ifneq ($(SYSROOT_LOCAL),) CFLAGS += -I$(SYSROOT_LOCAL)/include/rem endif CXXFLAGS += -I. -Iinclude -I$(LIBRE_INC) ifneq ($(LIBREM_PATH),) CXXFLAGS += -I$(LIBREM_PATH)/include endif CXXFLAGS += -I$(SYSROOT)/local/include/rem -I$(SYSROOT)/include/rem ifneq ($(SYSROOT_LOCAL),) CXXFLAGS += -I$(SYSROOT_LOCAL)/include/rem endif CXXFLAGS += $(EXTRA_CXXFLAGS) # XXX: common for C/C++ CPPFLAGS += -DHAVE_INTTYPES_H ifneq ($(LIBREM_PATH),) CLANG_OPTIONS += -I$(LIBREM_PATH)/include endif ifeq ($(OS),win32) STATIC := yes endif ifneq ($(SYSROOT),) ifeq ($(OS),freebsd) CFLAGS += -I$(SYSROOT)/local/include endif ifeq ($(OS),openbsd) CFLAGS += -isystem $(SYSROOT)/local/include endif endif # Optional dependencies ifneq ($(STATIC),) CFLAGS += -DSTATIC=1 CXXFLAGS += -DSTATIC=1 endif INSTALL := install ifeq ($(DESTDIR),) PREFIX := /usr/local else PREFIX := /usr endif BINDIR := $(PREFIX)/bin INCDIR := $(PREFIX)/include BIN := $(PROJECT)$(BIN_SUFFIX) TEST_BIN := selftest$(BIN_SUFFIX) SHARED := lib$(PROJECT)$(LIB_SUFFIX) STATICLIB := libbaresip.a ifeq ($(STATIC),) MOD_BINS:= $(patsubst %,%$(MOD_SUFFIX),$(MODULES)) endif APP_MK := src/srcs.mk TEST_MK := test/srcs.mk MOD_MK := $(patsubst %,modules/%/module.mk,$(MODULES)) MOD_BLD := $(patsubst %,$(BUILD)/modules/%,$(MODULES)) LIBDIR := $(PREFIX)/lib MOD_PATH := $(LIBDIR)/$(PROJECT)/modules SHARE_PATH := $(PREFIX)/share/$(PROJECT) CFLAGS += -DPREFIX=\"$(PREFIX)\" CFLAGS += -DMOD_PATH=\"$(MOD_PATH)\" CFLAGS += -DSHARE_PATH=\"$(SHARE_PATH)\" all: sanity $(MOD_BINS) $(BIN) .PHONY: modules modules: $(MOD_BINS) include $(APP_MK) include $(TEST_MK) include $(MOD_MK) OBJS := $(patsubst %.c,$(BUILD)/src/%.o,$(filter %.c,$(SRCS))) OBJS += $(patsubst %.m,$(BUILD)/src/%.o,$(filter %.m,$(SRCS))) OBJS += $(patsubst %.S,$(BUILD)/src/%.o,$(filter %.S,$(SRCS))) APP_OBJS := $(OBJS) $(patsubst %.c,$(BUILD)/src/%.o,$(APP_SRCS)) $(MOD_OBJS) LIB_OBJS := $(OBJS) $(MOD_OBJS) TEST_OBJS := $(patsubst %.c,$(BUILD)/test/%.o,$(filter %.c,$(TEST_SRCS))) TEST_OBJS += $(patsubst %.cpp,$(BUILD)/test/%.o,$(filter %.cpp,$(TEST_SRCS))) ifneq ($(LIBREM_PATH),) LIBS += -L$(LIBREM_PATH) endif # Static build: include module linker-flags in binary ifneq ($(STATIC),) LIBS += $(MOD_LFLAGS) else ifneq ($(SYSROOT_LOCAL),) LIBS += -L$(SYSROOT_LOCAL)/lib MOD_LFLAGS += -L$(SYSROOT_LOCAL)/lib endif endif LIBS += -lrem -lm #LIBS += -L$(SYSROOT)/lib ifeq ($(OS),win32) TEST_LIBS += -static-libgcc endif -include $(APP_OBJS:.o=.d) -include $(TEST_OBJS:.o=.d) sanity: ifeq ($(LIBRE_MK),) @echo "ERROR: Missing common makefile for libre. Check LIBRE_MK" @exit 2 endif ifeq ($(LIBRE_INC),) @echo "ERROR: Missing header files for libre. Check LIBRE_INC" @exit 2 endif ifeq ($(LIBRE_SO),) @echo "ERROR: Missing library files for libre. Check LIBRE_SO" @exit 2 endif Makefile: mk/*.mk $(MOD_MK) $(LIBRE_MK) $(SHARED): $(LIB_OBJS) @echo " LD $@" $(HIDE)$(LD) $(LFLAGS) $(SH_LFLAGS) $^ -L$(LIBRE_SO) -lre $(LIBS) -o $@ $(STATICLIB): $(LIB_OBJS) @echo " AR $@" @rm -f $@; $(AR) $(AFLAGS) $@ $^ ifneq ($(RANLIB),) @echo " RANLIB $@" $(HIDE)$(RANLIB) $@ endif libbaresip.pc: @echo 'prefix='$(PREFIX) > libbaresip.pc @echo 'exec_prefix=$${prefix}' >> libbaresip.pc @echo 'libdir=$${prefix}/lib' >> libbaresip.pc @echo 'includedir=$${prefix}/include' >> libbaresip.pc @echo '' >> libbaresip.pc @echo 'Name: libbaresip' >> libbaresip.pc @echo 'Description: $(DESCR)' >> libbaresip.pc @echo 'Version: '$(VERSION) >> libbaresip.pc @echo 'URL: http://www.creytiv.com/baresip.html' >> libbaresip.pc @echo 'Libs: -L$${libdir} -lbaresip' >> libbaresip.pc @echo 'Cflags: -I$${includedir}' >> libbaresip.pc $(BIN): $(APP_OBJS) @echo " LD $@" $(HIDE)$(LD) $(LFLAGS) $(APP_LFLAGS) $^ \ -L$(LIBRE_SO) -lre $(LIBS) -o $@ # # List of modules used by selftest # ifneq ($(STATIC),) TEST_MODULES := else TEST_MODULES := g711.so endif .PHONY: test test: $(TEST_BIN) ./$(TEST_BIN) $(TEST_BIN): $(STATICLIB) $(TEST_OBJS) $(TEST_MODULES) @echo " LD $@" $(HIDE)$(LD) $(LFLAGS) $(APP_LFLAGS) $(TEST_OBJS) \ -L$(LIBRE_SO) -L. \ -l$(PROJECT) -lre $(LIBS) $(TEST_LIBS) -o $@ $(BUILD)/%.o: %.c $(BUILD) Makefile $(APP_MK) @echo " CC $@" $(HIDE)$(CC) $(CFLAGS) -c $< -o $@ $(DFLAGS) $(BUILD)/%.o: %.cpp $(BUILD) Makefile $(APP_MK) @echo " CXX $@" $(HIDE)$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $< -o $@ $(DFLAGS) $(BUILD)/%.o: %.m $(BUILD) Makefile $(APP_MK) @echo " OC $@" $(HIDE)$(CC) $(CFLAGS) $(OBJCFLAGS) -c $< -o $@ $(DFLAGS) $(BUILD)/%.o: %.S $(BUILD) Makefile $(APP_MK) @echo " AS $@" $(HIDE)$(CC) $(CFLAGS) -c $< -o $@ $(DFLAGS) $(BUILD): Makefile @mkdir -p $(BUILD)/src $(MOD_BLD) $(BUILD)/test/mock $(BUILD)/test/sip @touch $@ install: $(BIN) $(MOD_BINS) @mkdir -p $(DESTDIR)$(BINDIR) $(INSTALL) -m 0755 $(BIN) $(DESTDIR)$(BINDIR) ifeq ($(STATIC),) @mkdir -p $(DESTDIR)$(MOD_PATH) $(INSTALL) -m 0644 $(MOD_BINS) $(DESTDIR)$(MOD_PATH) endif @mkdir -p $(DESTDIR)$(SHARE_PATH) $(INSTALL) -m 0644 share/* $(DESTDIR)$(SHARE_PATH) install-dev: install-shared install-static install-shared: $(SHARED) libbaresip.pc @mkdir -p $(DESTDIR)$(INCDIR) $(INSTALL) -Cm 0644 include/baresip.h $(DESTDIR)$(INCDIR) @mkdir -p $(DESTDIR)$(LIBDIR) $(DESTDIR)$(LIBDIR)/pkgconfig $(INSTALL) -m 0644 $(SHARED) $(DESTDIR)$(LIBDIR) $(INSTALL) -m 0644 libbaresip.pc $(DESTDIR)$(LIBDIR)/pkgconfig install-static: $(STATICLIB) @mkdir -p $(DESTDIR)$(INCDIR) $(INSTALL) -Cm 0644 include/baresip.h $(DESTDIR)$(INCDIR) @mkdir -p $(DESTDIR)$(LIBDIR) $(INSTALL) -m 0644 $(STATICLIB) $(DESTDIR)$(LIBDIR) uninstall: @rm -f $(DESTDIR)$(PREFIX)/bin/$(BIN) @rm -rf $(DESTDIR)$(MOD_PATH) @rm -f $(DESTDIR)$(PREFIX)/lib/$(SHARED) @rm -f $(DESTDIR)$(PREFIX)/lib/$(STATICLIB) @rm -f $(DESTDIR)$(PREFIX)/lib/pkgconfig/libbaresip.pc .PHONY: clean clean: @rm -rf $(BIN) $(MOD_BINS) $(SHARED) $(BUILD) $(TEST_BIN) \ $(STATICLIB) libbaresip.pc @rm -f *stamp \ `find . -name "*.[od]"` \ `find . -name "*~"` \ `find . -name "\.\#*"` .PHONY: ccheck ccheck: @test/ccheck.py version: @perl -pi -e 's/BARESIP_VERSION.*/BARESIP_VERSION \"$(VERSION)"/' \ include/baresip.h @perl -pi -e "s/PROJECT_NUMBER = .*/\ PROJECT_NUMBER = $(VERSION)/" \ mk/Doxyfile @echo "updating version number to $(VERSION)" src/static.c: $(BUILD) Makefile $(APP_MK) $(MOD_MK) @echo " SH $@" @echo "/* static.c - autogenerated by makefile */" > $@ @echo "#include " >> $@ @echo "#include " >> $@ @echo "" >> $@ @for n in $(MODULES); do \ echo "extern const struct mod_export exports_$${n};" >> $@ ; \ done @echo "" >> $@ @echo "const struct mod_export *mod_table[] = {" >> $@ @for n in $(MODULES); do \ echo " &exports_$${n}," >> $@ ; \ done @echo " NULL" >> $@ @echo "};" >> $@ baresip-1.0.0/README.md000066400000000000000000000322011372575704200144260ustar00rootroot00000000000000baresip README ============== ![Baresip Logo](https://raw.githubusercontent.com/baresip/baresip/master/share/logo.png) Baresip is a portable and modular SIP User-Agent with audio and video support. Copyright (c) 2010 - 2020 Creytiv.com Distributed under BSD license [![Build Status](https://travis-ci.org/baresip/baresip.svg?branch=master)](https://travis-ci.org/baresip/baresip) ## Features: * Call features: - Unlimited number of SIP accounts - Unlimited number of calls - Unattended call transfer - Auto answer - Call hold and resume - Microphone mute - Call waiting - Call recording - Peer to peer calls - Video calls - Instant Messaging - Custom ring tones - Repeat last call (redial) - Message Waiting Indication (MWI) - Address book with presence * Signaling: - SIP protocol support - SIP outbound protocol for NAT-traversal - SIP Re-invite - SIP Routes - SIP early media support - DNS NAPTR/SRV support - Multiple accounts support - DTMF support (RTP, SIP INFO) * Security: - Signalling encryption (TLS) - Audio and video encryption (Secure RTP) - DTLS-SRTP key exchange protocol - ZRTP key exchange protocol - SDES key exchange protocol * Audio: - Low latency audio pipeline - High definition audio codecs - Audio device configuration - Audio filter plugins - Internal audio resampler for fixed sampling rates - Linear 16 bit wave format support for ringtones - Packet loss concealment (PLC) - Configurable ringtone playback device - Automatic gain control (AGC) and Noise reducation - Acoustic echo control (AEC) - Configurable audio sample format (Signed 16-bit, 24-bit, Float etc) - EBU ACIP (Audio Contribution over IP) Profile * Audio-codecs: - AAC - aptX - AMR narrowband, AMR wideband - Codec2 - G.711 - G.722 - G.726 - GSM - iLBC - iSAC - L16 - MPA - Opus * Audio-drivers: - Advanced Linux Sound Architecture (ALSA) audio-driver - PulseAudio POSIX OSes audio-driver - Android OpenSLES audio-driver - Gstreamer playbin input audio-driver - JACK Audio Connection Kit audio-driver - MacOSX/iOS coreaudio/audiounit audio-driver - Open Sound System (OSS) audio-driver - Portaudio audio-driver - Windows winwave audio-driver * Video: - Support for H.265, H.264, H.263, VP8, VP9, MPEG-4 Video - Configurable resolution/framerate/bitrate - Configurable video input/output - Support for asymmetric video - Configurable video pixel format - Hardware acceleration for video encoder/decoder * Video-codecs: - H.265 - H.264 - H.263 - VP8 - VP9 - MPEG-4 * Video-drivers: - iOS avcapture video-source - FFmpeg/libav libavformat/avdevice input - Cairo video-source test module - Direct Show video-source - MacOSX QTcapture/AVCapture video-source - RST media player - Linux V4L/V4L2 video-source - X11 grabber video-source - DirectFB video-output - OpenGL video-output - SDL2 video-output - X11 video-output * NAT-traversal: - STUN support - TURN server support - ICE support - NATPMP support - PCP (Port Control Protocol) support * Networking: - multihoming, IPv4/IPv6 - automatic network roaming * Management: - Embedded web-server with HTTP interface - Command-line console over UDP/TCP - Command line interface (CLI) - Simple configuration files - MQTT (Message Queue Telemetry Transport) module * Profiles: - EBU ACIP (Audio Contribution over IP) Profile ## Building baresip is using GNU makefiles, and the following packages must be installed before building: * [libre](https://github.com/baresip/re) * [librem](https://github.com/creytiv/rem) * [openssl](https://www.openssl.org/) ### Build with debug enabled ``` $ make $ sudo make install ``` ### Build with release ``` $ make RELEASE=1 $ sudo make RELEASE=1 install ``` ### Build with clang compiler ``` $ make CC=clang $ sudo make CC=clang install ``` Modules will be built if external dependencies are installed. After building you can start baresip like this: ``` $ baresip ``` The config files in $HOME/.baresip are automatically generated the first time you run baresip. ## Documentation The online documentation generated with doxygen is available in the main [website](http://creytiv.com/doxygen/baresip-dox/html/) ### Examples Configuration examples are available from the [examples](https://github.com/baresip/baresip/tree/master/docs/examples) directory. ## License The baresip project is using the 3-clause BSD license. ## Contributing Patches can be sent via Github [Pull-Requests](https://github.com/baresip/baresip/pulls) or to the RE devel [mailing-list](http://lists.creytiv.com/mailman/listinfo/re-devel). ## Design goals: * Minimalistic and modular VoIP client * SIP, SDP, RTP/RTCP, STUN/TURN/ICE * IPv4 and IPv6 support * RFC-compliancy * Robust, fast, low footprint * Portable C89 and C99 source code ## Modular Plugin Architecture: ``` aac Advanced Audio Coding (AAC) audio codec account Account loader alsa ALSA audio driver amr Adaptive Multi-Rate (AMR) audio codec aptx Audio Processing Technology codec (aptX) aubridge Audio bridge module audiounit AudioUnit audio driver for MacOSX/iOS aufile Audio module for using a WAV-file as audio input auloop Audio-loop test module ausine Audio sine wave input module avcapture Video source using iOS AVFoundation video capture avcodec Video codec using FFmpeg/libav libavcodec avformat Video source using FFmpeg/libav libavformat b2bua Back-to-Back User-Agent (B2BUA) module cairo Cairo video source codec2 Codec2 low bit rate speech codec cons UDP/TCP console UI driver contact Contacts module coreaudio Apple macOS Coreaudio driver ctrl_tcp TCP control interface using JSON payload debug_cmd Debug commands directfb DirectFB video display module dshow Windows DirectShow video source dtls_srtp DTLS-SRTP end-to-end encryption ebuacip EBU ACIP (Audio Contribution over IP) Profile echo Echo server module evdev Linux input driver fakevideo Fake video input/output driver g711 G.711 audio codec g722 G.722 audio codec g7221 G.722.1 audio codec g726 G.726 audio codec gsm GSM audio codec gst Gstreamer audio source gst_video Gstreamer video codec gtk GTK+ 2.0 UI gzrtp ZRTP module using GNU ZRTP C++ library httpd HTTP webserver UI-module i2s I2S (Inter-IC Sound) audio driver ice ICE protocol for NAT Traversal ilbc iLBC audio codec isac iSAC audio codec jack JACK Audio Connection Kit audio-driver l16 L16 audio codec menu Interactive menu mpa MPA Speech and Audio Codec mqtt MQTT (Message Queue Telemetry Transport) module mwi Message Waiting Indication natpmp NAT Port Mapping Protocol (NAT-PMP) module omx OpenMAX IL video display module opengl OpenGL video output opensles OpenSLES audio driver opus OPUS Interactive audio codec oss Open Sound System (OSS) audio driver pcp Port Control Protocol (PCP) module plc Packet Loss Concealment (PLC) using spandsp portaudio Portaudio driver pulse Pulseaudio driver presence Presence module qtcapture Apple QTCapture video source driver rtcpsummary RTCP summary module rst Radio streamer using mpg123 sdl Simple DirectMedia Layer 2.0 (SDL) video output driver selfview Video selfview module snapshot Save video-stream as PNG images sndfile Audio dumper using libsndfile sndio Audio driver for OpenBSD speex_pp Audio pre-processor using libspeexdsp srtp Secure RTP encryption (SDES) using libre SRTP-stack stdio Standard input/output UI driver stun Session Traversal Utilities for NAT (STUN) module swscale Video scaling using libswscale syslog Syslog module turn Obtaining Relay Addresses from STUN (TURN) module uuid UUID generator and loader v4l2 Video4Linux2 video source v4l2_codec Video4Linux2 video codec module (H264 hardware encoding) vidbridge Video bridge module vidinfo Video info overlay module vidloop Video-loop test module vp8 VP8 video codec vp9 VP9 video codec vumeter Display audio levels in console webrtc_aec Acoustic Echo Cancellation (AEC) using WebRTC SDK wincons Console input driver for Windows winwave Audio driver for Windows x11 X11 video output driver x11grab X11 grabber video source zrtp ZRTP media encryption module ``` ## IETF RFC/I-Ds: * RFC 2190 RTP Payload Format for H.263 Video Streams (Historic) * RFC 2250 RTP Payload Format for the mpa Speech and Audio Codec * RFC 2429 RTP Payload Format for 1998 ver of ITU-T Rec. H.263 Video (H.263+) * RFC 3016 RTP Payload Format for MPEG-4 Audio/Visual Streams * RFC 3428 SIP Extension for Instant Messaging * RFC 3711 The Secure Real-time Transport Protocol (SRTP) * RFC 3640 RTP Payload Format for Transport of MPEG-4 Elementary Streams * RFC 3856 A Presence Event Package for SIP * RFC 3863 Presence Information Data Format (PIDF) * RFC 3951 Internet Low Bit Rate Codec (iLBC) * RFC 3952 RTP Payload Format for iLBC Speech * RFC 4145 TCP-Based Media Transport in SDP * RFC 4240 Basic Network Media Services with SIP (partly) * RFC 4347 Datagram Transport Layer Security * RFC 4568 SDP Security Descriptions for Media Streams * RFC 4572 Connection-Oriented Media Transport over TLS Protocol in SDP * RFC 4574 The SDP Label Attribute * RFC 4585 Extended RTP Profile for RTCP-Based Feedback (RTP/AVPF) * RFC 4587 RTP Payload Format for H.261 Video Streams * RFC 4629 RTP Payload Format for ITU-T Rec. H.263 Video * RFC 4796 The SDP Content Attribute * RFC 4867 RTP Payload Format for the AMR and AMR-WB Audio Codecs * RFC 4961 Symmetric RTP / RTP Control Protocol (RTCP) * RFC 5168 XML Schema for Media Control * RFC 5285 A General Mechanism for RTP Header Extensions * RFC 5506 Support for Reduced-Size RTCP * RFC 5576 Source-Specific Media Attributes in SDP * RFC 5577 RTP Payload Format for ITU-T Recommendation G.722.1 * RFC 5626 Managing Client-Initiated Connections in SIP * RFC 5627 Obtaining and Using GRUUs in SIP * RFC 5761 Multiplexing RTP Data and Control Packets on a Single Port * RFC 5763 Framework for Establishing a SRTP Security Context Using DTLS * RFC 5764 DTLS Extension to Establish Keys for SRTP * RFC 6157 IPv6 Transition in SIP * RFC 6184 RTP Payload Format for H.264 Video * RFC 6263 App. Mechanism for Keeping Alive NAT Associated with RTP / RTCP * RFC 6416 RTP Payload Format for MPEG-4 Audio/Visual Streams * RFC 6464 A RTP Header Extension for Client-to-Mixer Audio Level Indication * RFC 6716 Definition of the Opus Audio Codec * RFC 6886 NAT Port Mapping Protocol (NAT-PMP) * RFC 7064 URI Scheme for STUN Protocol * RFC 7065 TURN Uniform Resource Identifiers * RFC 7310 RTP Payload Format for Standard apt-X and Enhanced apt-X Codecs * RFC 7587 RTP Payload Format for the Opus Speech and Audio Codec * RFC 7741 RTP Payload Format for VP8 Video * RFC 7798 RTP Payload Format for High Efficiency Video Coding (HEVC) * draft-ietf-avt-rtp-isac-04 * draft-ietf-payload-vp9-07 ## Architecture: (note: out of date, needs updating) ``` .------. |Video | _ |Stream|\ /|'------' \ 1 / \ / _\| .--. N .----. M .------. 1 .-------. 1 .-----. |UA|--->|Call|--->|Audio |--->|Generic|--->|Media| '--' '----' |Stream| |Stream | | NAT | |1 '------' '-------' '-----' | C| 1| | \|/ .-----. .----. | .-------. |Codec| |Jbuf| |1 | SIP | '-----' '----' | |Session| 1| /|\ | '-------' .---. | \|/ |DSP| .--------. '---' |RTP/RTCP| '--------' | SRTP | '--------' ``` A User-Agent (UA) has 0-N SIP Calls A SIP Call has 0-M Media Streams ## Supported platforms: * Android (5.0 or later) * Apple Mac OS X and iOS * FreeBSD * Linux * NetBSD * OpenBSD * Solaris * Windows (mingw and VS2015) ### Supported versions of C Standard library * Android bionic * BSD libc * GNU C Library (glibc) * Windows C Run-Time Libraries (CRT) * uClibc ### Supported compilers: * gcc 3.x * gcc 4.x * gcc 5.x * gcc 6.x * ms vc2003 compiler * clang ### Supported versions of OpenSSL * OpenSSL version 1.0.1 * OpenSSL version 1.0.2 * OpenSSL version 1.1.0 * LibreSSL version 2.x ## Related projects * [libre](https://github.com/creytiv/re) * [libre - baresip fork](https://github.com/baresip/re) * [librem](https://github.com/creytiv/rem) * [retest](https://github.com/creytiv/retest) * [restund](http://creytiv.com/restund.html) ## References * Project homepage: http://www.creytiv.com/baresip.html * Github: https://github.com/baresip/baresip * Mailing-list: http://lists.creytiv.com/mailman/listinfo/re-devel baresip-1.0.0/debian/000077500000000000000000000000001372575704200143735ustar00rootroot00000000000000baresip-1.0.0/debian/changelog000066400000000000000000000134531372575704200162530ustar00rootroot00000000000000baresip (0.6.6) unstable; urgency=medium * version 0.6.6 -- Alfred E. Heggestad Thu, 16 Apr 2020 16:00:00 +0200 baresip (0.6.5) unstable; urgency=medium * version 0.6.5 -- Alfred E. Heggestad Sun, 1 Dec 2019 09:00:00 +0100 baresip (0.6.4) unstable; urgency=medium * version 0.6.4 -- Alfred E. Heggestad Sun, 1 Sep 2019 08:00:00 +0200 baresip (0.6.3) unstable; urgency=medium * version 0.6.3 -- Alfred E. Heggestad Sat, 22 Jun 2019 08:00:00 +0200 baresip (0.6.2) unstable; urgency=medium * version 0.6.2 -- Alfred E. Heggestad Fri, 19 Apr 2019 12:00:00 +0200 baresip (0.6.1) unstable; urgency=medium * version 0.6.1 -- Alfred E. Heggestad Sun, 17 Feb 2019 10:00:00 +0100 baresip (0.6.0) unstable; urgency=medium * version 0.6.0 -- Alfred E. Heggestad Sat, 1 Dec 2018 10:00:00 +0100 baresip (0.5.11) unstable; urgency=medium * version 0.5.11 -- Alfred E. Heggestad Sat, 15 Sep 2018 10:00:00 +0200 baresip (0.5.10) unstable; urgency=medium * version 0.5.10 -- Alfred E. Heggestad Wed, 4 Jul 2018 14:00:00 +0200 baresip (0.5.9) unstable; urgency=medium * version 0.5.9 -- Alfred E. Heggestad Sat, 21 Apr 2018 12:00:00 +0200 baresip (0.5.8) unstable; urgency=medium * version 0.5.8 -- Alfred E. Heggestad Sun, 11 Feb 2018 18:00:00 +0100 baresip (0.5.7) unstable; urgency=medium * version 0.5.7 -- Alfred E. Heggestad Mon, 25 Dec 2017 10:00:00 +0100 baresip (0.5.6) unstable; urgency=medium * version 0.5.6 -- Alfred E. Heggestad Sat, 14 Oct 2017 10:00:00 +0200 baresip (0.5.5) unstable; urgency=medium * version 0.5.5 -- Alfred E. Heggestad Thu, 7 Sep 2017 16:00:00 +0200 baresip (0.5.4) unstable; urgency=medium * version 0.5.4 -- Alfred E. Heggestad Sat, 24 Jun 2017 12:00:00 +0200 baresip (0.5.3) unstable; urgency=medium * version 0.5.3 -- Alfred E. Heggestad Sun, 14 May 2017 07:00:00 +0200 baresip (0.5.2) unstable; urgency=medium * version 0.5.2 -- Alfred E. Heggestad Fri, 7 Apr 2017 19:00:00 +0200 baresip (0.5.1) unstable; urgency=medium * version 0.5.1 -- Alfred E. Heggestad Sat, 4 Mar 2017 10:00:00 +0100 baresip (0.5.0) unstable; urgency=medium * version 0.5.0 -- Alfred E. Heggestad Fri, 23 Dec 2016 18:00:00 +0100 baresip (0.4.20) unstable; urgency=medium * version 0.4.20 -- Alfred E. Heggestad Fri, 22 July 2016 20:00:00 +0100 baresip (0.4.19) unstable; urgency=medium * version 0.4.19 -- Alfred E. Heggestad Fri, 20 May 2016 20:00:00 +0100 baresip (0.4.18) unstable; urgency=medium * version 0.4.18 -- Alfred E. Heggestad Sat, 12 Mar 2016 18:00:00 +0100 baresip (0.4.17) unstable; urgency=low * version 0.4.17 -- Alfred E. Heggestad Sun, 17 Jan 2016 12:00:00 +0100 baresip (0.4.16) unstable; urgency=low * version 0.4.16 -- Alfred E. Heggestad Tue, 1 Dec 2015 12:00:00 +0100 baresip (0.4.15) unstable; urgency=low * version 0.4.15 -- Alfred E. Heggestad Sat, 26 Sep 2015 12:00:00 +0100 baresip (0.4.14) unstable; urgency=low * version 0.4.14 -- Alfred E. Heggestad Sat, 8 Aug 2015 12:00:00 +0100 baresip (0.4.13) unstable; urgency=low * version 0.4.13 -- Alfred E. Heggestad Sat, 20 Jun 2015 20:00:00 +0100 baresip (0.4.12) unstable; urgency=low * version 0.4.12 -- Alfred E. Heggestad Wed, 24 Dec 2014 14:00:00 +0100 baresip (0.4.11) unstable; urgency=low * version 0.4.11 -- Alfred E. Heggestad Sat, 21 Jun 2014 14:00:00 +0100 baresip (0.4.10) unstable; urgency=low * version 0.4.10 -- Alfred E. Heggestad Thu, 23 Jan 2014 16:00:00 +0100 baresip (0.4.9) unstable; urgency=low * version 0.4.9 -- Alfred E. Heggestad Mon, 6 Jan 2014 16:00:00 +0100 baresip (0.4.8) unstable; urgency=low * version 0.4.8 -- Alfred E. Heggestad Fri, 6 Dec 2013 23:00:00 +0100 baresip (0.4.7) unstable; urgency=low * version 0.4.7 -- Alfred E. Heggestad Tue, 12 Nov 2013 22:00:00 +0100 baresip (0.4.6) unstable; urgency=low * version 0.4.6 -- Alfred E. Heggestad Fri, 11 Oct 2013 20:00:00 +0100 baresip (0.4.5) unstable; urgency=low * version 0.4.5 -- Alfred E. Heggestad Sat, 31 Aug 2013 18:00:00 +0100 baresip (0.4.4) unstable; urgency=low * version 0.4.4 -- Alfred E. Heggestad Sat, 18 May 2013 10:00:00 +0100 baresip (0.4.3) unstable; urgency=low * version 0.4.3 -- Alfred E. Heggestad Tue, 1 Jan 2013 01:01:00 +0100 baresip (0.4.2) unstable; urgency=low * version 0.4.2 -- Alfred E. Heggestad Sun, 9 Sept 2012 09:09:00 +0100 baresip (0.4.1) unstable; urgency=low * version 0.4.1 -- Alfred E. Heggestad Sat, 21 Apr 2012 21:04:00 +0100 baresip (0.4.0) unstable; urgency=low * version 0.4.0 -- Alfred E. Heggestad Sun, 25 Dec 2011 12:25:00 +0100 baresip (0.3.0) unstable; urgency=low * version 0.3.0 -- Alfred E. Heggestad Wed, 7 Sept 2011 07:11:00 +0100 baresip (0.2.0) unstable; urgency=low * version 0.2.0 -- Alfred E. Heggestad Fri, 20 May 2011 20:05:00 +0100 baresip (0.1.0) unstable; urgency=low * version 0.1.0 -- Alfred E. Heggestad Fri, 5 Nov 2010 05:11:10 +0100 baresip-1.0.0/debian/compat000066400000000000000000000000021372575704200155710ustar00rootroot000000000000009 baresip-1.0.0/debian/control000066400000000000000000000021201372575704200157710ustar00rootroot00000000000000Source: baresip Section: comm Priority: optional Maintainer: Alfred E. Heggestad Standards-Version: 3.9.5 Build-Depends: debhelper (>= 9.20120311), librem-dev (>= 0.6.0), libre-dev (>= 0.6.0), libasound2-dev, libavformat-dev, libavdevice-dev, libswscale-dev Homepage: http://www.creytiv.com/ Package: baresip Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends}, librem (>= 0.6.0), libre (>= 0.6.0) Description: Modular SIP User-Agent with audio and video support Design goals: . Minimalistic and modular VoIP client SIP, SDP, RTP/RTCP, STUN/TURN/ICE IPv4 and IPv6 support RFC compliant Robust, fast, low footprint Portable C89 and C99 source code Package: libbaresip Architecture: any Section: libs Depends: ${shlibs:Depends}, ${misc:Depends}, librem (>= 0.6.0), libre (>= 0.6.0) Description: Baresip library Package: libbaresip-dev Architecture: any Section: libdevel Depends: libbaresip (= ${binary:Version}), ${misc:Depends} Description: Baresip library development files See https://github.com/baresip/baresip/wiki/Using-baresip-as-a-library for an example. baresip-1.0.0/debian/copyright000066400000000000000000000031511372575704200163260ustar00rootroot00000000000000This package was debianized by Alfred E. Heggestad It was downloaded from www.creytiv.com Copyright (c) 2010 - 2014, Alfred E. Heggestad Copyright (c) 2010 - 2014, Richard Aas Copyright (c) 2010 - 2014, Creytiv.com All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the Creytiv.com nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. baresip-1.0.0/debian/dirs000066400000000000000000000000621372575704200152550ustar00rootroot00000000000000usr/bin usr/lib/baresip/modules usr/share/baresip baresip-1.0.0/debian/docs000066400000000000000000000000241372575704200152420ustar00rootroot00000000000000README.md docs/TODO baresip-1.0.0/debian/libbaresip-dev.dirs000066400000000000000000000000361372575704200201450ustar00rootroot00000000000000usr/include usr/lib usr/share baresip-1.0.0/debian/libbaresip-dev.files000066400000000000000000000000411372575704200203020ustar00rootroot00000000000000usr/include usr/lib/libbaresip.a baresip-1.0.0/debian/libbaresip.dirs000066400000000000000000000000101372575704200173610ustar00rootroot00000000000000usr/lib baresip-1.0.0/debian/libbaresip.files000066400000000000000000000000271372575704200175320ustar00rootroot00000000000000/usr/lib/libbaresip.so baresip-1.0.0/debian/rules000077500000000000000000000036751372575704200154660ustar00rootroot00000000000000#!/usr/bin/make -f # -*- makefile -*- # Sample debian/rules that uses debhelper. # This file was originally written by Joey Hess and Craig Small. # As a special exception, when this file is copied by dh-make into a # dh-make output file, you may use that output file without restriction. # This special exception was added by Craig Small in version 0.37 of dh-make. # Uncomment this to turn on verbose mode. #export DH_VERBOSE=1 BARESIP_FLAGS := MOD_AUTODETECT=1 EXTRA_CFLAGS:="$(shell dpkg-buildflags --get CFLAGS)" EXTRA_LFLAGS:="$(shell dpkg-buildflags --get LDFLAGS)" configure: configure-stamp configure-stamp: dh_testdir touch configure-stamp build: build-stamp build-stamp: configure-stamp dh_testdir $(MAKE) RELEASE=1 $(BARESIP_FLAGS) DESTDIR=$(CURDIR)/debian/baresip \ EXTRA_CFLAGS=$(EXTRA_CFLAGS) \ EXTRA_LFLAGS=$(EXTRA_LFLAGS) touch build-stamp clean: dh_testdir dh_testroot rm -f build-stamp configure-stamp $(MAKE) clean dh_clean install: build dh_testdir dh_testroot dh_prep dh_installdirs mkdir $(CURDIR)/debian/tmp $(MAKE) RELEASE=1 $(BARESIP_FLAGS) install DESTDIR=$(CURDIR)/debian/baresip $(MAKE) RELEASE=1 $(BARESIP_FLAGS) install-dev DESTDIR=$(CURDIR)/debian/tmp dh_movefiles # Build architecture-independent files here. binary-indep: build install # We have nothing to do by default. # Build architecture-dependent files here. binary-arch: build install dh_testdir dh_testroot dh_installchangelogs dh_installdocs dh_installexamples # dh_install # dh_installmenu # dh_installdebconf # dh_installlogrotate # dh_installemacsen # dh_installpam # dh_installmime # dh_installinit # dh_installcron # dh_installinfo dh_installman dh_link dh_strip dh_compress dh_fixperms # dh_perl # dh_python dh_makeshlibs dh_installdeb dh_shlibdeps dh_gencontrol dh_md5sums dh_builddeb build-arch: build build-indep: build binary: binary-indep binary-arch .PHONY: build clean binary-indep binary-arch binary install configure baresip-1.0.0/debian/source/000077500000000000000000000000001372575704200156735ustar00rootroot00000000000000baresip-1.0.0/debian/source/format000066400000000000000000000000041372575704200171000ustar00rootroot000000000000001.0 baresip-1.0.0/docs/000077500000000000000000000000001372575704200141015ustar00rootroot00000000000000baresip-1.0.0/docs/CONTRIBUTING.md000066400000000000000000000011741372575704200163350ustar00rootroot00000000000000## Contributions are welcome to the Baresip project The preferred way to contribute is via a Pull Request (PR). * The PR should be small and logical and solve a concrete problem. If your code is very large then please split it into smaller PRs. * The code must be tested on your platform. If the code involves SIP signaling or interop, it should also be tested against 3rd party SIP endpoints. * The code must compile with zero warnings * The code must pass "make ccheck" * Doxygen comments is nice to add, but it is not mandatory ## How to add new modules * https://github.com/baresip/baresip/wiki/How-to-add-new-modules baresip-1.0.0/docs/COPYING000066400000000000000000000030031372575704200151300ustar00rootroot00000000000000Copyright (c) 2010 - 2020, Alfred E. Heggestad Copyright (c) 2010 - 2020, Richard Aas Copyright (c) 2010 - 2020, Creytiv.com All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. baresip-1.0.0/docs/ChangeLog000066400000000000000000002517571372575704200156740ustar00rootroot000000000000002019-12-01 Alfred E. Heggestad * Version 0.6.5 Alfred E. Heggestad (138): mnat: add struct mnat pointer to session handler ice: add ice-lite, move to per-account config modules: check return value from uag_event_register() menu: check return value of account_set_answermode ua: move ua_print_sip_status to debug_cmd module pcp: updated mnat api modules: rename gst1.so to gst.so account: make answermode code more robust bfcp: remove code ua: remove uag_tls() sdl: add support for YUYV422 pixel format modules: rename gst_video1.so to gst_video.so sdl: add support for UYVY422 pixel format ua: fix whitespace test: mock_mnat_register return void stream: debug tuning test: enable wait_connected flag on mock mnat dtls_srtp: dont store remote address on the state test: enable wait_secure flag on mock mediaenc modules: rename sdl2.so to sdl.so menc: sort handlers in logical order audiounit: use error ENOTSUP if AudioSessionSetActive fails test: add webrtc test-case audiounit: check return value of AudioUnitSetProperty() bv32: remove module (#793) audiounit: fix samplerate for iOS config: add snd_path to template account: remove check for deprecated password audio: use dynamically allocated string for device name Update README.md avcodec: remove unused prototype avcodec: fix unused parameter warning move h265.so into avcodec.so Update .travis.yml (#798) Account specific audio source and playback (#796) mpa: switch encoder to use lame (#797) mk: remove GPROF ua: add support for SIP trace (#804) AAC codec (#805) audio: set the correct variable to false if pthread_create() fails sdl: properly close window (OSX) ua: fix warning rtcpsummary: use call object from event handler test: move aucodec list one level up video: add vidcodec accessor refactoring; move rtp stats code to separate .c file rtpstat cleanup call: check magic vidinfo: add video overlay box with decoder info vidinfo: fix compiler warning on linux vidinfo: fix compiler warning on Android stream: rename to stream_set_session_handlers() Fix osx build (#809) vidinfo: delete old file test: move ausrc list one level up test: move auplay list one level up test: move aufilt list one level up video: use vidcodec's list in video_decoder_set() stream: add stream-list to stream/audio/video API vidinfo: remove pixelformat, add packetloss mk: add detection in SYSROOT_LOCAL dtls_srtp: add media name and component type to logline mnat: make mnat_find() public audio: print name in parenthesis if not set video: move vidfilt list one level up audio: remove hack for starting source/player first video: set stream samplerate in alloc video: fix potential use of free'd string ice: fix documentation g711: use designated initialisers g722: use designated initialisers g726: use designated initialisers ilbc: use designated initialisers mk: check for ilbc in gsm: use designated initialisers amr: fix detection in SYSROOT_LOCAL amr: use designated initialisers isac: use designated initialisers test: add audio_codecs to account testcase win32: sort module exports in alphabetical order win32: add debug_cmd to static list of modules echo: no need to use uag_current() -- ref #815 mk: detect aac in SYSROOT_LOCAL modules: use designated initializers modules: use designated initializers v4l2_codec: use designated initializers wincons: use designated initializers gzrtp: use designated initializers avcodec: use designated initializers video: request keyframe during packet-loss mk: detect mqtt.so in SYSROOT_LOCAL menu: fix formatting menu: clean up usage of uag_current() -- ref #815 menu: save UA aor for redialing avcodec: use AVFrame key_frame flag to check for keyframes (#830) call: add call_find_id() -- ref #815 menu: new command /callfind -- ref #815 ice: make username/password optional mqtt: add ua/call selection -- fixes #815 stream: no RTCP socket for mediaenc, if muxed mqtt: encode response with JSON -- fix #826 main: change help text for -4 and -6 (ref #834) docs: thanks to @premultiply net: change prefer_ipv6 to int af, fixes #834 pulse: fix log text avformat: fix build on Debian 8 stream: log more details stream: make stream_start_mediaenc() public for core stream: move start_mediaenc to call.c audio: add ptime to struct aucodec (#849) README: add i2s module docs: thanks to Christian Spielberger test: remove unused setting of int err stream: remove code not executed message: no need to check err net: fix potential deref of NULL pointer vidinfo: no need to check err natpmp: no need to check err ilbc: no need to check err ctrl_tcp: no need to check oe_cmd here avformat: remove got_pict hack avcodec: minor fixes sdl: remove int err, not needed pulse: check the correct pointer v4l2_codec: remove int err, not needed alsa: store return value in a long avcodec: copy key_frame flag from hardware frame stream: make some functions public ctrl_tcp: restore mbuf pos on errors metric: add lock for multi-threading sdl: skip plane if wstep is zero aubridge: clear pointers after thread has exited fix doxygen comments av1: set allow_lowbitdepth to get correct pixel-format bump version to 0.6.5 stream: check return value of metric_init() stream: update doxygen comments update doxygen comments Christian Spielberger (2): aui2s: add rtos i2s audio driver module (#848) i2s: add doxygen defgroup header (#850) Juha Heinanen (3): - Added 'net_set_address' and 'net_set_af' API functions. Added safety check to net_set_address() API function. - Added AF_UNSPEC to supported net_set_af families. juha-h (4): - Exposed net_dns_debug function to API. (#791) Added possibility to include ";extra" parameter to an account and access (#803) - Search include files also from opencore-amr source directory (#822) Merge pull request #843 from alfredh/net_stuff premultiply (5): Unify response list header layout (#821) More common list format (#823) MPA fmtp mirroring (#837) MPA layer 3 encoding fixes (#839) MPA L2 and L3 encoding (#844) trampster (2): Pass NULL to pa_simple_new if no device specified to indicate to PulseAudio we want to use the default (#785) Add support for aes_256_gcm (#790) 2019-09-01 Alfred E. Heggestad * Version 0.6.4 Aleksei (1): Update MSVS project (Remove mos.c) (#744) Alfred E. Heggestad (77): test: added testcase for RTCP speex_pp: handle changes in frame_size mos: remove code (unused) (#739) speex_aec: deprecate and remove module (#740) aufilt: remove ptime parameter audio: add last sample count audio: remove recv ptime and pt from debug stream: common function for start mediaenc stream: added set/is_secure test: sort tests in alphabetical order test: added mock aufilt and testcase mnat: add media connected handler ice: use connected handler stream: add mnat_connected_handler call: split call start into audio/video stream: print mnat_connected dtls_srtp: remove 100ms timer stream: add stream_start() call: split update_media into audio/video srtp: use designated initializers to init struct menc zrtp: use designated initializers to init struct menc dtls_srtp: use designated initializers to init struct menc mnat: add wait_connected flag (#752) menc: add wait_secure flag (#754) opus: add opus_packet_loss config audio: fix rtp timestamps for opus mono (ref #753) webrtc interop (#756) avcodec: remove compile time check (LIBAVUTIL_VERSION_INT) avcodec: minor cleanup avcodec: define KEYFRAME_INTERVAL travis: use ubuntu xenial (#764) remove PIX_FMT wrapper for old ffmpeg stream: add lost count to RTP handler aucodec: add buffer to packet-loss handler add support for Opus FEC (WIP) (#755) test: explicitly set BEHAVIOUR_ANSWER test: set default action to ACTION_RECANCEL x11: remove support for 16-bit RGB colors sdl2: use vidisp name 'sdl' stream: reorder functions ice: check argument avcodec: remove decoder framerate stream: add media name to debug test: remove testcase for C++ avcodec: remove log-line avcodec: remove old ffmpeg wrapper for AVCodecID test: add media-line to mnat mock vidsrc: add wanted pixel format to parameters stream: add handler for mnat connected vp9: decode V and P fields opus: update docs (ref #768) test: use pixel format from api test: use pixel format YUV420P fix warning on linux video: fix warning test: fix warnings dtmfio: fix warning opus_multistream: fix warnings Avcodec hwaccel (#770) fakevideo: use pixel format from parameters sdl2: add support for pixel format NV21 bump version to 0.6.4 mk: update Doxyfile gst1: remove hard-coded uri config: update default config config: use cloudflare as sample DNS servers config: print default hwaccel for avcodec.so module dtls_srtp: make it more robust test: use LD to link selftest avformat: remove check for avformat >= 53.4.0 video: remove video_view avformat: better logging config: add mqtt template (ref #780) Update README.md docs: refresh example config config: remove openl.so from template README: fix typo Timmo Verlaan (1): menu: sndcode should signal release of key (#749) seamus (1): menu: add answermode command (#779) trampster (1): Allow CALL_CLOSED to be raised when call_id is not set. (#748) 2019-06-22 Alfred E. Heggestad * Version 0.6.3 Alfred E. Heggestad (99): baresip: remove prefer_ipv6 from api, use config instead ua: remove prefer_ipv6 from api, use config instead audio: allocate mbuf for encoded telephony events net: remove af from api, use config instead gst: remove old module, use gst1 instead gst_video: remove old module, use gst_video1 instead gst1: update comment httpd: update comment call: remove unused constant reg: print address family of registration ua: clean up prefer_ipv6 code test: disable test for AUDIO_MODE_THREAD config: remove old check for rtcp_enable config: remove unused macro SA_INIT config: remove unused MOD_PRE test: mock aucodec support all sample formats audio: check that ptime is within the range of 1-60ms audio: dont check sample format for packetloss handler audio: use audio codec srate directly, remove get_srate wrapper audio: remove get_framesize audio: handle rtcp sample-rate for asymmetric codecs audio: remove get_ch() mpa: return posix error code instead of -1 mk: sort list of files in alphabetical order menu: sort and align incall commands table ua: check input argument to ua_print_supported test: check error from test fixture ua: use a print handler to print allowed methods ua: use a single tick instead of backtick for logging audio: mirror ptime attribute if changed by peer (ref #688) (#700) audio: receive ptime is always set plc: count samples from audio input use sizeof(x) instead of sizeof x account: fix typo timestamp: add timestamp_calc_seconds() call: remove const from menc_event_handler call: swap order of menc event and error handler mnat: make struct mnat public mnat: change to a simpler register api menc: protocol is always UDP mnat: change api to always use UDP protocol stream: add remote RTP/RTCP address to object menc: add remote RTP/RTCP address to API dtls_srtp: use remote address from mediaenc API dtls_srtp: remove dtls_print_sha1_fingerprint remove audio/video codec cycle net: add network_if_getname() sdp: remove sdp_media_format_cycle (unused) sdp: remove sdp_rattr() -- unused pcp: updated MNAT api gzrtp: updated menc api (ref #713) dtls_srtp: fix warning zrtp: fix warnings net: use network_if_getname to get interface name stream: use enum media_type instead of a string call: only include aucodec codecs in remote sdp (ref #718) call: simplify audio encoder/decodet set stream: add pointer to medianat module webrtc_aec: add warning ua: use KEYCODE_REL in dtmf handler (ref #719) call: add prefix to logline webrtc_aec: add sample format converter to decoder (ref #712) webrtc_aec: add sample format converter to encoder (ref #712) webrtc_aec: add enc/dec to log line webrtc_aec: fix enum warning webrtc_aec: echo_cancellation.h is included in aec.h (ref #712) config: add sip_cafile to template net: add a function to print IP-addr and interface net: dont init local address to 127.0.0.1 audio: handle marker bit in stream.c (#724) avcodec: make sure ffmpeg input buffer has AV_INPUT_BUFFER_PADDING_SIZE space at the end stream: update doxygen comments stream: only flush jitter-buffer if it was started avcodec: fallback define for AV_INPUT_BUFFER_PADDING_SIZE stream: add pseq_set flag stream: dont calculate loss if no jitter buffer webrtc_aec: add support for 32000Hz samplerate net: multiple nameservers in net_use_nameserver() webrtc_aec: add reference to webrtc native dtmfio: use UA_EVENT_CALL_DTMF_START to handle dtmf events test: use event handler to receive DTMF events webrtc_aec: remove samplerate check prepare for 0.6.3 release gst_video1: cleanup stream: print mediaenc id config: add net prefix to prefer_ipv6 codec2: print mode codec2: modern init of struct aucodec codec2: add config param codec2_mode codec2: round up bytes per frame win32: add httpd module to static.c codec2: update description mk: add detection of codec2.so module video: check if frame pointer is valid contact: set err properly audio: no need to clear err, it is not used config: add opus_samplerate to template travis: add building of codec2 on OSX (#736) config: add webrtc_aec to template Christian Spielberger (2): call: reset streams on call hold (#707) Bugfix/flush buffers on call hold (#716) Dmitry (2): opus: fixed opus_inbandfec param name in config and examples (#704) menu: set default values for optional config params (#705) Juha Heinanen (1): webrtc_aec: enable delay-agnostic echo cancellation Nicolas Tizon (1): audio: increase buffer size for audio device string (#710) juha-h (5): - added prefer_ipv6 config variable (#692) webrtc_aec module: added pthread.h include to .cpp files (#714) - Updated ilbc module encode/decode/pkloss function arguments (#723) - Use opus in mono mode (opus/48000/1) if opus_stereo or (#730) - Added opus_samplerate config parameter. (#733) premultiply (1): Interop: Parameters reordering and whitespace removal (#698) weili-jiang (1): Count ua references prior to destroy in case UA_EVENT_SHUTDOWN causes references to be removed (#702) 2019-04-19 Alfred E. Heggestad * Version 0.6.2 Alfred E. Heggestad (124): daala: remove module remove USE_VIDEO compile flag (#658) config: remove sip_trans_bsize option contact: fix bug in contact prev/next cmd: remove unused complete flag log: add command to toggle loglevel ('v') debug_cmd: fix warning Remove natbd module (#659) message: make listen/unlisten more robust (ref #650) update doxygen comments srtp: fix warnings update README stream: define port 9 as PORT_DISCARD add offerer flag to video and stream stream: check for multiplexed RTCP packets on RTP port stream: change logic for rtcp-mux attribute omx: update doxygen comment bv32: add doxygen header mk: modules in alphabetical order mk: modules in alphabetical order mk: modules in alphabetical order h265: use avcodec API for the encoder h265: fixes for Debian 8 h265: make it work with old encoder api h265: init time_base manually fix av_packet_free allocate avpacket h265: cleanup cleanup cleanup h265: add configurable decoder cleanup use pkg-config for libs h265: update documentation mk: enable h265.so if avcodec installed h265: include avutil mem.h travis: use ubuntu 16.04 h265: add wrapper for av_frame_alloc h265: add wrapper for avcodec_free_context h265: fix config fix crash with ffmpeg 2.8 add wrapper for av_packet_free fix warning use av_free_packet cleanup deprecate v4l.so -- use v4l2.so instead h265: tested with YUV444P pixel format h265: check pixel format on changes Merge remote-tracking branch 'origin/master' into h265_use_avcodec_encoder h265: fix avcodec_free_context wrapper H265 use avcodec encoder (#668) debian: add source format 1.0 aufile: add sample config (ref #663) v4l: remove module, use v4l2.so instead video: remote orient parameter video: remove video_set_orient aubridge: remove audio resampler aubridge: fix warning aubridge: add support for multiple sample formats aubridge: fix warnings auloop: remove usage of audio codec jack: add support for FLOAT sample format Avcodec remove libx264 (#671) config: add avcodec.so sample config stream: set rtcp-mux attribute if enabled sdl: remove module stream: send a dummy RTCP packet to open NAT pinhole avcodec: use pkg-config for linker flags avformat: use pkg-config for linker flags config: remove usage of USE_AVCODEC coreaudio: remove ios specific code h265: one file per line avformat: move AVCodec from struct to stack avformat: remove codec_id check avformat: minor cleanup debian: remove usage of shlibs:Depends from dev package debug_cmd: fix warning avformat: minor cleanup avformat: minor cleanup vidloop: rename intra to keyframe vidloop: print keyframes only if codec is enabled avcodec: move destructor to the top of the file plc: check input arguments auloop: rename ab to aubuf Opus multistream (#678) mqtt: minor updates mqtt: use re_snprintf mqtt: update documentation (fixes #669) h264: fix h264_is_keyframe, IDR_SLICE is keyframe avcodec: check input arguments vidloop: show video display pixel-format in summary avcodec: clean up decoding code avcodec: add color range MPEG h265: add color range and GOP size ffmpeg: check avutil version for color range avcodec: set slice-max-size in H264 packetization-mode 0 avcodec: add sdp.c avcodec: move h264_fmtp_cmp to sdp.c avcodec: add support for H264 packetization mode 1 av1: update comment avcodec: handle H264 STAP-A packets test: fix ua register test-cases (ref #680) ua: add delayed_close flag (ref #680) menu: call uag_current() directly video: save pixel format of outgoing stream aulevel: add support for sample format FLOAT Vidfilt add param (#682) test: copy uri_cmp source from libre sdl2: handle window closed event (SDL_QUIT) vidloop: stop loop if window was closed sdl2: add support for quit key avcodec: fixes for packetization_mode 1 bump version to 0.6.2 vidfilt: update doxygen comments rtcpsummary: fix warnings about unused variables mqtt: fix warnings about unused variables gst_video1: use GST_BUFFER_PTS mk: add echo module to list of basic modules core: remove some unused values menu: call parameter is used mwi: minor formatting changes audio: align debug text Update README.md ua: add ua_destroy() -- ref #686 Andreas Hansson (1): Added debug cmd to print UUID (#674) Juha Heinanen (2): do not add basic modules if BASIC_MODULES has value 'no' exclude more modules if BASIC_MODULES=no Nicolas Tizon (1): vidloop: update vidsrc (#662) Roger Sandholm (1): Readme and config example correction, httpd comments (#666) Timmo Verlaan (1): menu: add uadel to delete a uac by aor (#680) juha-h (1): srtp: added sending of MENC_EVENT_SECURE event (#660) premultiply (1): Add 48 khz sampling rate support (#685) weili-jiang (1): Command not found returns error (#664) 2019-02-17 Alfred E. Heggestad * Version 0.6.1 Aleksei (2): Update MSVS project (#655) Fix warnings at windows compilation (#656) Alfred E. Heggestad (111): call: prm parameter is mandatory core: add address-family to stream_param (ref #583) core: add cname to stream_param (ref #583) realtime: remove code contact: add support for current contact (#573) play: update doxygen comments mk: add detection of OpenGL framework (ref #575) stream: make call optional (closes #583) net: update doxygen comments contact: update doxygen comments Module app unload (#589) mk: disable opengl module in default build opengles: updated vidisp api avcapture: fix build for ios (ref #593) module: update doxygen comments ua: add missing doxygen comments ua_set_custom_hdrs: add error checking ua: add doxygen comments ua: fix formatting and update doxygen ua: update doxygen comments call: update doxygen comments message: update doxygen comments custom_hdrs: add doxygen comments stream: update doxygen comments video: rename intra to key-frames sip: add doxygen comments event: add doxygen comments mediadev: minor code formatting mediadev: add doxygen comments audiounit: rename comp to 'audiounit_comp' audiounit: check input parameters coreaudio: remove blocking sleep (#605) audio: change logline to debug (ref #609) auloop: show read/write counters in stream duration (seconds) audiounit: print name of audio component used audiounit: move aufmt_to_formatflags to audiounit.c rpm: remove support for in-tree RPM building account: init mnat, fix warning on mingw32 mk: make sure omx.so is only added once (fixes #612) silk: remove codec (#611) aubridge: use sizeof sample format instead of 2 coreaudio: clarify that coreaudio module is for macOS audio: cleanup comment pcp: clean up comment audiounit: check for valid sample size audiounit: clarify usage of inputBus and outputBus add accessor to ausrc/auplay base-class auloop: add summary vidloop: rename variable mk: detect CoreAudio framework webrtc aec (#617) audiounit: clean up enable/disable auloop: print sample format audiounit: clarify usage of inputBus and outputBus dtls_srtp: remove support for SHA-1 fingerprint dtls_srtp: remove unused DTLS-SRTP methods menc: move and document event type menc: added menc_event_name() remove obsolete compile flag MODULE_CONF stream: move handlers to end of struct test: check magic in audio sample handler test: added testcase for call with mock medianat dshow: remove a comment call: using str_isset() is faster than strlen() config: remove 'rtcp_enable', always enabled (#623) stream: remove rtcp flag update comments Update README.md README: added rtcpsummary module aubridge: add module prefix to global symbols update copyright year to 2019 audiounit: fix warnings on ios stream: make stream_sdpmedia public stream: make stream_update public audio: make audio_{encoder,decoder}_set public stream: make struct stream_param public audio: use samplesize to calculate packet size audio: use sizeof int16_t instead of 2 stream: update doxygen comments audio: update doxygen comments video: update comment jack: allocate array of ports from channels (ref #625) jack: update comment audiounit: check memory allocation main: fix bug with reading of -u parameter value audio: split up definition of AUDIO_SAMPSZ gtk: minor formatting improvements gtk: check duration_timer_tag (ref #630) audio: make audio_alloc() public avformat: print decoder name (ref #639) menu: change some commands from CMD_IPRM to CMD_PRM avformat: add pixel format mapping function avcodec: add pixel format mapping function avcodec: add pixel format mapping function for encoder menu: use CMD_PRM for call transfer contact: add flag to enable presence (fixes #645) cmd: remove support for progress/interactive commands menu: fix warning config: update comment coreaudio: add support for multiple sample formats, including FLOAT menu: no need to use command's complete flag jack: allocate buffer before start (ref #647) auloop: print newline at the end Update .travis.yml (#652) Update .travis.yml (#653) fix some warnings reported by @Encamy dshow: fix warning on win32 update doxygen comments bump version to 0.6.1 config: refresh config template audiounit: fix warning on ios José Luis Millán (2): ctrl_tcp: increase command buffer size (#585) vumeter: configuration option to disable vumeter output to stderr (#608) Juha Heinanen (4): new account functions fixed typo added audio_codec api function added @return description Nicolas Tizon (4): sdl2: make window resizable (#587) coreaudio: mediadev support (#600) avcodec: force intra (H.263, H.264) frame request if no key frame received (#614) audiounit: add AUConverter resampler (recorder) (#624) Olle E. Johansson (1): Improve mqtt module (#642) Timmo Verlaan (2): menu: add uafind to select ua by aor (#626) menu: create_ua doesn't use dialbuf (#627) juha-h (5): Merge pull request #588 from alfredh/new_account_functions Merge pull request #598 from alfredh/audio_codec added account_set_answermode api function (#619) opengles android ndk r18 update (#629) do not accept incoming calls without srtp if account has mandatory srtp (#651) 2018-12-01 Alfred E. Heggestad * Version 0.6.0 * GIT URL: https://github.com/alfredh/baresip.git * GIT tag: v0.6.0 * NOTE: Requires libre v0.6.0 or later Requires librem v0.6.0 or later * config: opus_complexity {0-10} # Encoder's computational complexity opus_application {audio, voip} # Encoder's intended application sip_cafile ca.crt # trusted Certificate Authorities * baresip-core: - account: added support for per account mwi using ;mwi=on|off addr-param (#530) (thanks Juha Heinanen) per account support for call transfer (#535) (thanks Juha Heinanen) - audio: add audio_start() add audio_started() EBU/ACIP invite handler. flush aubuf when resetting codec - call: make call_connect() public make call_notify_sipfrag() public - contacts: make struct contacts opaque add contact_uri() - rtpkeep: code removed - sdp: remove unused functions - ua: add sip_cafile config option (thanks to @wnetbal for the original patch) add event UA_EVENT_MWI_NOTIFY (thanks Juha Heinanen) add event UA_EVENT_CALL_TRANSFER add event UA_EVENT_AUDIO_ERROR add ua_uri_complete() - vidfilt: add timestamp parameter to filter API - vidisp: add timestamp parameter to display API - video: add RTP timestamp state for receive * selftest: - test: add call transfer test (ref #538) - test: add call via tcp test * Modules: * avcapture: fix video resolutions mismatches (#580) (Nicolas Tizon) * avcodec: remove support for old versions of ffmpeg detect MPEG4 key-frames * avformat: remove support for old versions of ffmpeg * ctrl_tcp: Fix netstring frame handling (#569) (José Luis Millán) * debug_cmd: /play will always stop current file playing. (#578) (thanks Ola Palm) * directfb: updated vidisp api (#568) (thanks andreygursky) * dshow: mediadev support (#550) (Nicolas Tizon) * echo: add support for video * h265: change rate control to ABR (Average Bitrate) (#526) * mwi: moved printing of mwi info from mwi module to menu module (thanks Juha Heinanen) * opengl: properly handle linesize (#566) * opus: add configuration parameter 'opus_complexity' add configuration parameter 'opus_application' (thanks José Luis Millán) * libsrtp: module removed * v4l2_codec: use thread instead of fd event (#558) * winwave: add support for FLOAT sample format (#559) mediadev support (#556) (Nicolas Tizon) 2018-09-15 Alfred E. Heggestad * Version 0.5.11 * GIT URL: https://github.com/alfredh/baresip.git * GIT tag: v0.5.11 * NOTE: Requires libre v0.5.7 or later Requires librem v0.5.3 or later * build: * baresip-core: - account: disable password in the SIP uri - aucodec: add packet channels (pch) to struct (#489) - audio: add MAGIC_CHECK to some callback handlers - audio: fix timestamp for MPA codec - audio: remove audio_srate and audio_channels (#488) - audio: remove exception for MPA - aufilt: add sample format parameter (#492) - auplay/ausrc: Add dev_list to auplay and ausrc struct (#516) (thanks Nicolas Tizon) - call: dump SDP offer, ref #480 - call: Support also SIP URI with missing display name. (#512) (thanks Christian Spielberger) - config: update template for coreaudio - contact: consider empty contacts file as existing contacts file (#501) (thanks Juha Heinanen) - main: add -n option for network interface - main: turn off buffering to standard output (#504) (thanks Geoff Stewart) - opus: refresh config template - stream: add magic number for debugging (ref #514) - ua: do ua_register explicitly (refs #508) (#509) - ua: added ua param to message handler (#485) (thanks Juha Heinanen) - ua: Sending and receiving custom headers (#470) (thanks Encamy) - video: added more MAGIC_CHECK checks - vidsrc: Vidsrc devices list (#491) (thanks Nicolas Tizon) * selftest: - test: use event-handler in mediaenc mock - test: add sip uri with angle brackets (ref #512) * Modules: * alsa: remove check for alsa_sample_format config * alsa: On termination of alsa_play wait until buffer was processed. (#520) (thanks Christian Spielberger) * aubridge: check to make sure the device is running before dereferencing it. (#495) (thanks Geoff Stewart) * avahi: fix warning when RELEASE=1 * avcapture: use mediadev API to add device names * coreaudio: Coreaudio select device (#502) * daala: update vidcodec API * gtk: update message handler with struct ua pointer * httpd: add CORS header in http reply (#517) (thanks Nicolas Tizon) * menu: Send DTMF code command (#496) (thanks Nicolas Tizon) * rtcpsummary: new RTCP summary module (#505) (thanks Geoff Stewart) * speex: remove module (#494) * srtp: add support for AES-GCM cipher * vidloop: use portable lock instead of pthread mutex fix crash when resolution changes * vidloop: Vidloop fix: video frame rendering is moved to main thread (#481) (thanks Nicolas Tizon) * x11: check for shared memory extension * x11grab: remove old linker path 2018-07-04 Alfred E. Heggestad * Version 0.5.10 * GIT URL: https://github.com/alfredh/baresip.git * GIT tag: v0.5.10 * NOTE: Requires libre v0.5.7 or later Requires librem v0.5.3 or later * build: - Updated MSVS project (thanks Encamy) * baresip-core: - account: add more accessor functions (thanks Juha Heinanen) - audio: add audio_set_hold - aufilt: add struct audio parameter - mediaenc: add menc_event handler (thanks Juha Heinanen) - net: add support for IP-address in 'net_interface' (thanks @Encamy) - stream: add stream_call - stream: check SDP_SENDONLY flag - stream: correct flags in stream_send (thanks Andreas Hansson) - stream: set RTP socket buffersize to 65536 (ref #415) - ua: add events for VU level (thanks Ola Palm) - ua: add ua_update_account - ua: don't append domain if uri is IP address (thanks Ali Shirvani) - ui: add ui_input_long_command - videnc: add timestamp parameter - video: add video_calc_rtp_timestamp_fix - video: lock when setting encoder (ref #418) (#441) * Modules: * aufile: add slow cpu detection * auloop: add samplerate and channels argument to command * av1: add timestamp parameter to encode function * avcodec: add timestamp parameter to encode function set baseline profile on ffmpeg H.264 encoder remove checks for old versions of libx264 * dshow: fix build for VC and mingw (thanks @Encamy) add picture vertical flipping (thanks Nicolas Tizon) * dtls_srtp: add usage of medienc event handler * gst_video: add timestamp parameter to encode function * gst_video1: add timestamp parameter to encode function * h265: add timestamp parameter to encode function * httpd: no echoing of long commands * menu: add video switch command /vidsrc (thanks Ali Shirvani) * opensles: check state before calling Destroy * sdl2: print renderer info * vidloop: refactoring of timestamp routines * vp8: add timestamp parameter to encode function * vp9: add timestamp parameter to encode function * vumeter: add periodic events (thanks Ola Palm) * zrtp: add usage of medienc event handler (thanks Juha Heinanen) 2018-04-21 Alfred E. Heggestad * Version 0.5.9 * GIT URL: https://github.com/alfredh/baresip.git * GIT tag: v0.5.9 * NOTE: Requires libre v0.5.7 or later Requires librem v0.5.2 or later * build: - Updated MSVS project to VS15 and added several files to project settings (thanks Encamy) * config: video_fps 29.97 # float * baresip-core: - conf: add conf_get_float - timer: add tmr_jiffies_usec - timestamp: new file for timestamp helpers - ua: add catchall flag to struct ua - ua: add ua_set_catchall - ua: uag_find: return match if catchall flag is set - vidcodec: change rtp_ts from 32-bit to 64-bit - videnc: change framerate to double float - video: change framerate to double float - vidsrc: add frame timestamp - vidsrc: change framerate to double float * selftest: - mediaenc: add testcase for media encryption * Modules: * avcapture: add support for video frame timestamp * avcodec: fix compiling with old ffmpeg versions print framerate of decoded bitstream * avformat: add support for video frame timestamp * b2bua: add handling of all inbound SIP requests * cairo: add support for video frame timestamp * ctrl_tcp: Fix #369. documentation typo (#372) Fix #370. wrong assignent (#371) (thanks José Luis Millán) * dshow: add support for video frame timestamp * fakevideo: add support for video frame timestamp add support for timer polling (no pthreads) * menu: added "statmode_default" config variable (#359) (thanks Juha Heinanen) * rst: add support for video frame timestamp * swscale: add YUV444P pixel format * v4l: add support for video frame timestamp * v4l2: add support for video frame timestamp show actual framerate * vidbridge: add support for video frame timestamp * vidloop: add videoloop summary * x11grab: add support for video frame timestamp 2018-02-11 Alfred E. Heggestad * Version 0.5.8 * GIT URL: https://github.com/alfredh/baresip.git * GIT tag: v0.5.8 * NOTE: Requires libre v0.5.7 or later Requires librem v0.5.2 or later * new commands: - /aubitrate 64000 -- Set audio bitrate * new modules: - ctrl_tcp TCP control interface using JSON payload (thanks José Luis Millán) * config: auenc_format s16 # s16, float, .. audec_format s16 # s16, float, .. videnc_format yuv420p # yuv420p, yuv444p, .. * baresip-core: - account: password in SIP uri is now deprecated - aucodec: add encoder/decoder audio sample format (#352) - aucodec: add bitrate to encoder param - audio: add function to set encoder bitrate - audio: sample format for audio encoder/decoder - call: add call_id accessor - call: fix memory leak in case sipsess_connect() fails - config: add configurable video pixel format - config: set exact installation pathes at build time (#354) (thanks Guillaume Rousse) - event: fix memory leak - event: add call-id to JSON dict - log: rename log_enable_stderr to log_enable_stdout - metric: fix calculation of average bitrate - reg: add display-name to SIP register - stream: print a message when incoming RTP stream is established - timer: add tmr_jiffies_usec - video: save and show pixel format of incoming video - vidutil: new file for video utility functions * selftest: - event: add testcase for events - sip: make 'struct user' opaque - ua: update password using ;auth_pass=XXX parameter * Modules: * account: update template with auth_pass parameter * amr: update aucodec API with audio sample format * avcodec: Return EPROTO when encountering missing fragments in H264 stream, to trigger intra-frame request (#339) (thanks Jonathan Sieber) use AV_INPUT_BUFFER_MIN_SIZE (ref #351) add support for YUV444P pixel format * avformat: use av_dump_format() * bv32: update aucodec API with audio sample format * codec2: update aucodec API with audio sample format * ctrl_tcp: new module for TCP control interface using JSON payload (thanks José Luis Millán) * g711: update aucodec API with audio sample format * g722: update aucodec API with audio sample format * g7221: update aucodec API with audio sample format * g726: update aucodec API with audio sample format * gsm: update aucodec API with audio sample format * gst1: define _POSIX_C_SOURCE to make nanosleep visible * l16: update aucodec API with audio sample format * mpa: update aucodec API with audio sample format * mqtt: update README with correct JSON syntax (ref #356) * omx: fix compilation for Raspbian * opus: update aucodec API with audio sample format add support for FLOAT sample format * silk: update aucodec API with audio sample format * speex: deprecate, disable as autodetected module * speex_aec: always link to libspeexdsp * speex_pp: always link to libspeexdsp 2017-12-25 Alfred E. Heggestad * Version 0.5.7 * GIT URL: https://github.com/alfredh/baresip.git * GIT tag: v0.5.7 * NOTE: Requires libre v0.5.5 or later Requires librem v0.5.0 or later * Credits: Thanks to Swedish Radio who sponsored many new features in this release. * new commands: - 'conf_reload' -- Reload config file * new modules: - gzrtp ZRTP module using GNU ZRTP C++ library (thanks glenvt18) - mqtt MQTT (Message Queue Telemetry Transport) module (sponsored by Swedish Radio) * config: - audio_txmode poll|thread Set audio transmit mode - auplay_format s16|float|s24_3le Set playback sample format - ausrc_format s16|float|s24_3le Set source sample format - sdp_ebuacip yes|no Enable EBU-ACIP parameters - zrtp_hash yes|no Enable/disable ZRTP hash * baresip-core: - audio: add sample format conversion - audio: add sample format for source/playback - audio: check timestamps on incoming RTP packets - audio: pace outgoing packets in txmode=thread - audio: remove txmode with realtime thread - audio: remove txmode with timer - audio: set EBUACIP parameters in SDP - auplay: add sample format to auplay_prm - auplay: change write handler to any sample format - ausrc: add sample format to ausrc_prm - ausrc: change read handler to any sample format - event.c: new file for generic event handling - event: add event_encode_dict to encode event to a dictionary - event: added UA_EVENT_CALL_RTCP for received RTCP - log: print to stdout (ref #320) * selftest: - add test for different audio tx-modes - add test for float audio sample format * Modules: * alsa: add support for multiple sample formats * audiounit: add support for FLOAT sample format * auloop: add support for multiple sample formats * avahi: Bugfix: Destroy resolver after callback (#318) (thanks Jonathan Sieber) * avcodec: change x264 rate control mode to ABR (#334) (thanks Jonathan Sieber) * debug_cmd: add command 'conf_reload' to reload config file * gzrtp: ZRTP module using GNU ZRTP C++ library (thanks glenvt18) * menu: add config 'ringback_disabled' to disable playing of ringback tone. * mqtt: MQTT (Message Queue Telemetry Transport) module new module using libmosquitto as the backend. * opus: fix encoder bitrate, ref #305 add opus_stereo config parameter (thanks Ola Palm) add config param opus_sprop_stereo (thanks Ola Palm) * portaudio: add support for FLOAT sample format * pulse: add support for FLOAT sample format remove garbage at the beginning of a recording (#323) * quicktime: module was removed * rst: add support for multiple sample formats * zrtp: add signaling hash support (#311) 2017-10-14 Alfred E. Heggestad * Version 0.5.6 * GIT URL: https://github.com/alfredh/baresip.git * GIT tag: v0.5.6 * NOTE: Requires libre v0.5.5 or later Requires librem v0.5.0 or later * New Baresip logo (thanks Ernst and community) * baresip-core: - log: rename error to error_msg due to GNU extension clash - ua: remove ua_sipfd() * Modules: * avahi: Avahi Zeroconf Module (thanks Jonathan Sieber) * avcodec: handle fragment packet loss * cairo: draw a dancing logo * ice: set ICE role correctly set retransmit count (RC) to 4 * opensles: fix recorder speaker setup (thanks Juha Heinanen) * opus: fix encoder bitrate, ref #305 * zrtp: encrypt/decrypt RTCP packets (thanks @glenvt18) 2017-09-07 Alfred E. Heggestad * Version 0.5.5 * GIT URL: https://github.com/alfredh/baresip.git * GIT tag: v0.5.5 * NOTE: Requires libre v0.5.5 or later Requires librem v0.5.0 or later * new commands: - insmod module.so -- Load a module - rmmod module.so -- Unload a module * config: - fullscreen yes|no Enable fullscreen display * baresip-core: - account: optional param 'auth_pass' for password add account_set_auth_pass() add account_aor() add account_auth_pass() - contact: add update handler (thanks Jonathan Sieber) - h264: add rtp_ts RTP Timestamp - module: add module_load/unload remove list of application modules - stream: reset timer on incoming RTCP packets (fixes #271) - ui: make the API re-entrant - video: add RTP timestamp to videnc packet handler add video_calc_rtp_timestamp() add video_calc_seconds() - video: use RTP timestamp from video encoder * selftest: - add test for video timestamps * Modules: * account: move password prompt here * av1: use encoder PTS to calculate RTP timestamp * avcodec: use encoder PTS to calculate RTP timestamp use level_idc=0x1f for x264 * cons: updated UI api * evdev: updated UI api * gst_video: use encoder PTS to calculate RTP timestamp * gst_video1: use encoder PTS to calculate RTP timestamp * h265: use encoder PTS to calculate RTP timestamp fix FU decoder bug * httpd: updated UI api * ice: move gathering from lib to app (requires libre v0.5.5 or later) * menu: updated UI api * mwi: updated UI api * presence: Handle contacts added at run-time (thanks Jonathan Sieber) * sdl: updated UI api * sdl2: add support for fullscreen video * stdio: updated UI api * v4l: add support for more pixel-formats * v4l2_codec: use encoder PTS to calculate RTP timestamp * vp8: use encoder PTS to calculate RTP timestamp * vp9: use encoder PTS to calculate RTP timestamp * wincons: updated UI api 2017-06-24 Alfred E. Heggestad * Version 0.5.4 * GIT URL: https://github.com/alfredh/baresip.git * GIT tag: v0.5.4 * NOTE: Requires libre v0.5.4 or later Requires librem v0.5.0 or later * config: - audio_level yes|no Enable audio level RTP extension * baresip-core: - add support for Client-to-Mixer Audio Level Indication (RFC 6464) - add support for RTP Header Extensions (RFC 5285) - module: dont load same static module twice - ua: add ua_progress() - ua: check for Accept header in incoming OPTIONS request - use a dummy RTP port for incoming OPTIONS (ref #265) - vidcodec: make the API re-entrant - vidfilt: make the API re-entrant - vidisp: make the API re-entrant - vidsrc: make the API re-entrant * selftest: - add test for audio level indication in call - add test for call progress * Modules: * (all video modules updated with API-changes) * zrtp: check for RTP packet in send handler (ref #262) (thanks to MobiSciLab for reporting the bug) - registered zrtp_log function with zrtp engine - improved info message on how to verify remote peer - improved setting and printing of zrtp cache file (thanks Juha Heinanen) 2017-05-14 Alfred E. Heggestad * Version 0.5.3 * GIT URL: https://github.com/alfredh/baresip.git * GIT tag: v0.5.3 * NOTE: Requires libre v0.5.3 or later Requires librem v0.5.0 or later * config: - (no changes) * build: - detect jack module (thanks Tony Langley) - Updated MSVS projects to vs2015 (thanks Mikhail Barg) * baresip-core: - aulevel: add aulevel_calc_dbov() - audio: Set correct clock rate for telephone events (thanks Jan Hoffmann) - play: Add gapless repeat for tone playback (thanks Jan Hoffmann) * selftest: - add tests for aulevel - add tests for audio player - add mock aucodec/auplay * Modules: * gst_video1: Tune x264enc for low latency (thanks Jonathan Sieber) * httpd: fix a crash * ice: update to latest libre ICE-api * omx: Fixed some problems on OMX/RaspberryPi (thanks Jonathan Sieber) * srtp: fix SRTP for early-media (thanks Jan Hoffmann) * vumeter: use aulevel_calc_dbov to calculate signal energy * zrtp: update to latest libzrtp from freeswitch (thanks Juha Heinanen) 2017-04-07 Alfred E. Heggestad * Version 0.5.2 * GIT URL: https://github.com/alfredh/baresip.git * GIT tag: v0.5.2 * NOTE: Requires libre v0.5.0 or later Requires librem v0.5.0 or later * new modules: - omx OpenMAX IL video display module (thanks Jonathan Sieber) * config: - (no changes) * baresip-core: - aucodec: make the API re-entrant - aufilt: make the API re-entrant - auplay: make the API re-entrant - ausrc: make the API re-entrant - video: using a video-source is now optional * Modules: * avformat: add pixelformat AV_PIX_FMT_YUVJ420P (Thanks Gary Metalle) * cairo: print picture info, use grey background * dtmfio: check fd before calling fclose (thanks Richard Perez) * h265: enable YUV444P pixelformat * oss: fix build for Solaris 11 * speex: mark the module as deprecated, see speex.org 2017-03-04 Alfred E. Heggestad * Version 0.5.1 * GIT URL: https://github.com/alfredh/baresip.git * GIT tag: v0.5.1 * NOTE: Requires libre v0.5.0 or later Requires librem v0.5.0 or later * new modules: * config: - stunuser STUN username for STUN/TURN/ICE - stunpass STUN password for STUN/TURN/ICE - snd_path Path to sndfile audio dump files * baresip-core: - account: add more accessor functions - account: add 'stunuser' and 'stunpass' - commands: make the struct commands opaque - message: make the API re-entrant, multiple listeners - menc: make the API re-entrant - mnat: make the API re-entrant * selftest: - add tests for account - add tests for message * Modules: * amr: use MOD-CFLAGS instead of global CFLAGS * avcodec: added optional config 'avcodec_h264dec' to specify hardware accellerated FFmpeg decoder (thanks Harald Gutmann) * avformat: remove blocking sleep, use packet timestamp to pace video stream (thanks Harald Gutmann) * debug_cmd: add OpenSSL version to systems info * gtk: fix build where USE_NOTIFICATIONS is not defined get rid of system header warnings by using -isystem * httpd: add support for un-escaping of URL parameters (thanks to elektm93) * menu: add new command 'ausrc' to switch audio source add new command 'auplay' to switch audio player * sdl2: add more pixelformats (ref #202) (thanks Harald Gutmann) * sndfile: add config to specify path for dump files (thanks Elektm93) add test for sndfile on *BSD. (#194) (thanks jungle-boogie) * swscale: get dst-size from config (ref #203) * v4l2_codec: Video device selection bug (#218) (thanks Richard Perez) 2016-12-23 Alfred E. Heggestad * Version 0.5.0 * GIT URL: https://github.com/alfredh/baresip.git * GIT tag: v0.5.0 * NOTE: Requires libre v0.5.0 or later Requires librem v0.5.0 or later * new modules: - av1 Experimental AV1 video codec - debug_cmd Debug commands for advanced users - pcp Port Control Protocol (PCP) for NAT traversal - swscale Video scaling using FFmpeg's libswscale * config: - call_max_calls Maximum number of calls per account * baresip-core: - call: add multiple lines - call: start video on reinvite (thanks Gary Metalle) - cmd: add support for long commands - cmd: make it re-entrant - config: add some modules to template (thanks Dmitrij D. Czarkoff) - contact: make it re-entrant - play: make it re-entrant - vidcodec: add a intraframe-flag to api - video: resend FIR until Intra frame received * selftest: - add test for DTMF in call - add test for contacts - add test for long commands - add test for maximum calls - add test for multiple calls - add test for video call - add audio-source mock - add video-codec mock - add video-display mock - add video-source mock * Modules: * aufile: convert samples from little-endian to host-endian * auloop: use long commands /auloop and /auloop_stop * av1: new module for Experimental AV1 video codec * avcodec: add config option 'avcodec_h264enc' to set encoder name (thanks to @hargut) * avformat: fix init and warnings (thanks Maciej Koman) * b2bua: use long command /b2bua * contact: use long commands * debug_cmd: new module for advanced debug commands * g7221: expose spandsp api (thanks to Steve Underwood) * gtk: use long command /gtk * h265: add 'profile-id=1' to SDP * menu: add long commands add command 'line' or '@' to set current call * opengl: fix deprecated warnings on OSX 10.12 * opensles: add support for stereo (thanks to Juha Heinanen and Vijay Pratap Singh) * opus: add support for SDP parameter mirroring (thanks to Sveriges Radio) * pcp: new module for Port Control Protocol (PCP) NAT traversal requires librew (https://github.com/alfredh/rew) * plc: expose spandsp api (thanks to Steve Underwood) * presence: add long commands /presence_{on,off}line * snapshot: use long commands (thanks Dmitrij D. Czarkoff) * sndio: use driver-suggested buffer size (thanks Dmitrij D. Czarkoff) * swscale: new module for video filter using libswscale * v4l2: pick up VID_FMT_NV12 and VID_FMT_NV21 formats as well (#176) don't check for native/emulated format (#179) (thanks Dmitrij D. Czarkoff) * vidloop: use long commands * vp8: add 'intra' parameter to decoder api fix building with old versions of libvpx * wincons: graceful closing of thread (fixes #151) (thanks to @GGGO) * zrtp: use long command 2016-07-22 Alfred E. Heggestad * Version 0.4.20 * GIT URL: https://github.com/alfredh/baresip.git * GIT tag: v0.4.20 * NOTE: Requires libre v0.4.17 or later Requires librem v0.4.7 or later * new modules: - pulse Pulseaudio driver - vp9 VP9 video codec * config: - audio_path Path to audio files - call_local_timeout Timeout for incoming calls - redial_attempts Number of redial attempts - redial_delay Redial delay in seconds * baresip-core: - baresip: added a global baresip instance (WIP) - call: add RTP timeout (thanks to Sveriges Radio) - config: added call_local_timeout for incoming call timeout - config: added compile-time configureable CONFIG_PATH - config: added 'audio_path' config variable (thanks Juha Heinanen) - net: made it re-entrant with struct network - ua: added uag_set_exit_handler - ua: fix bug with reg_uri limited to 64-chars - video: vidfilters should not modify decoded image * selftest: - add test for network - add test for sending SIP OPTIONS - add test for RTP timeout * Modules: * avcodec: fix usage of deprecated API * avformat: remove support for scaling fix usage of deprecated API * cons: relay log-messages to active UDP/TCP connections https://github.com/alfredh/baresip/issues/144 * h265: fix usage of deprecated API * menu: added support for re-dial on failure (thanks to Sveriges Radio) * mpa: Bug with reinit of codec structs (thanks Christian Hoene) * natpmp: added support for RTCP * presence: use correct struct in deref handler * pulse: new module for Pulseaudio driver (thanks to Matthias Apitz for testing) * vidloop: vidfilters should not modify decoded image * vp8: module renamed from vpx.so to vp8.so * vp9: new module implementing VP9 video codec * wincons: use ReadConsoleInput, thanks to GGGO (fixes #139) https://github.com/alfredh/baresip/issues/139 2016-05-20 Alfred E. Heggestad * Version 0.4.19 * GIT URL: https://github.com/alfredh/baresip.git * GIT tag: v0.4.19 * NOTE: Requires libre v0.4.14 or later Requires librem v0.4.7 or later * new modules: - mpa MPA Speech and Audio Codec (thanks Christian Hoene) * baresip-core: - audio: remove is_g722 exception use aucodec's rtp clockrate for calculating RTP timestamp plc: make sure sampc is exactly one ptime frame - aucodec: split srate into DSP srate and RTP clockrate (these are different for e.g. G.722 and MDA) - mos: add mos_calculate() (thanks Lorenzo Mangani) - net: use configured dns servers only, if specified - ua: fix potential NULL-pointer crash for uag.cfg * selftest: - add test for SIP registration with DNS - add test for SIP registration with authentication - add test for MOS calculations - added a mock DNS Server - added a mock SIP Server * Modules: * aucodec: add support for NV12 and YUVJ420P pixel formats * daala: update to libdaala version 0.0-1564-g79787c7 * gtk: fix autodetection of libgtk+ 2.0 (thanks Charles Lehner) * h265: remove call to x265_cleanup, caused crash on OpenBSD * mpa: new module that implements MPA Speech and Audio Codec (this module was contributed by Christian Hoene) * opus: added new configuration parameters: opus_cbr {yes,no} # Constant Bitrate (inverse of VBR) opus_inbandfec {yes,no} # Enable inband FEC opus_dtx {yes,no} # Enable DTX * presence: improved interoperability, allow white space before xml element closing tags (thanks Juha Heinanen) * x11: added borderless window (thanks Doug Blewett) 2016-03-12 Alfred E. Heggestad * Version 0.4.18 * GIT URL: https://github.com/alfredh/baresip.git * GIT tag: v0.4.18 * NOTE: Requires libre v0.4.14 or later Requires librem v0.4.7 or later * baresip-core: - call: fix SIP INFO with dtmf-relay (thanks Gary Metalle) - ua: add event UA_EVENT_CALL_CLOSED for ua_hangup() * selftest: - add tests for answer a call and hangup * Modules: * alsa: fix potential crash (thanks Gary Metalle) * audiounit: fix compilation for iOS (issue #91) * avcodec: fix compilation for FFmpeg 3.0 * avformat: fix compilation for FFmpeg 3.0 * gtk: always handle incoming calls (thanks Charles Lehner) * h265: fix compilation for FFmpeg 3.0 * menu: add config 'menu_bell off/on' to enable Bell alert add command 'A' for switch audio device (thanks AlexMarlo) * v4l2_codec: add list of encoders (fixes #99) 2016-01-17 Alfred E. Heggestad * Version 0.4.17 * GIT URL: https://github.com/alfredh/baresip.git * GIT tag: v0.4.17 * NOTE: Requires libre v0.4.14 or later Requires librem v0.4.7 or later * new modules: - echo Echo server module - jack JACK Audio Connection Kit audio-driver * baresip-core: - config: keep config object in memory - ua: moved playing of ringtones out of core, to "menu" module (let's keep the core nice and slim..) - ui: added ui_password_prompt() * selftest: - silence debug/info log by default, only print warnings (use -v to see verbose logging) * Modules: * alsa: added config option to specify the sample format "alsa_sample_format {s16,float,s24_3le}" thanks to Ola Palm for valuable feedback * audiounit: fix recording on OSX (thanks Sebastian Reimers) print hardware samplerate in debug mode * auloop: add support for 44100 Hz samplerate * daala: update to latest libdaala API (thanks Dmitrij D. Czarkoff) * echo: new module which implements a simple Echo-server, to be used in combination with the aubridge.so module. contributed by Sebastian Reimers * gtk: fixes to support C89 compiler (thanks Dmitrij D. Czarkoff) * jack: new module which implements audio-driver for JACK * menu: playing of ringtones moved here, from ua.c * sndio: fix crash when device open fails (thanks Dmitrij D. Czarkoff) 2015-12-01 Alfred E. Heggestad * Version 0.4.16 * GIT URL: https://github.com/alfredh/baresip.git * GIT commit bed2241da3261e472f09b21958f0cc1324a94f27 * GIT tag: v0.4.16 * NOTE: Requires libre v0.4.14 or later * new modules: - v4l2_codec Video4Linux2 video codec (H264 hardware encoding) - vidinfo Video info overlay module * baresip-core: - audio: add audio_set_source() and audio_set_player() - audio: flush tx-buffer for all modes (thanks Thibault Gueslin) - call: add call_is_outgoing() - call: check address-family of incoming SDP offer (thanks Olle) - h264: move H.264 packetization code to core - main: add -u option to append extra global UA parameters - main: pre-load modules after all arguments are parsed - ua: add events UA_EVENT_SHUTDOWN,UA_EXIT - ua: add ua_hold_answer() - ua: add ua_set_media_af() - ua: delay mod-unloading if mods has a ref to struct ua * build: - add verbose build with V=1 (thanks Dmitrij D. Czarkoff) - add pkg-config file (thanks William King) - add travis.yml file for Github build-system * Modules: * alsa: fix memory leaks * avcodec: move common H.264 packetization code to core * cairo: use pkg-config in makefile * daala: update to latest libdaala (thanks Dmitrij D. Czarkoff) * gst_video: use H.264 packetization API from core * gst_video1: use H.264 packetization API from core * gtk: fix segmentation fault on window close * mwi: add 500ms delay after closing subscription * oss: use pthread for ausrc instead of fd_listen (fixes FreeBSD) * presence: use sipevent_sock instance from UA core add 500ms delay after closing subscription * v4l2_codec: new module * vidinfo: new module * zrtp: fix ZRTP over TURN by moving helper to layer 10 fix ZID verification (thanks Ingo Feinerer) 2015-09-26 Alfred E. Heggestad * Version 0.4.15 * GIT URL: https://github.com/alfredh/baresip.git * GIT commit 86262a6fc17e19e2be82eb8a2a05ec0f884d3d38 * GIT tag: v0.4.15 * NOTE: Requires libre v0.4.13 or later * added selftest binary * baresip-core: - audio: fix televent when pt != 101 (reported by AndyJRobinson) - magic: use __func__ for C99 or later - sip: make sip_req_send() public - ua: add UA_EVENT_CALL_DTMF_START/END, thanks Gary Metalle * Modules: * alsa: added extra logging * gtk: add support for libnotify (thanks Charles Lehner) * video: fix potential null deref (thanks Tomasz Ostrowski) * zrtp: added 36-bytes preamble for TURN-header 2015-08-08 Alfred E. Heggestad * Version 0.4.14 * GIT URL: https://github.com/alfredh/baresip.git * GIT commit ebac23b0692de71ee4c3a436f0372013150c937f * GIT tag: v0.4.14 * NOTE: Requires libre v0.4.13 or later * new modules: - gtk GTK+ 2.0 UI (thanks Charles E. Lehner) - gst1 Gstreamer 1.0 audio module - gst_video1 Gstreamer 1.0 video module (thanks Thomas Strobel) - daala Experimental video-codec using Daala * baresip-core: - baresip: added -m argument to pre-load modules - config: add kqueue to sample config (thanks Dmitrij D. Czarkoff) - log: make code C89 compliant (thanks Victor Sergienko) - module: added module_preload() - ua: add CALL_EVENT_TRANSFER_FAILED - ua: skip initial white space from uri (thanks Juha Heinanen) - ua: ua_prev_call() - videnc: move videnc_packet_h to update-handler * build: - added optional $(MOD)_CFLAGS for local module CFLAGS - added project file for Visual C++ Express 2010 - freebsd: add include path to $(SYSROOT)/local/include (thanks Hellmuth Michaelis) * Modules: * avcodec: make code C89 compliant (thanks Victor Sergienko) * cons: make code C89 compliant (thanks Victor Sergienko) * daala: new module * dshow: updates for VC2010 (thanks Victor Sergienko) * gst1: new module * gst_video1: new module * gtk: new module * menu: fix crash when 0 UAs (thanks Hans Petter Selasky) added command 'H' to hold previous call (thanks xanm) * wincons: make code C89 compliant (thanks ggcoding) 2015-06-20 Alfred E. Heggestad * Version 0.4.13 * GIT commit 2e3e825ef5532dfde5a8b52de9ebaac51aa20a9c * NOTE: Requires libre v0.4.12 or later * new modules: - aufile Audio module for using a WAV-file as audio input - b2bua Back-to-Back User-Agent (B2BUA) module - codec2 CODEC2 audio codec - gst_video Gstreamer video codec - h265 H.265 (HEVC) video codec * baresip-core: - contact: add support for access-control (thanks Doug Blewett) - ausrc: change base-class to a const pointer - auplay: change base-class to a const pointer - vidsrc: change base-class to a const pointer - vidisp: change base-class to a const pointer - video: smooth sending of video packets * Modules: * amr: added support for octet-align mode (thanks to Stefan Sayer) * aubridge: copy audio-samples if resampler not needed * aufile: new module for using a WAV-file as audio source * avcapture: only register 1 video source * avformat: fix segfault on recent versions of libav * b2bua: new experimental module * codec2: new module for CODEC2 audio codec * dtls_srtp: uppercase fingerprint, interop (thanks Juha Heinanen) alternative SDP protocols for interop * dtmfio: unregister event handler on close (thanks Hellmuth Michaelis) * gst_video: new module using Gstreamer as a video codec (Thanks to Victor Sergienko and Fadeev Alexander) * h265: new module for H.265 video codec * httpd: added raw mode (thanks Lorenzo Mangani) * menu: create user-agent with a command 'R' (thanks Lorenzo Mangani) * opus: add configuration of "opus_bitrate" (thanks to Juha Heinanen) * speex: add configuration of "speex_mode_nb" and "speex_mode_wb" (thanks to Dmitrij D. Czarkoff and Juha Heinanen) * vidloop: add VIDLOOP_INTERNAL_FMT and split encoder/decoder * x11: catch Window delete (thanks to Doug Blewett) * zrtp: initialize remote_zid (thanks to Ingo Feinerer) 2014-12-24 Alfred E. Heggestad * Version 0.4.12 * GIT commit 67993e35d980375458348b264c4a35a944bb5180 * NOTE: Requires libre v0.4.11 or later * baresip: - account: add regint and pubint - audio: fix checking of sample-rate range - config: remove the "input" block - config: added support for quoted device parameters - config: fix conversion of bandwidth to kbit/s - config: generate more relevant config for FreeBSD and OpenBSD (thanks Dmitrij D. Czarkoff) - reg: add support for extracting GRUU parameter - main: add -p option to set path to audio files - sipreq: make response-handler optional - ua: add support for GRUU (RFC 5627) (many thanks to Juha Heinanen for starting this work and helping out with the testing) - ua: moved presence-status to each struct ua instance - ua: add presence status to each User-Agent instance - ua: use public-GRUU if set, otherwise local cuser - ui: make UI single instance - video: add VIDENC_INTERNAL_FMT (suggested by Victor Sergienko) * docs: added sample configuration files * account: added pubint for Publishing Interval * avcodec: upgrade to recent ffmpeg/libav APIs either FFmpeg or libav can be used * celt: deleted module (replaced by opus) * cons: update usage of struct ui, added output handler added config: cons_listen 0.0.0.0:5555 * evdev: update usage of struct ui, added output handler added config: evdev_device /dev/input/event0 * httpd: added ui output handler * menu: added command 'o' for sending OPTION request (thanks to Juha Heinanen) added command 'D' for accepting incoming calls * mwi: subscribe to MWI after Registration succeeded (thanks to Juha Heinanen) * opensles: add double-buffering and some tuning (thanks to Francesco Bradascio) * opus: added config "opus_bitrate" (thanks to Sebastian Reimers) * presence: added support for PUBLISH (thanks to Juha Heinanen) interop fixes and tuning * stdio: update usage of struct ui, added output handler * uuid: use internal version of generating UUID * v4l2: use memory mapped mode only * vumeter: dont call tmr_start from non-RE thread * wincons: update usage of struct ui, added output handler * winwave: fix bug when closing player device (thanks to Tomasz Ostrowski) add support for mapping device name to index * zrtp: add support for verify SAS (thanks to Ingo Feinerer) 2014-06-21 Alfred E. Heggestad * Version 0.4.11 * GIT commit 7a465f2eb92f4e32740093e5ad4970d528908c51 * baresip: - audio: added audio_ismuted() to get audio mute status - audio: fix timestamp generation for stereo-streams - audio: send outgoing audio-packets as soon as possible - audio: upgrade to sample-based ausrc/auplay API - auplay: change API to use samples instead of 8-bit buffer - auplay: remove option to specify sample format (always S16LE) - ausrc: change API to use samples instead of 8-bit buffer - ausrc: remove option to specify sample format (always S16LE) - call: added support for X-RTP-Stat header (thanks Lorenzo Mangani) - call: check for common audio-codecs (thanks Juha Heinanen) - logging: use info() instead of DEBUG_INFO(); - logging: use warning() instead of DEBUG_WARNING() - play: convert WAV-file from little-endian to native-endian - removed support for Symbian OS * debian: upgrade debian files * avcapture: also build for MacOSX * alsa: fix sample-endianess with SND_PCM_FORMAT_S16 upgrade to sample-based ausrc/auplay API * audiounit: upgrade to sample-based ausrc/auplay API * auloop: upgrade to sample-based ausrc/auplay API * coreaudio: upgrade to sample-based ausrc/auplay API * dtls_srtp: use DTLS code from libre (needs libre v0.4.9 or later) use SRTP code from libre (needs libre v0.4.9 or later) * dtmfio: new module to send DTMF-events via FIFO file (contributed by Aaron Herting) * fakevideo: new module for fake video input/output driver * gst: upgrade to sample-based ausrc/auplay API * ice: set default candidates for ICE-lite * libsrtp: module 'srtp.so' renamed to 'libsrtp.so' * mda: Symbian MDA audio driver was deleted * menu: fix issue with audio-mute on multiple calls * opensles: upgrade to sample-based ausrc/auplay API * oss: upgrade to sample-based ausrc/auplay API * portaudio: upgrade to sample-based ausrc/auplay API * rst: upgrade to sample-based ausrc/auplay API * selftest: new module for testing the baresip core api * sndio: new module for OpenBSD audio driver (It was contributed by Dmitrij D. Czarkoff, thank you!) * srtp: module is now using SRTP-stack from libre (v0.4.9 or later) * syslog: use logging framework to get messages * v4l2: add format negotiation and OpenBSD support (contributed by Dmitrij D. Czarkoff) * winwave: upgrade to sample-based ausrc/auplay API 2014-01-23 Alfred E. Heggestad * Version 0.4.10 * baresip: - account: add account_set_display_name() -- thanks Dimitris - audio: use both srate/channels to check if resampler is needed - aufilt: change from frame_size to ptime - auplay: change from frame_size to ptime - ausrc: change from frame_size to ptime - config: add optional ausrc_channels and auplay_channels - config: create config dir with mode 0700 (suggested by Jann Horn) - play: update auplay usage with ptime * alsa: update to new ausrc/auplay API with ptime fix bug when snd_pcm_readi() returns -EPIPE (thanks Remik) open device from main thread instead of alsa-thread (thanks EL) (caused problems with Sennheiser Century SC 660 + USB adapter) * auloop: minor cleanups and improvements * coreaudio: update to new ausrc/auplay API with ptime * gst: update to new ausrc/auplay API with ptime * l16: fix a bug with sample count * opus: fix a memory corruption error in opus_decode_pkloss() * oss: update to new ausrc/auplay API with ptime * plc: update to new aufilt API with ptime * portaudio: update to new ausrc/auplay API with ptime fix bugs when using channels=2 (stereo) configure device index using "device" parameter * rst: update to new ausrc/auplay API with ptime * speex_aec: update to new aufilt API with ptime * speex_pp: update to new aufilt API with ptime * winwave: update to new ausrc/auplay API with ptime * zrtp: update to use libzrtp from Travis Cross' github use config dir to store ZRTP cache-file (thanks Juha Heinanen) 2014-01-06 Alfred E. Heggestad * Version 0.4.9 * new modules: - zrtp Media Path Key Agreement for Unicast Secure RTP * build: - added support for LLVM clang compiler * baresip: - account: add account_laddr() - audio: upgrade to new librem auresamp API - config: use oss,/dev/dsp as default device for FreeBSD - log: added new logging framework - main: added new verbose debug argument (-v) - net: added sanity check for HAVE_INET6 build flag - play: added play_set_path() -- thanks to Dimitris P. - ua: added uag_find_param() - ua: fix param-bug in ua_connect() -- thanks to Juha Heinanen * aubridge: upgrade to new librem auresamp API * avcodec: use new av_frame_alloc() api * celt: deprecate CELT-module, use OPUS instead * opengles: fix warnings (thanks to Dimitris P.) * opensles: fix bugs in player and recorder * opus: encode/decode sdp parameters as of I-D * speex_resamp: module removed, replaced by librem's resampler * zrtp: new module for ZRTP media encryption (use ;mediaenc=zrtp) 2013-12-06 Alfred E. Heggestad * Version 0.4.8 * new modules: - dtls_srtp DTLS-SRTP media encryption module (RFC 5763,5764) - aubridge Audio Bridge to connect auplay->ausrc - vidbridge Video Bridge module to connect vidisp->vidsrc * baresip: - added RFC 5576 Source-Specific Media Attributes in SDP - audio: set SDP bandwidth only if "rtp_bandwidth" config set - play: do not store a copy of global config - stream: save RTCP statistics from Sender-reports - stream: add SDP ssrc attribute - stream: added metrics for packets/bytes transmit/receive - ua: added uag_current()/_set() to get/set current User-Agent - video: set maximum RTP packet-size to 1024 bytes * config: - added "video_display module,device" for Video Display - added "rtp_stats {off,on}" for RTP Statistics after Call - default RTP bandwidth is now 0-0 * contact: dynamic command description for "Message" handling dial from current UA (thanks to Simon Liebold) * isac: upgrade to draft-ietf-avt-rtp-isac-04 * srtp: added auto-negotiation of RTP-profile for incoming calls (RTP/AVP, RTP/AVPF, RTP/SAVP, RTP/SAVPF) * vidloop: fix memory leak 2013-11-12 Alfred E. Heggestad * Version 0.4.7 * new modules: - httpd HTTP webserver UI module * baresip: - added RFC 5506 Support for Reduced-Size RTCP - audio: minor cleanups - cmd: ignore RELEASE key in editor mode - conf: add conf_get_sa() - mnat: add address family (af) to session handler - realtime: fixes for iOS (thanks Dimitris) - ua: make ua_register() public - ua: add ua_calls() to get list of calls - ua: only create register client if regint > 0 * debian: update dependencies (thanks Juha Heinanen) * rpm: added RPM package spec file * alsa: open device from thread to avoid blocking re-main loop * avcodec: build fixes for Debian Testing * avformat: use sys_msleep() * contact: improve matching logic (thanks EJC Lindner) * dshow: initialize variables (found with cppcheck) * evdev: fix formatted printing (found with cppcheck) * ice: use address family (AF) from call * ilbc: update to separate encoder/decoder states (thanks Dimitris) * snapshot: initialize variables (found with cppcheck) * stun: use address family (AF) from call * turn: use address family (AF) from call * uuid: fix usage of strncat() 2013-10-11 Alfred E. Heggestad * Version 0.4.6 * new modules: - directfb DirectFB video display module (thanks Andreas Shimokawa) - dshow Windows DirectShow vidsrc (thanks Dusan Stevanovic) - wincons Console input driver for Windows * baresip: - audio: print audio-pipelines in console/debug - aufilt: split into separate encoder+decoder states - call: add local uri/name, dtmf-handler - call: fix decoding of DTMF/SIP-INFO for '*' and '#' - export CALL_EVENT_* in public API - fix various clang warnings - sipreq: use outbound proxy if specified (thanks EJC Lindner) - ua: add possibility to specify 'struct call' for hangup/answer - ua: move SIP extensions into a dynamic vector container - ua: move playing of tones from call.c to ua.c - vidfilt: split into separate encoder+decoder states - vidisp: remove input handler * menu: improve call-transfer handling * plc: update to separate encoder/decoder states * selfview: update to separate encoder/decoder states * snapshot: remove state which was not needed * sndfile: update to separate encoder/decoder states print unique timestamp to saved files * speex_aec: update to separate encoder/decoder states * speex_pp: update to separate encoder/decoder states * vidloop: update to separate encoder/decoder vidfilt states * vumeter: update to separate encoder/decoder states * wincons: new module for Console input on Win32 2013-08-31 Alfred E. Heggestad * Version 0.4.5 * new modules: - account Account loader module - natpmp NAT-PMP client (RFC 6886) - sdl2 Video display using libSDL2 * baresip: - account: added SIP account parser and container - config: split conf.c into conf.c and config.c - config: move enum audio_mode to struct config - config: move uuid to struct config - more usage of the #ifdef USE_VIDEO macro - message: add handling of SIP MESSAGE send/recv - mediaenc: added rtp_sock parameter to media-handler - ua: cleanup public struct ua API - vidisp api: remove unused 'parent' parameter - call: handle incoming DTMF in SIP INFO (application/dtmf-relay) - sdp: added sdp_decode_multipart() - net: fix bug on IP-refresh when 'net_interface' is used - video: minor cleanups handle incoming RTCP_RTPFB_GNACK * isac: fix encode_update() signature * menu: move dialbuffer here from ua.c added command 'g' to print current config * mwi: multiple MWIs for multiple UAs * presence: include supported methods in SIP messages * srtp: improved interop and debugging handle incoming RTP/RTCP-demultiplexing * uuid: write loaded UUID directly to struct config * vidloop: added video-filters 2013-05-18 Alfred E. Heggestad * Version 0.4.4 * new modules: - g726 G.726 audio codec - mwi Message Waiting Indication - snapshot Save video-stream as PNG images * config: - added 'sip_certificate' to use a Certificate for SIP/TLS - added 'ausrc_srate' and 'auplay_srate' to force DSP samplerate * baresip: - added a simple BFCP client - aufilt: improved API - mediaenc: improved API with session state - ua: added event handler framework - aucodec: improved API with separate encode/decode state - vidcodec: improved API with separate encode/decode state - sdp.c: added SDP helper functions - ua: move registration client to reg.c - audio: added internal resampler * auloop: added config option 'auloop_codec' for setting codec * ice: remove old 'ice_interface' config option * menu: move handling of status-mode here * selfview: added config option 'selfview_size' * vp8: upgrade to draft-ietf-payload-vp8-08 * winwave: cleanup and minor fixes 2013-01-01 Alfred E. Heggestad * Version 0.4.3 * new modules: - selfview Video selfview as video-filter module - vumeter Audio-filter module to display recording/playback level * config: - added 'net_interface" to bind to a specific network interface - added accounts 'regq' parameter for SIP Register client * baresip: - added video-filter plugin API (vidfilt) - audio.c: cleanups, split into transmit/receive part - ua: added SIP Allow-header (thanks Juha Heinanen) - ua: added Register q-value (thanks Juha Heinanen) - ua: fix DTMF end event bug * avcodec: fix x264 fps bug (thanks Trevor Jim) * ice: only include ufrag/pwd in session SDP (thanks Juha Heinanen) 2012-09-09 Alfred E. Heggestad * Version 0.4.2 * new modules: - auloop Audio-loop test module - contact Contacts module - isac iSAC audio codec - menu Interactive menu - opengles OpenGLES video output - presence Presence module - syslog Syslog module - vidloop Video-loop test module * baresip: - added support for call transfer - added support for call waiting - added multiple calls per user-agent - added multiple registrations per user-agent - cmd: added new command interface - ua: handle SIP Require header for incoming calls - ui: cleanup, use dynamic interactive menu * config: - added 'audio_alert' for ringtones etc. - added 'outboundX=proxy' for multiple outbound proxies - added 'module_tmp' for temporary module loading - added 'module_app' for application modules * avcodec: upgrade to latest FFmpeg and fix pts bug * natbd: register command 'z' for status * srtp: fix memleak on close * uuid: added UUID loader 2012-04-21 Alfred E. Heggestad * Version 0.4.1 * baresip: do not include rem.h from baresip.h rename struct conf to struct config vidsrc API: move size to alloc handler aucodec API: change fmtp type to 'const char *' add SDP fmtp compare handler vidcodec API: added enqueue and packetizer handlers remove size from vidcodec_prm remove decoder parameters from alloc change fmtp type to 'const char *' add SDP fmtp compare handler remove aufile.c, use librem instead audio: fix Telev timestamp (thanks Paulo Vicentini) configurable order of playback/source start ua_find: match AOR for interop (thanks Tomasz Ostrowski) ua: more robust parsing for incoming MESSAGE ua: password prompt (thanks to Juha Heinanen) * build: detect amr, cairo, rst, silk modules * config: split 'audio_dev' parameter into 'audio_player/audio_source' order of audio_player/audio_source decide opening order rename 'video_dev' parameter to 'video_source' added optional 'auth_user=NAME' account parameter (idea was suggested by Juha Heinanen) * alsa: play: no need to call snd_pcm_start(), explictly started when writing data to the device. (thanks to Christof Meerwald) * amr: more portable AMR codec * avcodec: automatic size from encoded frames detect packetization-mode from SDP format use enqueue handler * avformat: update to latest versions of ffmpeg * cairo: new experimental video source module * cons: added support for TCP * evdev: added KEY_KPx (thanks to ccwufu on OpenWRT forum) * g7221: use bitrate from decoded SDP format added optional G722_PCM_SHIFT for 14-bit compat * rst: thread-based video source * silk: fix crash, init encoder, bitrate=64000 and complexity=2 (reported by Juha Heinanen) * srtp: decode SDES lifetime and MKI * v4l, v4l2: better module detection for FreeBSD 9 do not include malloc.h (thanks to Matthias Apitz) * vpx: auto init of encoder * winwave: fix memory leak (thanks to Tomasz Ostrowski) * x11: add support for 16-bit graphics 2011-12-25 Alfred E. Heggestad * Version 0.4.0 * updated doxygen comments (thanks to Olle E. Johansson) * docs: added modules description * baresip: add ua_set_aumode(), configurable audio-tx mode vidsrc API: added media_ctx shared with ausrc ausrc API: add media_ctx shared with vidsrc audio_encoder_set() - stop audio source first audio_decoder_set() - include SDP format parameters aufile: add PREFIX to share path (thanks to Juha Heinanen) natbd.c: move code to a new module 'natbd' get_login_name: check both LOGNAME and USER ua.c: unique contact-user with address of struct ua ua.c: find correct UA for incoming SIP Requests ua_connect: param is optional (thanks to Juha Heinanen) video: add video_set_source() * amr: minor improvements * audiounit: new module for MacOSX/iOS audio driver * avcapture: new module for iOS video source * avcodec: fixes for newer versions of libavcodec * gsm: handle packet-loss * natbd: move to separate module from core * opengl: fix building on MacOSX 10.7 (thanks to David Jedda and Atle Samuelsen) * opus: upgrade to opus v0.9.8 * rst: use media_ctx for shared audio/video stream * sndfile: fix stereo mode 2011-09-07 Alfred E. Heggestad * Version 0.3.0 * baresip: use librem for media processing added support for video selfview aubuf, autone, vutil: moved to librem ua: improved API conf: use internal parser instead of fscanf() vidloop: cleanup, use librem for processing * config: add video_selfview={pip,window} parameter * amr: new module for AMR and AMR-WB audio codecs (RFC 4867) * avcodec, avformat: update to latest version of FFmpeg * coreaudio: fix building on MacOSX 10.5 (thanks David Jedda) * ice: fix building on MacOSX 10.5 (thanks David Jedda) * opengl: remove deps to libswscale * opensles: new module OpenSLES audio driver * opus: new module for OPUS audio codec * qtcapture: remove deps to libswscale * rst: new module for mp3 audio streaming * silk: new module for SILK audio codec * v4l, v4l2: remove deps to libswscale * x11: remove deps to libswscale, use librem vidconv instead * x11grab: remove deps to libswscale 2011-05-20 Alfred E. Heggestad * Version 0.2.0 * baresip: Added support for SIP Outbound (RFC 5626) The SDP Content Attribute (RFC 4796) RTP/RTCP Multiplexing (RFC 5761) RTP Keepalive (draft-ietf-avt-app-rtp-keepalive-09) * config: add 'outbound' to sipnat parameter (remove stun, turn) add rtpkeep={zero,stun,dyna,rtcp} parameter audio_codecs parameter can now specify samplerate add rtcp_mux for RTP/RTCP multiplexing on/off * alsa: set buffersize and fix samplesize (thanks to Luigi Rizzo) * avcodec: added support for MPEG4 video codec (RFC 3016) wait for keyframe before decoding * celt: upgrade libcelt version and cleanups * coreaudio: fix buffering in recorder * ice: several improvements and fixes added new config options * ilbc: handle asymmetric modes * opengl: enable vertical sync * sdl: upgrade to latest version of libSDL from mercurial * vpx: added support for draft-westin-payload-vp8-02 * x11: handle remote display with optional shared memory * x11grab: new video-source module (thanks to Luigi Rizzo) * docs: updated doxygen comments baresip-1.0.0/docs/THANKS000066400000000000000000000013711372575704200150160ustar00rootroot00000000000000@Encamy @GGGO @elektm93 @glenvt18 @jungle-boogie @premultiply Aaron Herting AlexMarlo Andreas Shimokawa Atle Samuelsen Charles Lehner Christian Hoene Christian Spielberger David Jedda Dimitris P. Dmitrij D. Czarkoff Doug Blewett Dusan Stevanovic EJC Lindner Fadeev Alexander Gary Metalle Geoff Stewart Hans Petter Selasky Harald Gutmann Hellmuth Michaelis Ingo Feinerer Iwan BK Jan Hoffmann Jonathan Sieber José Luis Millán Juha Heinanen Lorenzo Mangani Luigi Rizzo Maciej Koman Marcel Battista Matthias Apitz Mikhail Barg Nicolas Tizon Ola Palm Olle E. Johansson Richard Perez Robert Scheck Sebastian Reimers Stefan Sayer Steve Underwood Thibault Gueslin Thomas Strobel Tomasz Ostrowski Tony Langley Trevor Jim Victor Sergienko William King Sveriges Radio baresip-1.0.0/docs/TODO000066400000000000000000000004251372575704200145720ustar00rootroot00000000000000TODO: ------------------------------------------------------------------------------- Please see: https://github.com/baresip/baresip/issues https://github.com/baresip/baresip/wiki/Roadmap ------------------------------------------------------------------------------- baresip-1.0.0/docs/examples/000077500000000000000000000000001372575704200157175ustar00rootroot00000000000000baresip-1.0.0/docs/examples/accounts000066400000000000000000000030371372575704200174640ustar00rootroot00000000000000# # SIP accounts - one account per line -- sample configuration # # Displayname ;addr-params # # uri-params: # ;transport={udp,tcp,tls} # # addr-params: # ;answermode={manual,early,auto} # ;audio_codecs=opus/48000/2,pcma,... # ;auth_user=username # ;auth_pass=password # ;call_transfer=no # ;mediaenc={srtp,srtp-mand,srtp-mandf,dtls_srtp,zrtp} # ;medianat={stun,turn,ice} # ;mwi=no # ;outbound="sip:primary.example.com;transport=tcp" # ;outbound2=sip:secondary.example.com # ;ptime={10,20,30,40,...} # ;regint=3600 # ;rwait=90 # ;pubint=0 (publishing off) # ;regq=0.5 # ;sipnat={outbound} # ;stunserver=stun:[user:pass]@host[:port] # ;video_codecs=h264,h263,... # # Examples: # # # # # # # A very basic example # # # Use SIP Outbound over TCP, with ICE for Media NAT Traversal, and DTLS-SRTP for encryption # ;sipnat=outbound;outbound="sip:example.com;transport=tcp";medianat=ice;mediaenc=dtls_srtp;auth_pass=pass # # Use ICE for Media NAT Traversal, using a specific STUN-server # ;medianat=ice;stunserver="stun:username:password@stunserver.org";auth_pass=pass # # Force audio-codec 'opus' and video-codec 'vp8' # ;audio_codecs=opus/48000/2;video_codecs=vp8;auth_pass=pass # ... more examples can be added here ... baresip-1.0.0/docs/examples/config000066400000000000000000000106351372575704200171140ustar00rootroot00000000000000# # baresip configuration -- example for linux # #------------------------------------------------------------------------------ # Core poll_method epoll # poll, select, epoll .. # SIP #sip_listen 0.0.0.0:5060 #sip_certificate cert.pem #sip_cafile ca.crt # Call call_local_timeout 120 call_max_calls 4 # Audio audio_buffer 200 # ms #audio_path /usr/local/share/baresip audio_player alsa,default audio_source alsa,default audio_alert alsa,default #ausrc_srate 48000 #auplay_srate 48000 #ausrc_channels 0 #auplay_channels 0 #audio_txmode poll # poll, thread audio_level no ausrc_format s16 # s16, float, .. auplay_format s16 # s16, float, .. auenc_format s16 # s16, float, .. audec_format s16 # s16, float, .. # Video #video_source v4l2,/dev/video0 #video_display x11,nil video_size 352x288 video_bitrate 512000 video_fps 25.00 video_fullscreen no videnc_format yuv420p # AVT - Audio/Video Transport rtp_tos 184 #rtp_ports 10000-20000 #rtp_bandwidth 512-1024 # [kbit/s] rtcp_mux no jitter_buffer_delay 5-10 # frames rtp_stats no #rtp_timeout 60 # Network #dns_server 1.1.1.1:53 #dns_server 1.0.0.1:53 #net_interface wlan1 #------------------------------------------------------------------------------ # Modules #module_path /usr/local/lib/baresip/modules # UI Modules module stdio.so #module cons.so #module evdev.so #module httpd.so # Audio codec Modules (in order) module opus.so #module amr.so #module g7221.so #module g722.so #module g726.so module g711.so #module gsm.so #module l16.so # Audio filter Modules (in encoding order) #module vumeter.so #module sndfile.so #module speex_pp.so #module plc.so #module webrtc_aec.so # Audio driver Modules module alsa.so #module portaudio.so # Video codec Modules (in order) module avcodec.so #module vp8.so #module vp9.so # Video filter Modules (in encoding order) #module selfview.so # Video source modules module v4l2.so #module avformat.so #module x11grab.so #module cairo.so # Video display modules module x11.so #module sdl.so # Audio/Video source modules #module rst.so #module gst.so #module gst_video.so # Compatibility modules #module ebuacip.so # Media NAT modules module stun.so module turn.so module ice.so #module natpmp.so #module pcp.so # Media encryption modules #module srtp.so module dtls_srtp.so #------------------------------------------------------------------------------ # Temporary Modules (loaded then unloaded) module_tmp uuid.so module_tmp account.so #------------------------------------------------------------------------------ # Application Modules module_app auloop.so #module_app b2bua.so module_app contact.so module_app debug_cmd.so #module_app echo.so #module_app gtk.so module_app menu.so #module_app mwi.so #module_app presence.so #module_app syslog.so #module_app mqtt.so #module_app ctrl_tcp.so module_app vidloop.so #------------------------------------------------------------------------------ # Module parameters # UI Modules parameters cons_listen 0.0.0.0:5555 # cons - Console UI UDP/TCP sockets http_listen 0.0.0.0:8000 # httpd - HTTP Server ctrl_tcp_listen 0.0.0.0:4444 # ctrl_tcp - TCP interface JSON evdev_device /dev/input/event0 # Opus codec parameters opus_bitrate 28000 # 6000-510000 #opus_stereo yes #opus_sprop_stereo yes #opus_cbr no #opus_inbandfec no #opus_dtx no #opus_mirror no #opus_complexity 10 #opus_application audio # {voip,audio} #opus_samplerate 48000 #opus_packet_loss 10 # 0-100 percent (expected packet loss) #jack_connect_ports yes # Selfview video_selfview window # {window,pip} #selfview_size 64x64 # ZRTP #zrtp_hash no # Disable SDP zrtp-hash (not recommended) # Menu #menu_bell yes #redial_attempts 0 # Num or #redial_delay 5 # Delay in seconds #ringback_disabled no #statmode_default off #menu_clean_number no # GTK #gtk_clean_number no # avcodec #avcodec_h264enc libx264 #avcodec_h264dec h264 #avcodec_h265enc libx265 #avcodec_h265dec hevc #avcodec_hwaccel videotoolbox # MQTT #mqtt_broker_host sollentuna.example.com #mqtt_broker_port 1883 #mqtt_broker_clientid baresip01 # Has to be unique for each client, defaults to "baresip" #mqtt_broker_user alfred #mqtt_broker_password Crocus #mqtt_basetopic baresip/01 # May be uniqe for each client you want to control. Defaults to "baresip" # sndfile #snd_path /tmp # EBU ACIP #ebuacip_jb_type fixed # auto,fixed baresip-1.0.0/docs/examples/contacts000066400000000000000000000002751372575704200174640ustar00rootroot00000000000000# # SIP contacts # # Displayname ;addr-params # # addr-params: # ;presence={none,p2p} # "Echo Server" "alfredh" ;presence=p2p baresip-1.0.0/include/000077500000000000000000000000001372575704200145745ustar00rootroot00000000000000baresip-1.0.0/include/baresip.h000066400000000000000000001361401372575704200163770ustar00rootroot00000000000000/** * @file baresip.h Public Interface to Baresip * * Copyright (C) 2010 Creytiv.com */ #ifndef BARESIP_H__ #define BARESIP_H__ #ifdef __cplusplus extern "C" { #endif /** Defines the Baresip version string */ #define BARESIP_VERSION "1.0.0" #ifndef NET_MAX_NS #define NET_MAX_NS (4) #endif /* * Clock-rate for audio timestamp */ #define AUDIO_TIMEBASE 1000000U /* * Clock-rate for video timestamp */ #define VIDEO_TIMEBASE 1000000U /* forward declarations */ struct sa; struct sdp_media; struct sdp_session; struct sip_msg; struct stream; struct ua; struct vidframe; struct vidrect; struct vidsz; /* * Account */ /** Defines the answermodes */ enum answermode { ANSWERMODE_MANUAL = 0, ANSWERMODE_EARLY, ANSWERMODE_AUTO }; struct account; int account_alloc(struct account **accp, const char *sipaddr); int account_debug(struct re_printf *pf, const struct account *acc); int account_json_api(struct odict *odacc, struct odict *odcfg, const struct account *acc); int account_set_auth_user(struct account *acc, const char *user); int account_set_auth_pass(struct account *acc, const char *pass); int account_set_outbound(struct account *acc, const char *ob, unsigned ix); int account_set_sipnat(struct account *acc, const char *sipnat); int account_set_answermode(struct account *acc, enum answermode mode); int account_set_display_name(struct account *acc, const char *dname); int account_set_regint(struct account *acc, uint32_t regint); int account_set_stun_uri(struct account *acc, const char *uri); int account_set_stun_host(struct account *acc, const char *host); int account_set_stun_port(struct account *acc, uint16_t port); int account_set_stun_user(struct account *acc, const char *user); int account_set_stun_pass(struct account *acc, const char *pass); int account_set_mediaenc(struct account *acc, const char *mediaenc); int account_set_medianat(struct account *acc, const char *medianat); int account_set_audio_codecs(struct account *acc, const char *codecs); int account_set_video_codecs(struct account *acc, const char *codecs); int account_set_mwi(struct account *acc, const char *value); int account_set_call_transfer(struct account *acc, const char *value); int account_auth(const struct account *acc, char **username, char **password, const char *realm); struct list *account_aucodecl(const struct account *acc); struct list *account_vidcodecl(const struct account *acc); struct sip_addr *account_laddr(const struct account *acc); struct uri *account_luri(const struct account *acc); uint32_t account_regint(const struct account *acc); uint32_t account_pubint(const struct account *acc); uint32_t account_ptime(const struct account *acc); enum answermode account_answermode(const struct account *acc); const char *account_display_name(const struct account *acc); const char *account_aor(const struct account *acc); const char *account_auth_user(const struct account *acc); const char *account_auth_pass(const struct account *acc); const char *account_outbound(const struct account *acc, unsigned ix); const char *account_sipnat(const struct account *acc); const char *account_stun_user(const struct account *acc); const char *account_stun_pass(const struct account *acc); const char *account_stun_host(const struct account *acc); const struct stun_uri *account_stun_uri(const struct account *acc); uint16_t account_stun_port(const struct account *acc); const char *account_mediaenc(const struct account *acc); const char *account_medianat(const struct account *acc); const char *account_mwi(const struct account *acc); const char *account_call_transfer(const struct account *acc); const char *account_extra(const struct account *acc); /* * Audio frame */ /** * Defines a frame of audio samples */ struct auframe { int fmt; /**< Sample format (enum aufmt) */ void *sampv; /**< Audio samples (must be mem_ref'd) */ size_t sampc; /**< Total number of audio samples */ uint64_t timestamp; /**< Timestamp in AUDIO_TIMEBASE units */ }; void auframe_init(struct auframe *af, int fmt, void *sampv, size_t sampc); size_t auframe_size(const struct auframe *af); void auframe_mute(struct auframe *af); /* * Audio-level */ #define AULEVEL_MIN (-96.0) #define AULEVEL_MAX (0.0) double aulevel_calc_dbov(int fmt, const void *sampv, size_t sampc); /* * Call */ enum call_event { CALL_EVENT_INCOMING, CALL_EVENT_RINGING, CALL_EVENT_PROGRESS, CALL_EVENT_ESTABLISHED, CALL_EVENT_CLOSED, CALL_EVENT_TRANSFER, CALL_EVENT_TRANSFER_FAILED, CALL_EVENT_MENC, }; /** Call States */ enum call_state { CALL_STATE_IDLE = 0, CALL_STATE_INCOMING, CALL_STATE_OUTGOING, CALL_STATE_RINGING, CALL_STATE_EARLY, CALL_STATE_ESTABLISHED, CALL_STATE_TERMINATED, CALL_STATE_UNKNOWN }; /** Video mode */ enum vidmode { VIDMODE_OFF = 0, /**< Video disabled */ VIDMODE_ON, /**< Video enabled */ }; struct call; typedef void (call_event_h)(struct call *call, enum call_event ev, const char *str, void *arg); typedef void (call_dtmf_h)(struct call *call, char key, void *arg); int call_connect(struct call *call, const struct pl *paddr); int call_answer(struct call *call, uint16_t scode, enum vidmode vmode); int call_progress(struct call *call); void call_hangup(struct call *call, uint16_t scode, const char *reason); int call_modify(struct call *call); int call_hold(struct call *call, bool hold); int call_set_video_dir(struct call *call, enum sdp_dir dir); int call_send_digit(struct call *call, char key); bool call_has_audio(const struct call *call); bool call_has_video(const struct call *call); int call_transfer(struct call *call, const char *uri); int call_status(struct re_printf *pf, const struct call *call); int call_debug(struct re_printf *pf, const struct call *call); int call_notify_sipfrag(struct call *call, uint16_t scode, const char *reason, ...); void call_set_handlers(struct call *call, call_event_h *eh, call_dtmf_h *dtmfh, void *arg); uint16_t call_scode(const struct call *call); enum call_state call_state(const struct call *call); uint32_t call_duration(const struct call *call); uint32_t call_setup_duration(const struct call *call); const char *call_id(const struct call *call); const char *call_peeruri(const struct call *call); const char *call_peername(const struct call *call); const char *call_localuri(const struct call *call); struct audio *call_audio(const struct call *call); struct video *call_video(const struct call *call); struct list *call_streaml(const struct call *call); struct ua *call_get_ua(const struct call *call); bool call_is_onhold(const struct call *call); bool call_is_outgoing(const struct call *call); void call_enable_rtp_timeout(struct call *call, uint32_t timeout_ms); uint32_t call_linenum(const struct call *call); struct call *call_find_linenum(const struct list *calls, uint32_t linenum); struct call *call_find_id(const struct list *calls, const char *id); void call_set_current(struct list *calls, struct call *call); const struct list *call_get_custom_hdrs(const struct call *call); /* * Custom headers */ typedef int (custom_hdrs_h)(const struct pl *name, const struct pl *val, void *arg); /* returns error code if any */ int custom_hdrs_add(struct list *hdrs, const char *name, const char *fmt, ...); int custom_hdrs_apply(const struct list *hdrs, custom_hdrs_h *h, void *arg); /* * Conf (utils) */ /** Defines the configuration line handler */ typedef int (confline_h)(const struct pl *addr, void *arg); int conf_configure(void); int conf_configure_buf(const uint8_t *buf, size_t sz); int conf_modules(void); void conf_path_set(const char *path); int conf_path_get(char *path, size_t sz); int conf_parse(const char *filename, confline_h *ch, void *arg); int conf_get_vidsz(const struct conf *conf, const char *name, struct vidsz *sz); int conf_get_sa(const struct conf *conf, const char *name, struct sa *sa); bool conf_fileexist(const char *path); void conf_close(void); struct conf *conf_cur(void); /* * Config (core configuration) */ /** A range of numbers */ struct range { uint32_t min; /**< Minimum number */ uint32_t max; /**< Maximum number */ }; static inline bool in_range(const struct range *rng, uint32_t val) { return rng ? (val >= rng->min && val <= rng->max) : false; } /** Audio transmit mode */ enum audio_mode { AUDIO_MODE_POLL = 0, /**< Polling mode */ AUDIO_MODE_THREAD, /**< Use dedicated thread */ }; /** SIP User-Agent */ struct config_sip { char uuid[64]; /**< Universally Unique Identifier */ char local[64]; /**< Local SIP Address */ char cert[256]; /**< SIP Certificate */ char cafile[256]; /**< SIP CA-file */ }; /** Call config */ struct config_call { uint32_t local_timeout; /**< Incoming call timeout [sec] 0=off */ uint32_t max_calls; /**< Maximum number of calls, 0=unlimited */ }; /** Audio */ struct config_audio { char audio_path[256]; /**< Audio file directory */ char src_mod[16]; /**< Audio source module */ char src_dev[128]; /**< Audio source device */ char play_mod[16]; /**< Audio playback module */ char play_dev[128]; /**< Audio playback device */ char alert_mod[16]; /**< Audio alert module */ char alert_dev[128]; /**< Audio alert device */ uint32_t srate_play; /**< Opt. sampling rate for player */ uint32_t srate_src; /**< Opt. sampling rate for source */ uint32_t channels_play; /**< Opt. channels for player */ uint32_t channels_src; /**< Opt. channels for source */ enum audio_mode txmode; /**< Audio transmit mode */ bool level; /**< Enable audio level indication */ int src_fmt; /**< Audio source sample format */ int play_fmt; /**< Audio playback sample format */ int enc_fmt; /**< Audio encoder sample format */ int dec_fmt; /**< Audio decoder sample format */ struct range buffer; /**< Audio receive buffer in [ms] */ }; /** Video */ struct config_video { char src_mod[16]; /**< Video source module */ char src_dev[128]; /**< Video source device */ char disp_mod[16]; /**< Video display module */ char disp_dev[128]; /**< Video display device */ unsigned width, height; /**< Video resolution */ uint32_t bitrate; /**< Encoder bitrate in [bit/s] */ double fps; /**< Video framerate */ bool fullscreen; /**< Enable fullscreen display */ int enc_fmt; /**< Encoder pixelfmt (enum vidfmt) */ }; /** Audio/Video Transport */ struct config_avt { uint8_t rtp_tos; /**< Type-of-Service for outg. RTP */ struct range rtp_ports; /**< RTP port range */ struct range rtp_bw; /**< RTP Bandwidth range [bit/s] */ bool rtcp_mux; /**< RTP/RTCP multiplexing */ struct range jbuf_del; /**< Delay, number of frames */ bool rtp_stats; /**< Enable RTP statistics */ uint32_t rtp_timeout; /**< RTP Timeout in seconds (0=off) */ }; /** Network Configuration */ struct config_net { int af; /**< AF_UNSPEC, AF_INET or AF_INET6 */ char ifname[64]; /**< Bind to interface (optional) */ struct { char addr[64]; bool fallback; } nsv[NET_MAX_NS]; /**< Configured DNS nameservers */ size_t nsc; /**< Number of DNS nameservers */ }; /** Core configuration */ struct config { struct config_sip sip; struct config_call call; struct config_audio audio; struct config_video video; struct config_avt avt; struct config_net net; }; int config_parse_conf(struct config *cfg, const struct conf *conf); int config_print(struct re_printf *pf, const struct config *cfg); int config_write_template(const char *file, const struct config *cfg); struct config *conf_config(void); /* * Contact */ enum presence_status { PRESENCE_UNKNOWN, PRESENCE_OPEN, PRESENCE_CLOSED, PRESENCE_BUSY }; struct contact; typedef void (contact_update_h)(struct contact *c, bool removed, void *arg); struct contacts; int contact_init(struct contacts **contactsp); int contact_add(struct contacts *contacts, struct contact **contactp, const struct pl *addr); void contact_remove(struct contacts *contacts, struct contact *c); void contacts_enable_presence(struct contacts *contacts, bool enabled); void contact_set_update_handler(struct contacts *contacs, contact_update_h *updateh, void *arg); int contact_print(struct re_printf *pf, const struct contact *cnt); int contacts_print(struct re_printf *pf, const struct contacts *contacts); enum presence_status contact_presence(const struct contact *c); void contact_set_presence(struct contact *c, enum presence_status status); bool contact_block_access(const struct contacts *contacts, const char *uri); struct contact *contact_find(const struct contacts *contacts, const char *uri); struct sip_addr *contact_addr(const struct contact *c); struct list *contact_list(const struct contacts *contacts); const char *contact_str(const struct contact *c); const char *contact_uri(const struct contact *c); const char *contact_presence_str(enum presence_status status); struct le *contact_le(struct contact *cnt); void contacts_set_current(struct contacts *contacts, struct contact *cnt); struct contact *contacts_current(const struct contacts *contacts); /* * Media Context */ /** Media Context */ struct media_ctx { const char *id; /**< Media Context identifier */ }; /* * Media Device */ /** Defines a media device */ struct mediadev { struct le le; char *name; }; int mediadev_add(struct list *dev_list, const char *name); struct mediadev *mediadev_find(const struct list *dev_list, const char *name); struct mediadev *mediadev_get_default(const struct list *dev_list); int mediadev_print(struct re_printf *pf, const struct list *dev_list); /* * Message */ typedef void (message_recv_h)(struct ua *ua, const struct pl *peer, const struct pl *ctype, struct mbuf *body, void *arg); struct message; int message_init(struct message **messagep); int message_listen(struct message *message, message_recv_h *h, void *arg); void message_unlisten(struct message *message, message_recv_h *recvh); int message_send(struct ua *ua, const char *peer, const char *msg, sip_resp_h *resph, void *arg); /* * Audio Source */ struct ausrc; struct ausrc_st; /** Audio Source parameters */ struct ausrc_prm { uint32_t srate; /**< Sampling rate in [Hz] */ uint8_t ch; /**< Number of channels */ uint32_t ptime; /**< Wanted packet-time in [ms] */ int fmt; /**< Sample format (enum aufmt) */ }; typedef void (ausrc_read_h)(struct auframe *af, void *arg); typedef void (ausrc_error_h)(int err, const char *str, void *arg); typedef int (ausrc_alloc_h)(struct ausrc_st **stp, const struct ausrc *ausrc, struct media_ctx **ctx, struct ausrc_prm *prm, const char *device, ausrc_read_h *rh, ausrc_error_h *errh, void *arg); /** Defines an Audio Source */ struct ausrc { struct le le; const char *name; struct list dev_list; ausrc_alloc_h *alloch; }; int ausrc_register(struct ausrc **asp, struct list *ausrcl, const char *name, ausrc_alloc_h *alloch); const struct ausrc *ausrc_find(const struct list *ausrcl, const char *name); int ausrc_alloc(struct ausrc_st **stp, struct list *ausrcl, struct media_ctx **ctx, const char *name, struct ausrc_prm *prm, const char *device, ausrc_read_h *rh, ausrc_error_h *errh, void *arg); struct ausrc *ausrc_get(struct ausrc_st *st); /* * Audio Player */ struct auplay; struct auplay_st; /** Audio Player parameters */ struct auplay_prm { uint32_t srate; /**< Sampling rate in [Hz] */ uint8_t ch; /**< Number of channels */ uint32_t ptime; /**< Wanted packet-time in [ms] */ int fmt; /**< Sample format (enum aufmt) */ }; typedef void (auplay_write_h)(void *sampv, size_t sampc, void *arg); typedef int (auplay_alloc_h)(struct auplay_st **stp, const struct auplay *ap, struct auplay_prm *prm, const char *device, auplay_write_h *wh, void *arg); /** Defines an Audio Player */ struct auplay { struct le le; const char *name; struct list dev_list; auplay_alloc_h *alloch; }; int auplay_register(struct auplay **pp, struct list *auplayl, const char *name, auplay_alloc_h *alloch); const struct auplay *auplay_find(const struct list *auplayl, const char *name); int auplay_alloc(struct auplay_st **stp, struct list *auplayl, const char *name, struct auplay_prm *prm, const char *device, auplay_write_h *wh, void *arg); struct auplay *auplay_get(struct auplay_st *st); /* * Audio Filter */ struct aufilt; /* Base class */ struct aufilt_enc_st { const struct aufilt *af; struct le le; }; struct aufilt_dec_st { const struct aufilt *af; struct le le; }; /** Audio Filter Parameters */ struct aufilt_prm { uint32_t srate; /**< Sampling rate in [Hz] */ uint8_t ch; /**< Number of channels */ int fmt; /**< Sample format (enum aufmt) */ }; typedef int (aufilt_encupd_h)(struct aufilt_enc_st **stp, void **ctx, const struct aufilt *af, struct aufilt_prm *prm, const struct audio *au); typedef int (aufilt_encode_h)(struct aufilt_enc_st *st, struct auframe *af); typedef int (aufilt_decupd_h)(struct aufilt_dec_st **stp, void **ctx, const struct aufilt *af, struct aufilt_prm *prm, const struct audio *au); typedef int (aufilt_decode_h)(struct aufilt_dec_st *st, struct auframe *af); struct aufilt { struct le le; const char *name; aufilt_encupd_h *encupdh; aufilt_encode_h *ench; aufilt_decupd_h *decupdh; aufilt_decode_h *dech; }; void aufilt_register(struct list *aufiltl, struct aufilt *af); void aufilt_unregister(struct aufilt *af); /* * Log */ enum log_level { LEVEL_DEBUG = 0, LEVEL_INFO, LEVEL_WARN, LEVEL_ERROR, }; typedef void (log_h)(uint32_t level, const char *msg); struct log { struct le le; log_h *h; }; void log_register_handler(struct log *logh); void log_unregister_handler(struct log *logh); void log_level_set(enum log_level level); enum log_level log_level_get(void); const char *log_level_name(enum log_level level); void log_enable_debug(bool enable); void log_enable_info(bool enable); void log_enable_stdout(bool enable); void vlog(enum log_level level, const char *fmt, va_list ap); void loglv(enum log_level level, const char *fmt, ...); void debug(const char *fmt, ...); void info(const char *fmt, ...); void warning(const char *fmt, ...); /* * Menc - Media encryption (for RTP) */ struct menc; struct menc_sess; struct menc_media; /** Defines a media encryption event */ enum menc_event { MENC_EVENT_SECURE, /**< Media is secured */ MENC_EVENT_VERIFY_REQUEST, /**< Request user to verify a code */ MENC_EVENT_PEER_VERIFIED, /**< Peer was verified successfully */ }; typedef void (menc_event_h)(enum menc_event event, const char *prm, struct stream *strm, void *arg); typedef void (menc_error_h)(int err, void *arg); typedef int (menc_sess_h)(struct menc_sess **sessp, struct sdp_session *sdp, bool offerer, menc_event_h *eventh, menc_error_h *errorh, void *arg); typedef int (menc_media_h)(struct menc_media **mp, struct menc_sess *sess, struct rtp_sock *rtp, struct udp_sock *rtpsock, struct udp_sock *rtcpsock, const struct sa *raddr_rtp, const struct sa *raddr_rtcp, struct sdp_media *sdpm, const struct stream *strm); struct menc { struct le le; const char *id; const char *sdp_proto; bool wait_secure; menc_sess_h *sessh; menc_media_h *mediah; }; void menc_register(struct list *mencl, struct menc *menc); void menc_unregister(struct menc *menc); const struct menc *menc_find(const struct list *mencl, const char *id); const char *menc_event_name(enum menc_event event); /* * Net - Networking */ struct network; typedef void (net_change_h)(void *arg); int net_alloc(struct network **netp, const struct config_net *cfg); int net_use_nameserver(struct network *net, const struct sa *srvv, size_t srvc); int net_set_address(struct network *net, const struct sa *ip); void net_change(struct network *net, uint32_t interval, net_change_h *ch, void *arg); void net_force_change(struct network *net); bool net_check(struct network *net); bool net_af_enabled(const struct network *net, int af); int net_set_af(struct network *net, int af); int net_dns_debug(struct re_printf *pf, const struct network *net); int net_debug(struct re_printf *pf, const struct network *net); const struct sa *net_laddr_af(const struct network *net, int af); const char *net_domain(const struct network *net); struct dnsc *net_dnsc(const struct network *net); /* * Play - audio file player */ struct play; struct player; int play_file(struct play **playp, struct player *player, const char *filename, int repeat, const char *play_mod, const char *play_dev); int play_tone(struct play **playp, struct player *player, struct mbuf *tone, uint32_t srate, uint8_t ch, int repeat, const char *play_mod, const char *play_dev); int play_init(struct player **playerp); void play_set_path(struct player *player, const char *path); /* * User Agent */ struct ua; /** Events from User-Agent */ enum ua_event { UA_EVENT_REGISTERING = 0, UA_EVENT_REGISTER_OK, UA_EVENT_REGISTER_FAIL, UA_EVENT_UNREGISTERING, UA_EVENT_MWI_NOTIFY, UA_EVENT_SHUTDOWN, UA_EVENT_EXIT, UA_EVENT_CALL_INCOMING, UA_EVENT_CALL_RINGING, UA_EVENT_CALL_PROGRESS, UA_EVENT_CALL_ESTABLISHED, UA_EVENT_CALL_CLOSED, UA_EVENT_CALL_TRANSFER, UA_EVENT_CALL_TRANSFER_FAILED, UA_EVENT_CALL_DTMF_START, UA_EVENT_CALL_DTMF_END, UA_EVENT_CALL_RTPESTAB, UA_EVENT_CALL_RTCP, UA_EVENT_CALL_MENC, UA_EVENT_VU_TX, UA_EVENT_VU_RX, UA_EVENT_AUDIO_ERROR, UA_EVENT_CALL_LOCAL_SDP, /**< param: offer or answer */ UA_EVENT_CALL_REMOTE_SDP, /**< param: offer or answer */ UA_EVENT_MAX, }; /** Defines the User-Agent event handler */ typedef void (ua_event_h)(struct ua *ua, enum ua_event ev, struct call *call, const char *prm, void *arg); typedef void (options_resp_h)(int err, const struct sip_msg *msg, void *arg); typedef void (ua_exit_h)(void *arg); /* Multiple instances */ int ua_alloc(struct ua **uap, const char *aor); int ua_connect(struct ua *ua, struct call **callp, const char *from_uri, const char *req_uri, enum vidmode vmode); void ua_hangup(struct ua *ua, struct call *call, uint16_t scode, const char *reason); int ua_answer(struct ua *ua, struct call *call, enum vidmode vmode); int ua_hold_answer(struct ua *ua, struct call *call, enum vidmode vmode); int ua_options_send(struct ua *ua, const char *uri, options_resp_h *resph, void *arg); int ua_debug(struct re_printf *pf, const struct ua *ua); int ua_state_json_api(struct odict *od, const struct ua *ua); int ua_print_calls(struct re_printf *pf, const struct ua *ua); int ua_print_status(struct re_printf *pf, const struct ua *ua); int ua_print_supported(struct re_printf *pf, const struct ua *ua); int ua_update_account(struct ua *ua); int ua_register(struct ua *ua); void ua_unregister(struct ua *ua); bool ua_isregistered(const struct ua *ua); unsigned ua_destroy(struct ua *ua); void ua_pub_gruu_set(struct ua *ua, const struct pl *pval); const char *ua_aor(const struct ua *ua); const char *ua_cuser(const struct ua *ua); const char *ua_local_cuser(const struct ua *ua); struct account *ua_account(const struct ua *ua); const char *ua_outbound(const struct ua *ua); struct call *ua_call(const struct ua *ua); struct call *ua_prev_call(const struct ua *ua); struct list *ua_calls(const struct ua *ua); enum presence_status ua_presence_status(const struct ua *ua); void ua_presence_status_set(struct ua *ua, const enum presence_status status); void ua_set_media_af(struct ua *ua, int af_media); void ua_set_catchall(struct ua *ua, bool enabled); void ua_event(struct ua *ua, enum ua_event ev, struct call *call, const char *fmt, ...); int ua_add_xhdr_filter(struct ua *ua, const char *hdr_name); int ua_set_custom_hdrs(struct ua *ua, struct list *custom_hdrs); int ua_uri_complete(struct ua *ua, struct mbuf *buf, const char *uri); int ua_call_alloc(struct call **callp, struct ua *ua, enum vidmode vidmode, const struct sip_msg *msg, struct call *xcall, const char *local_uri, bool use_rtp); /* One instance */ int ua_init(const char *software, bool udp, bool tcp, bool tls); void ua_close(void); void ua_stop_all(bool forced); void uag_set_exit_handler(ua_exit_h *exith, void *arg); void uag_enable_sip_trace(bool enable); int uag_reset_transp(bool reg, bool reinvite); int uag_event_register(ua_event_h *eh, void *arg); void uag_event_unregister(ua_event_h *eh); void uag_set_sub_handler(sip_msg_h *subh); int uag_set_extra_params(const char *eprm); struct ua *uag_find(const struct pl *cuser); struct ua *uag_find_aor(const char *aor); struct ua *uag_find_param(const char *name, const char *val); struct sip *uag_sip(void); const char *uag_event_str(enum ua_event ev); struct list *uag_list(void); void uag_current_set(struct ua *ua); struct ua *uag_current(void); struct sipsess_sock *uag_sipsess_sock(void); struct sipevent_sock *uag_sipevent_sock(void); /* * User Interface */ struct ui_sub { struct list uil; /**< List of UIs (struct ui) */ struct cmd_ctx *uictx; /**< Command context */ }; typedef int (ui_output_h)(const char *str); /** Defines a User-Interface module */ struct ui { struct le le; /**< Linked-list element */ const char *name; /**< Name of the UI-module */ ui_output_h *outputh; /**< Handler for output strings (optional) */ }; void ui_register(struct ui_sub *uis, struct ui *ui); void ui_unregister(struct ui *ui); void ui_reset(struct ui_sub *uis); void ui_input_key(struct ui_sub *uis, char key, struct re_printf *pf); void ui_input_str(const char *str); int ui_input_pl(struct re_printf *pf, const struct pl *pl); int ui_input_long_command(struct re_printf *pf, const struct pl *pl); void ui_output(struct ui_sub *uis, const char *fmt, ...); bool ui_isediting(const struct ui_sub *uis); int ui_password_prompt(char **passwordp); /* * Command interface */ /* special keys */ #define KEYCODE_NONE (0x00) /* No key */ #define KEYCODE_REL (0x04) /* Key was released */ #define KEYCODE_ESC (0x1b) /* Escape key */ /** Command flags */ enum { CMD_PRM = (1<<0), /**< Command with parameter */ }; /** Command arguments */ struct cmd_arg { char key; /**< Which key was pressed */ char *prm; /**< Optional parameter */ void *data; /**< Application data */ }; /** Defines a command */ struct cmd { const char *name; /**< Long command */ char key; /**< Short command */ int flags; /**< Optional command flags */ const char *desc; /**< Description string */ re_printf_h *h; /**< Command handler */ }; struct cmd_ctx; struct commands; int cmd_init(struct commands **commandsp); int cmd_register(struct commands *commands, const struct cmd *cmdv, size_t cmdc); void cmd_unregister(struct commands *commands, const struct cmd *cmdv); int cmd_process(struct commands *commands, struct cmd_ctx **ctxp, char key, struct re_printf *pf, void *data); int cmd_process_long(struct commands *commands, const char *str, size_t len, struct re_printf *pf_resp, void *data); int cmd_print(struct re_printf *pf, const struct commands *commands); const struct cmd *cmd_find_long(const struct commands *commands, const char *name); struct cmds *cmds_find(const struct commands *commands, const struct cmd *cmdv); /* * Video Source */ struct vidsrc; struct vidsrc_st; /** Video Source parameters */ struct vidsrc_prm { double fps; /**< Wanted framerate */ int fmt; /**< Wanted pixel format (enum vidfmt) */ }; /** * Provides video frames to the core * * @param frame Video frame * @param timestamp Frame timestamp in VIDEO_TIMEBASE units * @param arg Handler argument */ typedef void (vidsrc_frame_h)(struct vidframe *frame, uint64_t timestamp, void *arg); typedef void (vidsrc_error_h)(int err, void *arg); typedef int (vidsrc_alloc_h)(struct vidsrc_st **vsp, const struct vidsrc *vs, struct media_ctx **ctx, struct vidsrc_prm *prm, const struct vidsz *size, const char *fmt, const char *dev, vidsrc_frame_h *frameh, vidsrc_error_h *errorh, void *arg); typedef void (vidsrc_update_h)(struct vidsrc_st *st, struct vidsrc_prm *prm, const char *dev); /** Defines a video source */ struct vidsrc { struct le le; const char *name; struct list dev_list; vidsrc_alloc_h *alloch; vidsrc_update_h *updateh; }; int vidsrc_register(struct vidsrc **vp, struct list *vidsrcl, const char *name, vidsrc_alloc_h *alloch, vidsrc_update_h *updateh); const struct vidsrc *vidsrc_find(const struct list *vidsrcl, const char *name); int vidsrc_alloc(struct vidsrc_st **stp, struct list *vidsrcl, const char *name, struct media_ctx **ctx, struct vidsrc_prm *prm, const struct vidsz *size, const char *fmt, const char *dev, vidsrc_frame_h *frameh, vidsrc_error_h *errorh, void *arg); struct vidsrc *vidsrc_get(struct vidsrc_st *st); /* * Video Display */ struct vidisp; struct vidisp_st; /** Video Display parameters */ struct vidisp_prm { bool fullscreen; /**< Enable fullscreen display */ }; typedef void (vidisp_resize_h)(const struct vidsz *size, void *arg); typedef int (vidisp_alloc_h)(struct vidisp_st **vp, const struct vidisp *vd, struct vidisp_prm *prm, const char *dev, vidisp_resize_h *resizeh, void *arg); typedef int (vidisp_update_h)(struct vidisp_st *st, bool fullscreen, int orient, const struct vidrect *window); typedef int (vidisp_disp_h)(struct vidisp_st *st, const char *title, const struct vidframe *frame, uint64_t timestamp); typedef void (vidisp_hide_h)(struct vidisp_st *st); /** Defines a Video display */ struct vidisp { struct le le; const char *name; vidisp_alloc_h *alloch; vidisp_update_h *updateh; vidisp_disp_h *disph; vidisp_hide_h *hideh; }; int vidisp_register(struct vidisp **vp, struct list *vidispl, const char *name, vidisp_alloc_h *alloch, vidisp_update_h *updateh, vidisp_disp_h *disph, vidisp_hide_h *hideh); int vidisp_alloc(struct vidisp_st **stp, struct list *vidispl, const char *name, struct vidisp_prm *prm, const char *dev, vidisp_resize_h *resizeh, void *arg); int vidisp_display(struct vidisp_st *st, const char *title, const struct vidframe *frame, uint64_t timestamp); const struct vidisp *vidisp_find(const struct list *vidispl, const char *name); struct vidisp *vidisp_get(struct vidisp_st *st); /* * Audio Codec */ /** Audio Codec parameters */ struct auenc_param { uint32_t ptime; /**< Packet time in [ms] */ uint32_t bitrate; /**< Wanted bitrate in [bit/s] */ }; struct auenc_state; struct audec_state; struct aucodec; typedef int (auenc_update_h)(struct auenc_state **aesp, const struct aucodec *ac, struct auenc_param *prm, const char *fmtp); typedef int (auenc_encode_h)(struct auenc_state *aes, bool *marker, uint8_t *buf, size_t *len, int fmt, const void *sampv, size_t sampc); typedef int (audec_update_h)(struct audec_state **adsp, const struct aucodec *ac, const char *fmtp); typedef int (audec_decode_h)(struct audec_state *ads, int fmt, void *sampv, size_t *sampc, bool marker, const uint8_t *buf, size_t len); typedef int (audec_plc_h)(struct audec_state *ads, int fmt, void *sampv, size_t *sampc, const uint8_t *buf, size_t len); struct aucodec { struct le le; const char *pt; const char *name; uint32_t srate; /* Audio samplerate */ uint32_t crate; /* RTP Clock rate */ uint8_t ch; uint8_t pch; /* RTP packet channels */ uint32_t ptime; /* Packet time in [ms] (optional) */ const char *fmtp; auenc_update_h *encupdh; auenc_encode_h *ench; audec_update_h *decupdh; audec_decode_h *dech; audec_plc_h *plch; sdp_fmtp_enc_h *fmtp_ench; sdp_fmtp_cmp_h *fmtp_cmph; }; void aucodec_register(struct list *aucodecl, struct aucodec *ac); void aucodec_unregister(struct aucodec *ac); const struct aucodec *aucodec_find(const struct list *aucodecl, const char *name, uint32_t srate, uint8_t ch); /* * Video Codec */ /** Video Codec parameters */ struct videnc_param { unsigned bitrate; /**< Encoder bitrate in [bit/s] */ unsigned pktsize; /**< RTP packetsize in [bytes] */ double fps; /**< Video framerate (max) */ uint32_t max_fs; }; struct videnc_state; struct viddec_state; struct vidcodec; typedef int (videnc_packet_h)(bool marker, uint64_t rtp_ts, const uint8_t *hdr, size_t hdr_len, const uint8_t *pld, size_t pld_len, void *arg); typedef int (videnc_update_h)(struct videnc_state **vesp, const struct vidcodec *vc, struct videnc_param *prm, const char *fmtp, videnc_packet_h *pkth, void *arg); typedef int (videnc_encode_h)(struct videnc_state *ves, bool update, const struct vidframe *frame, uint64_t timestamp); typedef int (viddec_update_h)(struct viddec_state **vdsp, const struct vidcodec *vc, const char *fmtp); typedef int (viddec_decode_h)(struct viddec_state *vds, struct vidframe *frame, bool *intra, bool marker, uint16_t seq, struct mbuf *mb); struct vidcodec { struct le le; const char *pt; const char *name; const char *variant; const char *fmtp; videnc_update_h *encupdh; videnc_encode_h *ench; viddec_update_h *decupdh; viddec_decode_h *dech; sdp_fmtp_enc_h *fmtp_ench; sdp_fmtp_cmp_h *fmtp_cmph; }; void vidcodec_register(struct list *vidcodecl, struct vidcodec *vc); void vidcodec_unregister(struct vidcodec *vc); const struct vidcodec *vidcodec_find(const struct list *vidcodecl, const char *name, const char *variant); const struct vidcodec *vidcodec_find_encoder(const struct list *vidcodecl, const char *name); const struct vidcodec *vidcodec_find_decoder(const struct list *vidcodecl, const char *name); /* * Video Filter */ struct vidfilt; /* Base class */ struct vidfilt_enc_st { const struct vidfilt *vf; struct le le; }; struct vidfilt_dec_st { const struct vidfilt *vf; struct le le; }; /** Video Filter Parameters */ struct vidfilt_prm { unsigned width; /**< Picture width */ unsigned height; /**< Picture height */ int fmt; /**< Pixel format (enum vidfmt) */ double fps; /**< Video framerate */ }; typedef int (vidfilt_encupd_h)(struct vidfilt_enc_st **stp, void **ctx, const struct vidfilt *vf, struct vidfilt_prm *prm, const struct video *vid); typedef int (vidfilt_encode_h)(struct vidfilt_enc_st *st, struct vidframe *frame, uint64_t *timestamp); typedef int (vidfilt_decupd_h)(struct vidfilt_dec_st **stp, void **ctx, const struct vidfilt *vf, struct vidfilt_prm *prm, const struct video *vid); typedef int (vidfilt_decode_h)(struct vidfilt_dec_st *st, struct vidframe *frame, uint64_t *timestamp); struct vidfilt { struct le le; const char *name; vidfilt_encupd_h *encupdh; vidfilt_encode_h *ench; vidfilt_decupd_h *decupdh; vidfilt_decode_h *dech; }; void vidfilt_register(struct list *vidfiltl, struct vidfilt *vf); void vidfilt_unregister(struct vidfilt *vf); int vidfilt_enc_append(struct list *filtl, void **ctx, const struct vidfilt *vf, struct vidfilt_prm *prm, const struct video *vid); int vidfilt_dec_append(struct list *filtl, void **ctx, const struct vidfilt *vf, struct vidfilt_prm *prm, const struct video *vid); /* * Audio stream */ struct audio; struct stream_param; struct mnat; struct mnat_sess; typedef void (audio_event_h)(int key, bool end, void *arg); typedef void (audio_level_h)(bool tx, double lvl, void *arg); typedef void (audio_err_h)(int err, const char *str, void *arg); int audio_alloc(struct audio **ap, struct list *streaml, const struct stream_param *stream_prm, const struct config *cfg, struct account *acc, struct sdp_session *sdp_sess, int label, const struct mnat *mnat, struct mnat_sess *mnat_sess, const struct menc *menc, struct menc_sess *menc_sess, uint32_t ptime, const struct list *aucodecl, bool offerer, audio_event_h *eventh, audio_level_h *levelh, audio_err_h *errh, void *arg); void audio_mute(struct audio *a, bool muted); bool audio_ismuted(const struct audio *a); int audio_set_devicename(struct audio *a, const char *src, const char *play); int audio_set_source(struct audio *au, const char *mod, const char *device); int audio_set_player(struct audio *au, const char *mod, const char *device); void audio_level_put(const struct audio *au, bool tx, double lvl); int audio_level_get(const struct audio *au, double *level); int audio_debug(struct re_printf *pf, const struct audio *a); struct stream *audio_strm(const struct audio *au); uint64_t audio_jb_current_value(const struct audio *au); int audio_set_bitrate(struct audio *au, uint32_t bitrate); bool audio_rxaubuf_started(const struct audio *au); int audio_start(struct audio *a); int audio_start_source(struct audio *a, struct list *ausrcl, struct list *aufiltl); void audio_stop(struct audio *a); bool audio_started(const struct audio *a); void audio_set_hold(struct audio *au, bool hold); int audio_encoder_set(struct audio *a, const struct aucodec *ac, int pt_tx, const char *params); int audio_decoder_set(struct audio *a, const struct aucodec *ac, int pt_rx, const char *params); const struct aucodec *audio_codec(const struct audio *au, bool tx); struct config_audio *audio_config(struct audio *au); void audio_set_media_context(struct audio *au, struct media_ctx **ctx); /* * Video stream */ struct video; typedef void (video_err_h)(int err, const char *str, void *arg); int video_alloc(struct video **vp, struct list *streaml, const struct stream_param *stream_prm, const struct config *cfg, struct sdp_session *sdp_sess, int label, const struct mnat *mnat, struct mnat_sess *mnat_sess, const struct menc *menc, struct menc_sess *menc_sess, const char *content, const struct list *vidcodecl, const struct list *vidfiltl, bool offerer, video_err_h *errh, void *arg); int video_encoder_set(struct video *v, struct vidcodec *vc, int pt_tx, const char *params); int video_start_source(struct video *v, struct media_ctx **ctx); int video_start_display(struct video *v, const char *peer); void video_stop(struct video *v); void video_stop_display(struct video *v); int video_set_fullscreen(struct video *v, bool fs); void video_vidsrc_set_device(struct video *v, const char *dev); int video_set_source(struct video *v, const char *name, const char *dev); void video_set_devicename(struct video *v, const char *src, const char *disp); int video_debug(struct re_printf *pf, const struct video *v); uint64_t video_calc_rtp_timestamp_fix(uint64_t timestamp); double video_calc_seconds(uint64_t rtp_ts); struct stream *video_strm(const struct video *v); double video_timestamp_to_seconds(uint64_t timestamp); uint64_t video_calc_timebase_timestamp(uint64_t rtp_ts); const struct vidcodec *video_codec(const struct video *vid, bool tx); void video_sdp_attr_decode(struct video *v); /* * Generic stream */ /** Common parameters for media stream */ struct stream_param { bool use_rtp; /**< Enable or disable RTP */ int af; /**< Wanted address family */ const char *cname; /**< Canonical name */ }; typedef void (stream_mnatconn_h)(struct stream *strm, void *arg); typedef void (stream_rtpestab_h)(struct stream *strm, void *arg); typedef void (stream_rtcp_h)(struct stream *strm, struct rtcp_msg *msg, void *arg); typedef void (stream_error_h)(struct stream *strm, int err, void *arg); void stream_update(struct stream *s); const struct rtcp_stats *stream_rtcp_stats(const struct stream *strm); struct sdp_media *stream_sdpmedia(const struct stream *s); uint32_t stream_metric_get_tx_n_packets(const struct stream *strm); uint32_t stream_metric_get_tx_n_bytes(const struct stream *strm); uint32_t stream_metric_get_tx_n_err(const struct stream *strm); uint32_t stream_metric_get_rx_n_packets(const struct stream *strm); uint32_t stream_metric_get_rx_n_bytes(const struct stream *strm); uint32_t stream_metric_get_rx_n_err(const struct stream *strm); void stream_set_secure(struct stream *strm, bool secure); bool stream_is_secure(const struct stream *strm); int stream_start_mediaenc(struct stream *strm); int stream_start(const struct stream *strm); void stream_set_session_handlers(struct stream *strm, stream_mnatconn_h *mnatconnh, stream_rtpestab_h *rtpestabh, stream_rtcp_h *rtcph, stream_error_h *errorh, void *arg); const char *stream_name(const struct stream *strm); int stream_debug(struct re_printf *pf, const struct stream *s); /* * STUN URI */ /** Defines the STUN uri scheme */ enum stun_scheme { STUN_SCHEME_STUN, /**< STUN scheme */ STUN_SCHEME_STUNS, /**< Secure STUN scheme */ STUN_SCHEME_TURN, /**< TURN scheme */ STUN_SCHEME_TURNS, /**< Secure TURN scheme */ }; /** Defines a STUN/TURN uri */ struct stun_uri { enum stun_scheme scheme; /**< STUN Scheme */ char *host; /**< Hostname or IP-address */ uint16_t port; /**< Port number */ }; int stunuri_decode(struct stun_uri **sup, const struct pl *pl); int stunuri_set_host(struct stun_uri *su, const char *host); int stunuri_set_port(struct stun_uri *su, uint16_t port); int stunuri_print(struct re_printf *pf, const struct stun_uri *su); const char *stunuri_scheme_name(enum stun_scheme scheme); /* * Media NAT */ struct mnat; struct mnat_sess; struct mnat_media; typedef void (mnat_estab_h)(int err, uint16_t scode, const char *reason, void *arg); typedef void (mnat_connected_h)(const struct sa *raddr1, const struct sa *raddr2, void *arg); typedef int (mnat_sess_h)(struct mnat_sess **sessp, const struct mnat *mnat, struct dnsc *dnsc, int af, const struct stun_uri *srv, const char *user, const char *pass, struct sdp_session *sdp, bool offerer, mnat_estab_h *estabh, void *arg); typedef int (mnat_media_h)(struct mnat_media **mp, struct mnat_sess *sess, struct udp_sock *sock1, struct udp_sock *sock2, struct sdp_media *sdpm, mnat_connected_h *connh, void *arg); typedef int (mnat_update_h)(struct mnat_sess *sess); struct mnat { struct le le; const char *id; const char *ftag; bool wait_connected; mnat_sess_h *sessh; mnat_media_h *mediah; mnat_update_h *updateh; }; void mnat_register(struct list *mnatl, struct mnat *mnat); void mnat_unregister(struct mnat *mnat); const struct mnat *mnat_find(const struct list *mnatl, const char *id); /* * SDP */ bool sdp_media_has_media(const struct sdp_media *m); int sdp_fingerprint_decode(const char *attr, struct pl *hash, uint8_t *md, size_t *sz); /* * SIP Request */ int sip_req_send(struct ua *ua, const char *method, const char *uri, sip_resp_h *resph, void *arg, const char *fmt, ...); /* * H.264 */ /** NAL unit types (RFC 3984, Table 1) */ enum { H264_NAL_UNKNOWN = 0, /* 1-23 NAL unit Single NAL unit packet per H.264 */ H264_NAL_SLICE = 1, H264_NAL_DPA = 2, H264_NAL_DPB = 3, H264_NAL_DPC = 4, H264_NAL_IDR_SLICE = 5, H264_NAL_SEI = 6, H264_NAL_SPS = 7, H264_NAL_PPS = 8, H264_NAL_AUD = 9, H264_NAL_END_SEQUENCE = 10, H264_NAL_END_STREAM = 11, H264_NAL_FILLER_DATA = 12, H264_NAL_SPS_EXT = 13, H264_NAL_AUX_SLICE = 19, H264_NAL_STAP_A = 24, /**< Single-time aggregation packet */ H264_NAL_STAP_B = 25, /**< Single-time aggregation packet */ H264_NAL_MTAP16 = 26, /**< Multi-time aggregation packet */ H264_NAL_MTAP24 = 27, /**< Multi-time aggregation packet */ H264_NAL_FU_A = 28, /**< Fragmentation unit */ H264_NAL_FU_B = 29, /**< Fragmentation unit */ }; /** * H.264 Header defined in RFC 3984 * *
      +---------------+
      |0|1|2|3|4|5|6|7|
      +-+-+-+-+-+-+-+-+
      |F|NRI|  Type   |
      +---------------+
 * 
*/ struct h264_hdr { unsigned f:1; /**< 1 bit - Forbidden zero bit (must be 0) */ unsigned nri:2; /**< 2 bits - nal_ref_idc */ unsigned type:5; /**< 5 bits - nal_unit_type */ }; int h264_hdr_encode(const struct h264_hdr *hdr, struct mbuf *mb); int h264_hdr_decode(struct h264_hdr *hdr, struct mbuf *mb); /** Fragmentation Unit header */ struct h264_fu { unsigned s:1; /**< Start bit */ unsigned e:1; /**< End bit */ unsigned r:1; /**< The Reserved bit MUST be equal to 0 */ unsigned type:5; /**< The NAL unit payload type */ }; int h264_fu_hdr_encode(const struct h264_fu *fu, struct mbuf *mb); int h264_fu_hdr_decode(struct h264_fu *fu, struct mbuf *mb); const uint8_t *h264_find_startcode(const uint8_t *p, const uint8_t *end); int h264_packetize(uint64_t rtp_ts, const uint8_t *buf, size_t len, size_t pktsize, videnc_packet_h *pkth, void *arg); int h264_nal_send(bool first, bool last, bool marker, uint32_t ihdr, uint64_t rtp_ts, const uint8_t *buf, size_t size, size_t maxsz, videnc_packet_h *pkth, void *arg); const char *h264_nalunit_name(int type); static inline bool h264_is_keyframe(int type) { return type == H264_NAL_IDR_SLICE; } /* * Modules */ #ifdef STATIC #define DECL_EXPORTS(name) exports_ ##name #else #define DECL_EXPORTS(name) exports #endif int module_preload(const char *module); int module_load(const char *path, const char *name); void module_unload(const char *name); void module_app_unload(void); /* * Generic event */ int event_encode_dict(struct odict *od, struct ua *ua, enum ua_event ev, struct call *call, const char *prm); int event_add_au_jb_stat(struct odict *od_parent, const struct call *call); /* * Timer */ uint64_t tmr_jiffies_usec(void); /* * Baresip instance */ int baresip_init(struct config *cfg); void baresip_close(void); struct network *baresip_network(void); struct contacts *baresip_contacts(void); struct commands *baresip_commands(void); struct player *baresip_player(void); struct message *baresip_message(void); struct list *baresip_mnatl(void); struct list *baresip_mencl(void); struct list *baresip_aucodecl(void); struct list *baresip_ausrcl(void); struct list *baresip_auplayl(void); struct list *baresip_aufiltl(void); struct list *baresip_vidcodecl(void); struct list *baresip_vidsrcl(void); struct list *baresip_vidispl(void); struct list *baresip_vidfiltl(void); struct ui_sub *baresip_uis(void); #ifdef __cplusplus } #endif #endif /* BARESIP_H__ */ baresip-1.0.0/mk/000077500000000000000000000000001372575704200135605ustar00rootroot00000000000000baresip-1.0.0/mk/Doxyfile000066400000000000000000000213041372575704200152660ustar00rootroot00000000000000# Doxyfile 1.4.7 #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- PROJECT_NAME = baresip PROJECT_NUMBER = 1.0.0 OUTPUT_DIRECTORY = ../baresip-dox CREATE_SUBDIRS = NO OUTPUT_LANGUAGE = English #USE_WINDOWS_ENCODING = NO BRIEF_MEMBER_DESC = YES REPEAT_BRIEF = YES ABBREVIATE_BRIEF = "The $name class" \ "The $name widget" \ "The $name file" \ is \ provides \ specifies \ contains \ represents \ a \ an \ the ALWAYS_DETAILED_SEC = NO INLINE_INHERITED_MEMB = NO FULL_PATH_NAMES = NO STRIP_FROM_PATH = STRIP_FROM_INC_PATH = SHORT_NAMES = NO JAVADOC_AUTOBRIEF = YES MULTILINE_CPP_IS_BRIEF = NO INHERIT_DOCS = YES SEPARATE_MEMBER_PAGES = NO TAB_SIZE = 8 ALIASES = OPTIMIZE_OUTPUT_FOR_C = YES OPTIMIZE_OUTPUT_JAVA = NO #BUILTIN_STL_SUPPORT = NO DISTRIBUTE_GROUP_DOC = NO SUBGROUPING = YES #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- EXTRACT_ALL = NO EXTRACT_PRIVATE = NO EXTRACT_STATIC = NO EXTRACT_LOCAL_CLASSES = YES EXTRACT_LOCAL_METHODS = NO HIDE_UNDOC_MEMBERS = YES HIDE_UNDOC_CLASSES = YES HIDE_FRIEND_COMPOUNDS = NO HIDE_IN_BODY_DOCS = NO INTERNAL_DOCS = NO CASE_SENSE_NAMES = YES HIDE_SCOPE_NAMES = NO SHOW_INCLUDE_FILES = YES INLINE_INFO = YES SORT_MEMBER_DOCS = YES SORT_BRIEF_DOCS = NO SORT_BY_SCOPE_NAME = NO GENERATE_TODOLIST = YES GENERATE_TESTLIST = YES GENERATE_BUGLIST = YES GENERATE_DEPRECATEDLIST= YES ENABLED_SECTIONS = MAX_INITIALIZER_LINES = 30 SHOW_USED_FILES = YES #SHOW_DIRECTORIES = NO FILE_VERSION_FILTER = #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- QUIET = YES WARNINGS = YES WARN_IF_UNDOCUMENTED = YES WARN_IF_DOC_ERROR = YES WARN_NO_PARAMDOC = YES WARN_FORMAT = "$file:$line: $text" WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- INPUT = . FILE_PATTERNS = *.cpp *.c \ *.h \ *.m \ *.dox RECURSIVE = YES EXCLUDE = modules/ctrl_tcp/netstring EXCLUDE_SYMLINKS = NO EXCLUDE_PATTERNS = */.svn/* EXAMPLE_PATH = EXAMPLE_PATTERNS = * EXAMPLE_RECURSIVE = NO IMAGE_PATH = INPUT_FILTER = FILTER_PATTERNS = FILTER_SOURCE_FILES = NO #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- SOURCE_BROWSER = YES INLINE_SOURCES = NO STRIP_CODE_COMMENTS = YES REFERENCED_BY_RELATION = YES REFERENCES_RELATION = YES #REFERENCES_LINK_SOURCE = YES #USE_HTAGS = NO VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- ALPHABETICAL_INDEX = YES COLS_IN_ALPHA_INDEX = 5 IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- GENERATE_HTML = YES HTML_OUTPUT = html HTML_FILE_EXTENSION = .html HTML_HEADER = HTML_FOOTER = HTML_STYLESHEET = #HTML_ALIGN_MEMBERS = YES GENERATE_HTMLHELP = NO CHM_FILE = HHC_LOCATION = GENERATE_CHI = NO BINARY_TOC = NO TOC_EXPAND = NO DISABLE_INDEX = NO ENUM_VALUES_PER_LINE = 4 GENERATE_TREEVIEW = NO TREEVIEW_WIDTH = 250 #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- GENERATE_LATEX = NO LATEX_OUTPUT = latex LATEX_CMD_NAME = latex MAKEINDEX_CMD_NAME = makeindex COMPACT_LATEX = NO PAPER_TYPE = a4wide EXTRA_PACKAGES = LATEX_HEADER = PDF_HYPERLINKS = NO USE_PDFLATEX = NO LATEX_BATCHMODE = NO LATEX_HIDE_INDICES = NO #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- GENERATE_RTF = NO RTF_OUTPUT = rtf COMPACT_RTF = NO RTF_HYPERLINKS = NO RTF_STYLESHEET_FILE = RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- GENERATE_MAN = NO MAN_OUTPUT = man MAN_EXTENSION = .3 MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- GENERATE_XML = NO XML_OUTPUT = xml XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- GENERATE_PERLMOD = NO PERLMOD_LATEX = NO PERLMOD_PRETTY = YES PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- ENABLE_PREPROCESSING = YES MACRO_EXPANSION = YES EXPAND_ONLY_PREDEF = YES SEARCH_INCLUDES = YES INCLUDE_PATH = include INCLUDE_FILE_PATTERNS = PREDEFINED = "DEBUG_MODULE=foo /**< hei */" EXPAND_AS_DEFINED = SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- TAGFILES = GENERATE_TAGFILE = ALLEXTERNALS = NO EXTERNAL_GROUPS = YES #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- CLASS_DIAGRAMS = YES HIDE_UNDOC_RELATIONS = YES HAVE_DOT = YES CLASS_GRAPH = YES COLLABORATION_GRAPH = YES GROUP_GRAPHS = YES UML_LOOK = NO TEMPLATE_RELATIONS = NO INCLUDE_GRAPH = YES INCLUDED_BY_GRAPH = YES CALL_GRAPH = YES #CALLER_GRAPH = YES GRAPHICAL_HIERARCHY = YES DIRECTORY_GRAPH = YES DOT_IMAGE_FORMAT = png DOT_PATH = DOTFILE_DIRS = DOT_GRAPH_MAX_NODES = 250 #MAX_DOT_GRAPH_WIDTH = 1024 #MAX_DOT_GRAPH_HEIGHT = 1024 #MAX_DOT_GRAPH_DEPTH = 1000 DOT_TRANSPARENT = NO DOT_MULTI_TARGETS = NO GENERATE_LEGEND = YES DOT_CLEANUP = YES #--------------------------------------------------------------------------- # Configuration::additions related to the search engine #--------------------------------------------------------------------------- SEARCHENGINE = NO baresip-1.0.0/mk/mod.mk000066400000000000000000000060741372575704200146770ustar00rootroot00000000000000# # mod.mk # # Copyright (C) 2010 Creytiv.com # $(MOD)_OBJS := $(patsubst %.c,$(BUILD)/modules/$(MOD)/%.o,\ $(filter %.c,$($(MOD)_SRCS))) $(MOD)_OBJS += $(patsubst %.cpp,$(BUILD)/modules/$(MOD)/%.o,\ $(filter %.cpp,$($(MOD)_SRCS))) $(MOD)_OBJS += $(patsubst %.m,$(BUILD)/modules/$(MOD)/%.o,\ $(filter %.m,$($(MOD)_SRCS))) $(MOD)_OBJS += $(patsubst %.S,$(BUILD)/modules/$(MOD)/%.o,\ $(filter %.S,$($(MOD)_SRCS))) -include $($(MOD)_OBJS:.o=.d) $(MOD)_NAME := $(MOD) # # function to extract the name of the module from the file/dir path # modulename = $(lastword $(subst /, ,$(dir $1))) ifeq ($(STATIC),) # # Dynamically loaded modules # $(MOD)$(MOD_SUFFIX): $($(MOD)_OBJS) @echo " LD [M] $@" $(HIDE)$(LD) $(LFLAGS) $(SH_LFLAGS) $(MOD_LFLAGS) \ $($(basename $@)_OBJS) \ $($(basename $@)_LFLAGS) -L$(LIBRE_SO) -lre -o $@ $(BUILD)/modules/$(MOD)/%.o: modules/$(MOD)/%.c $(BUILD) Makefile mk/mod.mk \ modules/$(MOD)/module.mk mk/modules.mk @echo " CC [M] $@" @mkdir -p $(dir $@) $(HIDE)$(CC) $(CFLAGS) $($(call modulename,$@)_CFLAGS) \ -c $< -o $@ $(DFLAGS) $(BUILD)/modules/$(MOD)/%.o: modules/$(MOD)/%.m $(BUILD) Makefile mk/mod.mk \ modules/$(MOD)/module.mk mk/modules.mk @echo " OC [M] $@" @mkdir -p $(dir $@) $(HIDE)$(CC) $(CFLAGS) $($(call modulename,$@)_CFLAGS) $(OBJCFLAGS) \ -c $< -o $@ $(DFLAGS) $(BUILD)/modules/$(MOD)/%.o: modules/$(MOD)/%.cpp $(BUILD) Makefile mk/mod.mk \ modules/$(MOD)/module.mk mk/modules.mk @echo " CXX [M] $@" @mkdir -p $(dir $@) $(HIDE)$(CXX) $(CPPFLAGS) $(CXXFLAGS) \ $($(call modulename,$@)_CXXFLAGS) \ -c $< -o $@ $(DFLAGS) $(BUILD)/modules/$(MOD)/%.o: modules/$(MOD)/%.S $(BUILD) Makefile mk/mod.mk \ modules/$(MOD)/module.mk mk/modules.mk @echo " AS [M] $@" @mkdir -p $(dir $@) $(HIDE)$(CC) $(CFLAGS) -DMOD_NAME=\"$(MOD)\" -c $< -o $@ $(DFLAGS) else # # Static linking of modules # # needed to deref variable now, append to list MOD_OBJS := $(MOD_OBJS) $($(MOD)_OBJS) MOD_LFLAGS := $(MOD_LFLAGS) $($(MOD)_LFLAGS) $(BUILD)/modules/$(MOD)/%.o: modules/$(MOD)/%.c $(BUILD) Makefile mk/mod.mk \ modules/$(MOD)/module.mk mk/modules.mk @echo " CC [m] $@" @mkdir -p $(dir $@) $(HIDE)$(CC) $(CFLAGS) $($(call modulename,$@)_CFLAGS) \ -DMOD_NAME=\"$(MOD)\" -c $< -o $@ $(DFLAGS) $(BUILD)/modules/$(MOD)/%.o: modules/$(MOD)/%.m $(BUILD) Makefile mk/mod.mk \ modules/$(MOD)/module.mk mk/modules.mk @echo " OC [m] $@" @mkdir -p $(dir $@) $(HIDE)$(CC) $(CFLAGS) $($(call modulename,$@)_CFLAGS) $(OBJCFLAGS) \ -DMOD_NAME=\"$(MOD)\" -c $< -o $@ $(DFLAGS) $(BUILD)/modules/$(MOD)/%.o: modules/$(MOD)/%.cpp $(BUILD) Makefile mk/mod.mk \ modules/$(MOD)/module.mk mk/modules.mk @echo " CXX [m] $@" @mkdir -p $(dir $@) $(HIDE)$(CXX) $(CPPFLAGS) $(CXXFLAGS) \ $($(call modulename,$@)_CXXFLAGS) \ -DMOD_NAME=\"$(MOD)\" -c $< -o $@ $(DFLAGS) $(BUILD)/modules/$(MOD)/%.o: modules/$(MOD)/%.S $(BUILD) Makefile mk/mod.mk \ modules/$(MOD)/module.mk mk/modules.mk @echo " AS [m] $@" @mkdir -p $(dir $@) $(HIDE)$(CC) $(CFLAGS) -DMOD_NAME=\"$(MOD)\" -c $< -o $@ $(DFLAGS) endif baresip-1.0.0/mk/modules.mk000066400000000000000000000350311372575704200155630ustar00rootroot00000000000000# # modules.mk # # Copyright (C) 2010 - 2017 Creytiv.com # # External libraries: # # USE_AAC AAC audio codec # USE_ALSA ALSA audio driver # USE_AMR Adaptive Multi-Rate (AMR) audio codec # USE_APTX aptX audio codec # USE_AUDIOUNIT AudioUnit audio driver for OSX/iOS # USE_AVCAPTURE AVFoundation video capture for OSX/iOS # USE_AVCODEC avcodec video codec module # USE_AVFORMAT avformat video source module # USE_CAIRO Cairo module # USE_CODEC2 CODEC2 low-bitrate speech audio codec # USE_CONS Console input driver # USE_COREAUDIO MacOSX Coreaudio audio driver # USE_ECHO Echo module # USE_EVDEV Event Device module # USE_G711 G.711 audio codec # USE_G722 G.722 audio codec # USE_G722_1 G.722.1 audio codec # USE_G726 G.726 audio codec # USE_GSM GSM audio codec # USE_GST Gstreamer audio module # USE_GST_VIDEO Gstreamer video module # USE_GTK GTK+ user interface # USE_ILBC iLBC audio codec # USE_ISAC iSAC audio codec # USE_JACK JACK Audio Connection Kit audio driver # USE_L16 L16 audio codec # USE_MPA MPA audio codec # USE_MPG123 Use mpg123 # USE_OMX_RPI RaspberryPi VideoCore display driver # USE_OMX_BELLAGIO libomxil-bellagio xvideosink driver # USE_OPUS Opus audio codec # USE_OPUS_MS Opus multistream audio codec # USE_OSS OSS audio driver # USE_PLC Packet Loss Concealment # USE_PORTAUDIO Portaudio audio driver # USE_PULSE Pulseaudio audio driver # USE_RTCPSUMMARY RTCP summary output after calls # USE_SDL libSDL2 video output # USE_SNDFILE sndfile wav dumper # USE_SNDIO sndio audo driver # USE_SPEEX_PP Speex preprocessor # USE_SRTP Secure RTP module using libre # USE_STDIO stdio input driver # USE_SYSLOG Syslog module # USE_V4L2 Video4Linux2 module # USE_WINWAVE Windows audio driver # USE_X11 X11 video output # # Default is enabled MOD_AUTODETECT := 1 ifneq ($(MOD_AUTODETECT),) USE_CONS := 1 USE_G711 := 1 USE_L16 := 1 ifneq ($(OS),win32) USE_AAC := $(shell [ -f $(SYSROOT)/include/fdk-aac/FDK_audio.h ] || \ [ -f $(SYSROOT_LOCAL)/include/fdk-aac/FDK_audio.h ] || \ [ -f $(SYSROOT_ALT)/include/fdk-aac/FDK_audio.h ] && echo "yes") USE_ALSA := $(shell [ -f $(SYSROOT)/include/alsa/asoundlib.h ] || \ [ -f $(SYSROOT_ALT)/include/alsa/asoundlib.h ] && echo "yes") USE_AMR := $(shell [ -d $(SYSROOT)/include/opencore-amrnb ] || \ [ -d $(SYSROOT_LOCAL)/include/opencore-amrnb ] || \ [ -d $(SYSROOT_ALT)/include/opencore-amrnb ] || \ [ -d $(SYSROOT)/local/include/amrnb ] || \ [ -d $(SYSROOT)/include/amrnb ] && echo "yes") USE_APTX := $(shell [ -f $(SYSROOT)/include/openaptx.h ] || \ [ -f $(SYSROOT_LOCAL)/include/openaptx.h ] || \ [ -f $(SYSROOT_ALT)/include/openaptx.h ] && echo "yes") USE_AVCODEC := $(shell [ -f $(SYSROOT)/include/libavcodec/avcodec.h ] || \ [ -f $(SYSROOT_LOCAL)/include/libavcodec/avcodec.h ] || \ [ -f $(SYSROOT)/local/include/libavcodec/avcodec.h ] || \ [ -f $(SYSROOT)/include/$(MACHINE)/libavcodec/avcodec.h ] || \ [ -f $(SYSROOT_ALT)/include/libavcodec/avcodec.h ] && echo "yes") USE_AVFORMAT := $(shell ([ -f $(SYSROOT)/include/libavformat/avformat.h ] || \ [ -f $(SYSROOT_LOCAL)/include/libavformat/avformat.h ] || \ [ -f $(SYSROOT)/local/include/libavformat/avformat.h ] || \ [ -f $(SYSROOT)/include/$(MACHINE)/libavformat/avformat.h ] || \ [ -f $(SYSROOT_ALT)/include/libavformat/avformat.h ]) && \ ([ -f $(SYSROOT)/include/libavdevice/avdevice.h ] || \ [ -f $(SYSROOT_LOCAL)/include/libavdevice/avdevice.h ] || \ [ -f $(SYSROOT)/local/include/libavdevice/avdevice.h ] || \ [ -f $(SYSROOT)/include/$(MACHINE)/libavdevice/avdevice.h ] || \ [ -f $(SYSROOT_ALT)/include/libavdevice/avdevice.h ]) && echo "yes") USE_CAIRO := $(shell [ -f $(SYSROOT)/include/cairo/cairo.h ] || \ [ -f $(SYSROOT)/local/include/cairo/cairo.h ] || \ [ -f $(SYSROOT_ALT)/include/cairo/cairo.h ] && echo "yes") USE_CODEC2 := $(shell [ -f $(SYSROOT)/include/codec2/codec2.h ] || \ [ -f $(SYSROOT_LOCAL)/include/codec2/codec2.h ] || \ [ -f $(SYSROOT_ALT)/include/codec2/codec2.h ] && echo "yes") USE_DTLS := $(shell [ -f $(SYSROOT)/include/openssl/dtls1.h ] || \ [ -f $(SYSROOT)/local/include/openssl/dtls1.h ] || \ [ -f $(SYSROOT_ALT)/include/openssl/dtls1.h ] && echo "yes") USE_DTLS_SRTP := $(shell [ -f $(SYSROOT)/include/openssl/srtp.h ] || \ [ -f $(SYSROOT)/local/include/openssl/srtp.h ] || \ [ -f $(SYSROOT_ALT)/include/openssl/srtp.h ] && echo "yes") USE_G722 := $(shell [ -f $(SYSROOT)/include/spandsp/g722.h ] || \ [ -f $(SYSROOT_ALT)/include/spandsp/g722.h ] || \ [ -f $(SYSROOT_LOCAL)/include/spandsp/g722.h ] && echo "yes") USE_G722_1 := $(shell [ -f $(SYSROOT)/include/g722_1.h ] || \ [ -f $(SYSROOT_LOCAL)/include/g722_1.h ] || \ [ -f $(SYSROOT_ALT)/include/g722_1.h ] || \ [ -f $(SYSROOT)/local/include/g722_1.h ] && echo "yes") USE_G726 := $(shell [ -f $(SYSROOT)/include/spandsp/g726.h ] || \ [ -f $(SYSROOT_ALT)/include/spandsp/g726.h ] || \ [ -f $(SYSROOT_LOCAL)/include/spandsp/g726.h ] && echo "yes") USE_GSM := $(shell [ -f $(SYSROOT)/include/gsm.h ] || \ [ -f $(SYSROOT_ALT)/include/gsm.h ] || \ [ -f $(SYSROOT)/include/gsm/gsm.h ] || \ [ -f $(SYSROOT)/local/include/gsm.h ] || \ [ -f $(SYSROOT)/local/include/gsm/gsm.h ] && echo "yes") USE_GST := $(shell pkg-config --exists gstreamer-1.0 && echo "yes") USE_GST_VIDEO := $(shell pkg-config --exists gstreamer-1.0 gstreamer-app-1.0 \ && echo "yes") USE_GTK := $(shell pkg-config 'gtk+-2.0 >= 2.22' && \ pkg-config 'glib-2.0 >= 2.32' && echo "yes") USE_ILBC := $(shell [ -f $(SYSROOT)/include/iLBC_define.h ] || \ [ -f $(SYSROOT_LOCAL)/include/iLBC_define.h ] || \ [ -f $(SYSROOT)/local/include/iLBC_define.h ] && echo "yes") USE_ISAC := $(shell [ -f $(SYSROOT)/include/isac.h ] || \ [ -f $(SYSROOT)/local/include/isac.h ] && echo "yes") USE_JACK := $(shell [ -f $(SYSROOT)/include/jack/jack.h ] || \ [ -f $(SYSROOT_LOCAL)/include/jack/jack.h ] && echo "yes") USE_MPG123 := $(shell [ -f $(SYSROOT)/include/mpg123.h ] || \ [ -f $(SYSROOT)/local/include/mpg123.h ] || \ [ -f $(SYSROOT_ALT)/include/mpg123.h ] && echo "yes") USE_OPUS := $(shell [ -f $(SYSROOT)/include/opus/opus.h ] || \ [ -f $(SYSROOT_ALT)/include/opus/opus.h ] || \ [ -f $(SYSROOT_LOCAL)/include/opus/opus.h ] && echo "yes") USE_OPUS_MS := $(shell [ -f $(SYSROOT)/include/opus/opus_multistream.h ] || \ [ -f $(SYSROOT_ALT)/include/opus/opus_multistream.h ] || \ [ -f $(SYSROOT)/local/include/opus/opus_multistream.h ] && echo "yes") USE_OSS := $(shell [ -f $(SYSROOT)/include/soundcard.h ] || \ [ -f $(SYSROOT)/include/linux/soundcard.h ] || \ [ -f $(SYSROOT)/include/sys/soundcard.h ] && echo "yes") USE_PLC := $(shell [ -f $(SYSROOT)/include/spandsp/plc.h ] || \ [ -f $(SYSROOT_ALT)/include/spandsp/plc.h ] || \ [ -f $(SYSROOT_LOCAL)/include/spandsp/plc.h ] && echo "yes") USE_PORTAUDIO := $(shell [ -f $(SYSROOT_LOCAL)/include/portaudio.h ] || \ [ -f $(SYSROOT)/include/portaudio.h ] || \ [ -f $(SYSROOT_ALT)/include/portaudio.h ] && echo "yes") USE_PULSE := $(shell pkg-config --exists libpulse && echo "yes") USE_SDL := $(shell [ -f $(SYSROOT)/include/SDL2/SDL.h ] || \ [ -f $(SYSROOT)/local/include/SDL2/SDL.h ] || \ [ -f $(SYSROOT_ALT)/include/SDL2/SDl.h ] && echo "yes") USE_SNDFILE := $(shell [ -f $(SYSROOT)/include/sndfile.h ] || \ [ -f $(SYSROOT)/local/include/sndfile.h ] || \ [ -f $(SYSROOT_ALT)/include/sndfile.h ] || \ [ -f $(SYSROOT_ALT)/usr/local/include/sndfile.h ] && echo "yes") USE_SNDIO := $(shell [ -f $(SYSROOT)/include/sndio.h ] || \ [ -f $(SYSROOT)/local/include/sndio.h ] && echo "yes") USE_STDIO := $(shell [ -f $(SYSROOT)/include/termios.h ] && echo "yes") HAVE_SPEEXDSP := $(shell \ [ -f $(SYSROOT)/local/lib/libspeexdsp$(LIB_SUFFIX) ] || \ [ -f $(SYSROOT)/lib64/libspeexdsp$(LIB_SUFFIX) ] || \ [ -f $(SYSROOT)/lib/libspeexdsp$(LIB_SUFFIX) ] || \ [ -f $(SYSROOT_ALT)/lib/libspeexdsp$(LIB_SUFFIX) ] && echo "yes") ifeq ($(HAVE_SPEEXDSP),) HAVE_SPEEXDSP := \ $(shell find $(SYSROOT)/lib -name libspeexdsp$(LIB_SUFFIX) 2>/dev/null) endif ifneq ($(USE_MPG123),) ifneq ($(HAVE_SPEEXDSP),) USE_MPA := $(shell ([ -f $(SYSROOT)/include/twolame.h ] || \ [ -f $(SYSROOT)/local/include/twolame.h ] || \ [ -f $(SYSROOT_ALT)/include/twolame.h ]) && \ ([ -f $(SYSROOT)/include/lame/lame.h ] || \ [ -f $(SYSROOT)/local/include/lame/lame.h ] || \ [ -f $(SYSROOT_ALT)/include/lame/lame.h ]) && echo "yes") endif endif USE_SPEEX_PP := $(shell [ -f $(SYSROOT)/include/speex_preprocess.h ] || \ [ -f $(SYSROOT)/local/include/speex_preprocess.h ] || \ [ -f $(SYSROOT)/local/include/speex/speex_preprocess.h ] || \ [ -f $(SYSROOT_ALT)/include/speex/speex_preprocess.h ] || \ [ -f $(SYSROOT)/include/speex/speex_preprocess.h ] && echo "yes") USE_SYSLOG := $(shell [ -f $(SYSROOT)/include/syslog.h ] || \ [ -f $(SYSROOT_ALT)/include/syslog.h ] || \ [ -f $(SYSROOT)/local/include/syslog.h ] && echo "yes") USE_MQTT := $(shell [ -f $(SYSROOT)/include/mosquitto.h ] || \ [ -f $(SYSROOT_LOCAL)/include/mosquitto.h ] \ && echo "yes") HAVE_LIBV4L2 := $(shell [ -f $(SYSROOT)/include/libv4l2.h ] || \ [ -f $(SYSROOT)/local/include/libv4l2.h ] \ && echo "yes") USE_V4L2 := $(shell [ -f $(SYSROOT)/include/linux/videodev2.h ] || \ [ -f $(SYSROOT)/local/include/linux/videodev2.h ] || \ [ -f $(SYSROOT)/include/sys/videoio.h ] \ && echo "yes") USE_X11 := $(shell [ -f $(SYSROOT)/include/X11/Xlib.h ] || \ [ -f $(SYSROOT)/local/include/X11/Xlib.h ] || \ [ -f $(SYSROOT_ALT)/include/X11/Xlib.h ] && echo "yes") USE_ZRTP := $(shell [ -f $(SYSROOT)/include/libzrtp/zrtp.h ] || \ [ -f $(SYSROOT)/local/include/libzrtp/zrtp.h ] || \ [ -f $(SYSROOT_ALT)/include/libzrtp/zrtp.h ] && echo "yes") USE_VPX := $(shell [ -f $(SYSROOT)/include/vpx/vp8.h ] \ || [ -f $(SYSROOT)/local/include/vpx/vp8.h ] \ || [ -f $(SYSROOT_ALT)/include/vpx/vp8.h ] \ && echo "yes") USE_OMX_RPI := $(shell [ -f /opt/vc/include/bcm_host.h ] || \ [ -f $(SYSROOT)/include/bcm_host.h ] \ || [ -f $(SYSROOT_ALT)/include/bcm_host.h ] \ && echo "yes") USE_OMX_BELLAGIO := $(shell [ -f /usr/include/OMX_Core.h ] \ || [ -f $(SYSROOT)/include/OMX_Core.h ] \ || [ -f $(SYSROOT_ALT)/include/OMX_Core.h ] \ && echo "yes") else # Windows. # Accounts for mingw with Windows SDK (formerly known as Platform SDK) # mounted at /winsdk USE_DSHOW := $(shell [ -f /winsdk/Include/um/dshow.h ] && echo "yes") endif # Platform specific modules ifeq ($(OS),darwin) USE_AVFOUNDATION := \ $(shell [ -d /System/Library/Frameworks/AVFoundation.framework ] \ && echo "yes") USE_AUDIOUNIT := \ $(shell [ -d /System/Library/Frameworks/AudioUnit.framework ] \ && echo "yes") USE_COREAUDIO := \ $(shell [ -d /System/Library/Frameworks/CoreAudio.framework ] \ && echo "yes") ifneq ($(USE_AVFOUNDATION),) USE_AVCAPTURE := yes else USE_QTCAPTURE := yes endif endif ifeq ($(OS),linux) USE_EVDEV := $(shell [ -f $(SYSROOT)/include/linux/input.h ] && echo "yes") endif ifeq ($(OS),win32) USE_WINWAVE := yes MODULES += wincons endif ifneq ($(USE_GTK),) USE_LIBNOTIFY := $(shell pkg-config 'libnotify glib-2.0 < 2.40' && echo "yes") endif endif # ------------------------------------------------------------------------- # MODULES += $(EXTRA_MODULES) ifneq ($(BASIC_MODULES),no) MODULES += account MODULES += auloop MODULES += b2bua MODULES += contact MODULES += ctrl_tcp MODULES += debug_cmd MODULES += ebuacip MODULES += echo MODULES += fakevideo MODULES += httpd MODULES += ice MODULES += menu MODULES += mwi MODULES += natpmp MODULES += presence MODULES += selfview MODULES += srtp MODULES += stun MODULES += turn MODULES += uuid MODULES += vidbridge MODULES += vidinfo MODULES += vidloop MODULES += vumeter ifneq ($(HAVE_PTHREAD),) MODULES += aubridge aufile ausine endif endif ifneq ($(USE_AAC),) MODULES += aac endif ifneq ($(USE_ALSA),) MODULES += alsa endif ifneq ($(USE_AMR),) MODULES += amr endif ifneq ($(USE_APTX),) MODULES += aptx endif ifneq ($(USE_AUDIOUNIT),) MODULES += audiounit endif ifneq ($(USE_AVCAPTURE),) MODULES += avcapture endif ifneq ($(USE_AVCODEC),) MODULES += avcodec ifneq ($(USE_AVFORMAT),) MODULES += avformat endif endif ifneq ($(USE_AVFILTER),) MODULES += avfilter endif ifneq ($(USE_CAIRO),) MODULES += cairo ifneq ($(USE_MPG123),) MODULES += rst endif endif ifneq ($(USE_CODEC2),) MODULES += codec2 endif ifneq ($(USE_CONS),) MODULES += cons endif ifneq ($(USE_COREAUDIO),) MODULES += coreaudio endif ifneq ($(USE_DTLS_SRTP),) MODULES += dtls_srtp endif ifneq ($(USE_QTCAPTURE),) MODULES += qtcapture CFLAGS += -DQTCAPTURE_RUNLOOP endif ifneq ($(USE_ECHO),) MODULES += echo endif ifneq ($(USE_EVDEV),) MODULES += evdev endif ifneq ($(USE_G711),) MODULES += g711 endif ifneq ($(USE_G722),) MODULES += g722 endif ifneq ($(USE_G722_1),) MODULES += g7221 endif ifneq ($(USE_G726),) MODULES += g726 endif ifneq ($(USE_GSM),) MODULES += gsm endif ifneq ($(USE_GST),) MODULES += gst endif ifneq ($(USE_GST_VIDEO),) MODULES += gst_video endif ifneq ($(USE_GTK),) MODULES += gtk endif ifneq ($(USE_ILBC),) MODULES += ilbc endif ifneq ($(USE_ISAC),) MODULES += isac endif ifneq ($(USE_JACK),) MODULES += jack endif ifneq ($(USE_L16),) MODULES += l16 endif ifneq ($(USE_OPUS_MS),) MODULES += opus_multistream endif ifneq ($(USE_MPA),) MODULES += mpa endif ifneq ($(USE_MQTT),) MODULES += mqtt endif ifneq ($(USE_OPENGL),) MODULES += opengl endif ifneq ($(USE_OPUS),) MODULES += opus endif ifneq ($(USE_OSS),) MODULES += oss endif ifneq ($(USE_PLC),) MODULES += plc endif ifneq ($(USE_PORTAUDIO),) MODULES += portaudio endif ifneq ($(USE_PULSE),) MODULES += pulse endif ifneq ($(USE_SDL),) MODULES += sdl endif ifneq ($(USE_SNDFILE),) MODULES += sndfile endif ifneq ($(USE_SPEEX_PP),) MODULES += speex_pp endif ifneq ($(USE_STDIO),) MODULES += stdio endif ifneq ($(USE_SNDIO),) MODULES += sndio endif ifneq ($(USE_SYSLOG),) MODULES += syslog endif ifneq ($(USE_V4L2),) MODULES += v4l2 v4l2_codec endif ifneq ($(USE_OMX_RPI),) MODULES += omx else ifneq ($(USE_OMX_BELLAGIO),) MODULES += omx endif endif ifneq ($(USE_VPX),) MODULES += vp8 MODULES += $(shell pkg-config 'vpx >= 1.3.0' && echo "vp9") endif ifneq ($(USE_WINWAVE),) MODULES += winwave endif ifneq ($(USE_X11),) MODULES += x11 x11grab endif ifneq ($(USE_ZRTP),) MODULES += zrtp endif ifneq ($(USE_GZRTP),) MODULES += gzrtp endif ifneq ($(USE_DSHOW),) MODULES += dshow endif ifneq ($(USE_RTCPSUMMARY),) MODULES += rtcpsummary endif baresip-1.0.0/mk/win32/000077500000000000000000000000001372575704200145225ustar00rootroot00000000000000baresip-1.0.0/mk/win32/baresip.sln000066400000000000000000000045171372575704200166740ustar00rootroot00000000000000 Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 VisualStudioVersion = 15.0.26730.10 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "baresip-win32", "baresip.vcxproj", "{4B89C2D8-FB32-4D7C-9019-752A5664781C}" ProjectSection(ProjectDependencies) = postProject {3E767371-A72B-4F5C-A695-8F844B0889C5} = {3E767371-A72B-4F5C-A695-8F844B0889C5} {40B28DF6-4B4A-411A-9EB7-8D80C2A29B9D} = {40B28DF6-4B4A-411A-9EB7-8D80C2A29B9D} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "re-win32", "..\..\..\re\mk\win32\re.vcxproj", "{40B28DF6-4B4A-411A-9EB7-8D80C2A29B9D}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rem-win32", "..\..\..\rem\mk\win32\rem.vcxproj", "{3E767371-A72B-4F5C-A695-8F844B0889C5}" ProjectSection(ProjectDependencies) = postProject {40B28DF6-4B4A-411A-9EB7-8D80C2A29B9D} = {40B28DF6-4B4A-411A-9EB7-8D80C2A29B9D} EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 Release|Win32 = Release|Win32 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {4B89C2D8-FB32-4D7C-9019-752A5664781C}.Debug|Win32.ActiveCfg = Debug|Win32 {4B89C2D8-FB32-4D7C-9019-752A5664781C}.Debug|Win32.Build.0 = Debug|Win32 {4B89C2D8-FB32-4D7C-9019-752A5664781C}.Release|Win32.ActiveCfg = Release|Win32 {4B89C2D8-FB32-4D7C-9019-752A5664781C}.Release|Win32.Build.0 = Release|Win32 {40B28DF6-4B4A-411A-9EB7-8D80C2A29B9D}.Debug|Win32.ActiveCfg = Debug|Win32 {40B28DF6-4B4A-411A-9EB7-8D80C2A29B9D}.Debug|Win32.Build.0 = Debug|Win32 {40B28DF6-4B4A-411A-9EB7-8D80C2A29B9D}.Release|Win32.ActiveCfg = Release|Win32 {40B28DF6-4B4A-411A-9EB7-8D80C2A29B9D}.Release|Win32.Build.0 = Release|Win32 {3E767371-A72B-4F5C-A695-8F844B0889C5}.Debug|Win32.ActiveCfg = Debug|Win32 {3E767371-A72B-4F5C-A695-8F844B0889C5}.Debug|Win32.Build.0 = Debug|Win32 {3E767371-A72B-4F5C-A695-8F844B0889C5}.Release|Win32.ActiveCfg = Release|Win32 {3E767371-A72B-4F5C-A695-8F844B0889C5}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {8F3E56DF-4B18-4499-B228-37DC5DC474F9} EndGlobalSection EndGlobal baresip-1.0.0/mk/win32/baresip.vcxproj000066400000000000000000000300001372575704200175550ustar00rootroot00000000000000 Debug Win32 Release Win32 baresip-win32 {4B89C2D8-FB32-4D7C-9019-752A5664781C} Win32Proj 10.0.17763.0 Application MultiByte v141 Application MultiByte v141 <_ProjectFileVersion>10.0.30319.1 ..\..\$(Platform)\$(Configuration)\bin\ ..\..\$(Platform)\$(Configuration)\tmp\mk\win32\ false ..\..\$(Platform)\$(Configuration)\bin\ ..\..\$(Platform)\$(Configuration)\tmp\mk\win32\ false BasicDesignGuidelineRules.ruleset Disabled include;..\..\include;..\..\..\re\include;..\..\..\rem\include;..\..\..\misc;..\..\..\dirent\include;%(AdditionalIncludeDirectories) WIN32;STATIC;HAVE_GETOPT;HAVE_IO_H;HAVE_SELECT;_CRT_SECURE_NO_DEPRECATE;FD_SETSIZE=2048;SHARE_PATH="/usr/share/baresip";%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 EditAndContinue CompileAsC 4142;%(DisableSpecificWarnings) $(IntDir)%(RelativeDir)%(Filename).obj %(AdditionalOptions) winmm.lib ..\..\..\re\$(Platform)\$(Configuration)\bin\re-win32.lib ..\..\..\rem\$(Platform)\$(Configuration)\bin\rem-win32.lib %(AdditionalOptions) $(OutDir)baresip-win32.exe %(AdditionalLibraryDirectories) true $(OutDir)baresip-win32.pdb Console MachineX86 Iphlpapi.lib;%(AdditionalDependencies) include;..\..\include;..\..\..\re\include;..\..\..\rem\include;..\..\..\misc;..\..\..\dirent\include;%(AdditionalIncludeDirectories) WIN32;STATIC;HAVE_GETOPT;HAVE_IO_H;HAVE_SELECT;_CRT_SECURE_NO_DEPRECATE;FD_SETSIZE=2048;SHARE_PATH="/usr/share/baresip";%(PreprocessorDefinitions) MultiThreaded Level3 ProgramDatabase 4142;%(DisableSpecificWarnings) $(IntDir)%(RelativeDir)%(Filename).obj winmm.lib wsock32.lib ..\..\..\re\$(Platform)\$(Configuration)\bin\re-win32.lib ..\..\..\rem\$(Platform)\$(Configuration)\bin\rem-win32.lib %(AdditionalOptions) $(OutDir)baresip-win32.exe %(AdditionalLibraryDirectories) true Console true true MachineX86 Iphlpapi.lib;%(AdditionalDependencies) {3e767371-a72b-4f5c-a695-8f844b0889c5} {40b28df6-4b4a-411a-9eb7-8d80c2a29b9d} CompileAsCpp CompileAsCpp baresip-1.0.0/mk/win32/baresip.vcxproj.filters000066400000000000000000000325511372575704200212410ustar00rootroot00000000000000 {2334866b-8357-4e18-8898-48db4dfe2a15} {5c30c989-28e5-402f-aaa0-860eafa95cc5} {f5f435ce-121f-4b09-b66f-89e75e8abb40} {7f749aed-9d81-46c6-bdde-690ddc51a0a4} {6c97676c-7c18-404f-85a1-2fded4f104e3} {f528695e-cf16-4c35-89ed-adcc330b63bc} {b8e32268-7d2c-46ae-b6a1-d7b02bbd4026} {0e11ace7-27c2-4ad3-8b5e-b3bf772f0b4d} {f44d6650-15a0-4fb3-8fe3-d91f522be831} {6606d763-a0be-4bcc-a689-a9e5e38df7f5} {785597c1-f018-4f86-ae98-4855e6130bf7} {b139606b-86de-4c90-af91-f44b04bd1330} {4c01b3b6-a748-4cf1-af45-a8d5b7735267} {3c2cd0c3-9de0-42ca-8f3a-6d7d929ce501} {e679754c-643a-4284-9ed6-bf6fdc73e152} {8ca10960-9be4-4d19-9e32-2ae5bc415c0a} {1def0f02-ca40-49ee-b5e1-95aac5d2dda3} {5446737f-2a0f-4b4f-a86e-55d9c20118e7} {ebbcb368-d1fa-4899-80cf-e43ff4fde9b2} {a7b0f22a-b82a-4594-a367-d8b8a9882f0d} {c093ccc3-d662-46e0-83df-2eb34e7e7d21} {c82f29fb-bb8d-45c7-ad53-d25e997c1453} {ed5cc330-666d-4f9a-81a2-db7873b7abaa} {31ac6861-a9e9-467a-82ae-53d1d929e696} {6e5dac26-781e-4683-958f-2e18fdc0b42e} {5a3c72cb-a1a5-4c46-b0b5-761d3677e56a} {a4d5f1d9-5629-479e-86d4-4e7b6d58a38a} {044bc40b-b2a8-4450-b76a-d959559df6b1} {71dc9cb5-19b1-4f74-bc23-02ca6b5a10b3} {bc7810ea-bc52-4bee-a15c-aed12cf2a777} {8e7e8b8a-dbe7-4b58-80f3-e632b40d0e4e} {e3bd480b-289e-4754-b1a2-55ea85a7ef45} include src src modules\amr modules\natpmp modules\presence modules\srtp modules\vidbridge modules\winwave src src src src src src src src src src src src src src src src src src src src src src src src src src src src src\video src\video src\video src\video src\video src\video src\video src\static modules\account modules\amr modules\amr modules\auloop modules\b2bua modules\cons modules\contact modules\debug_cmd modules\dshow modules\echo modules\g711 modules\httpd modules\ice modules\l16 modules\menu modules\mwi modules\natpmp modules\natpmp modules\presence modules\presence modules\presence modules\presence modules\selfview modules\srtp modules\srtp modules\stun modules\turn modules\uuid modules\vidbridge modules\vidbridge modules\vidbridge modules\vidloop modules\vumeter modules\wincons modules\winwave modules\winwave modules\winwave src src src src baresip-1.0.0/mk/win32/static.c000066400000000000000000000022051372575704200161540ustar00rootroot00000000000000/* static.c - manually updated */ #include #include extern const struct mod_export exports_account; extern const struct mod_export exports_auloop; extern const struct mod_export exports_contact; extern const struct mod_export exports_debug_cmd; extern const struct mod_export exports_dshow; extern const struct mod_export exports_g711; extern const struct mod_export exports_httpd; extern const struct mod_export exports_ice; extern const struct mod_export exports_menu; extern const struct mod_export exports_stun; extern const struct mod_export exports_turn; extern const struct mod_export exports_uuid; extern const struct mod_export exports_vidloop; extern const struct mod_export exports_vumeter; extern const struct mod_export exports_wincons; extern const struct mod_export exports_winwave; const struct mod_export *mod_table[] = { &exports_account, &exports_auloop, &exports_contact, &exports_debug_cmd, &exports_dshow, &exports_g711, &exports_httpd, &exports_ice, &exports_menu, &exports_stun, &exports_turn, &exports_uuid, &exports_vidloop, &exports_vumeter, &exports_wincons, &exports_winwave, NULL }; baresip-1.0.0/modules/000077500000000000000000000000001372575704200146215ustar00rootroot00000000000000baresip-1.0.0/modules/aac/000077500000000000000000000000001372575704200153455ustar00rootroot00000000000000baresip-1.0.0/modules/aac/aac.c000066400000000000000000000201231372575704200162330ustar00rootroot00000000000000/** * @file aac.c MPEG-4 AAC Audio Codec * * Copyright (C) 2010 Creytiv.com * Copyright (C) 2019 Hessischer Rundfunk */ #include #include #include #include #include "aac.h" /** * @defgroup aac aac * * Advanced Audio Coding (AAC) audio codec * * Supported version: libfdk-aac 0.1.6 or later * * Configuration options: * \verbatim aac_samplerate 48000 # Encoded/decoded audio sample rate [Hz] aac_channels 1 # Encoded/decoded audio channels aac_aot 23 # Audio Object Type (AOT) # 2: MPEG-4 AAC Low Complexity (AAC-LC) # 5: MPEG-4 AAC Low Complexity with # Spectral Band Replication (HE-AAC) # 29: MPEG-4 AAC Low Complexity with # Spectral Band Replication and # Parametric Stereo (HE-AAC v2) # 23: MPEG-4 AAC Low-Delay (AAC-LD) # 39: MPEG-4 AAC Enhanced Low-Delay (AAC-ELD) aac_bitrate 128000 # Average bitrate in [bps] aac_constantduration 480 # Coded PCM frame size # 1024 or 960 for AAC-LC # 2048 or 1920 for HE-AAC (v2) # 512 or 480 for AAC-LD and AAC-ELD \endverbatim * * References: * * RFC 3640 RTP Payload Format for Transport of MPEG-4 Elementary Streams * * * ToDo: * - Support multiple access units per packet * - Add support for AAC-lbr * - Find and fix problem with fdk-aac HE-AAC v2 encoding * - Multichannel encoding (> stereo) * - SDP stereo and mono offer * - Find a way to set dynamic audio i/o ptime in samples for min. delay */ static char fmtp_local[256] = ""; static char fmtp_mirror[256]; uint32_t aac_samplerate, aac_channels, aac_aot; uint32_t aac_bitrate, aac_profile, aac_constantduration; static struct aucodec aac = { .name = "mpeg4-generic", .encupdh = aac_encode_update, .ench = aac_encode_frm, .decupdh = aac_decode_update, .dech = aac_decode_frm, .fmtp_ench = aac_fmtp_enc, .fmtp_cmph = aac_fmtp_cmp, /* try to make sure PCM audio buffer is always <= 120 samples */ .ptime = 4, /* 96 samples per channel @ 48000 hz */ }; void aac_encode_fmtp(const struct aac_param *prm) { (void)re_snprintf(fmtp_local, sizeof(fmtp_local), "streamType=%d" "; profile-level-id=%u" "; config=%s" "; mode=%s" "; constantDuration=%u" "; sizeLength=%u" "; indexLength=%u" "; indexDeltaLength=%u" "; bitrate=%u", AAC_STREAMTYPE_AUDIO, prm->profile_level_id, prm->config, "AAC-hbr", prm->constantduration, AAC_SIZELENGTH, AAC_INDEXLENGTH, AAC_INDEXDELTALENGTH, prm->bitrate); } /* Parse remote fmtp string and map it to aac_param struct */ void aac_decode_fmtp(struct aac_param *prm, const char *fmtp) { struct pl pl, val; if (!prm || !fmtp) return; pl_set_str(&pl, fmtp); if (fmt_param_get(&pl, "profile-level-id", &val)) prm->profile_level_id = pl_u32(&val); if (fmt_param_get(&pl, "constantDuration", &val)) prm->constantduration = pl_u32(&val); if (fmt_param_get(&pl, "bitrate", &val)) prm->bitrate = pl_u32(&val); if (fmt_param_get(&pl, "config", &val)) (void)pl_strcpy(&val, &prm->config[0], sizeof(prm->config)); } /* describe local encoded format to remote */ int aac_fmtp_enc(struct mbuf *mb, const struct sdp_format *fmt, bool offer, void *arg) { bool mirror; (void)offer; (void)arg; if (!mb || !fmt) return 0; mirror = !offer && str_isset(fmtp_mirror); return mbuf_printf(mb, "a=fmtp:%s %s\r\n", fmt->id, mirror ? fmtp_mirror : fmtp_local); } void aac_mirror_params(const char *x) { debug("aac: mirror parameters: \"%s\"\n", x); str_ncpy(fmtp_mirror, x, sizeof(fmtp_mirror)); } static int module_init(void) { struct conf *conf = conf_cur(); struct aac_param prm; HANDLE_AACENCODER enc; AACENC_InfoStruct enc_info; AACENC_ERROR error; uint32_t aac_ratio; /* default encoder configuration */ aac_samplerate = 48000; aac_channels = 2; aac_aot = AOT_ER_AAC_LD; aac_bitrate = 128000; aac_constantduration = 480; /* encoder configuration from config file */ (void)conf_get_u32(conf, "aac_samplerate", &aac_samplerate); (void)conf_get_u32(conf, "aac_channels", &aac_channels); (void)conf_get_u32(conf, "aac_aot", &aac_aot); (void)conf_get_u32(conf, "aac_bitrate", &aac_bitrate); (void)conf_get_u32(conf, "aac_constantduration", &aac_constantduration); if (aac_channels < 1 || aac_channels > 2) { aac_channels = 2; } aac.ch = aac_channels; aac.pch = aac_channels; switch (aac_samplerate) { case 8000: case 11025: case 12000: case 16000: case 22050: case 24000: case 32000: case 44100: case 48000: case 64000: case 88200: case 96000: break; default: aac_samplerate = 48000; break; } aac.srate = aac_samplerate; aac.crate = aac_samplerate; switch (aac_aot) { case AOT_AAC_LC: /* 2: MPEG-4 AAC Low Complexity */ aac_profile = HIGH_QUALITY_AUDIO_PROFILE; aac_constantduration = 1024; aac_ratio = 1; break; case AOT_SBR: /* 5: MPEG-4 AAC Low Complexity with Spectral Band Replication (HE-AAC) */ aac_profile = HIGH_EFFICIENCY_AAC_PROFILE; aac_constantduration = 2048; aac_ratio = 2; break; case AOT_PS: /* Stereo only! */ /* 29: MPEG-4 AAC Low Complexity with Spectral Band Replication and Parametric Stereo (HE-AAC v2) */ aac_profile = HIGH_EFFICIENCY_AAC_V2_PROFILE; aac_constantduration = 2048; aac_ratio = 2; aac_channels = 2; break; case AOT_ER_AAC_LD: /* 23: MPEG-4 AAC Low-Delay */ aac_profile = LOW_DELAY_AUDIO_PROFILE; aac_ratio = 1; if (aac_constantduration != 480 && aac_constantduration != 512) aac_constantduration = 480; break; case AOT_ER_AAC_ELD: /* 39: MPEG-4 AAC Enhanced Low-Delay */ aac_profile = ENHANCED_LOW_DELAY_AUDIO_PROFILE; if (aac_channels == 2) ++aac_profile; aac_ratio = 1; switch (aac_constantduration) { case 120: case 128: case 240: case 256: case 480: case 512: break; default: aac_constantduration = 120; break; } break; default: warning("AAC Audio object types 2 (AAC-LC), 5 " "(HE-AAC), 29 (HE-AAC v2), 23 (AAC-LD) " "and 39 (AAC-ELD) are allowed.\n"); return EINVAL; } error = aacEncOpen(&enc, 0, 0); if (error != AACENC_OK) { warning("aac: Unable to open the encoder (0x%x)\n", error); return ENOMEM; } /* set mandatory encoder params: */ error |= aacEncoder_SetParam(enc, AACENC_AOT, aac_aot); error |= aacEncoder_SetParam(enc, AACENC_SAMPLERATE, aac.srate); error |= aacEncoder_SetParam(enc, AACENC_CHANNELMODE, aac.ch); error |= aacEncoder_SetParam(enc, AACENC_BITRATE, aac_bitrate); error |= aacEncoder_SetParam(enc, AACENC_TRANSMUX, TT_MP4_RAW); /* set object specific encoder params: */ error |= aacEncoder_SetParam(enc, AACENC_GRANULE_LENGTH, aac_constantduration/aac_ratio); error |= aacEncEncode(enc, NULL, NULL, NULL, NULL); error |= aacEncInfo(enc, &enc_info); if (error != AACENC_OK) { return EINVAL; } prm.constantduration = enc_info.frameLength; prm.bitrate = aacEncoder_GetParam(enc, AACENC_BITRATE); prm.profile_level_id = aac_profile; debug("aac: Encoder configuration: conf=%w, " "frameLength=%u, inputChannels=%u\n", enc_info.confBuf, enc_info.confSize, enc_info.frameLength, enc_info.inputChannels); re_snprintf(prm.config, sizeof(prm.config), "%w", enc_info.confBuf, enc_info.confSize); aacEncClose(&enc); aac_encode_fmtp(&prm); debug("aac: fmtp=\"%s\"\n", fmtp_local); aucodec_register(baresip_aucodecl(), &aac); return 0; } static int module_close(void) { aucodec_unregister(&aac); return 0; } EXPORT_SYM const struct mod_export DECL_EXPORTS(aac) = { "aac", "audio codec", module_init, module_close, }; baresip-1.0.0/modules/aac/aac.h000066400000000000000000000034571372575704200162530ustar00rootroot00000000000000/** * @file aac.h MPEG-4 AAC Audio Codec -- internal interface * * Copyright (C) 2010 Creytiv.com * Copyright (C) 2019 Hessischer Rundfunk */ struct aac_param { uint32_t profile_level_id; uint32_t sizelength; uint32_t indexlength; uint32_t indexdeltalength; char config[64]; char mode[8]; uint32_t constantduration; uint32_t bitrate; }; enum { AU_HDR_LEN = 4, /* single access unit only!!! */ AAC_SIZELENGTH = 13, AAC_INDEXLENGTH = 3, AAC_INDEXDELTALENGTH = 3, AAC_STREAMTYPE_AUDIO = 5, HIGH_QUALITY_AUDIO_PROFILE = 16, /* L3 */ LOW_DELAY_AUDIO_PROFILE = 25, /* L4 */ ENHANCED_LOW_DELAY_AUDIO_PROFILE = 76, /* L1 */ HIGH_EFFICIENCY_AAC_PROFILE = 46, /* L4 */ HIGH_EFFICIENCY_AAC_V2_PROFILE = 49, /* L3 */ AAC_PROFILE = 41, /* L2 */ }; extern uint32_t aac_samplerate, aac_channels, aac_aot; extern uint32_t aac_bitrate, aac_profile, aac_constantduration; int aac_encode_update(struct auenc_state **aesp, const struct aucodec *ac, struct auenc_param *param, const char *fmtp); int aac_encode_frm(struct auenc_state *aes, bool *marker, uint8_t *buf, size_t *len, int fmt, const void *sampv, size_t sampc); int aac_decode_update(struct audec_state **adsp, const struct aucodec *ac, const char *fmtp); int aac_decode_frm(struct audec_state *ads, int fmt, void *sampv, size_t *sampc, bool marker, const uint8_t *buf, size_t len); int aac_fmtp_enc(struct mbuf *mb, const struct sdp_format *fmt, bool offer, void *arg); bool aac_fmtp_cmp(const char *lfmtp, const char *rfmtp, void *arg); void aac_encode_fmtp(const struct aac_param *prm); void aac_decode_fmtp(struct aac_param *prm, const char *fmtp); void aac_mirror_params(const char *fmtp); baresip-1.0.0/modules/aac/decode.c000066400000000000000000000120371372575704200167370ustar00rootroot00000000000000/** * @file aac/decode.c MPEG-4 AAC Decoder * * Copyright (C) 2010 Creytiv.com * Copyright (C) 2019 Hessischer Rundfunk */ #include #include #include #include #include #include "aac.h" struct au_hdr { uint16_t offset; uint16_t size; uint16_t count; }; struct audec_state { HANDLE_AACDECODER dec; }; static void destructor(void *arg) { struct audec_state *ads = arg; if (ads->dec) aacDecoder_Close(ads->dec); } static int hdr_decode(struct au_hdr *au_data, const uint8_t *p, const size_t plen) { uint16_t au_headers_length; uint16_t au_data_offset; uint16_t au_data_length; uint16_t bits; if (plen < sizeof(uint16_t) * 2) return EPROTO; au_headers_length = ntohs(*(uint16_t *)(void *)&p[0]); au_data_offset = sizeof(uint16_t) + (au_headers_length / 8); au_data_length = plen - au_data_offset; au_data->count = (au_headers_length / (sizeof(uint16_t) * 8)); au_data->offset = au_data_offset; bits = ntohs(*(uint16_t *)(void *)&p[2]); au_data->size = bits >> ((sizeof(uint16_t) * 8) - AAC_SIZELENGTH); if (au_data->size == 0) { warning("aac: decode: invalid access unit size (zero)\n", au_data->size); return EBADMSG; } if (au_data->size > au_data_length) { debug("aac: decode: fragmented access unit " "(au-data-size: %zu > packet-data-size: %zu)\n", au_data->size, au_data_length); } if (au_data->size != au_data_length) { debug("aac: decode: multiple access units per packet (%zu)\n", au_data->count); } return 0; } int aac_decode_update(struct audec_state **adsp, const struct aucodec *ac, const char *fmtp) { struct audec_state *ads; AAC_DECODER_ERROR error; int err = 0; (void)fmtp; struct pl config; char config_str[64]; uint8_t config_bin[32]; if (!adsp || !ac || !ac->ch) return EINVAL; ads = *adsp; if (ads) return 0; ads = mem_zalloc(sizeof(*ads), destructor); if (!ads) return ENOMEM; ads->dec = aacDecoder_Open(TT_MP4_RAW, 1); if (!ads->dec) { warning("aac: error opening decoder\n"); err = ENOMEM; goto out; } info("aac: decode update: fmtp='%s'\n", fmtp); err = re_regex(fmtp, str_len(fmtp), "config=[0-9a-f]+", &config); if (err) goto out; err = pl_strcpy(&config, config_str, sizeof(config_str)); if (err) goto out; err = str_hex(config_bin, strlen(config_str)/2, config_str); if (err) goto out; UCHAR *conf = config_bin; const UINT length = (UINT)strlen(config_str)/2; error = aacDecoder_ConfigRaw(ads->dec, &conf, &length); if (error != AAC_DEC_OK) { warning("aac: decode: set config error (0x%x)\n", error); err = EPROTO; goto out; } error = aacDecoder_SetParam(ads->dec, AAC_PCM_MIN_OUTPUT_CHANNELS, aac_channels); error |= aacDecoder_SetParam(ads->dec, AAC_PCM_MAX_OUTPUT_CHANNELS, aac_channels); if (error != AAC_DEC_OK) { warning("aac: decode: set param error (0x%x)\n", error); err = EINVAL; goto out; } out: if (err) mem_deref(ads); else *adsp = ads; return err; } int aac_decode_frm(struct audec_state *ads, int fmt, void *sampv, size_t *sampc, bool marker, const uint8_t *buf, size_t len) { UCHAR *pBuffer = (UCHAR *)buf; UINT bufferSize = 0; UINT valid = 0; AAC_DECODER_ERROR error; INT size; int err = 0; size_t nsamp = 0; int16_t *s16 = sampv; UINT pos = 0; struct au_hdr au_data; (void)marker; if (!ads || !sampv || !sampc || !buf) return EINVAL; if (fmt != AUFMT_S16LE) return ENOTSUP; err = hdr_decode(&au_data, buf, len); if (err) return err; pos = au_data.offset; pBuffer += pos; while (len > pos) { CStreamInfo *info; bufferSize = (UINT)len - pos; valid = bufferSize; error = aacDecoder_Fill(ads->dec, &pBuffer, &bufferSize, &valid); if (error != AAC_DEC_OK) { warning("aac: aacDecoder_Fill() failed (0x%x)\n", error); return EPROTO; } size = (INT)*sampc; error = aacDecoder_DecodeFrame(ads->dec, &s16[nsamp], size, 0); if (error == AAC_DEC_NOT_ENOUGH_BITS) { warning("aac: aacDecoder_DecodeFrame() failed: " "NOT ENOUGH BITS %u / %u\n", bufferSize, valid); break; } if (error != AAC_DEC_OK) { warning( "aac: aacDecoder_DecodeFrame() failed (0x%x)\n", error); return EPROTO; } info = aacDecoder_GetStreamInfo(ads->dec); if (!info) { warning("aac: decode: unable to get stream info\n"); return EBADMSG; } if (info->sampleRate != (INT)aac_samplerate) { warning( "aac: decode: samplerate mismatch (%d != %d)\n", info->sampleRate, aac_samplerate); return EPROTO; } if (info->numChannels != (INT)aac_channels) { warning( "aac: decode: channels mismatch (%d != %d)\n", info->numChannels, aac_channels); return EPROTO; } nsamp += (info->frameSize * info->numChannels); size -= (info->frameSize * info->numChannels); pos += bufferSize - valid; pBuffer += bufferSize - valid; } if (nsamp > *sampc) return ENOMEM; *sampc = nsamp; return 0; } baresip-1.0.0/modules/aac/encode.c000066400000000000000000000236201372575704200167510ustar00rootroot00000000000000/** * @file aac/encode.c MPEG-4 AAC Encoder * * Copyright (C) 2010 Creytiv.com * Copyright (C) 2019 Hessischer Rundfunk */ #include #include #include #include #include "aac.h" struct auenc_state { HANDLE_AACENCODER enc; }; static void destructor(void *arg) { struct auenc_state *aes = arg; if (aes->enc) aacEncClose(&aes->enc); } static void hdr_encode(uint8_t *p, uint16_t size) { uint8_t n = 1; /* we only have a single AU-header!!! */ /* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- .. -+-+-+-+-+-+-+-+-+-+ * |AU-headers-length|AU-header|AU-header| |AU-header|padding| * | | (1) | (2) | | (n) | bits | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- .. -+-+-+-+-+-+-+-+-+-+ */ /* AU-headers-length */ *(uint16_t *)(void *)&p[0] = htons(sizeof(uint16_t) * 8 * n); /* +---------------------------------------+ * | AU-size | * +---------------------------------------+ * | AU-Index / AU-Index-delta | * +---------------------------------------+ * | CTS-flag | * +---------------------------------------+ * | CTS-delta | * +---------------------------------------+ * | DTS-flag | * +---------------------------------------+ * | DTS-delta | * +---------------------------------------+ * | RAP-flag | * +---------------------------------------+ * | Stream-state | * +---------------------------------------+ */ /* The AU-header, no CTS, DTS, RAP, Stream-state * * AU-size is always the total size of the AU, not the fragmented * size */ *(uint16_t *)(void *)&p[2] = htons(size << ((sizeof(uint16_t) * 8) - AAC_SIZELENGTH)); } int aac_encode_update(struct auenc_state **aesp, const struct aucodec *ac, struct auenc_param *param, const char *fmtp) { struct auenc_state *aes; struct aac_param prm; uint32_t enc_aot, enc_ratio; AACENC_InfoStruct enc_info; AACENC_ERROR error; int err = 0; (void)param; (void)fmtp; if (!aesp || !ac || !ac->ch) return EINVAL; debug("aac: encoder fmtp (%s)\n", fmtp); if (str_isset(fmtp)) { aac_mirror_params(fmtp); aac_decode_fmtp(&prm, fmtp); } else { prm.profile_level_id = aac_profile; prm.bitrate = aac_bitrate; prm.constantduration = aac_constantduration; } aes = *aesp; if (!aes) { aes = mem_zalloc(sizeof(*aes), destructor); if (!aes) return ENOMEM; error = aacEncOpen(&aes->enc, 0, 0); if (error != AACENC_OK) { warning("aac: Unable to open the encoder (0x%x)\n", error); err = ENOMEM; goto out; } if ((prm.profile_level_id >= 14 && prm.profile_level_id <= 21) || (prm.profile_level_id >= 40 && prm.profile_level_id <= 43)) { info("aac: Encoder Profile AAC-LC\n"); enc_aot = AOT_AAC_LC; /* AAC-LC */ enc_ratio = 1; } else if (prm.profile_level_id == 52 || (prm.profile_level_id >= 22 && prm.profile_level_id <= 29)) { info("aac: Encoder Profile AAC-LD\n"); enc_aot = AOT_ER_AAC_LD; /* AAC-LD */ enc_ratio = 1; } else if (prm.profile_level_id >= 76 && prm.profile_level_id <= 77) { info("aac: Encoder Profile AAC-ELD\n"); enc_aot = AOT_ER_AAC_ELD; /* AAC-ELD */ enc_ratio = 1; switch (ac->ch) { case MODE_1: /* mono */ prm.profile_level_id = 76; break; case MODE_2: /* stereo */ prm.profile_level_id = 77; break; } } else if (prm.profile_level_id >= 44 && prm.profile_level_id <= 47) { info("aac: Encoder Profile HE-AAC\n"); enc_aot = AOT_SBR; /* HE-AAC */ enc_ratio = 2; /* SBR */ } else if (prm.profile_level_id >= 48 && prm.profile_level_id <= 51 && ac->ch == MODE_2) { info("aac: Encoder Profile HE-AAC v2\n"); enc_aot = AOT_PS; /* HE-AAC v2 */ enc_ratio = 2; /* SBR */ } else { err = EINVAL; goto out; } debug("srate: %u, crate: %u, ch: %u, pch: %u, ptime: %u\n", ac->srate, ac->crate, ac->ch, ac->pch, ac->ptime); /* set mandatory encoder params: */ error |= aacEncoder_SetParam(aes->enc, AACENC_AOT, enc_aot); error |= aacEncoder_SetParam(aes->enc, AACENC_SAMPLERATE, ac->srate); error |= aacEncoder_SetParam(aes->enc, AACENC_CHANNELMODE, ac->ch); error |= aacEncoder_SetParam(aes->enc, AACENC_BITRATE, prm.bitrate); error |= aacEncoder_SetParam(aes->enc, AACENC_TRANSMUX, TT_MP4_RAW); /* set object specific encoder params: */ error |= aacEncoder_SetParam(aes->enc, AACENC_GRANULE_LENGTH, prm.constantduration/enc_ratio); /* set optional encoder params: */ error |= aacEncoder_SetParam(aes->enc, AACENC_BITRATEMODE, 0); /* AACENC_BR_MODE_CBR */ error |= aacEncoder_SetParam(aes->enc, AACENC_AFTERBURNER, 1); if (error != AACENC_OK) { err = EINVAL; goto out; } error = aacEncEncode(aes->enc, NULL, NULL, NULL, NULL); if (error != AACENC_OK) { warning( "aac: Unable to initialize the encoder (0x%x)\n", error); err = EINVAL; goto out; } error = aacEncInfo(aes->enc, &enc_info); if (error != AACENC_OK) { warning( "aac: Failed to get AAC encoder info (0x%x)\n", error); err = EINVAL; goto out; } re_snprintf(prm.config, sizeof(prm.config), "%w", enc_info.confBuf, enc_info.confSize); prm.constantduration = enc_info.frameLength; prm.bitrate = aacEncoder_GetParam(aes->enc, AACENC_BITRATE); debug("aac: Encoder configuration: conf=%w, " "frameLength=%u, inputChannels=%u\n", enc_info.confBuf, enc_info.confSize, enc_info.frameLength, enc_info.inputChannels ); debug("aac: encoder setup:\n" "\tAOT=%u\n" "\tBITRATE=%u\n" "\tBITRATEMODE=%u\n" "\tSAMPLERATE=%u\n" "\tSBR_MODE=%u\n" "\tGRANULE_LENGTH=%u\n" "\tCHANNELMODE=%u\n" "\tCHANNELORDER=%u\n" "\tSBR_RATIO=%u\n" "\tAFTERBURNER=%u\n" "\tBANDWIDTH=%u\n" "\tTRANSMUX=%u\n" "\tHEADER PERIOD=%u\n" "\tSIGNALING_MODE=%u\n" "\tTPSUBFRAMES=%u\n" "\tPROTECTION=%u\n" "\tANCILLARY_BITRATE=%u\n" "\tMETADATA_MODE=%u\n", aacEncoder_GetParam(aes->enc, AACENC_AOT), aacEncoder_GetParam(aes->enc, AACENC_BITRATE), aacEncoder_GetParam(aes->enc, AACENC_BITRATEMODE), aacEncoder_GetParam(aes->enc, AACENC_SAMPLERATE), aacEncoder_GetParam(aes->enc, AACENC_SBR_MODE), aacEncoder_GetParam(aes->enc, AACENC_GRANULE_LENGTH), aacEncoder_GetParam(aes->enc, AACENC_CHANNELMODE), aacEncoder_GetParam(aes->enc, AACENC_CHANNELORDER), aacEncoder_GetParam(aes->enc, AACENC_SBR_RATIO), aacEncoder_GetParam(aes->enc, AACENC_AFTERBURNER), aacEncoder_GetParam(aes->enc, AACENC_BANDWIDTH), aacEncoder_GetParam(aes->enc, AACENC_TRANSMUX), aacEncoder_GetParam(aes->enc, AACENC_HEADER_PERIOD), aacEncoder_GetParam(aes->enc, AACENC_SIGNALING_MODE), aacEncoder_GetParam(aes->enc, AACENC_TPSUBFRAMES), aacEncoder_GetParam(aes->enc, AACENC_PROTECTION), aacEncoder_GetParam(aes->enc, AACENC_ANCILLARY_BITRATE), aacEncoder_GetParam(aes->enc, AACENC_METADATA_MODE)); /* aac_encode_fmtp(&prm); */ } *aesp = aes; out: if (err) mem_deref(aes); return err; } int aac_encode_frm(struct auenc_state *aes, bool *marker, uint8_t *buf, size_t *len, int fmt, const void *sampv, size_t sampc) { /*warning("aac_encode_frm()\n");*/ AACENC_BufDesc in_buf, out_buf; AACENC_InArgs in_args; AACENC_OutArgs out_args; AACENC_ERROR error; INT in_id = IN_AUDIO_DATA, in_size, in_elem_size = sizeof(int16_t); INT out_id = OUT_BITSTREAM_DATA, out_size, out_elem_size = 1; const int16_t *s16 = sampv; INT total = 0; INT sampi = 0; /* uint16_t au_sizes[UINT8_MAX]; */ uint8_t i = 0; if (!aes || !buf || !len || !sampv) return EINVAL; if (fmt != AUFMT_S16LE) return ENOTSUP; /* * ToDo: Implement encoding of multiple * access units. May need intermediate * buffering of au data before writing * headers and header length. */ buf += AU_HDR_LEN; /* single access unit only! */ while (((INT)sampc > sampi) && (i < UINT8_MAX)) { in_size = (INT)sizeof(int16_t) * ((INT)sampc - sampi); in_buf.numBufs = 1; in_buf.bufs = (void **)&s16; in_buf.bufferIdentifiers = &in_id; in_buf.bufSizes = &in_size; in_buf.bufElSizes = &in_elem_size; out_size = (INT)*len - total - AU_HDR_LEN; /* 1 au only! */ out_buf.numBufs = 1; out_buf.bufs = (void **)&buf; out_buf.bufferIdentifiers = &out_id; out_buf.bufSizes = &out_size; out_buf.bufElSizes = &out_elem_size; in_args.numInSamples = (INT)sampc - sampi; in_args.numAncBytes = 0; error = aacEncEncode(aes->enc, &in_buf, &out_buf, &in_args, &out_args); if (error != AACENC_OK) { warning("aac: aacEncEncode() failed (0x%x)\n", error); return EINVAL; } sampi += out_args.numInSamples; s16 += out_args.numInSamples; buf += out_args.numOutBytes; total += out_args.numOutBytes; if (out_args.numOutBytes > 0) { /* au_sizes[i] = out_args.numOutBytes; */ if (i > 0) /* single access unit only! */ warning("aac: Sorry, encoding multiple AU " "per packet is not implemented yet.\n" "Please reduce the amount of samples " "passed to encoder per packet by " "lowering ptime value.\n"); ++i; } } if (total == 0) { *len = 0; return 0; } *marker = true; buf -= total + AU_HDR_LEN; /* single access unit only! */ hdr_encode(buf, total); *len = total + AU_HDR_LEN; /* single access unit only! */ return 0; } baresip-1.0.0/modules/aac/module.mk000066400000000000000000000003141372575704200171610ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # MOD := aac $(MOD)_SRCS += decode.c $(MOD)_SRCS += encode.c $(MOD)_SRCS += aac.c $(MOD)_SRCS += sdp.c $(MOD)_LFLAGS += -lfdk-aac -lm include mk/mod.mk baresip-1.0.0/modules/aac/sdp.c000066400000000000000000000032311372575704200162760ustar00rootroot00000000000000/** * @file aac/sdp.c MPEG-4 AAC SDP Functions * * Copyright (C) 2010 Creytiv.com * Copyright (C) 2019 Hessischer Rundfunk */ #include #include #include #include #include "aac.h" static unsigned param_value(const char *fmtp, const char *name) { struct pl pl, val; if (!fmtp || !name) return 0; pl_set_str(&pl, fmtp); if (fmt_param_get(&pl, name, &val)) return pl_u32(&val); return 0; } /* check decoding compatibility of remote format */ bool aac_fmtp_cmp(const char *lfmtp, const char *rfmtp, void *arg) { struct pl pl, val; uint32_t plid; unsigned bitrate; (void)lfmtp; (void)arg; if (!rfmtp) return false; pl_set_str(&pl, rfmtp); debug("aac: compare: %s\n", rfmtp); if (fmt_param_get(&pl, "mode", &val)) { if (strncasecmp("AAC-hbr", val.p, val.l)) return false; } if (param_value(rfmtp, "streamType") != AAC_STREAMTYPE_AUDIO) return false; if (param_value(rfmtp, "sizeLength") != AAC_SIZELENGTH) return false; if (param_value(rfmtp, "indexLength") != AAC_INDEXLENGTH) return false; if (param_value(rfmtp, "indexDeltaLength") != AAC_INDEXDELTALENGTH) return false; bitrate = param_value(rfmtp, "bitrate"); if (bitrate && (bitrate < 8000 || bitrate > 576000)) return false; switch (param_value(rfmtp, "constantDuration")) { case 120: case 128: case 240: case 256: case 480: case 512: case 960: case 1024: case 1920: case 2048: break; default: return false; } plid = param_value(rfmtp, "profile-level-id"); if (!((plid >= 14 && plid <= 29) || (plid >= 41 && plid <= 52) || (plid >= 76 && plid <= 77))) return false; return true; } baresip-1.0.0/modules/account/000077500000000000000000000000001372575704200162555ustar00rootroot00000000000000baresip-1.0.0/modules/account/account.c000066400000000000000000000114201372575704200200530ustar00rootroot00000000000000/** * @file account/account.c Load SIP accounts from file * * Copyright (C) 2010 - 2015 Creytiv.com */ #include #include /** * @defgroup account account * * Load SIP accounts from a file * * This module is loading SIP accounts from file ~/.baresip/accounts. * If the file exist and is readable, all SIP accounts will be populated * from this file. If the file does not exist, a template file will be * created. * * Examples: \verbatim "User 1 with password prompt" "User 2 with stored password" ;auth_pass=pass "User 2 with ICE" ;medianat=ice "User 3 with IPv6" \endverbatim */ static int account_write_template(const char *file) { FILE *f = NULL; const char *login, *pass, *domain; int r, err = 0; info("account: creating accounts template %s\n", file); f = fopen(file, "w"); if (!f) return errno; login = sys_username(); if (!login) { login = "user"; } pass = "PASSWORD"; domain = net_domain(baresip_network()); if (!domain) domain = "domain"; r = re_fprintf(f, "#\n" "# SIP accounts - one account per line\n" "#\n" "# Displayname ;addr-params\n" "#\n" "# uri-params:\n" "# ;transport={udp,tcp,tls}\n" "#\n" "# addr-params:\n" "# ;answermode={manual,early,auto}\n" "# ;audio_codecs=opus/48000/2,pcma,...\n" "# ;audio_source=alsa,default\n" "# ;audio_player=alsa,default\n" "# ;auth_user=username\n" "# ;auth_pass=password\n" "# ;call_transfer=no\n" "# ;mediaenc={srtp,srtp-mand,srtp-mandf" ",dtls_srtp,zrtp}\n" "# ;medianat={stun,turn,ice}\n" "# ;mwi=no\n" "# ;outbound=\"sip:primary.example.com" ";transport=tcp\"\n" "# ;outbound2=sip:secondary.example.com\n" "# ;ptime={10,20,30,40,...}\n" "# ;regint=3600\n" "# ;pubint=0 (publishing off)\n" "# ;regq=0.5\n" "# ;sipnat={outbound}\n" "# ;stunuser=STUN/TURN/ICE-username\n" "# ;stunpass=STUN/TURN/ICE-password\n" "# ;stunserver=stun:[user:pass]@host[:port]\n" "# ;video_codecs=h264,h263,...\n" "#\n" "# Examples:\n" "#\n" "# " ";auth_pass=secret\n" "# " ";auth_pass=secret\n" "# ;auth_pass=secret\n" "#\n" "#;auth_pass=%s\n", login, domain, pass); if (r < 0) err = ENOMEM; if (f) (void)fclose(f); return err; } /** * Add a User-Agent (UA) * * @param addr SIP Address string * @param arg Handler argument (unused) * * @return 0 if success, otherwise errorcode */ static int line_handler(const struct pl *addr, void *arg) { char buf[512]; struct ua *ua; struct account *acc; int err; (void)arg; (void)pl_strcpy(addr, buf, sizeof(buf)); err = ua_alloc(&ua, buf); if (err) return err; acc = ua_account(ua); if (!acc) { warning("account: no account for this ua\n"); return ENOENT; } if (account_regint(acc) != 0) { int e; e = ua_register(ua); if (e) { warning("account: failed to register ua" " '%s' (%m)\n", account_aor(acc), e); } } /* prompt password if auth_user is set, but auth_pass is not */ if (str_isset(account_auth_user(acc)) && !str_isset(account_auth_pass(acc))) { char *pass = NULL; (void)re_printf("Please enter password for %s: ", account_aor(acc)); err = ui_password_prompt(&pass); if (err) goto out; err = account_set_auth_pass(acc, pass); mem_deref(pass); } out: return err; } /** * Read the SIP accounts from the ~/.baresip/accounts file * * @return 0 if success, otherwise errorcode */ static int account_read_file(void) { char path[256] = "", file[256] = ""; uint32_t n; int err; err = conf_path_get(path, sizeof(path)); if (err) { warning("account: conf_path_get (%m)\n", err); return err; } if (re_snprintf(file, sizeof(file), "%s/accounts", path) < 0) return ENOMEM; if (!conf_fileexist(file)) { (void)fs_mkdir(path, 0700); err = account_write_template(file); if (err) return err; } err = conf_parse(file, line_handler, NULL); if (err) return err; n = list_count(uag_list()); info("Populated %u account%s\n", n, 1==n ? "" : "s"); if (list_isempty(uag_list())) { info("account: No SIP accounts found\n" " -- check your config " "or add an account using 'uanew' command\n"); } return 0; } static int module_init(void) { return account_read_file(); } static int module_close(void) { return 0; } const struct mod_export DECL_EXPORTS(account) = { "account", "application", module_init, module_close }; baresip-1.0.0/modules/account/module.mk000066400000000000000000000001671372575704200200770ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 - 2015 Creytiv.com # MOD := account $(MOD)_SRCS += account.c include mk/mod.mk baresip-1.0.0/modules/alsa/000077500000000000000000000000001372575704200155415ustar00rootroot00000000000000baresip-1.0.0/modules/alsa/alsa.c000066400000000000000000000070701372575704200166310ustar00rootroot00000000000000/** * @file alsa.c ALSA sound driver * * Copyright (C) 2010 Creytiv.com */ #define _DEFAULT_SOURCE 1 #define _POSIX_SOURCE 1 #include #include #include #include #include #include #include #include #include "alsa.h" /** * @defgroup alsa alsa * * Advanced Linux Sound Architecture (ALSA) audio driver module * * * References: * * http://www.alsa-project.org/main/index.php/Main_Page */ char alsa_dev[64] = "default"; static struct ausrc *ausrc; static struct auplay *auplay; int alsa_reset(snd_pcm_t *pcm, uint32_t srate, uint32_t ch, uint32_t num_frames, snd_pcm_format_t pcmfmt) { snd_pcm_hw_params_t *hw_params = NULL; snd_pcm_uframes_t period = num_frames, bufsize = num_frames * 4; int err; debug("alsa: reset: srate=%u, ch=%u, num_frames=%u, pcmfmt=%s\n", srate, ch, num_frames, snd_pcm_format_name(pcmfmt)); err = snd_pcm_hw_params_malloc(&hw_params); if (err < 0) { warning("alsa: cannot allocate hw params (%s)\n", snd_strerror(err)); goto out; } err = snd_pcm_hw_params_any(pcm, hw_params); if (err < 0) { warning("alsa: cannot initialize hw params (%s)\n", snd_strerror(err)); goto out; } err = snd_pcm_hw_params_set_access(pcm, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED); if (err < 0) { warning("alsa: cannot set access type (%s)\n", snd_strerror(err)); goto out; } err = snd_pcm_hw_params_set_format(pcm, hw_params, pcmfmt); if (err < 0) { warning("alsa: cannot set sample format %d (%s)\n", pcmfmt, snd_strerror(err)); goto out; } err = snd_pcm_hw_params_set_rate(pcm, hw_params, srate, 0); if (err < 0) { warning("alsa: cannot set sample rate to %u Hz (%s)\n", srate, snd_strerror(err)); goto out; } err = snd_pcm_hw_params_set_channels(pcm, hw_params, ch); if (err < 0) { warning("alsa: cannot set channel count to %d (%s)\n", ch, snd_strerror(err)); goto out; } err = snd_pcm_hw_params_set_period_size_near(pcm, hw_params, &period, 0); if (err < 0) { warning("alsa: cannot set period size to %d (%s)\n", period, snd_strerror(err)); } err = snd_pcm_hw_params_set_buffer_size_near(pcm, hw_params, &bufsize); if (err < 0) { warning("alsa: cannot set buffer size to %d (%s)\n", bufsize, snd_strerror(err)); } err = snd_pcm_hw_params(pcm, hw_params); if (err < 0) { warning("alsa: cannot set parameters (%s)\n", snd_strerror(err)); goto out; } err = snd_pcm_prepare(pcm); if (err < 0) { warning("alsa: cannot prepare audio interface for use (%s)\n", snd_strerror(err)); goto out; } err = 0; out: snd_pcm_hw_params_free(hw_params); if (err) { warning("alsa: init failed: err=%d\n", err); } return err; } snd_pcm_format_t aufmt_to_alsaformat(enum aufmt fmt) { switch (fmt) { case AUFMT_S16LE: return SND_PCM_FORMAT_S16; case AUFMT_FLOAT: return SND_PCM_FORMAT_FLOAT; case AUFMT_S24_3LE: return SND_PCM_FORMAT_S24_3LE; default: return SND_PCM_FORMAT_UNKNOWN; } } static int alsa_init(void) { int err; err = ausrc_register(&ausrc, baresip_ausrcl(), "alsa", alsa_src_alloc); err |= auplay_register(&auplay, baresip_auplayl(), "alsa", alsa_play_alloc); return err; } static int alsa_close(void) { ausrc = mem_deref(ausrc); auplay = mem_deref(auplay); /* releases all resources of the global configuration tree, and sets snd_config to NULL. */ snd_config_update_free_global(); return 0; } const struct mod_export DECL_EXPORTS(alsa) = { "alsa", "sound", alsa_init, alsa_close }; baresip-1.0.0/modules/alsa/alsa.h000066400000000000000000000012211372575704200166260ustar00rootroot00000000000000/** * @file alsa.h ALSA sound driver -- internal interface * * Copyright (C) 2010 Creytiv.com */ extern char alsa_dev[64]; int alsa_reset(snd_pcm_t *pcm, uint32_t srate, uint32_t ch, uint32_t num_frames, snd_pcm_format_t pcmfmt); snd_pcm_format_t aufmt_to_alsaformat(enum aufmt fmt); int alsa_src_alloc(struct ausrc_st **stp, const struct ausrc *as, struct media_ctx **ctx, struct ausrc_prm *prm, const char *device, ausrc_read_h *rh, ausrc_error_h *errh, void *arg); int alsa_play_alloc(struct auplay_st **stp, const struct auplay *ap, struct auplay_prm *prm, const char *device, auplay_write_h *wh, void *arg); baresip-1.0.0/modules/alsa/alsa_play.c000066400000000000000000000063601372575704200176570ustar00rootroot00000000000000/** * @file alsa_play.c ALSA sound driver - player * * Copyright (C) 2010 Creytiv.com */ #define _DEFAULT_SOURCE 1 #define _POSIX_SOURCE 1 #include #include #include #include #include #include #include #include #include #include "alsa.h" struct auplay_st { const struct auplay *ap; /* pointer to base-class (inheritance) */ pthread_t thread; volatile bool run; snd_pcm_t *write; void *sampv; size_t sampc; auplay_write_h *wh; void *arg; struct auplay_prm prm; char *device; }; static void auplay_destructor(void *arg) { struct auplay_st *st = arg; /* Wait for termination of other thread */ if (st->run) { debug("alsa: stopping playback thread (%s)\n", st->device); st->run = false; (void)pthread_join(st->thread, NULL); } if (st->write) snd_pcm_close(st->write); mem_deref(st->sampv); mem_deref(st->device); } static void *write_thread(void *arg) { struct auplay_st *st = arg; int n; int num_frames; num_frames = st->prm.srate * st->prm.ptime / 1000; while (st->run) { const int samples = num_frames; void *sampv; st->wh(st->sampv, st->sampc, st->arg); sampv = st->sampv; n = snd_pcm_writei(st->write, sampv, samples); if (-EPIPE == n) { snd_pcm_prepare(st->write); n = snd_pcm_writei(st->write, sampv, samples); if (n != samples) { warning("alsa: write error: %s\n", snd_strerror(n)); } } else if (n < 0) { warning("alsa: write error: %s\n", snd_strerror(n)); } else if (n != samples) { warning("alsa: write: wrote %d of %d samples\n", n, samples); } } snd_pcm_drain(st->write); return NULL; } int alsa_play_alloc(struct auplay_st **stp, const struct auplay *ap, struct auplay_prm *prm, const char *device, auplay_write_h *wh, void *arg) { struct auplay_st *st; snd_pcm_format_t pcmfmt; int num_frames; int err; if (!stp || !ap || !prm || !wh) return EINVAL; if (!str_isset(device)) device = alsa_dev; st = mem_zalloc(sizeof(*st), auplay_destructor); if (!st) return ENOMEM; err = str_dup(&st->device, device); if (err) goto out; st->prm = *prm; st->ap = ap; st->wh = wh; st->arg = arg; st->sampc = prm->srate * prm->ch * prm->ptime / 1000; num_frames = st->prm.srate * st->prm.ptime / 1000; st->sampv = mem_alloc(aufmt_sample_size(prm->fmt) * st->sampc, NULL); if (!st->sampv) { err = ENOMEM; goto out; } err = snd_pcm_open(&st->write, st->device, SND_PCM_STREAM_PLAYBACK, 0); if (err < 0) { warning("alsa: could not open auplay device '%s' (%s)\n", st->device, snd_strerror(err)); goto out; } pcmfmt = aufmt_to_alsaformat(prm->fmt); if (pcmfmt == SND_PCM_FORMAT_UNKNOWN) { warning("alsa: unknown sample format '%s'\n", aufmt_name(prm->fmt)); err = EINVAL; goto out; } err = alsa_reset(st->write, st->prm.srate, st->prm.ch, num_frames, pcmfmt); if (err) { warning("alsa: could not reset player '%s' (%s)\n", st->device, snd_strerror(err)); goto out; } st->run = true; err = pthread_create(&st->thread, NULL, write_thread, st); if (err) { st->run = false; goto out; } debug("alsa: playback started (%s)\n", st->device); out: if (err) mem_deref(st); else *stp = st; return err; } baresip-1.0.0/modules/alsa/alsa_src.c000066400000000000000000000065121372575704200175000ustar00rootroot00000000000000/** * @file alsa_src.c ALSA sound driver - recorder * * Copyright (C) 2010 Creytiv.com */ #define _DEFAULT_SOURCE 1 #define _POSIX_SOURCE 1 #include #include #include #include #include #include #include #include #include #include "alsa.h" struct ausrc_st { const struct ausrc *as; /* pointer to base-class (inheritance) */ pthread_t thread; volatile bool run; snd_pcm_t *read; void *sampv; size_t sampc; ausrc_read_h *rh; void *arg; struct ausrc_prm prm; char *device; }; static void ausrc_destructor(void *arg) { struct ausrc_st *st = arg; /* Wait for termination of other thread */ if (st->run) { debug("alsa: stopping recording thread (%s)\n", st->device); st->run = false; (void)pthread_join(st->thread, NULL); } if (st->read) snd_pcm_close(st->read); mem_deref(st->sampv); mem_deref(st->device); } static void *read_thread(void *arg) { struct ausrc_st *st = arg; uint64_t frames = 0; int num_frames; int err; num_frames = st->prm.srate * st->prm.ptime / 1000; /* Start */ err = snd_pcm_start(st->read); if (err) { warning("alsa: could not start ausrc device '%s' (%s)\n", st->device, snd_strerror(err)); goto out; } while (st->run) { struct auframe af; long n; n = snd_pcm_readi(st->read, st->sampv, num_frames); if (n == -EPIPE) { snd_pcm_prepare(st->read); continue; } else if (n <= 0) { continue; } af.fmt = st->prm.fmt; af.sampv = st->sampv; af.sampc = n * st->prm.ch; af.timestamp = frames * AUDIO_TIMEBASE / st->prm.srate; frames += n; st->rh(&af, st->arg); } out: return NULL; } int alsa_src_alloc(struct ausrc_st **stp, const struct ausrc *as, struct media_ctx **ctx, struct ausrc_prm *prm, const char *device, ausrc_read_h *rh, ausrc_error_h *errh, void *arg) { struct ausrc_st *st; snd_pcm_format_t pcmfmt; int num_frames; int err; (void)ctx; (void)errh; if (!stp || !as || !prm || !rh) return EINVAL; if (!str_isset(device)) device = alsa_dev; st = mem_zalloc(sizeof(*st), ausrc_destructor); if (!st) return ENOMEM; err = str_dup(&st->device, device); if (err) goto out; st->prm = *prm; st->as = as; st->rh = rh; st->arg = arg; st->sampc = prm->srate * prm->ch * prm->ptime / 1000; num_frames = st->prm.srate * st->prm.ptime / 1000; st->sampv = mem_alloc(aufmt_sample_size(prm->fmt) * st->sampc, NULL); if (!st->sampv) { err = ENOMEM; goto out; } err = snd_pcm_open(&st->read, st->device, SND_PCM_STREAM_CAPTURE, 0); if (err < 0) { warning("alsa: could not open ausrc device '%s' (%s)\n", st->device, snd_strerror(err)); goto out; } pcmfmt = aufmt_to_alsaformat(prm->fmt); if (pcmfmt == SND_PCM_FORMAT_UNKNOWN) { warning("alsa: unknown sample format '%s'\n", aufmt_name(prm->fmt)); err = EINVAL; goto out; } err = alsa_reset(st->read, st->prm.srate, st->prm.ch, num_frames, pcmfmt); if (err) { warning("alsa: could not reset source '%s' (%s)\n", st->device, snd_strerror(err)); goto out; } st->run = true; err = pthread_create(&st->thread, NULL, read_thread, st); if (err) { st->run = false; goto out; } debug("alsa: recording started (%s) format=%s\n", st->device, aufmt_name(prm->fmt)); out: if (err) mem_deref(st); else *stp = st; return err; } baresip-1.0.0/modules/alsa/module.mk000066400000000000000000000002331372575704200173550ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # MOD := alsa $(MOD)_SRCS += alsa.c alsa_src.c alsa_play.c $(MOD)_LFLAGS += -lasound include mk/mod.mk baresip-1.0.0/modules/amr/000077500000000000000000000000001372575704200154005ustar00rootroot00000000000000baresip-1.0.0/modules/amr/amr.c000066400000000000000000000133151372575704200163260ustar00rootroot00000000000000/** * @file amr.c Adaptive Multi-Rate (AMR) audio codec * * Copyright (C) 2010 Creytiv.com */ #include #ifdef AMR_NB #include #include #endif #ifdef AMR_WB #ifdef _TYPEDEF_H #define typedef_h #endif #include #include #endif #include #include #include #include "amr.h" #ifdef VO_AMRWBENC_ENC_IF_H #define IF2E_IF_encode E_IF_encode #define IF2D_IF_decode D_IF_decode #endif /** * @defgroup amr amr * * This module supports both AMR Narrowband (8000 Hz) and * AMR Wideband (16000 Hz) audio codecs. * * NOTE: only octet-align mode is supported. * * * Reference: * * http://tools.ietf.org/html/rfc4867 * * http://www.penguin.cz/~utx/amr */ #ifndef L_FRAME16k #define L_FRAME16k 320 #endif #ifndef NB_SERIAL_MAX #define NB_SERIAL_MAX 61 #endif enum { FRAMESIZE_NB = 160 }; struct auenc_state { const struct aucodec *ac; void *enc; /**< Encoder state */ }; struct audec_state { const struct aucodec *ac; void *dec; /**< Decoder state */ }; static void encode_destructor(void *arg) { struct auenc_state *st = arg; switch (st->ac->srate) { #ifdef AMR_NB case 8000: Encoder_Interface_exit(st->enc); break; #endif #ifdef AMR_WB case 16000: E_IF_exit(st->enc); break; #endif } } static void decode_destructor(void *arg) { struct audec_state *st = arg; switch (st->ac->srate) { #ifdef AMR_NB case 8000: Decoder_Interface_exit(st->dec); break; #endif #ifdef AMR_WB case 16000: D_IF_exit(st->dec); break; #endif } } static int encode_update(struct auenc_state **aesp, const struct aucodec *ac, struct auenc_param *prm, const char *fmtp) { struct auenc_state *st; int err = 0; (void)prm; (void)fmtp; if (!aesp || !ac) return EINVAL; if (*aesp) return 0; st = mem_zalloc(sizeof(*st), encode_destructor); if (!st) return ENOMEM; st->ac = ac; switch (ac->srate) { #ifdef AMR_NB case 8000: st->enc = Encoder_Interface_init(0); break; #endif #ifdef AMR_WB case 16000: st->enc = E_IF_init(); break; #endif } if (!st->enc) err = ENOMEM; if (err) mem_deref(st); else *aesp = st; return err; } static int decode_update(struct audec_state **adsp, const struct aucodec *ac, const char *fmtp) { struct audec_state *st; int err = 0; (void)fmtp; if (!adsp || !ac) return EINVAL; if (*adsp) return 0; st = mem_zalloc(sizeof(*st), decode_destructor); if (!st) return ENOMEM; st->ac = ac; switch (ac->srate) { #ifdef AMR_NB case 8000: st->dec = Decoder_Interface_init(); break; #endif #ifdef AMR_WB case 16000: st->dec = D_IF_init(); break; #endif } if (!st->dec) err = ENOMEM; if (err) mem_deref(st); else *adsp = st; return err; } #ifdef AMR_WB static int encode_wb(struct auenc_state *st, bool *marker, uint8_t *buf, size_t *len, int fmt, const void *sampv, size_t sampc) { int n; (void)marker; if (sampc != L_FRAME16k) return EINVAL; if (*len < (1+NB_SERIAL_MAX)) return ENOMEM; if (fmt != AUFMT_S16LE) return ENOTSUP; /* CMR value 15 indicates that no mode request is present */ buf[0] = 15 << 4; n = IF2E_IF_encode(st->enc, 8, sampv, &buf[1], 0); if (n <= 0) return EPROTO; *len = (1 + n); return 0; } static int decode_wb(struct audec_state *st, int fmt, void *sampv, size_t *sampc, bool marker, const uint8_t *buf, size_t len) { (void)marker; if (*sampc < L_FRAME16k) return ENOMEM; if (len > (1+NB_SERIAL_MAX)) return EINVAL; if (fmt != AUFMT_S16LE) return ENOTSUP; IF2D_IF_decode(st->dec, &buf[1], sampv, 0); *sampc = L_FRAME16k; return 0; } #endif #ifdef AMR_NB static int encode_nb(struct auenc_state *st, bool *marker, uint8_t *buf, size_t *len, int fmt, const void *sampv, size_t sampc) { int r; (void)marker; if (!st || !buf || !len || !sampv || sampc != FRAMESIZE_NB) return EINVAL; if (*len < NB_SERIAL_MAX) return ENOMEM; if (fmt != AUFMT_S16LE) return ENOTSUP; /* CMR value 15 indicates that no mode request is present */ buf[0] = 15 << 4; r = Encoder_Interface_Encode(st->enc, MR122, sampv, &buf[1], 0); if (r <= 0) return EPROTO; *len = (1 + r); return 0; } static int decode_nb(struct audec_state *st, int fmt, void *sampv, size_t *sampc, bool marker, const uint8_t *buf, size_t len) { (void)marker; if (!st || !sampv || !sampc || !buf) return EINVAL; if (len > NB_SERIAL_MAX) return EPROTO; if (*sampc < L_FRAME16k) return ENOMEM; if (fmt != AUFMT_S16LE) return ENOTSUP; Decoder_Interface_Decode(st->dec, &buf[1], sampv, 0); *sampc = FRAMESIZE_NB; return 0; } #endif #ifdef AMR_WB static struct aucodec amr_wb = { .name = "AMR-WB", .srate = 16000, .crate = 16000, .ch = 1, .pch = 1, .encupdh = encode_update, .ench = encode_wb, .decupdh = decode_update, .dech = decode_wb, .fmtp_ench = amr_fmtp_enc, .fmtp_cmph = amr_fmtp_cmp }; #endif #ifdef AMR_NB static struct aucodec amr_nb = { .name = "AMR", .srate = 8000, .crate = 8000, .ch = 1, .pch = 1, .encupdh = encode_update, .ench = encode_nb, .decupdh = decode_update, .dech = decode_nb, .fmtp_ench = amr_fmtp_enc, .fmtp_cmph = amr_fmtp_cmp }; #endif static int module_init(void) { int err = 0; #ifdef AMR_WB aucodec_register(baresip_aucodecl(), &amr_wb); #endif #ifdef AMR_NB aucodec_register(baresip_aucodecl(), &amr_nb); #endif return err; } static int module_close(void) { #ifdef AMR_WB aucodec_unregister(&amr_wb); #endif #ifdef AMR_NB aucodec_unregister(&amr_nb); #endif return 0; } EXPORT_SYM const struct mod_export DECL_EXPORTS(amr) = { "amr", "codec", module_init, module_close }; baresip-1.0.0/modules/amr/amr.h000066400000000000000000000004131372575704200163260ustar00rootroot00000000000000/** * @file amr/amr.h AMR module -- internal interface * * Copyright (C) 2010 - 2015 Creytiv.com */ int amr_fmtp_enc(struct mbuf *mb, const struct sdp_format *fmt, bool offer, void *arg); bool amr_fmtp_cmp(const char *lfmtp, const char *rfmtp, void *arg); baresip-1.0.0/modules/amr/module.mk000066400000000000000000000053301372575704200172170ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # # opencore-amr source directory AMR_PATH ?= ../amr # opencore-amr vo-amrwbenc source directory AMRWBENC_PATH ?= ../vo-amrwbenc MOD := amr $(MOD)_SRCS += amr.c sdp.c ifneq ($(shell [ -d $(SYSROOT)/include/opencore-amrnb ] && echo 1 ),) $(MOD)_CFLAGS += -DAMR_NB=1 -I$(SYSROOT)/include/opencore-amrnb $(MOD)_LFLAGS += -lopencore-amrnb else ifneq ($(shell [ -d $(SYSROOT_LOCAL)/include/opencore-amrnb ] && echo 1 ),) $(MOD)_CFLAGS += -DAMR_NB=1 -I$(SYSROOT_LOCAL)/include/opencore-amrnb $(MOD)_LFLAGS += -lopencore-amrnb else ifneq ($(shell [ -d $(SYSROOT_ALT)/include/opencore-amrnb ] && echo 1 ),) $(MOD)_CFLAGS += -DAMR_NB=1 -I$(SYSROOT_ALT)/include/opencore-amrnb $(MOD)_LFLAGS += -lopencore-amrnb else ifneq ($(shell [ -d $(SYSROOT)/local/include/amrnb ] && echo 1),) $(MOD)_CFLAGS += -DAMR_NB=1 -I$(SYSROOT)/local/include/amrnb $(MOD)_LFLAGS += -lamrnb else ifneq ($(shell [ -d $(SYSROOT)/include/amrnb ] && echo 1),) $(MOD)_CFLAGS += -DAMR_NB=1 -I$(SYSROOT)/include/amrnb $(MOD)_LFLAGS += -lamrnb else ifneq ($(shell [ -d $(AMR_PATH)/include/opencore-amrnb ] && echo 1),) $(MOD)_CFLAGS += -DAMR_NB=1 -I$(AMR_PATH)/include/opencore-amrnb $(MOD)_LFLAGS += -lamrnb endif endif endif endif endif endif ifneq ($(shell [ -f $(SYSROOT_ALT)/include/opencore-amrwb/enc_if.h ] && \ echo 1 ),) $(MOD)_CFLAGS += -DAMR_WB=1 -I$(SYSROOT_ALT)/include/opencore-amrwb $(MOD)_LFLAGS += -lopencore-amrwb else ifneq ($(shell [ -f $(SYSROOT_LOCAL)/include/opencore-amrwb/enc_if.h ] && \ echo 1 ),) $(MOD)_CFLAGS += -DAMR_WB=1 -I$(SYSROOT_LOCAL)/include/opencore-amrwb $(MOD)_LFLAGS += -lopencore-amrwb else ifneq ($(shell [ -f $(SYSROOT)/local/include/amrwb/enc_if.h ] && echo 1),) $(MOD)_CFLAGS += -DAMR_WB=1 -I$(SYSROOT)/local/include/amrwb $(MOD)_LFLAGS += -lamrwb else ifneq ($(shell [ -f $(SYSROOT)/include/amrwb/enc_if.h ] && echo 1),) $(MOD)_CFLAGS += -DAMR_WB=1 -I$(SYSROOT)/include/amrwb $(MOD)_LFLAGS += -lamrwb else ifneq ($(shell [ -f $(SYSROOT)/include/vo-amrwbenc/enc_if.h ] && echo 1),) $(MOD)_CFLAGS += -DAMR_WB=1 -I$(SYSROOT)/include/vo-amrwbenc $(MOD)_LFLAGS += -lvo-amrwbenc else ifneq ($(shell [ -f $(AMRWBENC_PATH)/include/vo-amrwbenc/enc_if.h ] && \ echo 1),) $(MOD)_CFLAGS += -DAMR_WB=1 -I$(AMRWBENC_PATH)/include/vo-amrwbenc $(MOD)_LFLAGS += -lvo-amrwbenc endif endif endif endif endif endif # extra for decoder ifneq ($(shell [ -f $(SYSROOT)/include/opencore-amrwb/dec_if.h ] && echo 1 ),) $(MOD)_CFLAGS += -I$(SYSROOT)/include/opencore-amrwb $(MOD)_LFLAGS += -lopencore-amrwb else ifneq ($(shell [ -f $(AMR_PATH)/include/opencore-amrwb/dec_if.h ] && echo 1),) $(MOD)_CFLAGS += -I$(AMR_PATH)/include/opencore-amrwb $(MOD)_LFLAGS += -lopencore-amrwb endif endif $(MOD)_LFLAGS += -lm include mk/mod.mk baresip-1.0.0/modules/amr/sdp.c000066400000000000000000000015601372575704200163340ustar00rootroot00000000000000/** * @file amr/sdp.c AMR SDP Functions * * Copyright (C) 2010 - 2015 Creytiv.com */ #include #include #include "amr.h" static bool amr_octet_align(const char *fmtp) { struct pl pl, oa; if (!fmtp) return false; pl_set_str(&pl, fmtp); if (fmt_param_get(&pl, "octet-align", &oa)) return 0 == pl_strcmp(&oa, "1"); return false; } int amr_fmtp_enc(struct mbuf *mb, const struct sdp_format *fmt, bool offer, void *arg) { const struct aucodec *ac = arg; (void)offer; if (!mb || !fmt || !ac) return 0; return mbuf_printf(mb, "a=fmtp:%s octet-align=1\r\n", fmt->id); } bool amr_fmtp_cmp(const char *lfmtp, const char *rfmtp, void *arg) { const struct aucodec *ac = arg; (void)lfmtp; if (!ac) return false; if (!amr_octet_align(rfmtp)) { info("amr: octet-align mode is required\n"); return false; } return true; } baresip-1.0.0/modules/aptx/000077500000000000000000000000001372575704200155755ustar00rootroot00000000000000baresip-1.0.0/modules/aptx/aptx.c000066400000000000000000000023411372575704200167150ustar00rootroot00000000000000/** * @file aptx.c aptX Audio Codec * * Copyright (C) 2019 Hessischer Rundfunk */ #include #include #include "aptx.h" /** * @defgroup aptx aptx * * aptX audio codec (Standard and HD variant) * * Supported version: * libopenaptx 0.1.0 or later * * References: * RFC 7310 RTP Payload Format for Standard apt-X * and Enhanced apt-X Codecs * * TODOs: * - Code check, cleanup and error handling * - Add SDP fmtp negotiation & config preconfiguration * - Check and implement other sampling rates and channel modes * - Add optional real 24 bit audio I/O support * */ static struct aucodec aptx = { .name = "aptx", .srate = APTX_SRATE, .crate = APTX_SRATE, .ch = APTX_CHANNELS, .pch = APTX_CHANNELS, .ptime = 4, .encupdh = aptx_encode_update, .ench = aptx_encode_frm, .decupdh = aptx_decode_update, .dech = aptx_decode_frm, .fmtp_ench = aptx_fmtp_enc, .fmtp_cmph = aptx_fmtp_cmp, }; static int module_init(void) { aucodec_register(baresip_aucodecl(), &aptx); return 0; } static int module_close(void) { aucodec_unregister(&aptx); return 0; } EXPORT_SYM const struct mod_export DECL_EXPORTS(aptx) = { "aptx", "audio codec", module_init, module_close, }; baresip-1.0.0/modules/aptx/aptx.h000066400000000000000000000020161372575704200167210ustar00rootroot00000000000000/** * @file aptx.h aptX Audio Codec -- internal interface * * Copyright (C) 2019 Hessischer Rundfunk */ #define APTX_VARIANT 0 /* 0 = Standard, 1 = HQ */ enum { APTX_SRATE = 48000, APTX_CHANNELS = 2, APTX_VARIANT_HD = 1, APTX_VARIANT_STANDARD = 0, APTX_WORDSIZE = 3, }; int aptx_encode_update(struct auenc_state **aesp, const struct aucodec *ac, struct auenc_param *param, const char *fmtp); int aptx_encode_frm(struct auenc_state *aes, bool *marker, uint8_t *buf, size_t *len, int fmt, const void *sampv, size_t sampc); int aptx_decode_update(struct audec_state **adsp, const struct aucodec *ac, const char *fmtp); int aptx_decode_frm(struct audec_state *ads, int fmt, void *sampv, size_t *sampc, bool marker, const uint8_t *buf, size_t len); int aptx_fmtp_enc(struct mbuf *mb, const struct sdp_format *fmt, bool offer, void *arg); bool aptx_fmtp_cmp(const char *lfmtp, const char *rfmtp, void *arg); baresip-1.0.0/modules/aptx/decode.c000066400000000000000000000035141372575704200171670ustar00rootroot00000000000000/** * @file aptx/decode.c aptX Decoder * * Copyright (C) 2019 Hessischer Rundfunk */ #include #include #include #include #include #include "aptx.h" struct audec_state { struct aptx_context *dec; }; static void destructor(void *arg) { struct audec_state *ads = arg; if (ads->dec) aptx_finish(ads->dec); } int aptx_decode_update(struct audec_state **adsp, const struct aucodec *ac, const char *fmtp) { struct audec_state *ads; int err = 0; (void)fmtp; if (!adsp || !ac || !ac->ch) return EINVAL; ads = *adsp; if (ads) return 0; ads = mem_zalloc(sizeof(*ads), destructor); if (!ads) return ENOMEM; ads->dec = aptx_init(APTX_VARIANT); if (!ads->dec) { warning("aptx: Cannot initialize decoder.\n"); err = ENOMEM; goto out; } out: if (err) mem_deref(ads); else *adsp = ads; return err; } int aptx_decode_frm(struct audec_state *ads, int fmt, void *sampv, size_t *sampc, bool marker, const uint8_t *buf, size_t len) { size_t processed = 0; size_t written = 0; uint8_t *sampv_buf = sampv; (void)marker; if (!ads || !sampv || !sampc || !buf) return EINVAL; processed = aptx_decode(ads->dec, buf, len, sampv, *sampc, &written); *sampc = written / APTX_WORDSIZE; if (written == 0) return 0; if (processed != len) warning("aptx: Decoding stopped in the middle of the sample, " "dropped %u bytes\n", (unsigned int)(len - processed)); switch (fmt) { case AUFMT_S16LE: /* remap S24 to S16 in same buffer */ for (size_t s = 0; s < *sampc; s++) { sampv_buf[s * 2] = sampv_buf[(s * APTX_WORDSIZE) + 1]; sampv_buf[s * 2 + 1] = sampv_buf[(s * APTX_WORDSIZE) + 2]; } break; case AUFMT_S24_3LE: break; default: return ENOTSUP; } return 0; } baresip-1.0.0/modules/aptx/encode.c000066400000000000000000000043401372575704200171770ustar00rootroot00000000000000/** * @file aptx/encode.c aptX Encoder * * Copyright (C) 2019 Hessischer Rundfunk */ #include #include #include #include #include #include "aptx.h" struct auenc_state { struct aptx_context *enc; }; static void destructor(void *arg) { struct auenc_state *aes = arg; if (aes->enc) aptx_finish(aes->enc); } int aptx_encode_update(struct auenc_state **aesp, const struct aucodec *ac, struct auenc_param *param, const char *fmtp) { struct auenc_state *aes; int err = 0; (void)param; (void)fmtp; if (!aesp || !ac || !ac->ch) return EINVAL; aes = *aesp; if (aes) goto out; aes = mem_zalloc(sizeof(*aes), destructor); if (!aes) return ENOMEM; aes->enc = aptx_init(APTX_VARIANT); if (!aes->enc) { warning("aptx: Cannot initialize encoder.\n"); err = ENOMEM; goto out; } *aesp = aes; out: if (err) mem_deref(aes); return err; } int aptx_encode_frm(struct auenc_state *aes, bool *marker, uint8_t *buf, size_t *len, int fmt, const void *sampv, size_t sampc) { size_t processed = 0; size_t written = 0; uint8_t *intermediate_buf; size_t sampv_len; const uint8_t *sampv_buf = sampv; (void)marker; if (!aes || !buf || !len || !sampv) return EINVAL; sampv_len = sampc * APTX_WORDSIZE; switch (fmt) { case AUFMT_S16LE: intermediate_buf = mem_alloc(sampv_len, NULL); if (!intermediate_buf) return ENOMEM; /* map S16 to S24 intermediate buffer */ for (size_t s = 0; s < sampc; s++) { intermediate_buf[s * APTX_WORDSIZE] = 0; intermediate_buf[s * APTX_WORDSIZE + 1] = sampv_buf[s * 2]; intermediate_buf[s * APTX_WORDSIZE + 2] = sampv_buf[s * 2 + 1]; } processed = aptx_encode(aes->enc, intermediate_buf, sampv_len, buf, *len, &written); mem_deref(intermediate_buf); break; case AUFMT_S24_3LE: processed = aptx_encode(aes->enc, sampv_buf, sampv_len, buf, *len, &written); break; default: return ENOTSUP; } if (processed != sampv_len) warning("aptx: Encoding stopped in the middle of the sample, " "dropped %u bytes\n", (unsigned int)(sampv_len - processed)); *len = written; return 0; } baresip-1.0.0/modules/aptx/module.mk000066400000000000000000000003231372575704200174110ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2019 Hessischer Rundfunk # MOD := aptx $(MOD)_SRCS += decode.c $(MOD)_SRCS += encode.c $(MOD)_SRCS += aptx.c $(MOD)_SRCS += sdp.c $(MOD)_LFLAGS += -lopenaptx include mk/mod.mk baresip-1.0.0/modules/aptx/sdp.c000066400000000000000000000022001372575704200165210ustar00rootroot00000000000000/** * @file aptx/sdp.c aptX SDP Functions * * Copyright (C) 2019 Hessischer Rundfunk */ #include #include #include #include "aptx.h" static unsigned param_value(const char *fmtp, const char *name) { struct pl pl, val; if (!fmtp || !name) return 0; pl_set_str(&pl, fmtp); if (fmt_param_get(&pl, name, &val)) return pl_u32(&val); return 0; } int aptx_fmtp_enc(struct mbuf *mb, const struct sdp_format *fmt, bool offer, void *arg) { (void)offer; (void)arg; if (!mb || !fmt) return 0; return mbuf_printf(mb, "a=fmtp:%s " "variant=%s; bitresolution=%u;\r\n", fmt->id, APTX_VARIANT == APTX_VARIANT_HD ? "hd" : "standard", APTX_VARIANT == APTX_VARIANT_HD ? 24 : 16); } bool aptx_fmtp_cmp(const char *lfmtp, const char *rfmtp, void *arg) { (void)lfmtp; (void)arg; /* if (param_value(rfmtp, "variant") != APTX_VARIANT) return false; */ if (param_value(rfmtp, "bitresolution") != (APTX_VARIANT == APTX_VARIANT_HD ? 24 : 16)) return false; return true; } baresip-1.0.0/modules/aubridge/000077500000000000000000000000001372575704200164035ustar00rootroot00000000000000baresip-1.0.0/modules/aubridge/aubridge.c000066400000000000000000000022441372575704200203330ustar00rootroot00000000000000/** * @file aubridge.c Audio bridge * * Copyright (C) 2010 - 2015 Creytiv.com */ #include #include #include "aubridge.h" /** * @defgroup aubridge aubridge * * Audio bridge module * * This module can be used to connect two audio devices together, * so that all output to AUPLAY device is bridged as the input to * a AUSRC device. * * Sample config: * \verbatim audio_player aubridge,pseudo0 audio_source aubridge,pseudo0 \endverbatim */ static struct ausrc *ausrc; static struct auplay *auplay; struct hash *aubridge_ht_device; static int module_init(void) { int err; err = hash_alloc(&aubridge_ht_device, 32); if (err) return err; err = ausrc_register(&ausrc, baresip_ausrcl(), "aubridge", aubridge_src_alloc); err |= auplay_register(&auplay, baresip_auplayl(), "aubridge", aubridge_play_alloc); return err; } static int module_close(void) { ausrc = mem_deref(ausrc); auplay = mem_deref(auplay); aubridge_ht_device = mem_deref(aubridge_ht_device); return 0; } EXPORT_SYM const struct mod_export DECL_EXPORTS(aubridge) = { "aubridge", "audio", module_init, module_close, }; baresip-1.0.0/modules/aubridge/aubridge.h000066400000000000000000000017611372575704200203430ustar00rootroot00000000000000/** * @file aubridge.h Audio bridge -- internal interface * * Copyright (C) 2010 Creytiv.com */ struct device; struct ausrc_st { const struct ausrc *as; /* inheritance */ struct device *dev; struct ausrc_prm prm; ausrc_read_h *rh; void *arg; }; struct auplay_st { const struct auplay *ap; /* inheritance */ struct device *dev; struct auplay_prm prm; auplay_write_h *wh; void *arg; }; extern struct hash *aubridge_ht_device; int aubridge_play_alloc(struct auplay_st **stp, const struct auplay *ap, struct auplay_prm *prm, const char *device, auplay_write_h *wh, void *arg); int aubridge_src_alloc(struct ausrc_st **stp, const struct ausrc *as, struct media_ctx **ctx, struct ausrc_prm *prm, const char *device, ausrc_read_h *rh, ausrc_error_h *errh, void *arg); int aubridge_device_connect(struct device **devp, const char *device, struct auplay_st *auplay, struct ausrc_st *ausrc); void aubridge_device_stop(struct device *dev); baresip-1.0.0/modules/aubridge/device.c000066400000000000000000000065411372575704200200140ustar00rootroot00000000000000/** * @file device.c Audio bridge -- virtual device table * * Copyright (C) 2010 Creytiv.com */ #include #include #include #include #include "aubridge.h" /* The packet-time is fixed to 20 milliseconds */ enum {PTIME = 20}; struct device { struct le le; const struct ausrc_st *ausrc; const struct auplay_st *auplay; char name[64]; pthread_t thread; volatile bool run; }; static void destructor(void *arg) { struct device *dev = arg; aubridge_device_stop(dev); list_unlink(&dev->le); } static bool list_apply_handler(struct le *le, void *arg) { struct device *st = le->data; return 0 == str_cmp(st->name, arg); } static struct device *find_device(const char *device) { return list_ledata(hash_lookup(aubridge_ht_device, hash_joaat_str(device), list_apply_handler, (void *)device)); } static void *device_thread(void *arg) { uint64_t now, ts = tmr_jiffies(); struct device *dev = arg; int16_t *sampv_in, *sampv_out; size_t sampc_in; size_t sampc_out; size_t sampsz; if (!dev->run) return NULL; if (dev->auplay->prm.srate != dev->ausrc->prm.srate || dev->auplay->prm.ch != dev->ausrc->prm.ch || dev->auplay->prm.fmt != dev->ausrc->prm.fmt) { warning("aubridge: incompatible ausrc/auplay parameters\n"); return NULL; } info("aubridge: thread start: %u Hz, %u channels, format=%s\n", dev->auplay->prm.srate, dev->auplay->prm.ch, aufmt_name(dev->auplay->prm.fmt)); sampc_in = dev->auplay->prm.srate * dev->auplay->prm.ch * PTIME/1000; sampc_out = dev->ausrc->prm.srate * dev->ausrc->prm.ch * PTIME/1000; sampsz = aufmt_sample_size(dev->auplay->prm.fmt); sampv_in = mem_alloc(sampsz * sampc_in, NULL); sampv_out = mem_alloc(sampsz * sampc_out, NULL); if (!sampv_in || !sampv_out) goto out; while (dev->run) { (void)sys_msleep(4); if (!dev->run) break; now = tmr_jiffies(); if (ts > now) continue; if (dev->auplay->wh) { dev->auplay->wh(sampv_in, sampc_in, dev->auplay->arg); } if (dev->ausrc->rh) { struct auframe af = { .fmt = dev->ausrc->prm.fmt, .sampv = sampv_in, .sampc = sampc_in, .timestamp = ts * 1000 }; dev->ausrc->rh(&af, dev->ausrc->arg); } ts += PTIME; } out: mem_deref(sampv_in); mem_deref(sampv_out); return NULL; } int aubridge_device_connect(struct device **devp, const char *device, struct auplay_st *auplay, struct ausrc_st *ausrc) { struct device *dev; int err = 0; if (!devp) return EINVAL; if (!str_isset(device)) return ENODEV; dev = find_device(device); if (dev) { *devp = mem_ref(dev); } else { dev = mem_zalloc(sizeof(*dev), destructor); if (!dev) return ENOMEM; str_ncpy(dev->name, device, sizeof(dev->name)); hash_append(aubridge_ht_device, hash_joaat_str(device), &dev->le, dev); *devp = dev; info("aubridge: created device '%s'\n", device); } if (auplay) dev->auplay = auplay; if (ausrc) dev->ausrc = ausrc; /* wait until we have both SRC+PLAY */ if (dev->ausrc && dev->auplay && !dev->run) { dev->run = true; err = pthread_create(&dev->thread, NULL, device_thread, dev); if (err) { dev->run = false; } } return err; } void aubridge_device_stop(struct device *dev) { if (!dev) return; if (dev->run) { dev->run = false; pthread_join(dev->thread, NULL); } dev->auplay = NULL; dev->ausrc = NULL; } baresip-1.0.0/modules/aubridge/module.mk000066400000000000000000000002311372575704200202150ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # MOD := aubridge $(MOD)_SRCS += aubridge.c device.c src.c play.c $(MOD)_LFLAGS += include mk/mod.mk baresip-1.0.0/modules/aubridge/play.c000066400000000000000000000015111372575704200175120ustar00rootroot00000000000000/** * @file aubridge/play.c Audio bridge -- playback * * Copyright (C) 2010 Creytiv.com */ #include #include #include #include "aubridge.h" static void auplay_destructor(void *arg) { struct auplay_st *st = arg; aubridge_device_stop(st->dev); mem_deref(st->dev); } int aubridge_play_alloc(struct auplay_st **stp, const struct auplay *ap, struct auplay_prm *prm, const char *device, auplay_write_h *wh, void *arg) { struct auplay_st *st; int err; if (!stp || !ap || !prm) return EINVAL; st = mem_zalloc(sizeof(*st), auplay_destructor); if (!st) return ENOMEM; st->ap = ap; st->prm = *prm; st->wh = wh; st->arg = arg; err = aubridge_device_connect(&st->dev, device, st, NULL); if (err) goto out; out: if (err) mem_deref(st); else *stp = st; return err; } baresip-1.0.0/modules/aubridge/src.c000066400000000000000000000016171372575704200173430ustar00rootroot00000000000000/** * @file aubridge/src.c Audio bridge -- source * * Copyright (C) 2010 Creytiv.com */ #include #include #include #include "aubridge.h" static void ausrc_destructor(void *arg) { struct ausrc_st *st = arg; aubridge_device_stop(st->dev); mem_deref(st->dev); } int aubridge_src_alloc(struct ausrc_st **stp, const struct ausrc *as, struct media_ctx **ctx, struct ausrc_prm *prm, const char *device, ausrc_read_h *rh, ausrc_error_h *errh, void *arg) { struct ausrc_st *st; int err = 0; (void)ctx; (void)errh; if (!stp || !as || !prm) return EINVAL; st = mem_zalloc(sizeof(*st), ausrc_destructor); if (!st) return ENOMEM; st->as = as; st->prm = *prm; st->rh = rh; st->arg = arg; err = aubridge_device_connect(&st->dev, device, NULL, st); if (err) goto out; out: if (err) mem_deref(st); else *stp = st; return err; } baresip-1.0.0/modules/audiounit/000077500000000000000000000000001372575704200166225ustar00rootroot00000000000000baresip-1.0.0/modules/audiounit/audiounit.c000066400000000000000000000114451372575704200207740ustar00rootroot00000000000000/** * @file audiounit.c AudioUnit sound driver * * Copyright (C) 2010 Creytiv.com */ #include #include #include #include #include #include "audiounit.h" /** * @defgroup audiounit audiounit * * Audio driver module for OSX/iOS AudioUnit */ #define MAX_NB_FRAMES 4096 struct conv_buf { void *mem[2]; uint8_t mem_idx; uint32_t nb_frames; }; AudioComponent audiounit_io = NULL; AudioComponent audiounit_conv = NULL; static struct auplay *auplay; static struct ausrc *ausrc; static void conv_buf_destructor(void *arg) { struct conv_buf *buf = (struct conv_buf *)arg; mem_deref(buf->mem[0]); mem_deref(buf->mem[1]); } int conv_buf_alloc(struct conv_buf **bufp, size_t framesz) { struct conv_buf *buf; if (!bufp) return EINVAL; buf = mem_zalloc(sizeof(*buf), conv_buf_destructor); if (!buf) return ENOMEM; buf->mem_idx = 0; buf->nb_frames = 0; buf->mem[0] = mem_alloc(MAX_NB_FRAMES * framesz, NULL); buf->mem[1] = mem_alloc(MAX_NB_FRAMES * framesz, NULL); *bufp = buf; return 0; } int get_nb_frames(struct conv_buf *buf, uint32_t *nb_frames) { if (!buf) return EINVAL; *nb_frames = buf->nb_frames; return 0; } OSStatus init_data_write(struct conv_buf *buf, void **data, size_t framesz, uint32_t nb_frames) { uint32_t mem_idx = buf->mem_idx; if (buf->nb_frames + nb_frames > MAX_NB_FRAMES) { return kAudioUnitErr_TooManyFramesToProcess; } *data = (uint8_t*)buf->mem[mem_idx] + buf->nb_frames * framesz; buf->nb_frames = buf->nb_frames + nb_frames; return noErr; } OSStatus init_data_read(struct conv_buf *buf, void **data, size_t framesz, uint32_t nb_frames) { uint8_t *src; uint32_t delta = 0; uint32_t mem_idx = buf->mem_idx; if (buf->nb_frames < nb_frames) { return kAudioUnitErr_TooManyFramesToProcess; } *data = buf->mem[mem_idx]; delta = buf->nb_frames - nb_frames; src = (uint8_t *)buf->mem[mem_idx] + nb_frames * framesz; memcpy(buf->mem[(mem_idx+1)%2], (void *)src, delta * framesz); buf->mem_idx = (mem_idx + 1)%2; buf->nb_frames = delta; return noErr; } uint32_t audiounit_aufmt_to_formatflags(enum aufmt fmt) { switch (fmt) { case AUFMT_S16LE: return kLinearPCMFormatFlagIsSignedInteger; case AUFMT_S24_3LE:return kLinearPCMFormatFlagIsSignedInteger; case AUFMT_FLOAT: return kLinearPCMFormatFlagIsFloat; default: return 0; } } #if TARGET_OS_IPHONE static void interruptionListener(void *data, UInt32 inInterruptionState) { (void)data; if (inInterruptionState == kAudioSessionBeginInterruption) { info("audiounit: interrupt Begin\n"); audiosess_interrupt(true); } else if (inInterruptionState == kAudioSessionEndInterruption) { info("audiounit: interrupt End\n"); audiosess_interrupt(false); } } #endif static int module_init(void) { AudioComponentDescription desc; CFStringRef name = NULL; int err; #if TARGET_OS_IPHONE OSStatus ret; ret = AudioSessionInitialize(NULL, NULL, interruptionListener, 0); if (ret && ret != kAudioSessionAlreadyInitialized) { warning("audiounit: AudioSessionInitialize: %d\n", ret); return ENODEV; } #endif desc.componentType = kAudioUnitType_Output; #if TARGET_OS_IPHONE desc.componentSubType = kAudioUnitSubType_VoiceProcessingIO; #else desc.componentSubType = kAudioUnitSubType_HALOutput; #endif desc.componentManufacturer = kAudioUnitManufacturer_Apple; desc.componentFlags = 0; desc.componentFlagsMask = 0; audiounit_comp_io = AudioComponentFindNext(NULL, &desc); if (!audiounit_comp_io) { #if TARGET_OS_IPHONE warning("audiounit: Voice Processing I/O not found\n"); #else warning("audiounit: AUHAL not found\n"); #endif return ENOENT; } if (0 == AudioComponentCopyName(audiounit_comp_io, &name)) { debug("audiounit: using component '%s'\n", CFStringGetCStringPtr(name, kCFStringEncodingUTF8)); } desc.componentType = kAudioUnitType_FormatConverter; desc.componentSubType = kAudioUnitSubType_AUConverter; desc.componentManufacturer = kAudioUnitManufacturer_Apple; desc.componentFlags = 0; desc.componentFlagsMask = 0; audiounit_comp_conv = AudioComponentFindNext(NULL, &desc); if (!audiounit_comp_conv) { warning("audiounit: AU Converter not found\n"); return ENOENT; } if (0 == AudioComponentCopyName(audiounit_comp_conv, &name)) { debug("audiounit: using component '%s'\n", CFStringGetCStringPtr(name, kCFStringEncodingUTF8)); } err = auplay_register(&auplay, baresip_auplayl(), "audiounit", audiounit_player_alloc); err |= ausrc_register(&ausrc, baresip_ausrcl(), "audiounit", audiounit_recorder_alloc); return err; } static int module_close(void) { ausrc = mem_deref(ausrc); auplay = mem_deref(auplay); return 0; } EXPORT_SYM const struct mod_export DECL_EXPORTS(audiounit) = { "audiounit", "audio", module_init, module_close, }; baresip-1.0.0/modules/audiounit/audiounit.h000066400000000000000000000022621372575704200207760ustar00rootroot00000000000000/** * @file audiounit.h AudioUnit sound driver -- Internal interface * * Copyright (C) 2010 Creytiv.com */ AudioComponent audiounit_comp_io; AudioComponent audiounit_comp_conv; struct audiosess; struct audiosess_st; struct conv_buf; typedef void (audiosess_int_h)(bool start, void *arg); int audiosess_alloc(struct audiosess_st **stp, audiosess_int_h *inth, void *arg); void audiosess_interrupt(bool interrupted); int conv_buf_alloc(struct conv_buf **bufp, size_t framesz); int get_nb_frames(struct conv_buf *buf, uint32_t *nb_frames); OSStatus init_data_write(struct conv_buf *buf, void **data, size_t framesz, uint32_t nb_frames); OSStatus init_data_read(struct conv_buf *buf, void **data, size_t framesz, uint32_t nb_frames); int audiounit_player_alloc(struct auplay_st **stp, const struct auplay *ap, struct auplay_prm *prm, const char *device, auplay_write_h *wh, void *arg); int audiounit_recorder_alloc(struct ausrc_st **stp, const struct ausrc *as, struct media_ctx **ctx, struct ausrc_prm *prm, const char *device, ausrc_read_h *rh, ausrc_error_h *errh, void *arg); uint32_t audiounit_aufmt_to_formatflags(enum aufmt fmt); baresip-1.0.0/modules/audiounit/module.mk000066400000000000000000000003721372575704200204420ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # MOD := audiounit $(MOD)_SRCS += audiounit.c $(MOD)_SRCS += sess.c $(MOD)_SRCS += player.c $(MOD)_SRCS += recorder.c $(MOD)_LFLAGS += -framework CoreAudio -framework AudioToolbox include mk/mod.mk baresip-1.0.0/modules/audiounit/player.c000066400000000000000000000103241372575704200202620ustar00rootroot00000000000000/** * @file audiounit/player.c AudioUnit output player * * Copyright (C) 2010 Creytiv.com */ #include #include #include #include #include #include #include "audiounit.h" struct auplay_st { const struct auplay *ap; /* inheritance */ struct audiosess_st *sess; AudioUnit au; pthread_mutex_t mutex; uint32_t sampsz; auplay_write_h *wh; void *arg; }; static void auplay_destructor(void *arg) { struct auplay_st *st = arg; pthread_mutex_lock(&st->mutex); st->wh = NULL; pthread_mutex_unlock(&st->mutex); AudioOutputUnitStop(st->au); AudioUnitUninitialize(st->au); AudioComponentInstanceDispose(st->au); mem_deref(st->sess); pthread_mutex_destroy(&st->mutex); } static OSStatus output_callback(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData) { struct auplay_st *st = inRefCon; auplay_write_h *wh; void *arg; uint32_t i; (void)ioActionFlags; (void)inTimeStamp; (void)inBusNumber; (void)inNumberFrames; pthread_mutex_lock(&st->mutex); wh = st->wh; arg = st->arg; pthread_mutex_unlock(&st->mutex); if (!wh) return 0; for (i = 0; i < ioData->mNumberBuffers; ++i) { AudioBuffer *ab = &ioData->mBuffers[i]; wh(ab->mData, ab->mDataByteSize/st->sampsz, arg); } return 0; } static void interrupt_handler(bool interrupted, void *arg) { struct auplay_st *st = arg; if (interrupted) AudioOutputUnitStop(st->au); else AudioOutputUnitStart(st->au); } int audiounit_player_alloc(struct auplay_st **stp, const struct auplay *ap, struct auplay_prm *prm, const char *device, auplay_write_h *wh, void *arg) { AudioStreamBasicDescription fmt; const AudioUnitElement outputBus = 0; AURenderCallbackStruct cb; struct auplay_st *st; const UInt32 enable = 1; OSStatus ret = 0; Float64 hw_srate = 0.0; UInt32 hw_size = sizeof(hw_srate); int err; (void)device; if (!stp || !ap || !prm) return EINVAL; st = mem_zalloc(sizeof(*st), auplay_destructor); if (!st) return ENOMEM; st->ap = ap; st->wh = wh; st->arg = arg; st->sampsz = (uint32_t)aufmt_sample_size(prm->fmt); if (!st->sampsz) { err = ENOTSUP; goto out; } err = pthread_mutex_init(&st->mutex, NULL); if (err) goto out; err = audiosess_alloc(&st->sess, interrupt_handler, st); if (err) goto out; ret = AudioComponentInstanceNew(audiounit_comp_io, &st->au); if (ret) goto out; ret = AudioUnitSetProperty(st->au, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, outputBus, &enable, sizeof(enable)); if (ret) { warning("audiounit: EnableIO failed (%d)\n", ret); goto out; } fmt.mSampleRate = prm->srate; fmt.mFormatID = kAudioFormatLinearPCM; #if TARGET_OS_IPHONE fmt.mFormatFlags = audiounit_aufmt_to_formatflags(prm->fmt) | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked; #else fmt.mFormatFlags = audiounit_aufmt_to_formatflags(prm->fmt) | kAudioFormatFlagIsPacked; #endif fmt.mBitsPerChannel = 8 * st->sampsz; fmt.mChannelsPerFrame = prm->ch; fmt.mBytesPerFrame = st->sampsz * prm->ch; fmt.mFramesPerPacket = 1; fmt.mBytesPerPacket = st->sampsz * prm->ch; ret = AudioUnitInitialize(st->au); if (ret) goto out; ret = AudioUnitSetProperty(st->au, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, outputBus, &fmt, sizeof(fmt)); if (ret) goto out; cb.inputProc = output_callback; cb.inputProcRefCon = st; ret = AudioUnitSetProperty(st->au, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, outputBus, &cb, sizeof(cb)); if (ret) goto out; ret = AudioOutputUnitStart(st->au); if (ret) goto out; ret = AudioUnitGetProperty(st->au, kAudioUnitProperty_SampleRate, kAudioUnitScope_Output, outputBus, &hw_srate, &hw_size); if (ret) goto out; debug("audiounit: player hardware sample rate is now at %f Hz\n", hw_srate); out: if (ret) { warning("audiounit: player failed: %d (%c%c%c%c)\n", ret, ret>>24, ret>>16, ret>>8, ret); err = ENODEV; } if (err) mem_deref(st); else *stp = st; return err; } baresip-1.0.0/modules/audiounit/recorder.c000066400000000000000000000214141372575704200205750ustar00rootroot00000000000000/** * @file audiounit/recorder.c AudioUnit input recorder * * Copyright (C) 2010 Creytiv.com */ #include #include #include #include #include #include #include #include "audiounit.h" struct ausrc_st { const struct ausrc *as; /* inheritance */ struct audiosess_st *sess; AudioUnit au_in; AudioUnit au_conv; pthread_mutex_t mutex; struct ausrc_prm prm; int ch; uint32_t sampsz; int fmt; double sampc_ratio; AudioBufferList *abl; ausrc_read_h *rh; struct conv_buf *buf; void *arg; }; static void ausrc_destructor(void *arg) { struct ausrc_st *st = arg; pthread_mutex_lock(&st->mutex); st->rh = NULL; pthread_mutex_unlock(&st->mutex); AudioOutputUnitStop(st->au_in); AudioUnitUninitialize(st->au_in); AudioComponentInstanceDispose(st->au_in); AudioOutputUnitStop(st->au_conv); AudioUnitUninitialize(st->au_conv); AudioComponentInstanceDispose(st->au_conv); mem_deref(st->sess); mem_deref(st->buf); pthread_mutex_destroy(&st->mutex); } static OSStatus input_callback(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData) { struct ausrc_st *st = inRefCon; AudioBufferList abl_in, abl_conv; uint32_t nb_frames, nb_frames_max; size_t framesz; OSStatus ret; int err; ausrc_read_h *rh; void *arg; (void)ioData; pthread_mutex_lock(&st->mutex); rh = st->rh; arg = st->arg; pthread_mutex_unlock(&st->mutex); if (!rh) return 0; framesz = st->sampsz * st->ch; st->abl = &abl_in; abl_in.mNumberBuffers = 1; abl_in.mBuffers[0].mNumberChannels = st->ch; abl_in.mBuffers[0].mDataByteSize = inNumberFrames * (UInt32)framesz; ret = init_data_write(st->buf, &abl_in.mBuffers[0].mData, framesz, inNumberFrames); if (ret != noErr) return ret; ret = AudioUnitRender(st->au_in, ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, &abl_in); if (ret) { debug("audiounit: record: AudioUnitRender input error (%d)\n", ret); return ret; } while (1) { struct auframe af; uint64_t ts; err = get_nb_frames(st->buf, &nb_frames); if (err) return kAudioUnitErr_InvalidParameter; /* Maximun number of resampled frames which can be delivered by the converter */ nb_frames_max = nb_frames * st->sampc_ratio; if (inNumberFrames > nb_frames_max) return noErr; abl_conv.mNumberBuffers = 1; abl_conv.mBuffers[0].mNumberChannels = st->ch; abl_conv.mBuffers[0].mData = NULL; ret = AudioUnitRender(st->au_conv, ioActionFlags, inTimeStamp, 0, inNumberFrames, &abl_conv); if (ret) { debug("audiounit: record: " "AudioUnitRender convert error (%d)\n", ret); return ret; } ts = AUDIO_TIMEBASE*inTimeStamp->mSampleTime / st->prm.srate; ts *= st->sampc_ratio; af.fmt = st->fmt; af.sampv = abl_conv.mBuffers[0].mData; af.sampc = abl_conv.mBuffers[0].mDataByteSize/st->sampsz; af.timestamp = ts; rh(&af, arg); } return noErr; } static OSStatus convert_callback(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData) { struct ausrc_st *st = inRefCon; size_t framesz; OSStatus ret = noErr; (void)ioActionFlags; (void)inTimeStamp; (void)inBusNumber; framesz = st->sampsz * st->ch; ret = init_data_read(st->buf, &ioData->mBuffers[0].mData, framesz, inNumberFrames); return ret; } static void interrupt_handler(bool interrupted, void *arg) { struct ausrc_st *st = arg; if (interrupted) AudioOutputUnitStop(st->au_in); else AudioOutputUnitStart(st->au_in); } int audiounit_recorder_alloc(struct ausrc_st **stp, const struct ausrc *as, struct media_ctx **ctx, struct ausrc_prm *prm, const char *device, ausrc_read_h *rh, ausrc_error_h *errh, void *arg) { AudioStreamBasicDescription fmt, fmt_app; const AudioUnitElement inputBus = 1; const AudioUnitElement defaultBus = 0; AURenderCallbackStruct cb_in, cb_conv; struct ausrc_st *st; const UInt32 enable = 1; #if ! TARGET_OS_IPHONE const AudioUnitElement outputBus = 0; const UInt32 disable = 0; UInt32 ausize = sizeof(AudioDeviceID); AudioDeviceID inputDevice; AudioObjectPropertyAddress auAddress = { kAudioHardwarePropertyDefaultInputDevice, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster }; #endif Float64 hw_srate = 0.0; UInt32 hw_size = sizeof(hw_srate); size_t framesz; OSStatus ret = 0; int err; (void)ctx; (void)device; (void)errh; if (!stp || !as || !prm) return EINVAL; st = mem_zalloc(sizeof(*st), ausrc_destructor); if (!st) return ENOMEM; st->as = as; st->rh = rh; st->arg = arg; st->ch = prm->ch; st->sampsz = (uint32_t)aufmt_sample_size(prm->fmt); if (!st->sampsz) { err = ENOTSUP; goto out; } st->fmt = prm->fmt; st->prm = *prm; framesz = st->sampsz * st->ch; err = conv_buf_alloc(&st->buf, framesz); if (err) goto out; err = pthread_mutex_init(&st->mutex, NULL); if (err) goto out; err = audiosess_alloc(&st->sess, interrupt_handler, st); if (err) goto out; ret = AudioComponentInstanceNew(audiounit_comp_io, &st->au_in); if (ret) goto out; ret = AudioUnitSetProperty(st->au_in, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, inputBus, &enable, sizeof(enable)); if (ret) goto out; #if ! TARGET_OS_IPHONE ret = AudioUnitSetProperty(st->au_in, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, outputBus, &disable, sizeof(disable)); if (ret) goto out; ret = AudioObjectGetPropertyData(kAudioObjectSystemObject, &auAddress, 0, NULL, &ausize, &inputDevice); if (ret) goto out; ret = AudioUnitSetProperty(st->au_in, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &inputDevice, sizeof(inputDevice)); if (ret) goto out; #endif #if TARGET_OS_IPHONE hw_srate = prm->srate; (void)hw_size; #else ret = AudioUnitGetProperty(st->au_in, kAudioUnitProperty_SampleRate, kAudioUnitScope_Input, inputBus, &hw_srate, &hw_size); if (ret) goto out; #endif debug("audiounit: record hardware sample rate is now at %f Hz\n", hw_srate); st->sampc_ratio = prm->srate / hw_srate; fmt.mSampleRate = hw_srate; fmt.mFormatID = kAudioFormatLinearPCM; #if TARGET_OS_IPHONE fmt.mFormatFlags = audiounit_aufmt_to_formatflags(prm->fmt) | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked; #else fmt.mFormatFlags = audiounit_aufmt_to_formatflags(prm->fmt) | kLinearPCMFormatFlagIsPacked; #endif fmt.mBitsPerChannel = 8 * st->sampsz; fmt.mChannelsPerFrame = prm->ch; fmt.mBytesPerFrame = st->sampsz * prm->ch; fmt.mFramesPerPacket = 1; fmt.mBytesPerPacket = st->sampsz * prm->ch; fmt.mReserved = 0; ret = AudioUnitSetProperty(st->au_in, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, inputBus, &fmt, sizeof(fmt)); if (ret) goto out; /* NOTE: done after desc */ ret = AudioUnitInitialize(st->au_in); if (ret) goto out; cb_in.inputProc = input_callback; cb_in.inputProcRefCon = st; ret = AudioUnitSetProperty(st->au_in, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, inputBus, &cb_in, sizeof(cb_in)); if (ret) goto out; fmt_app = fmt; fmt_app.mSampleRate = prm->srate; ret = AudioComponentInstanceNew(audiounit_comp_conv, &st->au_conv); if (ret) { warning("audiounit: record: AudioConverter failed (%d)\n", ret); goto out; } info("audiounit: record: enable resampler %.1f -> %u Hz\n", hw_srate, prm->srate); ret = AudioUnitSetProperty(st->au_conv, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, defaultBus, &fmt, sizeof(fmt)); if (ret) goto out; ret = AudioUnitSetProperty(st->au_conv, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, defaultBus, &fmt_app, sizeof(fmt_app)); if (ret) goto out; cb_conv.inputProc = convert_callback; cb_conv.inputProcRefCon = st; ret = AudioUnitSetProperty(st->au_conv, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, defaultBus, &cb_conv, sizeof(cb_conv)); if (ret) goto out; ret = AudioUnitInitialize(st->au_conv); if (ret) goto out; ret = AudioOutputUnitStart(st->au_in); if (ret) goto out; out: if (ret) { warning("audiounit: record failed: %d (%c%c%c%c)\n", ret, ret>>24, ret>>16, ret>>8, ret); err = ENODEV; } if (err) mem_deref(st); else *stp = st; return err; } baresip-1.0.0/modules/audiounit/sess.c000066400000000000000000000060141372575704200177440ustar00rootroot00000000000000/** * @file sess.c AudioUnit sound driver - session * * Copyright (C) 2010 Creytiv.com */ #include #include #include #include #include #include "audiounit.h" struct audiosess { struct list sessl; }; struct audiosess_st { struct audiosess *as; struct le le; audiosess_int_h *inth; void *arg; }; static struct audiosess *gas; #if TARGET_OS_IPHONE static void propListener(void *inClientData, AudioSessionPropertyID inID, UInt32 inDataSize, const void *inData) { struct audiosess *sess = inClientData; CFDictionaryRef dref = inData; CFNumberRef nref; SInt32 reason = 0; (void)inDataSize; (void)sess; if (kAudioSessionProperty_AudioRouteChange != inID) return; nref = CFDictionaryGetValue( dref, CFSTR(kAudioSession_AudioRouteChangeKey_Reason) ); CFNumberGetValue(nref, kCFNumberSInt32Type, &reason); info("audiounit: AudioRouteChange - reason %d\n", reason); } #endif static void sess_destructor(void *arg) { struct audiosess_st *st = arg; list_unlink(&st->le); mem_deref(st->as); } static void destructor(void *arg) { struct audiosess *as = arg; #if TARGET_OS_IPHONE AudioSessionPropertyID id = kAudioSessionProperty_AudioRouteChange; AudioSessionRemovePropertyListenerWithUserData(id, propListener, as); AudioSessionSetActive(false); #endif list_flush(&as->sessl); gas = NULL; } int audiosess_alloc(struct audiosess_st **stp, audiosess_int_h *inth, void *arg) { struct audiosess_st *st = NULL; struct audiosess *as = NULL; int err = 0; bool created = false; #if TARGET_OS_IPHONE AudioSessionPropertyID id = kAudioSessionProperty_AudioRouteChange; UInt32 category; OSStatus ret; #endif if (!stp) return EINVAL; #if TARGET_OS_IPHONE /* Must be done for all modules */ category = kAudioSessionCategory_PlayAndRecord; ret = AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(category), &category); if (ret) { warning("audiounit: Audio Category: %d\n", ret); return EINVAL; } #endif if (gas) goto makesess; as = mem_zalloc(sizeof(*as), destructor); if (!as) return ENOMEM; #if TARGET_OS_IPHONE ret = AudioSessionSetActive(true); if (ret) { warning("audiounit: AudioSessionSetActive: %d\n", ret); err = ENOTSUP; goto out; } ret = AudioSessionAddPropertyListener(id, propListener, as); if (ret) { warning("audiounit: AudioSessionAddPropertyListener: %d\n", ret); err = EINVAL; goto out; } #endif gas = as; created = true; makesess: st = mem_zalloc(sizeof(*st), sess_destructor); if (!st) { err = ENOMEM; goto out; } st->inth = inth; st->arg = arg; st->as = created ? gas : mem_ref(gas); list_append(&gas->sessl, &st->le, st); out: if (err) { mem_deref(as); mem_deref(st); } else { *stp = st; } return err; } void audiosess_interrupt(bool start) { struct le *le; if (!gas) return; for (le = gas->sessl.head; le; le = le->next) { struct audiosess_st *st = le->data; if (st->inth) st->inth(start, st->arg); } } baresip-1.0.0/modules/aufile/000077500000000000000000000000001372575704200160665ustar00rootroot00000000000000baresip-1.0.0/modules/aufile/aufile.c000066400000000000000000000110051372575704200174740ustar00rootroot00000000000000/** * @file aufile.c WAV Audio Source * * Copyright (C) 2015 Creytiv.com */ #define _DEFAULT_SOURCE 1 #define _BSD_SOURCE 1 #include #include #include #include /** * @defgroup aufile aufile * * Audio module for using a WAV-file as audio input * * Sample config: * \verbatim audio_source aufile,/tmp/test.wav \endverbatim */ struct ausrc_st { const struct ausrc *as; /* base class */ struct tmr tmr; struct aufile *aufile; struct aubuf *aubuf; uint32_t ptime; size_t sampc; bool run; pthread_t thread; ausrc_read_h *rh; ausrc_error_h *errh; void *arg; }; static struct ausrc *ausrc; static void destructor(void *arg) { struct ausrc_st *st = arg; if (st->run) { st->run = false; pthread_join(st->thread, NULL); } tmr_cancel(&st->tmr); mem_deref(st->aufile); mem_deref(st->aubuf); } static void *play_thread(void *arg) { uint64_t now, ts = tmr_jiffies(); struct ausrc_st *st = arg; int16_t *sampv; sampv = mem_alloc(st->sampc * sizeof(int16_t), NULL); if (!sampv) return NULL; while (st->run) { struct auframe af = { .fmt = AUFMT_S16LE, .sampv = sampv, .sampc = st->sampc, .timestamp = ts * 1000 }; sys_msleep(4); now = tmr_jiffies(); if (ts > now) continue; aubuf_read_samp(st->aubuf, sampv, st->sampc); st->rh(&af, st->arg); ts += st->ptime; } mem_deref(sampv); return NULL; } static void timeout(void *arg) { struct ausrc_st *st = arg; tmr_start(&st->tmr, 1000, timeout, st); /* check if audio buffer is empty */ if (aubuf_cur_size(st->aubuf) < (sizeof(int16_t) * st->sampc)) { info("aufile: end of file\n"); /* error handler must be called from re_main thread */ if (st->errh) st->errh(0, "end of file", st->arg); } } static int read_file(struct ausrc_st *st) { struct mbuf *mb; int err; for (;;) { uint16_t *sampv; size_t i; mb = mbuf_alloc(4096); if (!mb) return ENOMEM; mb->end = mb->size; err = aufile_read(st->aufile, mb->buf, &mb->end); if (err) break; if (mb->end == 0) { info("aufile: end of file\n"); break; } /* convert from Little-Endian to Native-Endian */ sampv = (void *)mb->buf; for (i=0; iend/sizeof(int16_t); i++) { sampv[i] = sys_ltohs(sampv[i]); } aubuf_append(st->aubuf, mb); mb = mem_deref(mb); } info("aufile: loaded %zu bytes\n", aubuf_cur_size(st->aubuf)); mem_deref(mb); return err; } static int alloc_handler(struct ausrc_st **stp, const struct ausrc *as, struct media_ctx **ctx, struct ausrc_prm *prm, const char *dev, ausrc_read_h *rh, ausrc_error_h *errh, void *arg) { struct ausrc_st *st; struct aufile_prm fprm; int err; (void)ctx; if (!stp || !as || !prm || !rh) return EINVAL; if (prm->fmt != AUFMT_S16LE) { warning("aufile: unsupported sample format (%s)\n", aufmt_name(prm->fmt)); return ENOTSUP; } info("aufile: loading input file '%s'\n", dev); st = mem_zalloc(sizeof(*st), destructor); if (!st) return ENOMEM; st->as = as; st->rh = rh; st->errh = errh; st->arg = arg; err = aufile_open(&st->aufile, &fprm, dev, AUFILE_READ); if (err) { warning("aufile: failed to open file '%s' (%m)\n", dev, err); goto out; } info("aufile: %s: %u Hz, %d channels\n", dev, fprm.srate, fprm.channels); if (fprm.srate != prm->srate) { warning("aufile: input file (%s) must have sample-rate" " %u Hz\n", dev, prm->srate); err = ENODEV; goto out; } if (fprm.channels != prm->ch) { warning("aufile: input file (%s) must have channels = %d\n", dev, prm->ch); err = ENODEV; goto out; } if (fprm.fmt != AUFMT_S16LE) { warning("aufile: input file must have format S16LE\n"); err = ENODEV; goto out; } st->sampc = prm->srate * prm->ch * prm->ptime / 1000; st->ptime = prm->ptime; info("aufile: audio ptime=%u sampc=%zu\n", st->ptime, st->sampc); /* 1 - inf seconds of audio */ err = aubuf_alloc(&st->aubuf, st->sampc * 2, 0); if (err) goto out; err = read_file(st); if (err) goto out; tmr_start(&st->tmr, 1000, timeout, st); st->run = true; err = pthread_create(&st->thread, NULL, play_thread, st); if (err) { st->run = false; goto out; } out: if (err) mem_deref(st); else *stp = st; return err; } static int module_init(void) { return ausrc_register(&ausrc, baresip_ausrcl(), "aufile", alloc_handler); } static int module_close(void) { ausrc = mem_deref(ausrc); return 0; } EXPORT_SYM const struct mod_export DECL_EXPORTS(aufile) = { "aufile", "ausrc", module_init, module_close }; baresip-1.0.0/modules/aufile/module.mk000066400000000000000000000001771372575704200177110ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # MOD := aufile $(MOD)_SRCS += aufile.c $(MOD)_LFLAGS += include mk/mod.mk baresip-1.0.0/modules/auloop/000077500000000000000000000000001372575704200161205ustar00rootroot00000000000000baresip-1.0.0/modules/auloop/auloop.c000066400000000000000000000211421372575704200175630ustar00rootroot00000000000000/** * @file auloop.c Audio loop * * Copyright (C) 2010 - 2015 Creytiv.com */ #include #include #include #include /** * @defgroup auloop auloop * * Application module for testing audio drivers * * The audio loop will connect the AUSRC device to the AUPLAY device * so that a local loopback audio can be heard. Different audio parameters * can be tested, such as sampling rate and number of channels. * * The following commands are available: \verbatim /auloop Start audio-loop /auloop_stop Stop audio-loop \endverbatim */ /* Configurable items */ #define PTIME 20 /** Audio Loop */ struct audio_loop { struct aubuf *aubuf; struct ausrc_st *ausrc; struct auplay_st *auplay; struct lock *lock; struct tmr tmr; uint32_t srate; uint8_t ch; enum aufmt fmt; bool started; size_t aubuf_maxsz; uint64_t aubuf_overrun; uint64_t aubuf_underrun; struct stats { uint64_t n_samp; uint64_t n_frames; } stats_src, stats_play; }; static struct audio_loop *gal = NULL; static inline uint32_t calc_nsamp(uint32_t srate, uint8_t channels, uint16_t ptime) { return srate * channels * ptime / 1000; } static int print_summary(struct re_printf *pf, struct audio_loop *al) { const double scale = al->srate * al->ch; int err; err = re_hprintf(pf, "~~~~~ Audioloop summary: ~~~~~\n"); err |= re_hprintf(pf, "%u Hz %uch %s\n\n", al->srate, al->ch, aufmt_name(al->fmt)); /* Source */ if (al->ausrc) { struct ausrc *as = ausrc_get(al->ausrc); const char *name = as->name; const struct stats *stats = &al->stats_src; double dur; al->ausrc = mem_deref(al->ausrc); dur = (double)stats->n_samp / scale; err |= re_hprintf(pf, "* Source\n" " module %s\n" " samples %llu\n" " duration %.3f sec\n" " frames %llu (avg ptime %.2fms)\n" "\n" , name, stats->n_samp, dur, al->stats_src.n_frames, 1000.0*dur / (double)al->stats_src.n_frames ); } if (al->aubuf) { err |= re_hprintf(pf, "* Aubuf\n" " overrun %llu\n" " underrun %llu\n" "\n" , al->aubuf_overrun, al->aubuf_underrun); } /* Player */ if (al->auplay) { struct auplay *ap = auplay_get(al->auplay); const char *name = ap->name; const struct stats *stats = &al->stats_play; double dur; /* stop device first */ al->auplay = mem_deref(al->auplay); dur = (double)stats->n_samp / scale; err |= re_hprintf(pf, "* Player\n" " module %s\n" " samples %llu\n" " duration %.3f sec\n" " frames %llu (avg ptime %.2fms)\n" "\n" , name, stats->n_samp, dur, stats->n_frames, 1000.0*dur / (double)stats->n_frames ); } return err; } static void auloop_destructor(void *arg) { struct audio_loop *al = arg; if (al->started) re_printf("%H\n", print_summary, al); tmr_cancel(&al->tmr); mem_deref(al->ausrc); mem_deref(al->auplay); mem_deref(al->aubuf); mem_deref(al->lock); } static void print_stats(struct audio_loop *al) { double rw_ratio = 0.0; double delay; const double scale = al->srate * al->ch; lock_read_get(al->lock); delay = (double)al->stats_src.n_samp - (double)al->stats_play.n_samp; rw_ratio = (double)al->stats_src.n_samp/(double)al->stats_play.n_samp; (void)re_fprintf(stdout, "\r%uHz %dch %s " " n_read=%.3f n_write=%.3f rw_delay=%.3f [sec]" " rw_ratio=%f" , al->srate, al->ch, aufmt_name(al->fmt), (double)al->stats_src.n_samp / scale, (double)al->stats_play.n_samp / scale, delay / scale, rw_ratio); (void)re_fprintf(stdout, " \r"); lock_rel(al->lock); fflush(stdout); } static void tmr_handler(void *arg) { struct audio_loop *al = arg; tmr_start(&al->tmr, 100, tmr_handler, al); print_stats(al); } static void src_read_handler(struct auframe *af, void *arg) { struct audio_loop *al = arg; struct stats *stats = &al->stats_src; int err; if (af->fmt != (int)al->fmt) { warning("auloop: format mismatch: exp=%d, actual=%d\n", al->fmt, af->fmt); return; } lock_write_get(al->lock); stats->n_samp += af->sampc; stats->n_frames += 1; if (aubuf_cur_size(al->aubuf) >= al->aubuf_maxsz) { ++al->aubuf_overrun; } lock_rel(al->lock); err = aubuf_write(al->aubuf, af->sampv, auframe_size(af)); if (err) { warning("auloop: aubuf_write: %m\n", err); } } static void write_handler(void *sampv, size_t sampc, void *arg) { struct audio_loop *al = arg; size_t num_bytes = sampc * aufmt_sample_size(al->fmt); struct stats *stats = &al->stats_play; lock_write_get(al->lock); stats->n_samp += sampc; stats->n_frames += 1; if (stats->n_samp && aubuf_cur_size(al->aubuf) < num_bytes) { ++al->aubuf_underrun; } lock_rel(al->lock); /* read from beginning */ aubuf_read(al->aubuf, sampv, num_bytes); } static void error_handler(int err, const char *str, void *arg) { (void)arg; warning("auloop: ausrc error: %m (%s)\n", err, str); gal = mem_deref(gal); } static int auloop_reset(struct audio_loop *al, uint32_t srate, uint8_t ch) { struct auplay_prm auplay_prm; struct ausrc_prm ausrc_prm; const struct config *cfg = conf_config(); size_t min_sz, sampsz; int err; if (!cfg) return ENOENT; if (cfg->audio.src_fmt != cfg->audio.play_fmt) { warning("auloop: ausrc_format and auplay_format" " must be the same\n"); return EINVAL; } al->fmt = cfg->audio.src_fmt; /* audio player/source must be stopped first */ al->auplay = mem_deref(al->auplay); al->ausrc = mem_deref(al->ausrc); al->aubuf = mem_deref(al->aubuf); al->srate = srate; al->ch = ch; info("Audio-loop: %uHz, %dch, %s\n", al->srate, al->ch, aufmt_name(al->fmt)); sampsz = aufmt_sample_size(al->fmt); min_sz = sampsz * calc_nsamp(al->srate, al->ch, PTIME); al->aubuf_maxsz = sampsz * calc_nsamp(al->srate, al->ch, PTIME*5); err = aubuf_alloc(&al->aubuf, min_sz, al->aubuf_maxsz); if (err) return err; auplay_prm.srate = al->srate; auplay_prm.ch = al->ch; auplay_prm.ptime = PTIME; auplay_prm.fmt = al->fmt; err = auplay_alloc(&al->auplay, baresip_auplayl(), cfg->audio.play_mod, &auplay_prm, cfg->audio.play_dev, write_handler, al); if (err) { warning("auloop: auplay %s,%s failed: %m\n", cfg->audio.play_mod, cfg->audio.play_dev, err); return err; } ausrc_prm.srate = al->srate; ausrc_prm.ch = al->ch; ausrc_prm.ptime = PTIME; ausrc_prm.fmt = al->fmt; err = ausrc_alloc(&al->ausrc, baresip_ausrcl(), NULL, cfg->audio.src_mod, &ausrc_prm, cfg->audio.src_dev, src_read_handler, error_handler, al); if (err) { warning("auloop: ausrc %s,%s failed: %m\n", cfg->audio.src_mod, cfg->audio.src_dev, err); return err; } return err; } static int audio_loop_alloc(struct audio_loop **alp, uint32_t srate, uint8_t ch) { struct audio_loop *al; int err; al = mem_zalloc(sizeof(*al), auloop_destructor); if (!al) return ENOMEM; err = lock_alloc(&al->lock); if (err) goto out; tmr_start(&al->tmr, 100, tmr_handler, al); err = auloop_reset(al, srate, ch); if (err) goto out; al->started = true; out: if (err) mem_deref(al); else *alp = al; return err; } /* * Start the audio loop (for testing) */ static int auloop_start(struct re_printf *pf, void *arg) { struct cmd_arg *carg = arg; struct pl pl_srate, pl_ch; uint32_t srate, ch; int err; if (gal) return re_hprintf(pf, "audio-loop already running.\n"); err = re_regex(carg->prm, str_len(carg->prm), "[0-9]+ [0-9]+", &pl_srate, &pl_ch); if (err) { return re_hprintf(pf, "Usage:" " /auloop \n"); } srate = pl_u32(&pl_srate); ch = pl_u32(&pl_ch); if (!srate || !ch) return re_hprintf(pf, "invalid samplerate or channels\n"); err = audio_loop_alloc(&gal, srate, (uint8_t)ch); if (err) { warning("auloop: alloc failed %m\n", err); } return err; } static int auloop_stop(struct re_printf *pf, void *arg) { (void)arg; if (gal) { (void)re_hprintf(pf, "audio-loop stopped\n"); gal = mem_deref(gal); } return 0; } static const struct cmd cmdv[] = { {"auloop", 0,CMD_PRM, "Start audio-loop ", auloop_start}, {"auloop_stop",0,0, "Stop audio-loop", auloop_stop }, }; static int module_init(void) { return cmd_register(baresip_commands(), cmdv, ARRAY_SIZE(cmdv)); } static int module_close(void) { auloop_stop(NULL, NULL); cmd_unregister(baresip_commands(), cmdv); return 0; } EXPORT_SYM const struct mod_export DECL_EXPORTS(auloop) = { "auloop", "application", module_init, module_close, }; baresip-1.0.0/modules/auloop/module.mk000066400000000000000000000001561372575704200177400ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # MOD := auloop $(MOD)_SRCS += auloop.c include mk/mod.mk baresip-1.0.0/modules/ausine/000077500000000000000000000000001372575704200161055ustar00rootroot00000000000000baresip-1.0.0/modules/ausine/ausine.c000066400000000000000000000070271372575704200175430ustar00rootroot00000000000000/** * @file ausine.c sine Audio Source * * Copyright (C) 2020 Creytiv.com */ #define _DEFAULT_SOURCE 1 #define _BSD_SOURCE 1 #include #include #include #include #include #include #define SCALE (32767) /** * @defgroup ausine ausine * * Audio module generating sine wave as audio input * * Sample config: * \verbatim audio_source ausine,400 \endverbatim */ static const double PI = 3.14159265358979323846264338328; struct ausrc_st { const struct ausrc *as; /* base class */ uint32_t ptime; size_t sampc; bool run; pthread_t thread; ausrc_read_h *rh; ausrc_error_h *errh; void *arg; int freq; double sec_offset; }; static struct ausrc *ausrc; static void destructor(void *arg) { struct ausrc_st *st = arg; if (st->run) { st->run = false; pthread_join(st->thread, NULL); } } static void *play_thread(void *arg) { uint64_t now, ts = tmr_jiffies(); struct ausrc_st *st = arg; int16_t *sampv; double sample, rad_per_sec; double sec_per_frame = 1.0 / 48000; int inc; size_t frames; sampv = mem_alloc(st->sampc * sizeof(int16_t), NULL); if (!sampv) return NULL; while (st->run) { struct auframe af = { .fmt = AUFMT_S16LE, .sampv = sampv, .sampc = st->sampc, .timestamp = ts * 1000 }; sys_msleep(4); now = tmr_jiffies(); if (ts > now) continue; inc = 0; rad_per_sec = st->freq * 2.0 * PI; frames = st->sampc / 2; for (size_t frame = 0; frame < frames; frame += 1) { sample = sin((st->sec_offset + frame * sec_per_frame) * rad_per_sec); sampv[inc] = (int16_t)(SCALE * 50 / 100.0f * sample); sampv[inc+1] = (int16_t)(SCALE * 50 / 100.0f * sample); inc += 2; } st->sec_offset = fmod(st->sec_offset + sec_per_frame * frames, 1.0); st->rh(&af, st->arg); ts += st->ptime; } mem_deref(sampv); return NULL; } static int alloc_handler(struct ausrc_st **stp, const struct ausrc *as, struct media_ctx **ctx, struct ausrc_prm *prm, const char *dev, ausrc_read_h *rh, ausrc_error_h *errh, void *arg) { struct ausrc_st *st; int err; (void)ctx; if (!stp || !as || !prm || !rh || !dev) return EINVAL; if (prm->fmt != AUFMT_S16LE) { warning("ausine: unsupported sample format (%s)\n", aufmt_name(prm->fmt)); return ENOTSUP; } if (prm->srate != 48000) { warning("ausine: supports only 48kHz samplerate"); return ENOTSUP; } if (prm->ch != 2) { warning("ausine: supports only 2 channels"); return ENOTSUP; } st = mem_zalloc(sizeof(*st), destructor); if (!st) return ENOMEM; st->as = as; st->rh = rh; st->errh = errh; st->arg = arg; st->sec_offset = 0.0; st->freq = atoi(dev); if (st->freq < 10 || st->freq > 20000) { warning("ausine: frequency must be between 10 and 20000 Hz\n"); err = ENOTSUP; goto out; } info("ausine: %u Hz, %d channels, frequency %d Hz\n", prm->srate, prm->ch, st->freq); st->sampc = prm->srate * prm->ch * prm->ptime / 1000; st->ptime = prm->ptime; info("ausine: audio ptime=%u sampc=%zu\n", st->ptime, st->sampc); st->run = true; err = pthread_create(&st->thread, NULL, play_thread, st); if (err) { st->run = false; goto out; } out: if (err) mem_deref(st); else *stp = st; return err; } static int module_init(void) { return ausrc_register(&ausrc, baresip_ausrcl(), "ausine", alloc_handler); } static int module_close(void) { ausrc = mem_deref(ausrc); return 0; } EXPORT_SYM const struct mod_export DECL_EXPORTS(ausine) = { "ausine", "ausrc", module_init, module_close }; baresip-1.0.0/modules/ausine/module.mk000066400000000000000000000001771372575704200177300ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # MOD := ausine $(MOD)_SRCS += ausine.c $(MOD)_LFLAGS += include mk/mod.mk baresip-1.0.0/modules/av1/000077500000000000000000000000001372575704200153105ustar00rootroot00000000000000baresip-1.0.0/modules/av1/av1.c000066400000000000000000000013231372575704200161420ustar00rootroot00000000000000/** * @file av1.c AV1 Video Codec * * Copyright (C) 2010 - 2016 Creytiv.com */ #include #include #include #include "av1.h" /** * @defgroup av1 av1 * * The AV1 video codec (Experimental) * * Reference: http://aomedia.org/ */ static struct vidcodec av1 = { .name = "AV1", .encupdh = av1_encode_update, .ench = av1_encode_packet, .decupdh = av1_decode_update, .dech = av1_decode, }; static int module_init(void) { vidcodec_register(baresip_vidcodecl(), &av1); return 0; } static int module_close(void) { vidcodec_unregister(&av1); return 0; } EXPORT_SYM const struct mod_export DECL_EXPORTS(av1) = { "av1", "codec", module_init, module_close }; baresip-1.0.0/modules/av1/av1.h000066400000000000000000000012061372575704200161470ustar00rootroot00000000000000/** * @file av1.h Private AV1 Interface * * Copyright (C) 2010 - 2016 Creytiv.com */ /* Encode */ int av1_encode_update(struct videnc_state **vesp, const struct vidcodec *vc, struct videnc_param *prm, const char *fmtp, videnc_packet_h *pkth, void *arg); int av1_encode_packet(struct videnc_state *ves, bool update, const struct vidframe *frame, uint64_t timestamp); /* Decode */ int av1_decode_update(struct viddec_state **vdsp, const struct vidcodec *vc, const char *fmtp); int av1_decode(struct viddec_state *vds, struct vidframe *frame, bool *intra, bool marker, uint16_t seq, struct mbuf *mb); baresip-1.0.0/modules/av1/decode.c000066400000000000000000000114321372575704200167000ustar00rootroot00000000000000/** * @file av1/decode.c AV1 Decode * * Copyright (C) 2010 - 2016 Creytiv.com */ #include #include #include #include #include #include #include #include "av1.h" enum { DECODE_MAXSZ = 524288, }; /* NOTE: re-using VP9 header format for now.. */ struct hdr { unsigned x:1; unsigned noref:1; unsigned start:1; unsigned partid:4; /* extension fields */ unsigned i:1; unsigned l:1; unsigned t:1; unsigned k:1; uint16_t picid; uint8_t tl0picidx; unsigned tid:2; unsigned y:1; unsigned keyidx:5; }; struct viddec_state { aom_codec_ctx_t ctx; struct mbuf *mb; bool ctxup; bool started; uint16_t seq; }; static void destructor(void *arg) { struct viddec_state *vds = arg; if (vds->ctxup) aom_codec_destroy(&vds->ctx); mem_deref(vds->mb); } int av1_decode_update(struct viddec_state **vdsp, const struct vidcodec *vc, const char *fmtp) { struct viddec_state *vds; aom_codec_dec_cfg_t cfg = { .allow_lowbitdepth = 1 }; aom_codec_err_t res; int err = 0; (void)vc; (void)fmtp; if (!vdsp) return EINVAL; vds = *vdsp; if (vds) return 0; vds = mem_zalloc(sizeof(*vds), destructor); if (!vds) return ENOMEM; vds->mb = mbuf_alloc(1024); if (!vds->mb) { err = ENOMEM; goto out; } res = aom_codec_dec_init(&vds->ctx, &aom_codec_av1_dx_algo, &cfg, 0); if (res) { err = ENOMEM; goto out; } vds->ctxup = true; out: if (err) mem_deref(vds); else *vdsp = vds; return err; } static inline int hdr_decode(struct hdr *hdr, struct mbuf *mb) { uint8_t v; memset(hdr, 0, sizeof(*hdr)); if (mbuf_get_left(mb) < 1) return EBADMSG; v = mbuf_read_u8(mb); hdr->x = v>>7 & 0x1; hdr->noref = v>>5 & 0x1; hdr->start = v>>4 & 0x1; hdr->partid = v & 0x07; if (hdr->x) { if (mbuf_get_left(mb) < 1) return EBADMSG; v = mbuf_read_u8(mb); hdr->i = v>>7 & 0x1; hdr->l = v>>6 & 0x1; hdr->t = v>>5 & 0x1; hdr->k = v>>4 & 0x1; } if (hdr->i) { if (mbuf_get_left(mb) < 1) return EBADMSG; v = mbuf_read_u8(mb); if (v>>7 & 0x1) { if (mbuf_get_left(mb) < 1) return EBADMSG; hdr->picid = (v & 0x7f)<<8; hdr->picid += mbuf_read_u8(mb); } else { hdr->picid = v & 0x7f; } } if (hdr->l) { if (mbuf_get_left(mb) < 1) return EBADMSG; hdr->tl0picidx = mbuf_read_u8(mb); } if (hdr->t || hdr->k) { if (mbuf_get_left(mb) < 1) return EBADMSG; v = mbuf_read_u8(mb); hdr->tid = v>>6 & 0x3; hdr->y = v>>5 & 0x1; hdr->keyidx = v & 0x1f; } return 0; } static inline bool is_keyframe(struct mbuf *mb) { aom_codec_stream_info_t si; aom_codec_err_t ret; memset(&si, 0, sizeof(si)); ret = aom_codec_peek_stream_info(&aom_codec_av1_dx_algo, mbuf_buf(mb), (unsigned int)mbuf_get_left(mb), &si); if (ret != AOM_CODEC_OK) return false; return si.is_kf; } static inline int16_t seq_diff(uint16_t x, uint16_t y) { return (int16_t)(y - x); } int av1_decode(struct viddec_state *vds, struct vidframe *frame, bool *intra, bool marker, uint16_t seq, struct mbuf *mb) { aom_codec_iter_t iter = NULL; aom_codec_err_t res; aom_image_t *img; struct hdr hdr; int err, i; if (!vds || !frame || !intra || !mb) return EINVAL; *intra = false; err = hdr_decode(&hdr, mb); if (err) return err; #if 1 debug("av1: header: x=%u noref=%u start=%u partid=%u " "i=%u l=%u t=%u k=%u " "picid=%u tl0picidx=%u tid=%u y=%u keyidx=%u\n", hdr.x, hdr.noref, hdr.start, hdr.partid, hdr.i, hdr.l, hdr.t, hdr.k, hdr.picid, hdr.tl0picidx, hdr.tid, hdr.y, hdr.keyidx); #endif if (hdr.start && hdr.partid == 0) { if (is_keyframe(mb)) *intra = true; mbuf_rewind(vds->mb); vds->started = true; } else { if (!vds->started) return 0; if (seq_diff(vds->seq, seq) != 1) { mbuf_rewind(vds->mb); vds->started = false; return 0; } } vds->seq = seq; err = mbuf_write_mem(vds->mb, mbuf_buf(mb), mbuf_get_left(mb)); if (err) goto out; if (!marker) { if (vds->mb->end > DECODE_MAXSZ) { warning("av1: decode buffer size exceeded\n"); err = ENOMEM; goto out; } return 0; } res = aom_codec_decode(&vds->ctx, vds->mb->buf, (unsigned int)vds->mb->end, NULL); if (res) { debug("av1: decode error: %s\n", aom_codec_err_to_string(res)); err = EPROTO; goto out; } img = aom_codec_get_frame(&vds->ctx, &iter); if (!img) { debug("av1: no picture\n"); goto out; } if (img->fmt != AOM_IMG_FMT_I420) { warning("av1: bad pixel format (%i)\n", img->fmt); goto out; } for (i=0; i<4; i++) { frame->data[i] = img->planes[i]; frame->linesize[i] = img->stride[i]; } frame->size.w = img->d_w; frame->size.h = img->d_h; frame->fmt = VID_FMT_YUV420P; out: mbuf_rewind(vds->mb); vds->started = false; return err; } baresip-1.0.0/modules/av1/encode.c000066400000000000000000000120201372575704200167040ustar00rootroot00000000000000/** * @file av1/encode.c AV1 Encode * * Copyright (C) 2010 - 2016 Creytiv.com */ #include #include #include #include #include #include #include #include "av1.h" enum { HDR_SIZE = 4, }; struct videnc_state { aom_codec_ctx_t ctx; struct vidsz size; double fps; unsigned bitrate; unsigned pktsize; bool ctxup; uint16_t picid; videnc_packet_h *pkth; void *arg; }; static void destructor(void *arg) { struct videnc_state *ves = arg; if (ves->ctxup) aom_codec_destroy(&ves->ctx); } int av1_encode_update(struct videnc_state **vesp, const struct vidcodec *vc, struct videnc_param *prm, const char *fmtp, videnc_packet_h *pkth, void *arg) { struct videnc_state *ves; if (!vesp || !vc || !prm || prm->pktsize < (HDR_SIZE + 1)) return EINVAL; ves = *vesp; if (!ves) { ves = mem_zalloc(sizeof(*ves), destructor); if (!ves) return ENOMEM; ves->picid = rand_u16(); *vesp = ves; } else { if (ves->ctxup && (ves->bitrate != prm->bitrate || ves->fps != prm->fps)) { aom_codec_destroy(&ves->ctx); ves->ctxup = false; } } ves->bitrate = prm->bitrate; ves->pktsize = prm->pktsize; ves->fps = prm->fps; ves->pkth = pkth; ves->arg = arg; return 0; } static int open_encoder(struct videnc_state *ves, const struct vidsz *size) { aom_codec_enc_cfg_t cfg; aom_codec_err_t res; res = aom_codec_enc_config_default(&aom_codec_av1_cx_algo, &cfg, 0); if (res) return EPROTO; cfg.g_w = size->w; cfg.g_h = size->h; cfg.g_timebase.num = 1; cfg.g_timebase.den = VIDEO_TIMEBASE; cfg.g_threads = 8; cfg.g_usage = AOM_USAGE_REALTIME; cfg.g_error_resilient = AOM_ERROR_RESILIENT_DEFAULT; cfg.g_pass = AOM_RC_ONE_PASS; cfg.g_lag_in_frames = 0; cfg.rc_end_usage = AOM_VBR; cfg.rc_target_bitrate = ves->bitrate / 1000; cfg.kf_mode = AOM_KF_AUTO; if (ves->ctxup) { debug("av1: re-opening encoder\n"); aom_codec_destroy(&ves->ctx); ves->ctxup = false; } res = aom_codec_enc_init(&ves->ctx, &aom_codec_av1_cx_algo, &cfg, 0); if (res) { warning("av1: enc init: %s\n", aom_codec_err_to_string(res)); return EPROTO; } ves->ctxup = true; res = aom_codec_control(&ves->ctx, AOME_SET_CPUUSED, 8); if (res) { warning("av1: codec ctrl C: %s\n", aom_codec_err_to_string(res)); } return 0; } static inline void hdr_encode(uint8_t hdr[HDR_SIZE], bool noref, bool start, uint8_t partid, uint16_t picid) { hdr[0] = 1<<7 | noref<<5 | start<<4 | (partid & 0x7); hdr[1] = 1<<7; hdr[2] = 1<<7 | (picid>>8 & 0x7f); hdr[3] = picid & 0xff; } static inline int packetize(bool marker, uint64_t rtp_ts, const uint8_t *buf, size_t len, size_t maxlen, bool noref, uint8_t partid, uint16_t picid, videnc_packet_h *pkth, void *arg) { uint8_t hdr[HDR_SIZE]; bool start = true; int err = 0; maxlen -= sizeof(hdr); while (len > maxlen) { hdr_encode(hdr, noref, start, partid, picid); err |= pkth(false, rtp_ts, hdr, sizeof(hdr), buf, maxlen, arg); buf += maxlen; len -= maxlen; start = false; } hdr_encode(hdr, noref, start, partid, picid); err |= pkth(marker, rtp_ts, hdr, sizeof(hdr), buf, len, arg); return err; } int av1_encode_packet(struct videnc_state *ves, bool update, const struct vidframe *frame, uint64_t timestamp) { aom_enc_frame_flags_t flags = 0; aom_codec_iter_t iter = NULL; aom_codec_err_t res; aom_image_t *img; aom_img_fmt_t img_fmt; int err = 0, i; if (!ves || !frame || frame->fmt != VID_FMT_YUV420P) return EINVAL; if (!ves->ctxup || !vidsz_cmp(&ves->size, &frame->size)) { err = open_encoder(ves, &frame->size); if (err) return err; ves->size = frame->size; } if (update) { /* debug("av1: picture update\n"); */ flags |= AOM_EFLAG_FORCE_KF; } img_fmt = AOM_IMG_FMT_I420; img = aom_img_wrap(NULL, img_fmt, frame->size.w, frame->size.h, 16, NULL); if (!img) { warning("av1: encoder: could not allocate image\n"); err = ENOMEM; goto out; } for (i=0; i<3; i++) { img->stride[i] = frame->linesize[i]; img->planes[i] = frame->data[i]; } res = aom_codec_encode(&ves->ctx, img, timestamp, 1, flags); if (res) { warning("av1: enc error: %s\n", aom_codec_err_to_string(res)); return ENOMEM; } ++ves->picid; for (;;) { bool keyframe = false, marker = true; const aom_codec_cx_pkt_t *pkt; uint8_t partid = 0; uint64_t ts; pkt = aom_codec_get_cx_data(&ves->ctx, &iter); if (!pkt) break; if (pkt->kind != AOM_CODEC_CX_FRAME_PKT) continue; if (pkt->data.frame.flags & AOM_FRAME_IS_KEY) keyframe = true; if (pkt->data.frame.partition_id >= 0) partid = pkt->data.frame.partition_id; ts = video_calc_rtp_timestamp_fix(pkt->data.frame.pts); err = packetize(marker, ts, pkt->data.frame.buf, pkt->data.frame.sz, ves->pktsize, !keyframe, partid, ves->picid, ves->pkth, ves->arg); if (err) return err; } out: if (img) aom_img_free(img); return err; } baresip-1.0.0/modules/av1/module.mk000066400000000000000000000002661372575704200171320ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 - 2016 Creytiv.com # MOD := av1 $(MOD)_SRCS += av1.c $(MOD)_SRCS += decode.c $(MOD)_SRCS += encode.c $(MOD)_LFLAGS += -laom include mk/mod.mk baresip-1.0.0/modules/avcapture/000077500000000000000000000000001372575704200166135ustar00rootroot00000000000000baresip-1.0.0/modules/avcapture/avcapture.m000066400000000000000000000166751372575704200210020ustar00rootroot00000000000000/** * @file avcapture.m AVFoundation video capture * * Copyright (C) 2010 Creytiv.com */ #include #include #include #include /** * @defgroup avcapture avcapture * * Video source using OSX/iOS AVFoundation */ static struct vidsrc *vidsrc; @interface avcap : NSObject < AVCaptureVideoDataOutputSampleBufferDelegate > { AVCaptureSession *sess; AVCaptureDeviceInput *input; AVCaptureVideoDataOutput *output; struct vidsrc_st *vsrc; } - (void)setCamera:(const char *)name; @end struct vidsrc_st { const struct vidsrc *vs; avcap *cap; vidsrc_frame_h *frameh; void *arg; }; static void vidframe_set_pixbuf(struct vidframe *f, const CVImageBufferRef b) { OSType type; int i; if (!f || !b) return; type = CVPixelBufferGetPixelFormatType(b); switch (type) { case kCVPixelFormatType_32BGRA: f->fmt = VID_FMT_ARGB; break; case kCVPixelFormatType_422YpCbCr8: f->fmt = VID_FMT_UYVY422; break; case kCVPixelFormatType_420YpCbCr8Planar: f->fmt = VID_FMT_YUV420P; break; case kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange: f->fmt = VID_FMT_NV12; break; default: warning("avcapture: unknown pixfmt %c%c%c%c\n", type>>24, type>>16, type>>8, type>>0); f->fmt = -1; f->data[0] = NULL; return; } f->size.w = (int)CVPixelBufferGetWidth(b); f->size.h = (int)CVPixelBufferGetHeight(b); if (!CVPixelBufferIsPlanar(b)) { f->data[0] = CVPixelBufferGetBaseAddress(b); f->linesize[0] = (int)CVPixelBufferGetBytesPerRow(b); f->data[1] = f->data[2] = f->data[3] = NULL; f->linesize[1] = f->linesize[2] = f->linesize[3] = 0; return; } for (i=0; i<4; i++) { f->data[i] = CVPixelBufferGetBaseAddressOfPlane(b, i); f->linesize[i] = CVPixelBufferGetBytesPerRowOfPlane(b, i); } } @implementation avcap - (NSString *)map_preset:(AVCaptureDevice *)dev sz:(const struct vidsz *)sz { static const struct { struct vidsz sz; NSString * const * preset; } mapv[] = { #if !TARGET_OS_IPHONE {{ 320 ,240}, &AVCaptureSessionPreset320x240 }, #endif {{ 352, 288}, &AVCaptureSessionPreset352x288 }, {{ 640, 480}, &AVCaptureSessionPreset640x480 }, #if !TARGET_OS_IPHONE {{ 960, 540}, &AVCaptureSessionPreset960x540 }, #endif {{1280, 720}, &AVCaptureSessionPreset1280x720} }; int i, best = -1; for (i=ARRAY_SIZE(mapv)-1; i>=0; i--) { NSString *preset = *mapv[i].preset; if (![sess canSetSessionPreset:preset] || ![dev supportsAVCaptureSessionPreset:preset]) continue; best = i; if (mapv[i].sz.w <= sz->w && mapv[i].sz.h <= sz->h) break; } if (best >= 0) return *mapv[best].preset; else { NSLog(@"no suitable preset found for %d x %d", sz->w, sz->h); return AVCaptureSessionPreset352x288; } } + (AVCaptureDevicePosition)get_position:(const char *)name { if (0 == str_casecmp(name, "back")) return AVCaptureDevicePositionBack; else if (0 == str_casecmp(name, "front")) return AVCaptureDevicePositionFront; else return -1; } + (AVCaptureDevice *)get_device:(AVCaptureDevicePosition)pos { AVCaptureDevice *dev; for (dev in [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo]) { if (dev.position == pos) return dev; } return [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; } - (void)start:(id)unused { (void)unused; [sess startRunning]; } - (id)init:(struct vidsrc_st *)st dev:(const char *)name size:(const struct vidsz *)sz { dispatch_queue_t queue; AVCaptureDevice *dev; self = [super init]; if (!self) return nil; vsrc = st; dev = [avcap get_device:[avcap get_position:name]]; if (!dev) return nil; input = [AVCaptureDeviceInput deviceInputWithDevice:dev error:nil]; output = [[AVCaptureVideoDataOutput alloc] init]; sess = [[AVCaptureSession alloc] init]; if (!input || !output || !sess) return nil; output.alwaysDiscardsLateVideoFrames = YES; queue = dispatch_queue_create("avcapture", NULL); [output setSampleBufferDelegate:self queue:queue]; dispatch_release(queue); sess.sessionPreset = [self map_preset:dev sz:sz]; [sess addInput:input]; [sess addOutput:output]; [self start:nil]; return self; } - (void)stop:(id)unused { (void)unused; [sess stopRunning]; if (output) { AVCaptureConnection *conn; for (conn in output.connections) conn.enabled = NO; } [sess beginConfiguration]; if (input) [sess removeInput:input]; if (output) [sess removeOutput:output]; [sess commitConfiguration]; [sess release]; } - (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)conn { const CVImageBufferRef b = CMSampleBufferGetImageBuffer(sampleBuffer); CMTime ts = CMSampleBufferGetOutputPresentationTimeStamp(sampleBuffer); struct vidframe vf; uint64_t timestamp; (void)captureOutput; (void)conn; if (!vsrc->frameh) return; CVPixelBufferLockBaseAddress(b, 0); vidframe_set_pixbuf(&vf, b); timestamp = CMTimeGetSeconds(ts) * VIDEO_TIMEBASE; if (vidframe_isvalid(&vf)) vsrc->frameh(&vf, timestamp, vsrc->arg); CVPixelBufferUnlockBaseAddress(b, 0); } - (void)setCamera:(const char *)name { AVCaptureDevicePosition pos; AVCaptureDevice *dev; pos = [avcap get_position:name]; if (pos == input.device.position) return; dev = [avcap get_device:pos]; if (!dev) return; [sess beginConfiguration]; [sess removeInput:input]; input = [AVCaptureDeviceInput deviceInputWithDevice:dev error:nil]; [sess addInput:input]; [sess commitConfiguration]; } @end static void destructor(void *arg) { struct vidsrc_st *st = arg; st->frameh = NULL; [st->cap performSelectorOnMainThread:@selector(stop:) withObject:nil waitUntilDone:YES]; [st->cap release]; } static int alloc(struct vidsrc_st **stp, const struct vidsrc *vs, struct media_ctx **ctx, struct vidsrc_prm *prm, const struct vidsz *size, const char *fmt, const char *dev, vidsrc_frame_h *frameh, vidsrc_error_h *errorh, void *arg) { NSAutoreleasePool *pool; struct vidsrc_st *st; int err = 0; (void)ctx; (void)prm; (void)fmt; (void)dev; (void)errorh; if (!stp || !size) return EINVAL; st = mem_zalloc(sizeof(*st), destructor); if (!st) return ENOMEM; pool = [NSAutoreleasePool new]; st->vs = vs; st->frameh = frameh; st->arg = arg; st->cap = [[avcap alloc] init:st dev:dev ? dev : "front" size:size]; if (!st->cap) { err = ENODEV; goto out; } out: if (err) mem_deref(st); else *stp = st; [pool release]; return err; } static void update(struct vidsrc_st *st, struct vidsrc_prm *prm, const char *dev) { (void)prm; if (!st) return; if (dev) [st->cap setCamera:dev]; } static int module_init(void) { AVCaptureDevice *dev = nil; NSAutoreleasePool *pool; Class cls = NSClassFromString(@"AVCaptureDevice"); int err = 0; if (!cls) return ENOSYS; pool = [NSAutoreleasePool new]; err = vidsrc_register(&vidsrc, baresip_vidsrcl(), "avcapture", alloc, update); if (err) goto out; /* populate devices */ for (dev in [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo]) { const char *name = [[dev localizedName] UTF8String]; debug("avcapture: found video device '%s'\n", name); err = mediadev_add(&vidsrc->dev_list, name); if (err) goto out; } out: [pool drain]; return err; } static int module_close(void) { vidsrc = mem_deref(vidsrc); return 0; } EXPORT_SYM const struct mod_export DECL_EXPORTS(avcapture) = { "avcapture", "vidsrc", module_init, module_close }; baresip-1.0.0/modules/avcapture/module.mk000066400000000000000000000002351372575704200204310ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # MOD := avcapture $(MOD)_SRCS += avcapture.m $(MOD)_LFLAGS += -framework AVFoundation include mk/mod.mk baresip-1.0.0/modules/avcodec/000077500000000000000000000000001372575704200162255ustar00rootroot00000000000000baresip-1.0.0/modules/avcodec/avcodec.c000066400000000000000000000157411372575704200200050ustar00rootroot00000000000000/** * @file avcodec.c Video codecs using libavcodec * * Copyright (C) 2010 - 2016 Creytiv.com */ #include #include #include #include #include #include "h26x.h" #include "avcodec.h" /** * @defgroup avcodec avcodec * * Video codecs using libavcodec * * This module implements H.263, H.264 and MPEG4 video codecs * using libavcodec from FFmpeg or libav projects. * * * Config options: * \verbatim avcodec_h264enc ; e.g. h264_nvenc, h264_videotoolbox avcodec_h264dec ; e.g. h264_cuvid, h264_vda, h264_qsv \endverbatim * * References: * * http://ffmpeg.org * * https://libav.org * * RTP Payload Format for H.264 Video * https://tools.ietf.org/html/rfc6184 */ AVCodec *avcodec_h264enc; /* optional; specified H.264 encoder */ AVCodec *avcodec_h264dec; /* optional; specified H.264 decoder */ AVCodec *avcodec_h265enc; AVCodec *avcodec_h265dec; #if LIBAVUTIL_VERSION_MAJOR >= 56 AVBufferRef *avcodec_hw_device_ctx = NULL; enum AVPixelFormat avcodec_hw_pix_fmt; enum AVHWDeviceType avcodec_hw_type = AV_HWDEVICE_TYPE_NONE; #endif int avcodec_resolve_codecid(const char *s) { if (0 == str_casecmp(s, "H263")) return AV_CODEC_ID_H263; else if (0 == str_casecmp(s, "H264")) return AV_CODEC_ID_H264; else if (0 == str_casecmp(s, "MP4V-ES")) return AV_CODEC_ID_MPEG4; #ifdef AV_CODEC_ID_H265 else if (0 == str_casecmp(s, "H265")) return AV_CODEC_ID_H265; #endif else return AV_CODEC_ID_NONE; } static int h263_fmtp_enc(struct mbuf *mb, const struct sdp_format *fmt, bool offer, void *arg) { (void)offer; (void)arg; if (!mb || !fmt) return 0; return mbuf_printf(mb, "a=fmtp:%s CIF=1;CIF4=1\r\n", fmt->id); } static int mpg4_fmtp_enc(struct mbuf *mb, const struct sdp_format *fmt, bool offer, void *arg) { (void)offer; (void)arg; if (!mb || !fmt) return 0; return mbuf_printf(mb, "a=fmtp:%s profile-level-id=3\r\n", fmt->id); } static struct vidcodec h264 = { .name = "H264", .variant = "packetization-mode=0", .encupdh = avcodec_encode_update, .ench = avcodec_encode, .decupdh = avcodec_decode_update, .dech = avcodec_decode_h264, .fmtp_ench = avcodec_h264_fmtp_enc, .fmtp_cmph = avcodec_h264_fmtp_cmp, }; static struct vidcodec h264_1 = { .name = "H264", .variant = "packetization-mode=1", .encupdh = avcodec_encode_update, .ench = avcodec_encode, .decupdh = avcodec_decode_update, .dech = avcodec_decode_h264, .fmtp_ench = avcodec_h264_fmtp_enc, .fmtp_cmph = avcodec_h264_fmtp_cmp, }; static struct vidcodec h263 = { .pt = "34", .name = "H263", .encupdh = avcodec_encode_update, .ench = avcodec_encode, .decupdh = avcodec_decode_update, .dech = avcodec_decode_h263, .fmtp_ench = h263_fmtp_enc, }; static struct vidcodec mpg4 = { .name = "MP4V-ES", .encupdh = avcodec_encode_update, .ench = avcodec_encode, .decupdh = avcodec_decode_update, .dech = avcodec_decode_mpeg4, .fmtp_ench = mpg4_fmtp_enc, }; static struct vidcodec h265 = { .name = "H265", .fmtp = "profile-id=1", .encupdh = avcodec_encode_update, .ench = avcodec_encode, .decupdh = avcodec_decode_update, .dech = avcodec_decode_h265, }; static int module_init(void) { struct list *vidcodecl = baresip_vidcodecl(); char h264enc[64] = "libx264"; char h264dec[64] = "h264"; char h265enc[64] = "libx265"; char h265dec[64] = "hevc"; #if LIBAVUTIL_VERSION_MAJOR >= 56 char hwaccel[64]; #endif #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(53, 10, 0) avcodec_init(); #endif #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 9, 100) avcodec_register_all(); #endif conf_get_str(conf_cur(), "avcodec_h264enc", h264enc, sizeof(h264enc)); conf_get_str(conf_cur(), "avcodec_h264dec", h264dec, sizeof(h264dec)); conf_get_str(conf_cur(), "avcodec_h265enc", h265enc, sizeof(h265enc)); conf_get_str(conf_cur(), "avcodec_h265dec", h265dec, sizeof(h265dec)); avcodec_h264enc = avcodec_find_encoder_by_name(h264enc); if (!avcodec_h264enc) { warning("avcodec: h264 encoder not found (%s)\n", h264enc); } avcodec_h264dec = avcodec_find_decoder_by_name(h264dec); if (!avcodec_h264dec) { warning("avcodec: h264 decoder not found (%s)\n", h264dec); } avcodec_h265enc = avcodec_find_encoder_by_name(h265enc); avcodec_h265dec = avcodec_find_decoder_by_name(h265dec); if (avcodec_h264enc || avcodec_h264dec) { vidcodec_register(vidcodecl, &h264); vidcodec_register(vidcodecl, &h264_1); } if (avcodec_find_decoder(AV_CODEC_ID_H263)) vidcodec_register(vidcodecl, &h263); if (avcodec_find_decoder(AV_CODEC_ID_MPEG4)) vidcodec_register(vidcodecl, &mpg4); if (avcodec_h265enc || avcodec_h265dec) vidcodec_register(vidcodecl, &h265); if (avcodec_h264enc) { info("avcodec: using H.264 encoder '%s' -- %s\n", avcodec_h264enc->name, avcodec_h264enc->long_name); } if (avcodec_h264dec) { info("avcodec: using H.264 decoder '%s' -- %s\n", avcodec_h264dec->name, avcodec_h264dec->long_name); } if (avcodec_h265enc) { info("avcodec: using H.265 encoder '%s' -- %s\n", avcodec_h265enc->name, avcodec_h265enc->long_name); } if (avcodec_h265dec) { info("avcodec: using H.265 decoder '%s' -- %s\n", avcodec_h265dec->name, avcodec_h265dec->long_name); } #if LIBAVUTIL_VERSION_MAJOR >= 56 /* common for encode/decode */ if (0 == conf_get_str(conf_cur(), "avcodec_hwaccel", hwaccel, sizeof(hwaccel))) { enum AVHWDeviceType type; int ret; int i; info("avcodec: enable hwaccel using '%s'\n", hwaccel); type = av_hwdevice_find_type_by_name(hwaccel); if (type == AV_HWDEVICE_TYPE_NONE) { warning("avcodec: Device type" " '%s' is not supported.\n", hwaccel); return ENOSYS; } for (i = 0;; i++) { const AVCodecHWConfig *config; config = avcodec_get_hw_config(avcodec_h264dec, i); if (!config) { warning("avcodec: Decoder does not" " support device type %s.\n", av_hwdevice_get_type_name(type)); return ENOSYS; } if (config->methods & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX && config->device_type == type) { avcodec_hw_pix_fmt = config->pix_fmt; info("avcodec: decode: using hardware" " pixel format '%s'\n", av_get_pix_fmt_name(config->pix_fmt)); break; } } ret = av_hwdevice_ctx_create(&avcodec_hw_device_ctx, type, NULL, NULL, 0); if (ret < 0) { warning("avcodec: Failed to create HW device (%s)\n", av_err2str(ret)); return ENOTSUP; } avcodec_hw_type = type; } #endif return 0; } static int module_close(void) { vidcodec_unregister(&h265); vidcodec_unregister(&mpg4); vidcodec_unregister(&h263); vidcodec_unregister(&h264); vidcodec_unregister(&h264_1); #if LIBAVUTIL_VERSION_MAJOR >= 56 if (avcodec_hw_device_ctx) av_buffer_unref(&avcodec_hw_device_ctx); #endif return 0; } EXPORT_SYM const struct mod_export DECL_EXPORTS(avcodec) = { "avcodec", "codec", module_init, module_close }; baresip-1.0.0/modules/avcodec/avcodec.h000066400000000000000000000042411372575704200200030ustar00rootroot00000000000000/** * @file avcodec.h Video codecs using libavcodec -- internal API * * Copyright (C) 2010 Creytiv.com */ #if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(52, 20, 100) #define av_frame_alloc avcodec_alloc_frame #endif #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55, 63, 100) #define avcodec_free_context(ctx) \ \ if (*(ctx)) { \ avcodec_close(*(ctx)); \ av_freep((ctx)); \ } #endif #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 37, 100) #define av_packet_free(pkt) \ \ if (*(pkt)) { \ \ av_free_packet(*(pkt)); \ av_freep((pkt)); \ } #endif extern AVCodec *avcodec_h264enc; extern AVCodec *avcodec_h264dec; extern AVCodec *avcodec_h265enc; extern AVCodec *avcodec_h265dec; #if LIBAVUTIL_VERSION_MAJOR >= 56 extern AVBufferRef *avcodec_hw_device_ctx; extern enum AVPixelFormat avcodec_hw_pix_fmt; extern enum AVHWDeviceType avcodec_hw_type; #endif /* * Encode */ struct videnc_state; int avcodec_encode_update(struct videnc_state **vesp, const struct vidcodec *vc, struct videnc_param *prm, const char *fmtp, videnc_packet_h *pkth, void *arg); int avcodec_encode(struct videnc_state *st, bool update, const struct vidframe *frame, uint64_t timestamp); /* * Decode */ struct viddec_state; int avcodec_decode_update(struct viddec_state **vdsp, const struct vidcodec *vc, const char *fmtp); int avcodec_decode_h263(struct viddec_state *st, struct vidframe *frame, bool *intra, bool eof, uint16_t seq, struct mbuf *src); int avcodec_decode_h264(struct viddec_state *st, struct vidframe *frame, bool *intra, bool eof, uint16_t seq, struct mbuf *src); int avcodec_decode_h265(struct viddec_state *st, struct vidframe *frame, bool *intra, bool eof, uint16_t seq, struct mbuf *src); int avcodec_decode_mpeg4(struct viddec_state *st, struct vidframe *frame, bool *intra, bool eof, uint16_t seq, struct mbuf *src); int avcodec_resolve_codecid(const char *s); /* * SDP */ uint32_t h264_packetization_mode(const char *fmtp); int avcodec_h264_fmtp_enc(struct mbuf *mb, const struct sdp_format *fmt, bool offer, void *arg); bool avcodec_h264_fmtp_cmp(const char *lfmtp, const char *rfmtp, void *data); baresip-1.0.0/modules/avcodec/decode.c000066400000000000000000000347661372575704200176340ustar00rootroot00000000000000/** * @file avcodec/decode.c Video codecs using libavcodec -- decoder * * Copyright (C) 2010 - 2013 Creytiv.com */ #include #include #include #include #include #include #include #include "h26x.h" #include "avcodec.h" #ifndef AV_INPUT_BUFFER_PADDING_SIZE #define AV_INPUT_BUFFER_PADDING_SIZE 64 #endif enum { DECODE_MAXSZ = 524288, }; struct viddec_state { AVCodec *codec; AVCodecContext *ctx; AVFrame *pict; struct mbuf *mb; bool got_keyframe; size_t frag_start; bool frag; uint16_t frag_seq; struct { unsigned n_key; unsigned n_lost; } stats; }; static void destructor(void *arg) { struct viddec_state *st = arg; debug("avcodec: decoder stats" " (keyframes:%u, lost_fragments:%u)\n", st->stats.n_key, st->stats.n_lost); mem_deref(st->mb); if (st->ctx) avcodec_free_context(&st->ctx); if (st->pict) av_free(st->pict); } static enum vidfmt avpixfmt_to_vidfmt(enum AVPixelFormat pix_fmt) { switch (pix_fmt) { case AV_PIX_FMT_YUV420P: return VID_FMT_YUV420P; case AV_PIX_FMT_YUVJ420P: return VID_FMT_YUV420P; case AV_PIX_FMT_YUV444P: return VID_FMT_YUV444P; case AV_PIX_FMT_NV12: return VID_FMT_NV12; case AV_PIX_FMT_NV21: return VID_FMT_NV21; default: return (enum vidfmt)-1; } } static inline int16_t seq_diff(uint16_t x, uint16_t y) { return (int16_t)(y - x); } static inline void fragment_rewind(struct viddec_state *vds) { vds->mb->pos = vds->frag_start; vds->mb->end = vds->frag_start; } #if LIBAVUTIL_VERSION_MAJOR >= 56 static enum AVPixelFormat get_hw_format(AVCodecContext *ctx, const enum AVPixelFormat *pix_fmts) { const enum AVPixelFormat *p; (void)ctx; for (p = pix_fmts; *p != -1; p++) { if (*p == avcodec_hw_pix_fmt) return *p; } warning("avcodec: decode: Failed to get HW surface format.\n"); return AV_PIX_FMT_NONE; } #endif static int init_decoder(struct viddec_state *st, const char *name) { enum AVCodecID codec_id; codec_id = avcodec_resolve_codecid(name); if (codec_id == AV_CODEC_ID_NONE) return EINVAL; /* * Special handling of H.264 decoder */ if (codec_id == AV_CODEC_ID_H264 && avcodec_h264dec) { st->codec = avcodec_h264dec; info("avcodec: h264 decoder activated\n"); } else if (0 == str_casecmp(name, "h265")) { st->codec = avcodec_h265dec; info("avcodec: h265 decoder activated\n"); } else { st->codec = avcodec_find_decoder(codec_id); if (!st->codec) return ENOENT; } st->ctx = avcodec_alloc_context3(st->codec); /* TODO: If avcodec_h264dec is h264_mediacodec, extradata needs to added to context that contains Sequence Parameter Set (SPS) and Picture Parameter Set (PPS), before avcodec_open2() is called. */ st->pict = av_frame_alloc(); if (!st->ctx || !st->pict) return ENOMEM; #if LIBAVUTIL_VERSION_MAJOR >= 56 /* Hardware accelleration */ if (avcodec_hw_device_ctx) { st->ctx->hw_device_ctx = av_buffer_ref(avcodec_hw_device_ctx); st->ctx->get_format = get_hw_format; info("avcodec: decode: hardware accel enabled (%s)\n", av_hwdevice_get_type_name(avcodec_hw_type)); } else { info("avcodec: decode: hardware accel disabled\n"); } #endif if (avcodec_open2(st->ctx, st->codec, NULL) < 0) return ENOENT; return 0; } int avcodec_decode_update(struct viddec_state **vdsp, const struct vidcodec *vc, const char *fmtp) { struct viddec_state *st; int err = 0; if (!vdsp || !vc) return EINVAL; if (*vdsp) return 0; (void)fmtp; st = mem_zalloc(sizeof(*st), destructor); if (!st) return ENOMEM; st->mb = mbuf_alloc(1024); if (!st->mb) { err = ENOMEM; goto out; } err = init_decoder(st, vc->name); if (err) { warning("avcodec: %s: could not init decoder\n", vc->name); goto out; } debug("avcodec: video decoder %s (%s)\n", vc->name, fmtp); out: if (err) mem_deref(st); else *vdsp = st; return err; } static int ffdecode(struct viddec_state *st, struct vidframe *frame, bool *intra) { AVFrame *hw_frame = NULL; AVPacket avpkt; int i, got_picture, ret; int err = 0; #if LIBAVUTIL_VERSION_MAJOR >= 56 if (st->ctx->hw_device_ctx) { hw_frame = av_frame_alloc(); if (!hw_frame) return ENOMEM; } #endif err = mbuf_fill(st->mb, 0x00, AV_INPUT_BUFFER_PADDING_SIZE); if (err) return err; st->mb->end -= AV_INPUT_BUFFER_PADDING_SIZE; av_init_packet(&avpkt); avpkt.data = st->mb->buf; avpkt.size = (int)st->mb->end; #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 37, 100) ret = avcodec_send_packet(st->ctx, &avpkt); if (ret < 0) { warning("avcodec: avcodec_send_packet error," " packet=%zu bytes, ret=%d (%s)\n", st->mb->end, ret, av_err2str(ret)); err = EBADMSG; goto out; } ret = avcodec_receive_frame(st->ctx, hw_frame ? hw_frame : st->pict); if (ret == AVERROR(EAGAIN)) { goto out; } else if (ret < 0) { warning("avcodec_receive_frame error ret=%d\n", ret); err = EBADMSG; goto out; } got_picture = true; #else ret = avcodec_decode_video2(st->ctx, st->pict, &got_picture, &avpkt); if (ret < 0) { err = EBADMSG; goto out; } #endif if (got_picture) { #if LIBAVUTIL_VERSION_MAJOR >= 56 if (hw_frame) { /* retrieve data from GPU to CPU */ ret = av_hwframe_transfer_data(st->pict, hw_frame, 0); if (ret < 0) { warning("avcodec: decode: Error transferring" " the data to system memory\n"); goto out; } st->pict->key_frame = hw_frame->key_frame; } #endif frame->fmt = avpixfmt_to_vidfmt(st->pict->format); if (frame->fmt == (enum vidfmt)-1) { warning("avcodec: decode: bad pixel format" " (%i) (%s)\n", st->pict->format, av_get_pix_fmt_name(st->pict->format)); goto out; } for (i=0; i<4; i++) { frame->data[i] = st->pict->data[i]; frame->linesize[i] = st->pict->linesize[i]; } frame->size.w = st->ctx->width; frame->size.h = st->ctx->height; if (st->pict->key_frame) { *intra = true; st->got_keyframe = true; ++st->stats.n_key; } } out: av_frame_free(&hw_frame); return err; } int avcodec_decode_h264(struct viddec_state *st, struct vidframe *frame, bool *intra, bool marker, uint16_t seq, struct mbuf *src) { struct h264_hdr h264_hdr; const uint8_t nal_seq[3] = {0, 0, 1}; int err; if (!st || !frame || !intra || !src) return EINVAL; *intra = false; err = h264_hdr_decode(&h264_hdr, src); if (err) return err; #if 0 re_printf("avcodec: decode: %s %s type=%2d %s \n", marker ? "[M]" : " ", h264_is_keyframe(h264_hdr.type) ? "" : " ", h264_hdr.type, h264_nalunit_name(h264_hdr.type)); #endif if (h264_hdr.type == H264_NAL_SLICE && !st->got_keyframe) { debug("avcodec: decoder waiting for keyframe\n"); return EPROTO; } if (h264_hdr.f) { info("avcodec: H264 forbidden bit set!\n"); return EBADMSG; } if (st->frag && h264_hdr.type != H264_NAL_FU_A) { debug("avcodec: lost fragments; discarding previous NAL\n"); fragment_rewind(st); st->frag = false; ++st->stats.n_lost; } /* handle NAL types */ if (1 <= h264_hdr.type && h264_hdr.type <= 23) { --src->pos; /* prepend H.264 NAL start sequence */ err = mbuf_write_mem(st->mb, nal_seq, 3); err |= mbuf_write_mem(st->mb, mbuf_buf(src), mbuf_get_left(src)); if (err) goto out; } else if (H264_NAL_FU_A == h264_hdr.type) { struct h264_fu fu; err = h264_fu_hdr_decode(&fu, src); if (err) return err; h264_hdr.type = fu.type; if (fu.s) { if (st->frag) { debug("avcodec: start: lost fragments;" " ignoring previous NAL\n"); fragment_rewind(st); ++st->stats.n_lost; } st->frag_start = st->mb->pos; st->frag = true; /* prepend H.264 NAL start sequence */ mbuf_write_mem(st->mb, nal_seq, 3); /* encode NAL header back to buffer */ err = h264_hdr_encode(&h264_hdr, st->mb); if (err) goto out; } else { if (!st->frag) { debug("avcodec: ignoring fragment" " (nal=%u)\n", fu.type); ++st->stats.n_lost; return 0; } if (seq_diff(st->frag_seq, seq) != 1) { debug("avcodec: lost fragments detected\n"); fragment_rewind(st); st->frag = false; ++st->stats.n_lost; return 0; } } err = mbuf_write_mem(st->mb, mbuf_buf(src), mbuf_get_left(src)); if (err) goto out; if (fu.e) st->frag = false; st->frag_seq = seq; } else if (H264_NAL_STAP_A == h264_hdr.type) { while (mbuf_get_left(src) >= 2) { const uint16_t len = ntohs(mbuf_read_u16(src)); struct h264_hdr lhdr; if (mbuf_get_left(src) < len) return EBADMSG; err = h264_hdr_decode(&lhdr, src); if (err) return err; --src->pos; err = mbuf_write_mem(st->mb, nal_seq, 3); err |= mbuf_write_mem(st->mb, mbuf_buf(src), len); if (err) goto out; src->pos += len; } } else { warning("avcodec: unknown NAL type %u\n", h264_hdr.type); return EBADMSG; } if (!marker) { if (st->mb->end > DECODE_MAXSZ) { warning("avcodec: decode buffer size exceeded\n"); err = ENOMEM; goto out; } return 0; } if (st->frag) { err = EPROTO; goto out; } err = ffdecode(st, frame, intra); if (err) goto out; out: mbuf_rewind(st->mb); st->frag = false; return err; } int avcodec_decode_mpeg4(struct viddec_state *st, struct vidframe *frame, bool *intra, bool marker, uint16_t seq, struct mbuf *src) { int err; if (!src) return 0; (void)seq; *intra = false; err = mbuf_write_mem(st->mb, mbuf_buf(src), mbuf_get_left(src)); if (err) goto out; if (!marker) { if (st->mb->end > DECODE_MAXSZ) { warning("avcodec: decode buffer size exceeded\n"); err = ENOMEM; goto out; } return 0; } err = ffdecode(st, frame, intra); if (err) goto out; out: mbuf_rewind(st->mb); return err; } int avcodec_decode_h263(struct viddec_state *st, struct vidframe *frame, bool *intra, bool marker, uint16_t seq, struct mbuf *src) { struct h263_hdr hdr; int err; if (!st || !frame || !intra) return EINVAL; *intra = false; if (!src) return 0; (void)seq; err = h263_hdr_decode(&hdr, src); if (err) return err; if (hdr.i && !st->got_keyframe) return EPROTO; #if 0 debug(".....[%s seq=%5u ] MODE %s -" " SBIT=%u EBIT=%u I=%s" " (%5u/%5u bytes)\n", marker ? "M" : " ", seq, h263_hdr_mode(&hdr) == H263_MODE_A ? "A" : "B", hdr.sbit, hdr.ebit, hdr.i ? "Inter" : "Intra", mbuf_get_left(src), st->mb->end); #endif #if 0 if (st->mb->pos == 0) { uint8_t *p = mbuf_buf(src); if (p[0] != 0x00 || p[1] != 0x00) { warning("invalid PSC detected (%02x %02x)\n", p[0], p[1]); return EPROTO; } } #endif /* * The H.263 Bit-stream can be fragmented on bit-level, * indicated by SBIT and EBIT. Example: * * 8 bit 2 bit * .--------.--. * Packet 1 | | | * SBIT=0 '--------'--' * EBIT=6 * .------.--------.--------. * Packet 2 | | | | * SBIT=2 '------'--------'--------' * EBIT=0 6bit 8bit 8bit * */ if (hdr.sbit > 0) { const uint8_t mask = (1 << (8 - hdr.sbit)) - 1; const uint8_t sbyte = mbuf_read_u8(src) & mask; st->mb->buf[st->mb->end - 1] |= sbyte; } err = mbuf_write_mem(st->mb, mbuf_buf(src), mbuf_get_left(src)); if (err) goto out; if (!marker) { if (st->mb->end > DECODE_MAXSZ) { warning("avcodec: decode buffer size exceeded\n"); err = ENOMEM; goto out; } return 0; } err = ffdecode(st, frame, intra); if (err) goto out; out: mbuf_rewind(st->mb); return err; } enum { H265_FU_HDR_SIZE = 1 }; struct h265_fu { unsigned s:1; unsigned e:1; unsigned type:6; }; static inline int h265_fu_decode(struct h265_fu *fu, struct mbuf *mb) { uint8_t v; if (mbuf_get_left(mb) < 1) return EBADMSG; v = mbuf_read_u8(mb); fu->s = v>>7 & 0x1; fu->e = v>>6 & 0x1; fu->type = v>>0 & 0x3f; return 0; } int avcodec_decode_h265(struct viddec_state *vds, struct vidframe *frame, bool *intra, bool marker, uint16_t seq, struct mbuf *mb) { static const uint8_t nal_seq[3] = {0, 0, 1}; struct h265_nal hdr; int err; if (!vds || !frame || !intra || !mb) return EINVAL; *intra = false; err = h265_nal_decode(&hdr, mbuf_buf(mb)); if (err) return err; mbuf_advance(mb, H265_HDR_SIZE); #if 0 debug("h265: decode: %s type=%2d %s\n", h265_is_keyframe(hdr.nal_unit_type) ? "" : " ", hdr.nal_unit_type, h265_nalunit_name(hdr.nal_unit_type)); #endif if (vds->frag && hdr.nal_unit_type != H265_NAL_FU) { debug("h265: lost fragments; discarding previous NAL\n"); fragment_rewind(vds); vds->frag = false; } /* handle NAL types */ if (hdr.nal_unit_type <= 40) { mb->pos -= H265_HDR_SIZE; err = mbuf_write_mem(vds->mb, nal_seq, 3); err |= mbuf_write_mem(vds->mb, mbuf_buf(mb),mbuf_get_left(mb)); if (err) goto out; } else if (H265_NAL_FU == hdr.nal_unit_type) { struct h265_fu fu; err = h265_fu_decode(&fu, mb); if (err) return err; if (fu.s) { if (vds->frag) { debug("h265: lost fragments; ignoring NAL\n"); fragment_rewind(vds); } vds->frag_start = vds->mb->pos; vds->frag = true; hdr.nal_unit_type = fu.type; err = mbuf_write_mem(vds->mb, nal_seq, 3); err |= h265_nal_encode_mbuf(vds->mb, &hdr); if (err) goto out; } else { if (!vds->frag) { debug("h265: ignoring fragment\n"); return 0; } if (seq_diff(vds->frag_seq, seq) != 1) { debug("h265: lost fragments detected\n"); fragment_rewind(vds); vds->frag = false; return 0; } } err = mbuf_write_mem(vds->mb, mbuf_buf(mb), mbuf_get_left(mb)); if (err) goto out; if (fu.e) vds->frag = false; vds->frag_seq = seq; } else if (hdr.nal_unit_type == H265_NAL_AP) { while (mbuf_get_left(mb) >= 2) { const uint16_t len = ntohs(mbuf_read_u16(mb)); if (mbuf_get_left(mb) < len) return EBADMSG; err = mbuf_write_mem(vds->mb, nal_seq, 3); err |= mbuf_write_mem(vds->mb, mbuf_buf(mb), len); if (err) goto out; mb->pos += len; } } else { warning("h265: unknown NAL type %u (%s) [%zu bytes]\n", hdr.nal_unit_type, h265_nalunit_name(hdr.nal_unit_type), mbuf_get_left(mb)); return EPROTO; } if (!marker) { if (vds->mb->end > DECODE_MAXSZ) { warning("h265: decode buffer size exceeded\n"); err = ENOMEM; goto out; } return 0; } if (vds->frag) { err = EPROTO; goto out; } err = ffdecode(vds, frame, intra); if (err) goto out; out: mbuf_rewind(vds->mb); vds->frag = false; return err; } baresip-1.0.0/modules/avcodec/encode.c000066400000000000000000000342341372575704200176340ustar00rootroot00000000000000/** * @file avcodec/encode.c Video codecs using libavcodec -- encoder * * Copyright (C) 2010 - 2013 Creytiv.com */ #include #include #include #include #include #include #include #include "h26x.h" #include "avcodec.h" enum { KEYFRAME_INTERVAL = 10 /* Keyframes per second */ }; struct picsz { enum h263_fmt fmt; /**< Picture size */ uint8_t mpi; /**< Minimum Picture Interval (1-32) */ }; struct videnc_state { AVCodec *codec; AVCodecContext *ctx; struct mbuf *mb_frag; struct videnc_param encprm; struct vidsz encsize; enum vidfmt fmt; enum AVCodecID codec_id; videnc_packet_h *pkth; void *arg; union { struct { struct picsz picszv[8]; uint32_t picszn; } h263; struct { uint32_t packetization_mode; uint32_t profile_idc; uint32_t profile_iop; uint32_t level_idc; uint32_t max_fs; uint32_t max_smbps; } h264; } u; }; static void destructor(void *arg) { struct videnc_state *st = arg; mem_deref(st->mb_frag); if (st->ctx) avcodec_free_context(&st->ctx); } #if LIBAVUTIL_VERSION_MAJOR >= 56 static int set_hwframe_ctx(AVCodecContext *ctx, AVBufferRef *device_ctx, int width, int height) { AVBufferRef *hw_frames_ref; AVHWFramesContext *frames_ctx = NULL; int err = 0; info("avcodec: encode: create hardware frames.. (%d x %d)\n", width, height); if (!(hw_frames_ref = av_hwframe_ctx_alloc(device_ctx))) { warning("avcodec: encode: Failed to create hardware" " frame context.\n"); return ENOMEM; } frames_ctx = (AVHWFramesContext *)(void *)hw_frames_ref->data; frames_ctx->format = avcodec_hw_pix_fmt; frames_ctx->sw_format = AV_PIX_FMT_NV12; frames_ctx->width = width; frames_ctx->height = height; frames_ctx->initial_pool_size = 20; if ((err = av_hwframe_ctx_init(hw_frames_ref)) < 0) { warning("avcodec: encode:" " Failed to initialize hardware frame context." "Error code: %s\n",av_err2str(err)); av_buffer_unref(&hw_frames_ref); return err; } ctx->hw_frames_ctx = av_buffer_ref(hw_frames_ref); if (!ctx->hw_frames_ctx) err = AVERROR(ENOMEM); av_buffer_unref(&hw_frames_ref); return err; } #endif static enum AVPixelFormat vidfmt_to_avpixfmt(enum vidfmt fmt) { switch (fmt) { case VID_FMT_YUV420P: return AV_PIX_FMT_YUV420P; case VID_FMT_YUV444P: return AV_PIX_FMT_YUV444P; case VID_FMT_NV12: return AV_PIX_FMT_NV12; case VID_FMT_NV21: return AV_PIX_FMT_NV21; default: return AV_PIX_FMT_NONE; } } static enum h263_fmt h263_fmt(const struct pl *name) { if (0 == pl_strcasecmp(name, "sqcif")) return H263_FMT_SQCIF; if (0 == pl_strcasecmp(name, "qcif")) return H263_FMT_QCIF; if (0 == pl_strcasecmp(name, "cif")) return H263_FMT_CIF; if (0 == pl_strcasecmp(name, "cif4")) return H263_FMT_4CIF; if (0 == pl_strcasecmp(name, "cif16")) return H263_FMT_16CIF; return H263_FMT_OTHER; } static int decode_sdpparam_h263(struct videnc_state *st, const struct pl *name, const struct pl *val) { enum h263_fmt fmt = h263_fmt(name); const int mpi = pl_u32(val); if (fmt == H263_FMT_OTHER) { info("h263: unknown param '%r'\n", name); return 0; } if (mpi < 1 || mpi > 32) { info("h263: %r: MPI out of range %d\n", name, mpi); return 0; } if (st->u.h263.picszn >= ARRAY_SIZE(st->u.h263.picszv)) { info("h263: picszv overflow: %r\n", name); return 0; } st->u.h263.picszv[st->u.h263.picszn].fmt = fmt; st->u.h263.picszv[st->u.h263.picszn].mpi = mpi; ++st->u.h263.picszn; return 0; } static int init_encoder(struct videnc_state *st, const char *name) { /* * Special handling of H.264 encoder */ if (st->codec_id == AV_CODEC_ID_H264 && avcodec_h264enc) { st->codec = avcodec_h264enc; info("avcodec: h264 encoder activated\n"); return 0; } if (0 == str_casecmp(name, "h265")) { st->codec = avcodec_h265enc; info("avcodec: h265 encoder activated\n"); return 0; } st->codec = avcodec_find_encoder(st->codec_id); if (!st->codec) return ENOENT; return 0; } static int open_encoder(struct videnc_state *st, const struct videnc_param *prm, const struct vidsz *size, int pix_fmt) { int err = 0; if (st->ctx) avcodec_free_context(&st->ctx); st->ctx = avcodec_alloc_context3(st->codec); if (!st->ctx) { err = ENOMEM; goto out; } av_opt_set_defaults(st->ctx); st->ctx->bit_rate = prm->bitrate; st->ctx->width = size->w; st->ctx->height = size->h; #if LIBAVUTIL_VERSION_MAJOR >= 56 if (avcodec_hw_type == AV_HWDEVICE_TYPE_VAAPI) st->ctx->pix_fmt = avcodec_hw_pix_fmt; else #endif st->ctx->pix_fmt = pix_fmt; st->ctx->time_base.num = 1; st->ctx->time_base.den = prm->fps; st->ctx->gop_size = KEYFRAME_INTERVAL * prm->fps; if (0 == str_cmp(st->codec->name, "libx264")) { av_opt_set(st->ctx->priv_data, "profile", "baseline", 0); av_opt_set(st->ctx->priv_data, "preset", "ultrafast", 0); av_opt_set(st->ctx->priv_data, "tune", "zerolatency", 0); if (st->u.h264.packetization_mode == 0) { av_opt_set_int(st->ctx->priv_data, "slice-max-size", prm->pktsize, 0); } } /* params to avoid libavcodec/x264 default preset error */ if (st->codec_id == AV_CODEC_ID_H264) { if (0 == str_cmp(st->codec->name, "h264_vaapi")) { av_opt_set(st->ctx->priv_data, "profile", "constrained_baseline", 0); } else { av_opt_set(st->ctx->priv_data, "profile", "baseline", 0); } st->ctx->me_range = 16; st->ctx->qmin = 10; st->ctx->qmax = 51; st->ctx->max_qdiff = 4; if (st->codec == avcodec_find_encoder_by_name("nvenc_h264") || st->codec == avcodec_find_encoder_by_name("h264_nvenc")) { err = av_opt_set(st->ctx->priv_data, "preset", "llhp", 0); if (err < 0) { debug("avcodec: h264 nvenc setting preset " "\"llhp\" failed; error: %u\n", err); } else { debug("avcodec: h264 nvenc preset " "\"llhp\" selected\n"); } err = av_opt_set_int(st->ctx->priv_data, "2pass", 1, 0); if (err < 0) { debug("avcodec: h264 nvenc option " "\"2pass\" failed; error: %u\n", err); } else { debug("avcodec: h264 nvenc option " "\"2pass\" selected\n"); } } } if (0 == str_cmp(st->codec->name, "libx265")) { av_opt_set(st->ctx->priv_data, "profile", "main444-8", 0); av_opt_set(st->ctx->priv_data, "preset", "ultrafast", 0); av_opt_set(st->ctx->priv_data, "tune", "zerolatency", 0); } #if LIBAVUTIL_VERSION_MAJOR >= 56 if (avcodec_hw_type == AV_HWDEVICE_TYPE_VAAPI) { /* set hw_frames_ctx for encoder's AVCodecContext */ err = set_hwframe_ctx(st->ctx, avcodec_hw_device_ctx, size->w, size->h); if (err < 0) { warning("avcodec: encode: Failed to set" " hwframe context.\n"); goto out; } } #endif if (avcodec_open2(st->ctx, st->codec, NULL) < 0) { err = ENOENT; goto out; } st->encsize = *size; out: if (err) { if (st->ctx) avcodec_free_context(&st->ctx); } return err; } static int decode_sdpparam_h264(struct videnc_state *st, const struct pl *name, const struct pl *val) { if (0 == pl_strcasecmp(name, "packetization-mode")) { st->u.h264.packetization_mode = pl_u32(val); if (st->u.h264.packetization_mode != 0 && st->u.h264.packetization_mode != 1 ) { warning("avcodec: illegal packetization-mode %u\n", st->u.h264.packetization_mode); return EPROTO; } } else if (0 == pl_strcasecmp(name, "profile-level-id")) { struct pl prof = *val; if (prof.l != 6) { warning("avcodec: invalid profile-level-id (%r)\n", val); return EPROTO; } prof.l = 2; st->u.h264.profile_idc = pl_x32(&prof); prof.p += 2; st->u.h264.profile_iop = pl_x32(&prof); prof.p += 2; st->u.h264.level_idc = pl_x32(&prof); } else if (0 == pl_strcasecmp(name, "max-fs")) { st->u.h264.max_fs = pl_u32(val); } else if (0 == pl_strcasecmp(name, "max-smbps")) { st->u.h264.max_smbps = pl_u32(val); } return 0; } static void param_handler(const struct pl *name, const struct pl *val, void *arg) { struct videnc_state *st = arg; if (st->codec_id == AV_CODEC_ID_H263) (void)decode_sdpparam_h263(st, name, val); else if (st->codec_id == AV_CODEC_ID_H264) (void)decode_sdpparam_h264(st, name, val); } static int general_packetize(uint64_t rtp_ts, struct mbuf *mb, size_t pktsize, videnc_packet_h *pkth, void *arg) { int err = 0; /* Assemble frame into smaller packets */ while (!err) { size_t sz, left = mbuf_get_left(mb); bool last = (left < pktsize); if (!left) break; sz = last ? left : pktsize; err = pkth(last, rtp_ts, NULL, 0, mbuf_buf(mb), sz, arg); mbuf_advance(mb, sz); } return err; } static int h263_packetize(struct videnc_state *st, uint64_t rtp_ts, struct mbuf *mb, videnc_packet_h *pkth, void *arg) { struct h263_strm h263_strm; struct h263_hdr h263_hdr; size_t pos; int err; /* Decode bit-stream header, used by packetizer */ err = h263_strm_decode(&h263_strm, mb); if (err) return err; h263_hdr_copy_strm(&h263_hdr, &h263_strm); st->mb_frag->pos = st->mb_frag->end = 0; err = h263_hdr_encode(&h263_hdr, st->mb_frag); pos = st->mb_frag->pos; /* Assemble frame into smaller packets */ while (!err) { size_t sz, left = mbuf_get_left(mb); bool last = (left < st->encprm.pktsize); if (!left) break; sz = last ? left : st->encprm.pktsize; st->mb_frag->pos = st->mb_frag->end = pos; err = mbuf_write_mem(st->mb_frag, mbuf_buf(mb), sz); if (err) break; st->mb_frag->pos = 0; err = pkth(last, rtp_ts, NULL, 0, mbuf_buf(st->mb_frag), mbuf_get_left(st->mb_frag), arg); mbuf_advance(mb, sz); } return err; } int avcodec_encode_update(struct videnc_state **vesp, const struct vidcodec *vc, struct videnc_param *prm, const char *fmtp, videnc_packet_h *pkth, void *arg) { struct videnc_state *st; int err = 0; if (!vesp || !vc || !prm || !pkth) return EINVAL; if (*vesp) return 0; st = mem_zalloc(sizeof(*st), destructor); if (!st) return ENOMEM; st->encprm = *prm; st->pkth = pkth; st->arg = arg; st->codec_id = avcodec_resolve_codecid(vc->name); if (st->codec_id == AV_CODEC_ID_NONE) { warning("avcodec: unknown encoder (%s)\n", vc->name); err = EINVAL; goto out; } st->mb_frag = mbuf_alloc(1024); if (!st->mb_frag) { err = ENOMEM; goto out; } st->fmt = -1; err = init_encoder(st, vc->name); if (err) { warning("avcodec: %s: could not init encoder\n", vc->name); goto out; } if (str_isset(fmtp)) { struct pl sdp_fmtp; pl_set_str(&sdp_fmtp, fmtp); fmt_param_apply(&sdp_fmtp, param_handler, st); } debug("avcodec: video encoder %s: %.2f fps, %d bit/s, pktsize=%u\n", vc->name, prm->fps, prm->bitrate, prm->pktsize); out: if (err) mem_deref(st); else *vesp = st; return err; } int avcodec_encode(struct videnc_state *st, bool update, const struct vidframe *frame, uint64_t timestamp) { AVFrame *pict = NULL; AVFrame *hw_frame = NULL; AVPacket *pkt = NULL; int i, err = 0, ret; #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 37, 100) int got_packet = 0; #endif uint64_t ts; struct mbuf mb; if (!st || !frame) return EINVAL; if (!st->ctx || !vidsz_cmp(&st->encsize, &frame->size) || st->fmt != frame->fmt) { enum AVPixelFormat pix_fmt; pix_fmt = vidfmt_to_avpixfmt(frame->fmt); if (pix_fmt == AV_PIX_FMT_NONE) { warning("avcodec: pixel format not supported (%s)\n", vidfmt_name(frame->fmt)); return ENOTSUP; } err = open_encoder(st, &st->encprm, &frame->size, pix_fmt); if (err) { warning("avcodec: open_encoder: %m\n", err); return err; } st->fmt = frame->fmt; } pict = av_frame_alloc(); if (!pict) { err = ENOMEM; goto out; } #if LIBAVUTIL_VERSION_MAJOR >= 56 if (avcodec_hw_type == AV_HWDEVICE_TYPE_VAAPI) { hw_frame = av_frame_alloc(); if (!hw_frame) { err = ENOMEM; goto out; } } #endif pict->format = vidfmt_to_avpixfmt(frame->fmt); pict->width = frame->size.w; pict->height = frame->size.h; pict->pts = timestamp; for (i=0; i<4; i++) { pict->data[i] = frame->data[i]; pict->linesize[i] = frame->linesize[i]; } if (update) { debug("avcodec: encoder picture update\n"); pict->key_frame = 1; pict->pict_type = AV_PICTURE_TYPE_I; } #if LIBAVUTIL_VERSION_MAJOR >= 55 pict->color_range = AVCOL_RANGE_MPEG; #endif #if LIBAVUTIL_VERSION_MAJOR >= 56 if (avcodec_hw_type == AV_HWDEVICE_TYPE_VAAPI) { if ((err = av_hwframe_get_buffer(st->ctx->hw_frames_ctx, hw_frame, 0)) < 0) { warning("avcodec: encode: Error code: %s.\n", av_err2str(err)); goto out; } if (!hw_frame->hw_frames_ctx) { err = AVERROR(ENOMEM); goto out; } if ((err = av_hwframe_transfer_data(hw_frame, pict, 0)) < 0) { warning("avcodec: encode: Error while transferring" " frame data to surface." "Error code: %s.\n", av_err2str(err)); goto out; } av_frame_copy_props(hw_frame, pict); } #endif #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 37, 100) pkt = av_packet_alloc(); if (!pkt) { err = ENOMEM; goto out; } ret = avcodec_send_frame(st->ctx, hw_frame ? hw_frame : pict); if (ret < 0) { err = EBADMSG; goto out; } ret = avcodec_receive_packet(st->ctx, pkt); if (ret < 0) { err = 0; goto out; } #else pkt = av_malloc(sizeof(*pkt)); if (!pkt) { err = ENOMEM; goto out; } av_init_packet(pkt); av_new_packet(pkt, 65536); ret = avcodec_encode_video2(st->ctx, pkt, pict, &got_packet); if (ret < 0) { err = EBADMSG; goto out; } if (!got_packet) return 0; #endif mb.buf = pkt->data; mb.pos = 0; mb.end = pkt->size; mb.size = pkt->size; ts = video_calc_rtp_timestamp_fix(pkt->pts); switch (st->codec_id) { case AV_CODEC_ID_H263: err = h263_packetize(st, ts, &mb, st->pkth, st->arg); break; case AV_CODEC_ID_H264: err = h264_packetize(ts, pkt->data, pkt->size, st->encprm.pktsize, st->pkth, st->arg); break; case AV_CODEC_ID_MPEG4: err = general_packetize(ts, &mb, st->encprm.pktsize, st->pkth, st->arg); break; #ifdef AV_CODEC_ID_H265 case AV_CODEC_ID_H265: err = h265_packetize(ts, pkt->data, pkt->size, st->encprm.pktsize, st->pkth, st->arg); break; #endif default: err = EPROTO; break; } out: if (pict) av_free(pict); if (pkt) av_packet_free(&pkt); av_frame_free(&hw_frame); return err; } baresip-1.0.0/modules/avcodec/h263.c000066400000000000000000000072541372575704200170630ustar00rootroot00000000000000/** * @file h263.c H.263 video codec (RFC 4629) * * Copyright (C) 2010 Creytiv.com */ #include #include #include #include #include "h26x.h" #include "avcodec.h" int h263_hdr_encode(const struct h263_hdr *hdr, struct mbuf *mb) { uint32_t v; /* host byte order */ v = hdr->f<<31 | hdr->p<<30 | hdr->sbit<<27 | hdr->ebit<<24; v |= hdr->src<<21 | hdr->i<<20 | hdr->u<<19 | hdr->s<<18 | hdr->a<<17; v |= hdr->r<<13 | hdr->dbq<<11 | hdr->trb<<8 | hdr->tr<<0; return mbuf_write_u32(mb, htonl(v)); } enum h263_mode h263_hdr_mode(const struct h263_hdr *hdr) { if (!hdr->f) { return H263_MODE_A; } else { if (!hdr->p) return H263_MODE_B; else return H263_MODE_C; } } int h263_hdr_decode(struct h263_hdr *hdr, struct mbuf *mb) { uint32_t v; if (!hdr) return EINVAL; if (mbuf_get_left(mb) < H263_HDR_SIZE_MODEA) return EBADMSG; v = ntohl(mbuf_read_u32(mb)); /* Common */ hdr->f = v>>31 & 0x1; hdr->p = v>>30 & 0x1; hdr->sbit = v>>27 & 0x7; hdr->ebit = v>>24 & 0x7; hdr->src = v>>21 & 0x7; switch (h263_hdr_mode(hdr)) { case H263_MODE_A: hdr->i = v>>20 & 0x1; hdr->u = v>>19 & 0x1; hdr->s = v>>18 & 0x1; hdr->a = v>>17 & 0x1; hdr->r = v>>13 & 0xf; hdr->dbq = v>>11 & 0x3; hdr->trb = v>>8 & 0x7; hdr->tr = v>>0 & 0xff; break; case H263_MODE_B: hdr->quant = v>>16 & 0x1f; hdr->gobn = v>>11 & 0x1f; hdr->mba = v>>2 & 0x1ff; if (mbuf_get_left(mb) < 4) return EBADMSG; v = ntohl(mbuf_read_u32(mb)); hdr->i = v>>31 & 0x1; hdr->u = v>>30 & 0x1; hdr->s = v>>29 & 0x1; hdr->a = v>>28 & 0x1; hdr->hmv1 = v>>21 & 0x7f; hdr->vmv1 = v>>14 & 0x7f; hdr->hmv2 = v>>7 & 0x7f; hdr->vmv2 = v>>0 & 0x7f; break; case H263_MODE_C: /* NOTE: Mode C is optional, only parts decoded */ if (mbuf_get_left(mb) < 8) return EBADMSG; v = ntohl(mbuf_read_u32(mb)); hdr->i = v>>31 & 0x1; hdr->u = v>>30 & 0x1; hdr->s = v>>29 & 0x1; hdr->a = v>>28 & 0x1; (void)mbuf_read_u32(mb); /* ignore */ break; } return 0; } /** * Find PSC (Picture Start Code) in bit-stream * * @param p Input bit-stream * @param size Number of bytes in bit-stream * * @return Pointer to PSC if found, otherwise NULL */ const uint8_t *h263_strm_find_psc(const uint8_t *p, uint32_t size) { const uint8_t *end = p + size - 1; for (; p < end; p++) { if (p[0] == 0x00 && p[1] == 0x00) return p; } return NULL; } int h263_strm_decode(struct h263_strm *s, struct mbuf *mb) { const uint8_t *p; if (mbuf_get_left(mb) < 6) return EINVAL; p = mbuf_buf(mb); s->psc[0] = p[0]; s->psc[1] = p[1]; s->temp_ref = (p[2]<<6 & 0xc0) | (p[3]>>2 & 0x3f); s->split_scr = p[4]>>7 & 0x1; s->doc_camera = p[4]>>6 & 0x1; s->pic_frz_rel = p[4]>>5 & 0x1; s->src_fmt = p[4]>>2 & 0x7; s->pic_type = p[4]>>1 & 0x1; s->umv = p[4]>>0 & 0x1; s->sac = p[5]>>7 & 0x1; s->apm = p[5]>>6 & 0x1; s->pb = p[5]>>5 & 0x1; s->pquant = p[5]>>0 & 0x1f; s->cpm = p[6]>>7 & 0x1; s->pei = p[6]>>6 & 0x1; return 0; } /** * Copy H.263 bit-stream to H.263 RTP payload header * * @param hdr H.263 header to be written to * @param s H.263 stream header */ void h263_hdr_copy_strm(struct h263_hdr *hdr, const struct h263_strm *s) { hdr->f = 0; /* Mode A */ hdr->p = 0; hdr->sbit = 0; hdr->ebit = 0; hdr->src = s->src_fmt; hdr->i = s->pic_type; hdr->u = s->umv; hdr->s = s->sac; hdr->a = s->apm; hdr->r = 0; hdr->dbq = 0; /* No PB-frames */ hdr->trb = 0; /* No PB-frames */ hdr->tr = s->temp_ref; } baresip-1.0.0/modules/avcodec/h265.c000066400000000000000000000137131372575704200170620ustar00rootroot00000000000000/** * @file h265.c H.265 Video Codec -- protocol format * * Copyright (C) 2010 Creytiv.com */ #include #include #include #include #include "h26x.h" #include "avcodec.h" /* 1.1.4 NAL Unit Header HEVC maintains the NAL unit concept of H.264 with modifications. HEVC uses a two-byte NAL unit header, as shown in Figure 1. The payload of a NAL unit refers to the NAL unit excluding the NAL unit header. +---------------+---------------+ |0|1|2|3|4|5|6|7|0|1|2|3|4|5|6|7| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |F| Type | LayerId | TID | +-------------+-----------------+ Figure 1 The structure of HEVC NAL unit header */ void h265_nal_encode(uint8_t buf[2], unsigned nal_unit_type, unsigned nuh_temporal_id_plus1) { if (!buf) return; buf[0] = (nal_unit_type & 0x3f) << 1; buf[1] = nuh_temporal_id_plus1 & 0x07; } int h265_nal_encode_mbuf(struct mbuf *mb, const struct h265_nal *nal) { uint8_t buf[2]; h265_nal_encode(buf, nal->nal_unit_type, nal->nuh_temporal_id_plus1); return mbuf_write_mem(mb, buf, sizeof(buf)); } int h265_nal_decode(struct h265_nal *nal, const uint8_t *p) { bool forbidden_zero_bit; unsigned nuh_layer_id; if (!nal || !p) return EINVAL; forbidden_zero_bit = p[0] >> 7; nal->nal_unit_type = (p[0] >> 1) & 0x3f; nuh_layer_id = (p[0]&1)<<5 | p[1] >> 3; nal->nuh_temporal_id_plus1 = p[1] & 0x07; if (forbidden_zero_bit) { warning("h265: nal_decode: FORBIDDEN bit set\n"); return EBADMSG; } if (nuh_layer_id != 0) { warning("h265: nal_decode: LayerId MUST be zero\n"); return EBADMSG; } return 0; } void h265_nal_print(const struct h265_nal *nal) { re_printf("type=%u(%s), TID=%u\n", nal->nal_unit_type, h265_nalunit_name(nal->nal_unit_type), nal->nuh_temporal_id_plus1); } static const uint8_t sc3[3] = {0, 0, 1}; static const uint8_t sc4[4] = {0, 0, 0, 1}; const uint8_t *h265_find_startcode(const uint8_t *p, const uint8_t *end) { const uint8_t *a = p + 4 - ((long)p & 3); for (end -= 3; p < a && p < end; p++ ) { if (p[0] == 0 && p[1] == 0 && p[2] == 1) return p; } for (end -= 3; p < end; p += 4) { uint32_t x = *(const uint32_t*)(void *)p; if ( (x - 0x01010101) & (~x) & 0x80808080 ) { if (p[1] == 0 ) { if ( p[0] == 0 && p[2] == 1 ) return p; if ( p[2] == 0 && p[3] == 1 ) return p+1; } if ( p[3] == 0 ) { if ( p[2] == 0 && p[4] == 1 ) return p+2; if ( p[4] == 0 && p[5] == 1 ) return p+3; } } } for (end += 3; p < end; p++) { if (p[0] == 0 && p[1] == 0 && p[2] == 1) return p; } return end + 3; } void h265_skip_startcode(uint8_t **p, size_t *n) { if (*n < 4) return; if (0 == memcmp(*p, sc4, 4)) { (*p) += 4; *n -= 4; } else if (0 == memcmp(*p, sc3, 3)) { (*p) += 3; *n -= 3; } } bool h265_have_startcode(const uint8_t *p, size_t len) { if (len >= 4 && 0 == memcmp(p, sc4, 4)) return true; if (len >= 3 && 0 == memcmp(p, sc3, 3)) return true; return false; } bool h265_is_keyframe(enum h265_naltype type) { /* between 16 and 21 (inclusive) */ switch (type) { case H265_NAL_BLA_W_LP: case H265_NAL_BLA_W_RADL: case H265_NAL_BLA_N_LP: case H265_NAL_IDR_W_RADL: case H265_NAL_IDR_N_LP: case H265_NAL_CRA_NUT: return true; default: return false; } } const char *h265_nalunit_name(enum h265_naltype type) { switch (type) { /* VCL class */ case H265_NAL_TRAIL_N: return "TRAIL_N"; case H265_NAL_TRAIL_R: return "TRAIL_R"; case H265_NAL_TSA_N: return "TSA_N"; case H265_NAL_TSA_R: return "TSA_R"; case H265_NAL_RASL_N: return "RASL_N"; case H265_NAL_RASL_R: return "RASL_R"; case H265_NAL_BLA_W_LP: return "BLA_W_LP"; case H265_NAL_BLA_W_RADL: return "BLA_W_RADL"; case H265_NAL_BLA_N_LP: return "BLA_N_LP"; case H265_NAL_IDR_W_RADL: return "IDR_W_RADL"; case H265_NAL_IDR_N_LP: return "IDR_N_LP"; case H265_NAL_CRA_NUT: return "CRA_NUT"; /* non-VCL class */ case H265_NAL_VPS_NUT: return "VPS_NUT"; case H265_NAL_SPS_NUT: return "SPS_NUT"; case H265_NAL_PPS_NUT: return "PPS_NUT"; case H265_NAL_PREFIX_SEI_NUT: return "PREFIX_SEI_NUT"; case H265_NAL_SUFFIX_SEI_NUT: return "SUFFIX_SEI_NUT"; /* draft-ietf-payload-rtp-h265 */ case H265_NAL_AP: return "H265_NAL_AP"; case H265_NAL_FU: return "H265_NAL_FU"; } return "???"; } static inline int packetize(bool marker, const uint8_t *buf, size_t len, size_t maxlen, uint64_t rtp_ts, videnc_packet_h *pkth, void *arg) { int err = 0; if (len <= maxlen) { err = pkth(marker, rtp_ts, NULL, 0, buf, len, arg); } else { struct h265_nal nal; uint8_t fu_hdr[3]; const size_t flen = maxlen - sizeof(fu_hdr); err = h265_nal_decode(&nal, buf); if (err) { warning("h265: encode: could not decode" " NAL of %zu bytes (%m)\n", len, err); return err; } h265_nal_encode(fu_hdr, H265_NAL_FU, nal.nuh_temporal_id_plus1); fu_hdr[2] = 1<<7 | nal.nal_unit_type; buf+=2; len-=2; while (len > flen) { err |= pkth(false, rtp_ts, fu_hdr, 3, buf, flen, arg); buf += flen; len -= flen; fu_hdr[2] &= ~(1 << 7); /* clear Start bit */ } fu_hdr[2] |= 1<<6; /* set END bit */ err |= pkth(marker, rtp_ts, fu_hdr, 3, buf, len, arg); } return err; } int h265_packetize(uint64_t rtp_ts, const uint8_t *buf, size_t len, size_t pktsize, videnc_packet_h *pkth, void *arg) { const uint8_t *start = buf; const uint8_t *end = buf + len; const uint8_t *r; int err = 0; r = h265_find_startcode(start, end); while (r < end) { const uint8_t *r1; bool marker; /* skip zeros */ while (!*(r++)) ; r1 = h265_find_startcode(r, end); marker = (r1 >= end); err |= packetize(marker, r, r1-r, pktsize, rtp_ts, pkth, arg); r = r1; } return err; } baresip-1.0.0/modules/avcodec/h26x.h000066400000000000000000000115201372575704200171640ustar00rootroot00000000000000/** * @file h26x.h Interface to H.26x video codecs * * Copyright (C) 2010 Creytiv.com */ /* * H.263 */ enum h263_mode { H263_MODE_A, H263_MODE_B, H263_MODE_C }; enum { H263_HDR_SIZE_MODEA = 4, H263_HDR_SIZE_MODEB = 8, H263_HDR_SIZE_MODEC = 12 }; /** H.263 picture size format */ enum h263_fmt { H263_FMT_SQCIF = 1, /**< 128 x 96 */ H263_FMT_QCIF = 2, /**< 176 x 144 */ H263_FMT_CIF = 3, /**< 352 x 288 */ H263_FMT_4CIF = 4, /**< 704 x 576 */ H263_FMT_16CIF = 5, /**< 1408 x 1152 */ H263_FMT_OTHER = 7, }; /** * H.263 Header defined in RFC 2190 */ struct h263_hdr { /* common */ unsigned f:1; /**< 1 bit - Flag; 0=mode A, 1=mode B/C */ unsigned p:1; /**< 1 bit - PB-frames, 0=mode B, 1=mode C */ unsigned sbit:3; /**< 3 bits - Start Bit Position (SBIT) */ unsigned ebit:3; /**< 3 bits - End Bit Position (EBIT) */ unsigned src:3; /**< 3 bits - Source format */ /* mode A */ unsigned i:1; /**< 1 bit - 0=intra-coded, 1=inter-coded */ unsigned u:1; /**< 1 bit - Unrestricted Motion Vector */ unsigned s:1; /**< 1 bit - Syntax-based Arithmetic Coding */ unsigned a:1; /**< 1 bit - Advanced Prediction option */ unsigned r:4; /**< 4 bits - Reserved (zero) */ unsigned dbq:2; /**< 2 bits - DBQUANT */ unsigned trb:3; /**< 3 bits - Temporal Reference for B-frame */ unsigned tr:8; /**< 8 bits - Temporal Reference for P-frame */ /* mode B */ unsigned quant:5; //=0 for GOB header unsigned gobn:5; // gob number unsigned mba:9; // address unsigned hmv1:7; // horizontal motion vector unsigned vmv1:7; // vertical motion vector unsigned hmv2:7; unsigned vmv2:7; }; enum {I_FRAME=0, P_FRAME=1}; /** H.263 bit-stream header */ struct h263_strm { uint8_t psc[2]; /**< Picture Start Code (PSC) */ uint8_t temp_ref; /**< Temporal Reference */ unsigned split_scr:1; /**< Split Screen Indicator */ unsigned doc_camera:1; /**< Document Camera Indicator */ unsigned pic_frz_rel:1; /**< Full Picture Freeze Release */ unsigned src_fmt:3; /**< Source Format. 3=CIF */ unsigned pic_type:1; /**< Picture Coding Type. 0=I, 1=P */ unsigned umv:1; /**< Unrestricted Motion Vector mode */ unsigned sac:1; /**< Syntax-based Arithmetic Coding */ unsigned apm:1; /**< Advanced Prediction mode */ unsigned pb:1; /**< PB-frames mode */ unsigned pquant:5; /**< Quantizer Information */ unsigned cpm:1; /**< Continuous Presence Multipoint */ unsigned pei:1; /**< Extra Insertion Information */ /* H.263 bit-stream ... */ }; int h263_hdr_encode(const struct h263_hdr *hdr, struct mbuf *mb); int h263_hdr_decode(struct h263_hdr *hdr, struct mbuf *mb); enum h263_mode h263_hdr_mode(const struct h263_hdr *hdr); const uint8_t *h263_strm_find_psc(const uint8_t *p, uint32_t size); int h263_strm_decode(struct h263_strm *s, struct mbuf *mb); void h263_hdr_copy_strm(struct h263_hdr *hdr, const struct h263_strm *s); /* * H.265 format */ enum { H265_HDR_SIZE = 2 }; enum h265_naltype { /* VCL class */ H265_NAL_TRAIL_N = 0, H265_NAL_TRAIL_R = 1, H265_NAL_TSA_N = 2, H265_NAL_TSA_R = 3, H265_NAL_RASL_N = 8, H265_NAL_RASL_R = 9, H265_NAL_BLA_W_LP = 16, H265_NAL_BLA_W_RADL = 17, H265_NAL_BLA_N_LP = 18, H265_NAL_IDR_W_RADL = 19, H265_NAL_IDR_N_LP = 20, H265_NAL_CRA_NUT = 21, /* non-VCL class */ H265_NAL_VPS_NUT = 32, H265_NAL_SPS_NUT = 33, H265_NAL_PPS_NUT = 34, H265_NAL_PREFIX_SEI_NUT = 39, H265_NAL_SUFFIX_SEI_NUT = 40, /* draft-ietf-payload-rtp-h265 */ H265_NAL_AP = 48, /* Aggregation Packets */ H265_NAL_FU = 49, }; struct h265_nal { unsigned nal_unit_type:6; /* NAL unit type (0-40) */ unsigned nuh_temporal_id_plus1:3; /* temporal identifier plus 1 */ }; void h265_nal_encode(uint8_t buf[2], unsigned nal_unit_type, unsigned nuh_temporal_id_plus1); int h265_nal_encode_mbuf(struct mbuf *mb, const struct h265_nal *nal); int h265_nal_decode(struct h265_nal *nal, const uint8_t *p); void h265_nal_print(const struct h265_nal *nal); const uint8_t *h265_find_startcode(const uint8_t *p, const uint8_t *end); bool h265_have_startcode(const uint8_t *p, size_t len); void h265_skip_startcode(uint8_t **p, size_t *n); bool h265_is_keyframe(enum h265_naltype type); const char *h265_nalunit_name(enum h265_naltype type); int h265_packetize(uint64_t rtp_ts, const uint8_t *buf, size_t len, size_t pktsize, videnc_packet_h *pkth, void *arg); baresip-1.0.0/modules/avcodec/module.mk000066400000000000000000000005101372575704200200370ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # MOD := avcodec $(MOD)_SRCS += avcodec.c $(MOD)_SRCS += decode.c $(MOD)_SRCS += encode.c $(MOD)_SRCS += h263.c $(MOD)_SRCS += h265.c $(MOD)_SRCS += sdp.c $(MOD)_CFLAGS += -isystem /usr/local/include $(MOD)_LFLAGS += `pkg-config --libs libavcodec libavutil` include mk/mod.mk baresip-1.0.0/modules/avcodec/sdp.c000066400000000000000000000022231372575704200171560ustar00rootroot00000000000000/** * @file avcodec/sdp.c Video codecs using libavcodec -- SDP functions * * Copyright (C) 2010 Creytiv.com */ #include #include #include #include "avcodec.h" static const uint8_t h264_level_idc = 0x1f; uint32_t h264_packetization_mode(const char *fmtp) { struct pl pl, mode; if (!fmtp) return 0; pl_set_str(&pl, fmtp); if (fmt_param_get(&pl, "packetization-mode", &mode)) return pl_u32(&mode); return 0; } int avcodec_h264_fmtp_enc(struct mbuf *mb, const struct sdp_format *fmt, bool offer, void *arg) { struct vidcodec *vc = arg; const uint8_t profile_idc = 0x42; /* baseline profile */ const uint8_t profile_iop = 0xe0; (void)offer; if (!mb || !fmt || !vc) return 0; return mbuf_printf(mb, "a=fmtp:%s" " %s" ";profile-level-id=%02x%02x%02x" "\r\n", fmt->id, vc->variant, profile_idc, profile_iop, h264_level_idc); } bool avcodec_h264_fmtp_cmp(const char *lfmtp, const char *rfmtp, void *arg) { const struct vidcodec *vc = arg; (void)lfmtp; if (!vc) return false; return h264_packetization_mode(vc->variant) == h264_packetization_mode(rfmtp); } baresip-1.0.0/modules/avfilter/000077500000000000000000000000001372575704200164355ustar00rootroot00000000000000baresip-1.0.0/modules/avfilter/avfilter.c000066400000000000000000000057411372575704200204240ustar00rootroot00000000000000/** * @file avfilter.c Video filter using libavfilter * * Copyright (C) 2020 Mikhail Kurkov */ #include #include #include #include #include #include #include #include #include "avfilter.h" /** * @defgroup avfilter avfilter * * Video filters using libavfilter * * This module allows to dynamically apply complex video filter graphs * to outcoming stream using libavfilter from FFmpeg project. * * Commands: * \verbatim avfilter - Enable avfilter for outcoming stream avfilter - Disable avfilter \endverbatim * * Example: * \verbatim avfilter movie=watermark.png[pic];[in][pic]overlay=10:10[out] \endverbatim * * References: * * https://ffmpeg.org/ffmpeg-filters.html * */ static struct lock *lock; static char filter_descr[MAX_DESCR] = ""; static bool filter_updated = false; static void st_destructor(void *arg) { struct avfilter_st *st = arg; list_unlink(&st->vf.le); filter_reset(st); } static int update(struct vidfilt_enc_st **stp, void **ctx, const struct vidfilt *vf, struct vidfilt_prm *prm, const struct video *vid) { struct avfilter_st *st; (void)vid; if (!stp || !ctx || !vf || !prm) return EINVAL; if (*stp) return 0; st = mem_zalloc(sizeof(*st), st_destructor); if (!st) return ENOMEM; st->enabled = false; *stp = (struct vidfilt_enc_st *)st; return 0; } static int encode(struct vidfilt_enc_st *enc_st, struct vidframe *frame, uint64_t *timestamp) { struct avfilter_st *st = (struct avfilter_st *)enc_st; int err; if (!frame) return 0; lock_write_get(lock); if (filter_updated || !filter_valid(st, frame)) { filter_reset(st); filter_init(st, filter_descr, frame); } filter_updated = false; lock_rel(lock); err = filter_encode(st, frame, timestamp); return err; } static int avfilter_command(struct re_printf *pf, void *arg) { const struct cmd_arg *carg = arg; (void)pf; lock_write_get(lock); if (str_isset(carg->prm)) { str_ncpy(filter_descr, carg->prm, sizeof(filter_descr)); info("avfilter: enabled for %s\n", filter_descr); } else { str_ncpy(filter_descr, "", sizeof(filter_descr)); info("avfilter: disabled\n"); } filter_updated = true; lock_rel(lock); return 0; } static struct vidfilt avfilter = { .name = "avfilter", .ench = encode, .encupdh = update }; static const struct cmd cmdv[] = { {"avfilter", 0, CMD_PRM, "Start avfilter", avfilter_command} }; static int module_init(void) { int err; err = lock_alloc(&lock); if (err) return err; vidfilt_register(baresip_vidfiltl(), &avfilter); return cmd_register(baresip_commands(), cmdv, ARRAY_SIZE(cmdv)); } static int module_close(void) { lock = mem_deref(lock); vidfilt_unregister(&avfilter); cmd_unregister(baresip_commands(), cmdv); return 0; } EXPORT_SYM const struct mod_export DECL_EXPORTS(avfilter) = { "avfilter", "vidfilt", module_init, module_close }; baresip-1.0.0/modules/avfilter/avfilter.h000066400000000000000000000014261372575704200204250ustar00rootroot00000000000000/** * @file avfilter.h Video filter using libavfilter -- internal API * * Copyright (C) 2020 Mikhail Kurkov */ /* Maximum filter length */ #define MAX_DESCR 512 /* Filter state */ struct avfilter_st { struct vidfilt_enc_st vf; /* base class */ struct vidsz size; enum vidfmt format; bool enabled; AVFilterContext *buffersink_ctx; AVFilterContext *buffersrc_ctx; AVFilterGraph *filter_graph; AVFrame *vframe_in; AVFrame *vframe_out; }; /* * Filter API */ int filter_init(struct avfilter_st *st, const char *filter_descr, struct vidframe *frame); void filter_reset(struct avfilter_st *st); bool filter_valid(const struct avfilter_st *st, const struct vidframe *frame); int filter_encode(struct avfilter_st *st, struct vidframe *frame, uint64_t *timestamp); baresip-1.0.0/modules/avfilter/filter.c000066400000000000000000000114501372575704200200670ustar00rootroot00000000000000/** * @file avfilter/filter.c Video filter using libavfilter -- filtering * * Copyright (C) 2020 Mikhail Kurkov */ #include #include #include #include #include #include #include #include #include "avfilter.h" #include "util.h" int filter_init(struct avfilter_st *st, const char *filter_descr, struct vidframe *frame) { char args[512]; int err = 0; if (!str_isset(filter_descr)) { st->enabled = false; return 0; } const AVFilter *buffersrc = avfilter_get_by_name("buffer"); const AVFilter *buffersink = avfilter_get_by_name("buffersink"); AVFilterInOut *outputs = avfilter_inout_alloc(); AVFilterInOut *inputs = avfilter_inout_alloc(); enum AVPixelFormat src_format = vidfmt_to_avpixfmt(frame->fmt); enum AVPixelFormat pix_fmts[] = { src_format, AV_PIX_FMT_NONE }; st->filter_graph = avfilter_graph_alloc(); st->vframe_in = av_frame_alloc(); st->vframe_out = av_frame_alloc(); if (!outputs || !inputs || !st->filter_graph || !st->vframe_in || !st->vframe_out) { err = AVERROR(ENOMEM); goto end; } /* buffer video source */ snprintf(args, sizeof(args), "video_size=%dx%d:pix_fmt=%d:" "time_base=%d/%d:pixel_aspect=1/1", frame->size.w, frame->size.h, src_format, 1, VIDEO_TIMEBASE); err = avfilter_graph_create_filter( &st->buffersrc_ctx, buffersrc, "in", args, NULL, st->filter_graph); if (err < 0) { warning("avfilter: cannot create buffer source\n"); goto end; } /* buffer video sink: to terminate the filter chain. */ err = avfilter_graph_create_filter( &st->buffersink_ctx, buffersink, "out", NULL, NULL, st->filter_graph); if (err < 0) { warning("avfilter: cannot create buffer sink\n"); goto end; } err = av_opt_set_int_list( st->buffersink_ctx, "pix_fmts", pix_fmts, AV_PIX_FMT_NONE, AV_OPT_SEARCH_CHILDREN); if (err < 0) { warning("avfilter: cannot set output pixel format\n"); goto end; } outputs->name = av_strdup("in"); outputs->filter_ctx = st->buffersrc_ctx; outputs->pad_idx = 0; outputs->next = NULL; inputs->name = av_strdup("out"); inputs->filter_ctx = st->buffersink_ctx; inputs->pad_idx = 0; inputs->next = NULL; err = avfilter_graph_parse_ptr(st->filter_graph, filter_descr, &inputs, &outputs, NULL); if (err < 0) { warning("avfilter: error parsing filter description: %s\n", filter_descr); goto end; } err = avfilter_graph_config(st->filter_graph, NULL); if (err < 0) { warning("avfilter: filter graph config failed\n"); goto end; } st->size = frame->size; st->format = frame->fmt; st->enabled = true; info("avfilter: filter graph initialized for %s\n", filter_descr); end: avfilter_inout_free(&inputs); avfilter_inout_free(&outputs); return err; } void filter_reset(struct avfilter_st *st) { if (!st) return; if (!st->enabled) return; if (st->filter_graph) avfilter_graph_free(&st->filter_graph); if (st->vframe_in) av_frame_free(&st->vframe_in); if (st->vframe_out) av_frame_free(&st->vframe_out); st->enabled = false; info("avfilter: filter graph reset\n"); } bool filter_valid(const struct avfilter_st *st, const struct vidframe *frame) { bool res = !st->enabled || ((st->size.h == frame->size.h) && (st->size.w == frame->size.w) && (st->format == frame->fmt)); return res; } int filter_encode(struct avfilter_st *st, struct vidframe *frame, uint64_t *timestamp) { unsigned i; int err; if (!frame) return 0; if (!st->enabled) { return 0; } /* fill the source frame */ st->vframe_in->format = vidfmt_to_avpixfmt(frame->fmt); st->vframe_in->width = frame->size.w; st->vframe_in->height = frame->size.h; st->vframe_in->pts = *timestamp; for (i=0; i<4; i++) { st->vframe_in->data[i] = frame->data[i]; st->vframe_in->linesize[i] = frame->linesize[i]; } /* push source frame into the filter graph */ err = av_buffersrc_add_frame_flags( st->buffersrc_ctx, st->vframe_in, AV_BUFFERSRC_FLAG_KEEP_REF); if (err < 0) { warning("avfilter: error while feeding the filtergraph\n"); goto out; } /* pull filtered frames from the filtergraph */ av_frame_unref(st->vframe_out); err = av_buffersink_get_frame(st->buffersink_ctx, st->vframe_out); if (err == AVERROR(EAGAIN) || err == AVERROR_EOF) goto out; if (err < 0) { warning("avfilter: error while getting" " filtered frame from the filtergraph\n"); goto out; } avframe_ensure_topdown(st->vframe_out); /* Copy filtered frame back to the input frame */ for (i=0; i<4; i++) { frame->data[i] = st->vframe_out->data[i]; frame->linesize[i] = st->vframe_out->linesize[i]; } frame->size.h = st->vframe_out->height; frame->size.w = st->vframe_out->width; frame->fmt = avpixfmt_to_vidfmt(st->vframe_out->format); out: return err; } baresip-1.0.0/modules/avfilter/module.mk000066400000000000000000000003101372575704200202450ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2020 Mikhail Kurkov # MOD := avfilter $(MOD)_SRCS += avfilter.c $(MOD)_SRCS += filter.c $(MOD)_SRCS += util.c $(MOD)_LFLAGS += -lavfilter -lavutil include mk/mod.mk baresip-1.0.0/modules/avfilter/util.c000066400000000000000000000044541372575704200175650ustar00rootroot00000000000000/** * @file util.c Video filter using libavfilter -- utility functions * * Copyright (C) 2020 Mikhail Kurkov */ #include #include #include #include #include #include #include "util.h" static int swap_lines(uint8_t *a, uint8_t *b, uint8_t *tmp, size_t size) { memcpy(tmp, a, size); memcpy(a, b, size); memcpy(b, tmp, size); return 0; } static int reverse_lines(uint8_t *data, int linesize, int count) { size_t size = abs(linesize) * sizeof(uint8_t); uint8_t *tmp = malloc(size); if (!tmp) return ENOMEM; for (int i = 0; i < count/2; i++) swap_lines(data + linesize * i, data + linesize * (count - i - 1), tmp, size); free(tmp); return 0; } /* * Sometimes AVFrame contains planes with lines in bottom-up order. * Then linesize is negative and data points to the last row in buffer. * Baresip uses unsigned linesizes, lets reorder lines to fix it. */ int avframe_ensure_topdown(AVFrame *frame) { int i; if (!frame) return EINVAL; switch (frame->format) { case AV_PIX_FMT_YUV420P: for (i=0; i<4; i++) { int ls = frame->linesize[i]; if (ls >= 0) continue; int h = i == 0 ? frame->height : frame->height/2; reverse_lines(frame->data[i], ls, h); frame->data[i] = frame->data[i] + ls * (h - 1); frame->linesize[i] = abs(ls); } break; default: /* TODO support more formats */ for (i=0; i<4; i++) { if (frame->linesize[i] <0) { warning("avfilter: unsupported frame" " format with negative linesize: %d", frame->format); return EPROTO; } } } return 0; } enum AVPixelFormat vidfmt_to_avpixfmt(enum vidfmt fmt) { switch (fmt) { case VID_FMT_YUV420P: return AV_PIX_FMT_YUV420P; case VID_FMT_YUV444P: return AV_PIX_FMT_YUV444P; case VID_FMT_NV12: return AV_PIX_FMT_NV12; case VID_FMT_NV21: return AV_PIX_FMT_NV21; default: return AV_PIX_FMT_NONE; } } enum vidfmt avpixfmt_to_vidfmt(enum AVPixelFormat pix_fmt) { switch (pix_fmt) { case AV_PIX_FMT_YUV420P: return VID_FMT_YUV420P; case AV_PIX_FMT_YUVJ420P: return VID_FMT_YUV420P; case AV_PIX_FMT_YUV444P: return VID_FMT_YUV444P; case AV_PIX_FMT_NV12: return VID_FMT_NV12; case AV_PIX_FMT_NV21: return VID_FMT_NV21; default: return (enum vidfmt)-1; } } baresip-1.0.0/modules/avfilter/util.h000066400000000000000000000004271372575704200175660ustar00rootroot00000000000000/** * @file util.h Video filter using libavfilter -- utility functions * * Copyright (C) 2020 Mikhail Kurkov */ int avframe_ensure_topdown(AVFrame *frame); enum AVPixelFormat vidfmt_to_avpixfmt(enum vidfmt fmt); enum vidfmt avpixfmt_to_vidfmt(enum AVPixelFormat pix_fmt); baresip-1.0.0/modules/avformat/000077500000000000000000000000001372575704200164405ustar00rootroot00000000000000baresip-1.0.0/modules/avformat/audio.c000066400000000000000000000075341372575704200177160ustar00rootroot00000000000000/** * @file avformat/audio.c libavformat media-source -- audio * * Copyright (C) 2010 - 2020 Creytiv.com */ #include #include #include #include #include #include #include #include #include "mod_avformat.h" struct ausrc_st { const struct ausrc *as; /* base class */ struct shared *shared; struct ausrc_prm prm; SwrContext *swr; ausrc_read_h *readh; ausrc_error_h *errh; void *arg; }; static void audio_destructor(void *arg) { struct ausrc_st *st = arg; avformat_shared_set_audio(st->shared, NULL); mem_deref(st->shared); if (st->swr) swr_free(&st->swr); } static enum AVSampleFormat aufmt_to_avsampleformat(enum aufmt fmt) { switch (fmt) { case AUFMT_S16LE: return AV_SAMPLE_FMT_S16; case AUFMT_FLOAT: return AV_SAMPLE_FMT_FLT; default: return AV_SAMPLE_FMT_NONE; } } int avformat_audio_alloc(struct ausrc_st **stp, const struct ausrc *as, struct media_ctx **ctx, struct ausrc_prm *prm, const char *dev, ausrc_read_h *readh, ausrc_error_h *errh, void *arg) { struct ausrc_st *st; struct shared *sh; int err = 0; if (!stp || !as || !prm || !readh) return EINVAL; info("avformat: audio: loading input file '%s'\n", dev); st = mem_zalloc(sizeof(*st), audio_destructor); if (!st) return ENOMEM; st->as = as; st->readh = readh; st->errh = errh; st->arg = arg; st->prm = *prm; if (ctx && *ctx && (*ctx)->id && !strcmp((*ctx)->id, "avformat")) { st->shared = mem_ref(*ctx); } else { err = avformat_shared_alloc(&st->shared, dev, 0.0, NULL, false); if (err) goto out; if (ctx) *ctx = (struct media_ctx *)st->shared; } sh = st->shared; if (st->shared->au.idx < 0 || !st->shared->au.ctx) { info("avformat: audio: media file has no audio stream\n"); err = ENOENT; goto out; } st->swr = swr_alloc(); if (!st->swr) { err = ENOMEM; goto out; } avformat_shared_set_audio(st->shared, st); info("avformat: audio: converting %u/%u %s -> %u/%u %s\n", sh->au.ctx->sample_rate, sh->au.ctx->channels, av_get_sample_fmt_name(sh->au.ctx->sample_fmt), prm->srate, prm->ch, aufmt_name(prm->fmt)); out: if (err) mem_deref(st); else *stp = st; return err; } void avformat_audio_decode(struct shared *st, AVPacket *pkt) { AVFrame frame; AVFrame frame2; int ret; #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 37, 100) int got_frame; #endif if (!st || !st->au.ctx) return; memset(&frame, 0, sizeof(frame)); memset(&frame2, 0, sizeof(frame2)); #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 37, 100) ret = avcodec_send_packet(st->au.ctx, pkt); if (ret < 0) return; ret = avcodec_receive_frame(st->au.ctx, &frame); if (ret < 0) return; #else ret = avcodec_decode_audio4(st->au.ctx, &frame, &got_frame, pkt); if (ret < 0 || !got_frame) return; #endif /* NOTE: pass timestamp to application */ lock_read_get(st->lock); if (st->ausrc_st && st->ausrc_st->readh) { const AVRational tb = st->au.time_base; struct auframe af; frame.channel_layout = av_get_default_channel_layout(frame.channels); frame2.channels = st->ausrc_st->prm.ch; frame2.channel_layout = av_get_default_channel_layout(st->ausrc_st->prm.ch); frame2.sample_rate = st->ausrc_st->prm.srate; frame2.format = aufmt_to_avsampleformat(st->ausrc_st->prm.fmt); ret = swr_convert_frame(st->ausrc_st->swr, &frame2, &frame); if (ret) { warning("avformat: swr_convert_frame failed (%d)\n", ret); goto unlock; } auframe_init(&af, st->ausrc_st->prm.fmt, frame2.data[0], frame2.nb_samples * frame2.channels); af.timestamp = frame.pts * AUDIO_TIMEBASE * tb.num / tb.den; st->ausrc_st->readh(&af, st->ausrc_st->arg); } unlock: lock_rel(st->lock); av_frame_unref(&frame2); av_frame_unref(&frame); } baresip-1.0.0/modules/avformat/avformat.c000066400000000000000000000161701372575704200204300ustar00rootroot00000000000000/** * @file avformat.c libavformat media-source * * Copyright (C) 2010 - 2020 Creytiv.com */ #define _DEFAULT_SOURCE 1 #define _BSD_SOURCE 1 #include #include #include #include #include #include #include #include #include #include "mod_avformat.h" /** * @defgroup avformat avformat * * Audio/video source using FFmpeg libavformat * * * Example config: \verbatim audio_source avformat,/tmp/testfile.mp4 video_source avformat,/tmp/testfile.mp4 \endverbatim */ static struct ausrc *ausrc; static struct vidsrc *mod_avf; static void shared_destructor(void *arg) { struct shared *st = arg; if (st->run) { st->run = false; pthread_join(st->thread, NULL); } if (st->au.ctx) { avcodec_close(st->au.ctx); avcodec_free_context(&st->au.ctx); } if (st->vid.ctx) { avcodec_close(st->vid.ctx); avcodec_free_context(&st->vid.ctx); } if (st->ic) avformat_close_input(&st->ic); mem_deref(st->lock); } static void *read_thread(void *data) { struct shared *st = data; uint64_t now, offset = tmr_jiffies(); double auts = 0, vidts = 0; while (st->run) { AVPacket pkt; int ret; sys_msleep(4); now = tmr_jiffies(); for (;;) { double xts; if (!st->run) break; if (st->au.idx >=0 && st->vid.idx >=0) xts = min(auts, vidts); else if (st->au.idx >=0) xts = auts; else if (st->vid.idx >=0) xts = vidts; else break; if (!(st->is_realtime)) if (now < (offset + xts)) break; av_init_packet(&pkt); ret = av_read_frame(st->ic, &pkt); if (ret == (int)AVERROR_EOF) { debug("avformat: rewind stream\n"); sys_msleep(1000); ret = av_seek_frame(st->ic, -1, 0, AVSEEK_FLAG_BACKWARD); if (ret < 0) { info("avformat: seek error (%d)\n", ret); goto out; } offset = tmr_jiffies(); break; } else if (ret < 0) { debug("avformat: read error (%d)\n", ret); goto out; } if (pkt.stream_index == st->au.idx) { if (pkt.pts == AV_NOPTS_VALUE) { warning("no audio pts\n"); } auts = 1000 * pkt.pts * av_q2d(st->au.time_base); avformat_audio_decode(st, &pkt); } else if (pkt.stream_index == st->vid.idx) { if (pkt.pts == AV_NOPTS_VALUE) { warning("no video pts\n"); } vidts = 1000 * pkt.pts * av_q2d(st->vid.time_base); avformat_video_decode(st, &pkt); } av_packet_unref(&pkt); } } out: return NULL; } static int open_codec(struct stream *s, const struct AVStream *strm, int i, AVCodecContext *ctx) { AVCodec *codec; int ret; if (s->idx >= 0 || s->ctx) return 0; codec = avcodec_find_decoder(ctx->codec_id); if (!codec) { info("avformat: can't find codec %i\n", ctx->codec_id); return ENOENT; } ret = avcodec_open2(ctx, codec, NULL); if (ret < 0) { warning("avformat: error opening codec (%i)\n", ret); return ENOMEM; } s->time_base = strm->time_base; s->ctx = ctx; s->idx = i; debug("avformat: '%s' using decoder '%s' (%s)\n", av_get_media_type_string(ctx->codec_type), codec->name, codec->long_name); return 0; } int avformat_shared_alloc(struct shared **shp, const char *dev, const double fps, const struct vidsz *size, bool video) { struct shared *st; struct pl pl_fmt, pl_dev; char *device = NULL; AVInputFormat *input_format = NULL; AVDictionary *format_opts = NULL; char buf[16]; unsigned i; int err; int ret; if (!shp || !dev) return EINVAL; st = mem_zalloc(sizeof(*st), shared_destructor); if (!st) return ENOMEM; st->id = "avformat"; st->au.idx = -1; st->vid.idx = -1; if (0 == re_regex(dev, str_len(dev), "[^,]+,[^]+", &pl_fmt, &pl_dev)) { char format[32]; pl_strcpy(&pl_fmt, format, sizeof(format)); pl_strdup(&device, &pl_dev); dev = device; st->is_realtime = 0==strcmp(format, "avfoundation") || 0==strcmp(format, "android_camera") || 0==strcmp(format, "v4l2"); input_format = av_find_input_format(format); if (input_format) { debug("avformat: using format '%s' (%s)\n", input_format->name, input_format->long_name); } else { warning("avformat: input format not found (%s)\n", format); } } err = lock_alloc(&st->lock); if (err) goto out; if (video && size->w) { re_snprintf(buf, sizeof(buf), "%dx%d", size->w, size->h); ret = av_dict_set(&format_opts, "video_size", buf, 0); if (ret != 0) { warning("avformat: av_dict_set(video_size) failed" " (ret=%s)\n", av_err2str(ret)); err = ENOENT; goto out; } } if (video && fps) { re_snprintf(buf, sizeof(buf), "%2.f", fps); ret = av_dict_set(&format_opts, "framerate", buf, 0); if (ret != 0) { warning("avformat: av_dict_set(framerate) failed" " (ret=%s)\n", av_err2str(ret)); err = ENOENT; goto out; } } if (video && device) { ret = av_dict_set(&format_opts, "camera_index", device, 0); if (ret != 0) { warning("avformat: av_dict_set(camera_index) failed" " (ret=%s)\n", av_err2str(ret)); err = ENOENT; goto out; } } ret = avformat_open_input(&st->ic, dev, input_format, &format_opts); if (ret < 0) { warning("avformat: avformat_open_input(%s) failed (ret=%s)\n", dev, av_err2str(ret)); err = ENOENT; goto out; } for (i=0; iic->nb_streams; i++) { const struct AVStream *strm = st->ic->streams[i]; AVCodecContext *ctx; #if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 33, 100) ctx = avcodec_alloc_context3(NULL); if (!ctx) { err = ENOMEM; goto out; } ret = avcodec_parameters_to_context(ctx, strm->codecpar); if (ret < 0) { warning("avformat: avcodec_parameters_to_context\n"); err = EPROTO; goto out; } #else ctx = strm->codec; #endif switch (ctx->codec_type) { case AVMEDIA_TYPE_AUDIO: err = open_codec(&st->au, strm, i, ctx); if (err) goto out; break; case AVMEDIA_TYPE_VIDEO: err = open_codec(&st->vid, strm, i, ctx); if (err) goto out; break; default: break; } } st->run = true; err = pthread_create(&st->thread, NULL, read_thread, st); if (err) { st->run = false; goto out; } out: if (err) mem_deref(st); else *shp = st; mem_deref(device); av_dict_free(&format_opts); return err; } void avformat_shared_set_audio(struct shared *sh, struct ausrc_st *st) { if (!sh) return; lock_write_get(sh->lock); sh->ausrc_st = st; lock_rel(sh->lock); } void avformat_shared_set_video(struct shared *sh, struct vidsrc_st *st) { if (!sh) return; lock_write_get(sh->lock); sh->vidsrc_st = st; lock_rel(sh->lock); } static int module_init(void) { int err; avformat_network_init(); avdevice_register_all(); err = ausrc_register(&ausrc, baresip_ausrcl(), "avformat", avformat_audio_alloc); err |= vidsrc_register(&mod_avf, baresip_vidsrcl(), "avformat", avformat_video_alloc, NULL); return err; } static int module_close(void) { mod_avf = mem_deref(mod_avf); ausrc = mem_deref(ausrc); avformat_network_deinit(); return 0; } EXPORT_SYM const struct mod_export DECL_EXPORTS(avformat) = { "avformat", "avsrc", module_init, module_close }; baresip-1.0.0/modules/avformat/mod_avformat.h000066400000000000000000000024321372575704200212700ustar00rootroot00000000000000/** * @file mod_avformat.h libavformat media-source -- internal interface * * Copyright (C) 2010 - 2020 Creytiv.com */ struct shared { const char *id; struct ausrc_st *ausrc_st; /* pointer */ struct vidsrc_st *vidsrc_st; /* pointer */ struct lock *lock; AVFormatContext *ic; pthread_t thread; bool is_realtime; bool run; struct stream { AVRational time_base; AVCodecContext *ctx; int idx; } au, vid; }; int avformat_shared_alloc(struct shared **shp, const char *dev, const double fps, const struct vidsz *size, bool video); void avformat_shared_set_audio(struct shared *sh, struct ausrc_st *st); void avformat_shared_set_video(struct shared *sh, struct vidsrc_st *st); int avformat_audio_alloc(struct ausrc_st **stp, const struct ausrc *as, struct media_ctx **ctx, struct ausrc_prm *prm, const char *dev, ausrc_read_h *readh, ausrc_error_h *errh, void *arg); void avformat_audio_decode(struct shared *st, AVPacket *pkt); int avformat_video_alloc(struct vidsrc_st **stp, const struct vidsrc *vs, struct media_ctx **ctx, struct vidsrc_prm *prm, const struct vidsz *size, const char *fmt, const char *dev, vidsrc_frame_h *frameh, vidsrc_error_h *errorh, void *arg); void avformat_video_decode(struct shared *st, AVPacket *pkt); baresip-1.0.0/modules/avformat/module.mk000066400000000000000000000004521372575704200202570ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # MOD := avformat $(MOD)_SRCS += avformat.c $(MOD)_SRCS += audio.c $(MOD)_SRCS += video.c $(MOD)_LFLAGS += \ `pkg-config --libs libavformat libavcodec libswresample \ libavutil libavdevice libavfilter libswscale libpostproc` include mk/mod.mk baresip-1.0.0/modules/avformat/video.c000066400000000000000000000067471372575704200177300ustar00rootroot00000000000000/** * @file avformat/video.c libavformat media-source -- video * * Copyright (C) 2010 - 2020 Creytiv.com */ #include #include #include #include #include #include #include #include "mod_avformat.h" struct vidsrc_st { const struct vidsrc *vs; /* base class */ struct shared *shared; vidsrc_frame_h *frameh; void *arg; }; static void video_destructor(void *arg) { struct vidsrc_st *st = arg; avformat_shared_set_video(st->shared, NULL); mem_deref(st->shared); } static enum vidfmt avpixfmt_to_vidfmt(enum AVPixelFormat pix_fmt) { switch (pix_fmt) { case AV_PIX_FMT_YUV420P: return VID_FMT_YUV420P; case AV_PIX_FMT_YUVJ420P: return VID_FMT_YUV420P; case AV_PIX_FMT_YUV444P: return VID_FMT_YUV444P; case AV_PIX_FMT_NV12: return VID_FMT_NV12; case AV_PIX_FMT_NV21: return VID_FMT_NV21; case AV_PIX_FMT_UYVY422: return VID_FMT_UYVY422; case AV_PIX_FMT_YUYV422: return VID_FMT_YUYV422; default: return (enum vidfmt)-1; } } int avformat_video_alloc(struct vidsrc_st **stp, const struct vidsrc *vs, struct media_ctx **ctx, struct vidsrc_prm *prm, const struct vidsz *size, const char *fmt, const char *dev, vidsrc_frame_h *frameh, vidsrc_error_h *errorh, void *arg) { struct vidsrc_st *st; int err = 0; (void)fmt; (void)errorh; if (!stp || !vs || !prm || !size || !frameh) return EINVAL; debug("avformat: video: alloc dev='%s'\n", dev); st = mem_zalloc(sizeof(*st), video_destructor); if (!st) return ENOMEM; st->vs = vs; st->frameh = frameh; st->arg = arg; if (ctx && *ctx && (*ctx)->id && !strcmp((*ctx)->id, "avformat")) { st->shared = mem_ref(*ctx); } else { err = avformat_shared_alloc(&st->shared, dev, prm->fps, size, true); if (err) goto out; if (ctx) *ctx = (struct media_ctx *)st->shared; } if (st->shared->vid.idx < 0 || !st->shared->vid.ctx) { info("avformat: video: media file has no video stream\n"); err = ENOENT; goto out; } avformat_shared_set_video(st->shared, st); out: if (err) mem_deref(st); else *stp = st; return err; } void avformat_video_decode(struct shared *st, AVPacket *pkt) { AVRational tb; struct vidframe vf; AVFrame *frame; uint64_t timestamp; unsigned i; int ret; #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 37, 100) int got_pict; #endif if (!st || !st->vid.ctx) return; tb = st->vid.time_base; frame = av_frame_alloc(); if (!frame) return; #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 37, 100) ret = avcodec_send_packet(st->vid.ctx, pkt); if (ret < 0) goto out; ret = avcodec_receive_frame(st->vid.ctx, frame); if (ret < 0) goto out; #else ret = avcodec_decode_video2(st->vid.ctx, frame, &got_pict, pkt); if (ret < 0 || !got_pict) goto out; #endif vf.fmt = avpixfmt_to_vidfmt(frame->format); if (vf.fmt == (enum vidfmt)-1) { warning("avformat: decode: bad pixel format" " (%i) (%s)\n", frame->format, av_get_pix_fmt_name(frame->format)); goto out; } vf.size.w = st->vid.ctx->width; vf.size.h = st->vid.ctx->height; for (i=0; i<4; i++) { vf.data[i] = frame->data[i]; vf.linesize[i] = frame->linesize[i]; } /* convert timestamp */ timestamp = frame->pts * VIDEO_TIMEBASE * tb.num / tb.den; lock_read_get(st->lock); if (st->vidsrc_st && st->vidsrc_st->frameh) st->vidsrc_st->frameh(&vf, timestamp, st->vidsrc_st->arg); lock_rel(st->lock); out: if (frame) av_frame_free(&frame); } baresip-1.0.0/modules/b2bua/000077500000000000000000000000001372575704200156145ustar00rootroot00000000000000baresip-1.0.0/modules/b2bua/b2bua.c000066400000000000000000000115411372575704200167550ustar00rootroot00000000000000/** * @file b2bua.c Back-to-Back User-Agent (B2BUA) module * * Copyright (C) 2010 Creytiv.com */ #include #include /** * @defgroup b2bua b2bua * * Back-to-Back User-Agent (B2BUA) module * * NOTE: This module is experimental. * * N session objects * 1 session object has 2 call objects (left, right leg) */ struct session { struct le le; struct call *call_in, *call_out; }; static struct list sessionl; static struct ua *ua_in, *ua_out; static struct call *other_call(struct session *sess, const struct call *call) { if (sess->call_in == call) return sess->call_out; if (sess->call_out == call) return sess->call_in; return NULL; } static void destructor(void *arg) { struct session *sess = arg; debug("b2bua: session destroyed (in=%p, out=%p)\n", sess->call_in, sess->call_out); list_unlink(&sess->le); mem_deref(sess->call_out); mem_deref(sess->call_in); } static void call_event_handler(struct call *call, enum call_event ev, const char *str, void *arg) { struct session *sess = arg; struct call *call2 = other_call(sess, call); switch (ev) { case CALL_EVENT_ESTABLISHED: debug("b2bua: CALL_ESTABLISHED: peer_uri=%s\n", call_peeruri(call)); call_answer(call2, 200, call_has_video(call) ? VIDMODE_ON : VIDMODE_OFF); break; case CALL_EVENT_CLOSED: debug("b2bua: CALL_CLOSED: %s\n", str); call_hangup(call2, call_scode(call), ""); mem_deref(sess); break; default: break; } } static void call_dtmf_handler(struct call *call, char key, void *arg) { struct session *sess = arg; debug("b2bua: relaying DTMF event: key = '%c'\n", key ? key : '.'); call_send_digit(other_call(sess, call), key); } static int new_session(struct call *call) { struct session *sess; char a[64], b[64]; int err; sess = mem_zalloc(sizeof(*sess), destructor); if (!sess) return ENOMEM; sess->call_in = call; err = ua_connect(ua_out, &sess->call_out, call_peeruri(call), call_localuri(call), call_has_video(call) ? VIDMODE_ON : VIDMODE_OFF); if (err) { warning("b2bua: ua_connect failed (%m)\n", err); goto out; } re_snprintf(a, sizeof(a), "A-%x", sess); re_snprintf(b, sizeof(b), "B-%x", sess); /* connect the audio/video-bridge devices */ audio_set_devicename(call_audio(sess->call_in), a, b); audio_set_devicename(call_audio(sess->call_out), b, a); video_set_devicename(call_video(sess->call_in), a, b); video_set_devicename(call_video(sess->call_out), b, a); call_set_handlers(sess->call_in, call_event_handler, call_dtmf_handler, sess); call_set_handlers(sess->call_out, call_event_handler, call_dtmf_handler, sess); list_append(&sessionl, &sess->le, sess); out: if (err) mem_deref(sess); return err; } static void ua_event_handler(struct ua *ua, enum ua_event ev, struct call *call, const char *prm, void *arg) { int err; (void)ua; (void)prm; (void)arg; switch (ev) { case UA_EVENT_CALL_INCOMING: debug("b2bua: CALL_INCOMING: peer=%s --> local=%s\n", call_peeruri(call), call_localuri(call)); err = new_session(call); if (err) { call_hangup(call, 500, "Server Error"); } break; default: break; } } static int b2bua_status(struct re_printf *pf, void *arg) { struct le *le; int err = 0; (void)arg; err |= re_hprintf(pf, "B2BUA status:\n"); err |= re_hprintf(pf, " inbound: %s\n", ua_aor(ua_in)); err |= re_hprintf(pf, " outbound: %s\n", ua_aor(ua_out)); err |= re_hprintf(pf, "sessions:\n"); for (le = sessionl.head; le; le = le->next) { struct session *sess = le->data; err |= re_hprintf(pf, "%-42s ---> %42s\n", call_peeruri(sess->call_in), call_peeruri(sess->call_out)); err |= re_hprintf(pf, " %H\n", call_status, sess->call_in); err |= re_hprintf(pf, " %H\n", call_status, sess->call_out); } return err; } static const struct cmd cmdv[] = { {"b2bua", 0, 0, "b2bua status", b2bua_status }, }; static int module_init(void) { int err; ua_in = uag_find_param("b2bua", "inbound"); ua_out = uag_find_param("b2bua", "outbound"); if (!ua_in) { warning("b2bua: inbound UA not found\n"); return ENOENT; } if (!ua_out) { warning("b2bua: outbound UA not found\n"); return ENOENT; } err = cmd_register(baresip_commands(), cmdv, ARRAY_SIZE(cmdv)); if (err) return err; err = uag_event_register(ua_event_handler, NULL); if (err) return err; /* The inbound UA will handle all non-matching requests */ ua_set_catchall(ua_in, true); debug("b2bua: module loaded\n"); return 0; } static int module_close(void) { debug("b2bua: module closing..\n"); if (!list_isempty(&sessionl)) { info("b2bua: flushing %u sessions\n", list_count(&sessionl)); list_flush(&sessionl); } uag_event_unregister(ua_event_handler); cmd_unregister(baresip_commands(), cmdv); return 0; } const struct mod_export DECL_EXPORTS(b2bua) = { "b2bua", "application", module_init, module_close }; baresip-1.0.0/modules/b2bua/module.mk000066400000000000000000000001541372575704200174320ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # MOD := b2bua $(MOD)_SRCS += b2bua.c include mk/mod.mk baresip-1.0.0/modules/cairo/000077500000000000000000000000001372575704200157165ustar00rootroot00000000000000baresip-1.0.0/modules/cairo/cairo.c000066400000000000000000000152471372575704200171700ustar00rootroot00000000000000/** * @file cairo.c Cairo module * * Copyright (C) 2010 Creytiv.com */ #define _DEFAULT_SOURCE 1 #define _BSD_SOURCE 1 #include #include #include #include #include #include #include #if !defined (M_PI) #define M_PI 3.14159265358979323846264338327 #endif /** * @defgroup cairo cairo * * Cairo video-source module is a video generator for testing * and demo purposes. * * Note: This module is very experimental! * * Use Cairo library to draw graphics into a frame buffer */ enum { FONT_SIZE = 18 }; struct vidsrc_st { const struct vidsrc *vs; /* inheritance */ struct vidsrc_prm prm; struct vidsz size; cairo_surface_t *surface; cairo_t *cr; cairo_surface_t *surface_logo; cairo_t *cr_logo; double logo_width; double logo_height; double step; bool run; pthread_t thread; vidsrc_frame_h *frameh; void *arg; }; static struct vidsrc *vidsrc; static void destructor(void *arg) { struct vidsrc_st *st = arg; if (st->run) { st->run = false; pthread_join(st->thread, NULL); } if (st->cr) cairo_destroy(st->cr); if (st->surface) cairo_surface_destroy(st->surface); if (st->cr_logo) cairo_destroy(st->cr_logo); if (st->surface_logo) cairo_surface_destroy(st->surface_logo); } static void draw_background(cairo_t *cr, double color_step, int width, int height) { cairo_pattern_t *pat; double grey, r, g, b; grey = 0.1 + fabs(sin(3 * color_step)); r = grey; g = grey; b = grey; pat = cairo_pattern_create_linear (0.0, 0.0, 0.0, height); cairo_pattern_add_color_stop_rgba (pat, 1, r, g, b, 1); cairo_pattern_add_color_stop_rgba (pat, 0, 0, 0, 0, 1); cairo_rectangle (cr, 0, 0, width, height); cairo_set_source (cr, pat); cairo_fill (cr); cairo_pattern_destroy (pat); } static void draw_text(struct vidsrc_st *st, int x, int y, const char *fmt, ...) { char buf[4096] = ""; va_list ap; va_start(ap, fmt); (void)re_vsnprintf(buf, sizeof(buf), fmt, ap); va_end(ap); cairo_set_source_rgb(st->cr, 1.0, 1.0, 1.0); /* white */ cairo_set_font_size(st->cr, FONT_SIZE); cairo_move_to(st->cr, x, y); cairo_show_text(st->cr, buf); } static void draw_logo(struct vidsrc_st *st) { double x, y; x = (st->size.w - st->logo_width) * (sin(10 * st->step) + 1)/2; y = (st->size.h - st->logo_height)* (1 - fabs(sin(30 * st->step))); cairo_set_source_surface(st->cr, st->surface_logo, x, y); cairo_paint(st->cr); } static void process(struct vidsrc_st *st, uint64_t timestamp) { struct vidframe f; unsigned xoffs = 2, yoffs = 24; draw_background(st->cr, st->step, st->size.w, st->size.h); draw_text(st, xoffs, yoffs + FONT_SIZE, "%H", fmt_gmtime, NULL); draw_text(st, xoffs, yoffs + FONT_SIZE*2, "%u x %u @ %.2f fps", st->size.w, st->size.h, st->prm.fps); draw_text(st, xoffs, yoffs + FONT_SIZE*3, "Time: %.3f sec", timestamp / (double)VIDEO_TIMEBASE); draw_logo(st); st->step += 0.02 / st->prm.fps; vidframe_init_buf(&f, VID_FMT_RGB32, &st->size, cairo_image_surface_get_data(st->surface)); st->frameh(&f, timestamp, st->arg); } static void *read_thread(void *arg) { struct vidsrc_st *st = arg; uint64_t ts = 0, ts_start = 0; while (st->run) { uint64_t now; uint64_t timestamp; sys_msleep(2); now = tmr_jiffies(); if (!ts) { ts = ts_start = now; } if (ts > now) continue; timestamp = (ts - ts_start) * VIDEO_TIMEBASE / 1000; process(st, timestamp); ts += 1000/st->prm.fps; } return NULL; } static int load_logo(struct vidsrc_st *st, const char *filename) { cairo_surface_t *logo; double lw; double scale; int err = 0; logo = cairo_image_surface_create_from_png(filename); if (!logo) { warning("cairo: failed to load PNG logo\n"); err = ENOENT; goto out; } if (!cairo_image_surface_get_width(logo) || !cairo_image_surface_get_height(logo)) { warning("cairo: invalid logo (%s)\n", filename); err = ENOENT; goto out; } st->logo_width = st->size.w / 2; lw = cairo_image_surface_get_width(logo); scale = (double)st->logo_width / (double)lw; st->logo_height = cairo_image_surface_get_height(logo) * scale; /* create a scaled-down logo with same aspect ratio */ st->surface_logo = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, st->logo_width, st->logo_height); if (!st->surface_logo) { err = ENOMEM; goto out; } st->cr_logo = cairo_create(st->surface_logo); if (!st->cr_logo) { err = ENOMEM; goto out; } cairo_scale(st->cr_logo, scale, scale); cairo_set_source_surface(st->cr_logo, logo, 0, 0); cairo_paint(st->cr_logo); info("cairo: scaling logo '%s' from %d x %d to %.1f x %.1f\n", filename, cairo_image_surface_get_width(logo), cairo_image_surface_get_height(logo), st->logo_width, st->logo_height); out: if (logo) cairo_surface_destroy(logo); return err; } static int alloc(struct vidsrc_st **stp, const struct vidsrc *vs, struct media_ctx **ctx, struct vidsrc_prm *prm, const struct vidsz *size, const char *fmt, const char *dev, vidsrc_frame_h *frameh, vidsrc_error_h *errorh, void *arg) { struct config *cfg; struct vidsrc_st *st; char logo[256]; int err = 0; (void)ctx; (void)fmt; (void)dev; (void)errorh; if (!stp || !prm || !size || !frameh) return EINVAL; cfg = conf_config(); if (!cfg) return EINVAL; st = mem_zalloc(sizeof(*st), destructor); if (!st) return ENOMEM; st->vs = vs; st->frameh = frameh; st->arg = arg; st->prm = *prm; st->size = *size; st->surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, size->w, size->h); if (!st->surface) { err = ENOMEM; goto out; } st->cr = cairo_create(st->surface); if (!st->cr) { err = ENOMEM; goto out; } cairo_select_font_face(st->cr, "Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD); info("cairo: surface with format %d (%d x %d) stride=%d\n", cairo_image_surface_get_format(st->surface), cairo_image_surface_get_width(st->surface), cairo_image_surface_get_height(st->surface), cairo_image_surface_get_stride(st->surface)); st->step = rand_u16() / 1000.0; re_snprintf(logo, sizeof(logo), "%s/logo.png", cfg->audio.audio_path); err = load_logo(st, logo); if (err) { goto out; } st->run = true; err = pthread_create(&st->thread, NULL, read_thread, st); if (err) { st->run = false; goto out; } out: if (err) mem_deref(st); else *stp = st; return err; } static int module_init(void) { return vidsrc_register(&vidsrc, baresip_vidsrcl(), "cairo", alloc, NULL); } static int module_close(void) { vidsrc = mem_deref(vidsrc); return 0; } EXPORT_SYM const struct mod_export DECL_EXPORTS(cairo) = { "cairo", "vidsrc", module_init, module_close }; baresip-1.0.0/modules/cairo/module.mk000066400000000000000000000003221372575704200175310ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # MOD := cairo $(MOD)_SRCS += cairo.c $(MOD)_LFLAGS += $(shell pkg-config --libs cairo) $(MOD)_CFLAGS += $(shell pkg-config --cflags cairo) include mk/mod.mk baresip-1.0.0/modules/codec2/000077500000000000000000000000001372575704200157605ustar00rootroot00000000000000baresip-1.0.0/modules/codec2/codec2.c000066400000000000000000000066221372575704200172710ustar00rootroot00000000000000/** * @file codec2.c CODEC2 audio codec * * Copyright (C) 2015 Creytiv.com */ #include #include #include #include /** * @defgroup codec2 codec2 * * The CODEC2 low-bitrate speech audio codec * * https://en.wikipedia.org/wiki/Codec2 */ struct auenc_state { struct CODEC2 *c2; }; struct audec_state { struct CODEC2 *c2; }; static uint32_t codec2_mode = CODEC2_MODE_2400; static void encode_destructor(void *data) { struct auenc_state *st = data; if (st->c2) codec2_destroy(st->c2); } static int encode_update(struct auenc_state **aesp, const struct aucodec *ac, struct auenc_param *prm, const char *fmtp) { struct auenc_state *st; int err = 0; (void)prm; (void)fmtp; if (!aesp || !ac) return EINVAL; if (*aesp) return 0; st = mem_zalloc(sizeof(*st), encode_destructor); if (!st) return ENOMEM; st->c2 = codec2_create(codec2_mode); if (!st->c2) { err = ENOMEM; goto out; } info("codec2: %d samples per frame, %d bits per frame\n", codec2_samples_per_frame(st->c2), codec2_bits_per_frame(st->c2)); out: if (err) mem_deref(st); else *aesp = st; return err; } static void decode_destructor(void *data) { struct audec_state *st = data; if (st->c2) codec2_destroy(st->c2); } static int decode_update(struct audec_state **adsp, const struct aucodec *ac, const char *fmtp) { struct audec_state *st; int err = 0; (void)fmtp; if (!adsp || !ac) return EINVAL; if (*adsp) return 0; st = mem_zalloc(sizeof(*st), decode_destructor); if (!st) return ENOMEM; st->c2 = codec2_create(codec2_mode); if (!st->c2) { err = ENOMEM; goto out; } out: if (err) mem_deref(st); else *adsp = st; return err; } static int encode(struct auenc_state *aes, bool *marker, uint8_t *buf, size_t *len, int fmt, const void *sampv, size_t sampc) { size_t bytes_per_frame; (void)marker; if (!buf || !len || !sampv) return EINVAL; bytes_per_frame = (codec2_bits_per_frame(aes->c2) + 7) / 8; if (*len < bytes_per_frame) return ENOMEM; if (sampc != (size_t)codec2_samples_per_frame(aes->c2)) return EPROTO; if (fmt != AUFMT_S16LE) return ENOTSUP; codec2_encode(aes->c2, buf, (short *)sampv); *len = bytes_per_frame; return 0; } static int decode(struct audec_state *ads, int fmt, void *sampv, size_t *sampc, bool marker, const uint8_t *buf, size_t len) { size_t bytes_per_frame; (void)marker; if (!sampv || !sampc || !buf) return EINVAL; bytes_per_frame = (codec2_bits_per_frame(ads->c2) + 7) / 8; if (*sampc < (size_t)codec2_samples_per_frame(ads->c2)) return ENOMEM; if (len < bytes_per_frame) return EPROTO; if (fmt != AUFMT_S16LE) return ENOTSUP; codec2_decode(ads->c2, sampv, buf); *sampc = codec2_samples_per_frame(ads->c2); return 0; } static struct aucodec codec2 = { .name = "CODEC2", .srate = 8000, .crate = 8000, .ch = 1, .pch = 1, .encupdh = encode_update, .ench = encode, .decupdh = decode_update, .dech = decode, }; static int module_init(void) { conf_get_u32(conf_cur(), "codec2_mode", &codec2_mode); info("codec2: using mode %d\n", codec2_mode); aucodec_register(baresip_aucodecl(), &codec2); return 0; } static int module_close(void) { aucodec_unregister(&codec2); return 0; } EXPORT_SYM const struct mod_export DECL_EXPORTS(codec2) = { "codec2", "audio codec", module_init, module_close, }; baresip-1.0.0/modules/codec2/module.mk000066400000000000000000000002101372575704200175670ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # MOD := codec2 $(MOD)_SRCS += codec2.c $(MOD)_LFLAGS += -lcodec2 include mk/mod.mk baresip-1.0.0/modules/cons/000077500000000000000000000000001372575704200155635ustar00rootroot00000000000000baresip-1.0.0/modules/cons/cons.c000066400000000000000000000103241372575704200166710ustar00rootroot00000000000000/** * @file cons.c Socket-based command-line console * * Copyright (C) 2010 Creytiv.com */ #include #include /** * @defgroup cons cons * * Console User-Interface (UI) using UDP/TCP sockets * * * This module implements a simple console for connecting to Baresip via * UDP or TCP-based sockets. You can use programs like telnet or netcat to * connect to the command-line interface. * * Example, with the cons-module listening on default port 5555: * \verbatim $ netcat -u 127.0.0.1 5555 \endverbatim * * The following options can be configured: * \verbatim cons_listen 0.0.0.0:5555 # IP-address and port to listen on \endverbatim */ enum {CONS_PORT = 5555}; struct ui_st { struct udp_sock *us; struct tcp_sock *ts; struct tcp_conn *tc; struct sa udp_peer; }; static struct ui_st *cons = NULL; /* allow only one instance */ static int print_handler(const char *p, size_t size, void *arg) { return mbuf_write_mem(arg, (uint8_t *)p, size); } static void udp_recv(const struct sa *src, struct mbuf *mb, void *arg) { struct ui_st *st = arg; struct mbuf *mbr = mbuf_alloc(64); struct re_printf pf; st->udp_peer = *src; pf.vph = print_handler; pf.arg = mbr; while (mbuf_get_left(mb)) { char ch = mbuf_read_u8(mb); if (ch == '\r') ch = '\n'; ui_input_key(baresip_uis(), ch, &pf); } if (mbr->end > 0) { mbr->pos = 0; (void)udp_send(st->us, src, mbr); } mem_deref(mbr); } static void cons_destructor(void *arg) { struct ui_st *st = arg; mem_deref(st->us); mem_deref(st->tc); mem_deref(st->ts); } static int tcp_write_handler(const char *p, size_t size, void *arg) { struct mbuf mb; mb.buf = (uint8_t *)p; mb.pos = 0; mb.end = mb.size = size; return tcp_send(arg, &mb); } static void tcp_recv_handler(struct mbuf *mb, void *arg) { struct ui_st *st = arg; struct re_printf pf; pf.vph = tcp_write_handler; pf.arg = st->tc; while (mbuf_get_left(mb) > 0) { char ch = mbuf_read_u8(mb); if (ch == '\r') ch = '\n'; ui_input_key(baresip_uis(), ch, &pf); } } static void tcp_close_handler(int err, void *arg) { struct ui_st *st = arg; (void)err; st->tc = mem_deref(st->tc); } static void tcp_conn_handler(const struct sa *peer, void *arg) { struct ui_st *st = arg; (void)peer; /* only one connection allowed */ st->tc = mem_deref(st->tc); (void)tcp_accept(&st->tc, st->ts, NULL, tcp_recv_handler, tcp_close_handler, st); } static int cons_alloc(struct ui_st **stp, const struct sa *laddr) { struct ui_st *st; int err; if (!stp) return EINVAL; st = mem_zalloc(sizeof(*st), cons_destructor); if (!st) return ENOMEM; err = udp_listen(&st->us, laddr, udp_recv, st); if (err) { warning("cons: failed to listen on UDP %J (%m)\n", laddr, err); goto out; } err = tcp_listen(&st->ts, laddr, tcp_conn_handler, st); if (err) { warning("cons: failed to listen on TCP %J (%m)\n", laddr, err); goto out; } debug("cons: UI console listening on %J\n", laddr); out: if (err) mem_deref(st); else *stp = st; return err; } static int output_handler(const char *str) { struct mbuf *mb; int err = 0; if (!str) return EINVAL; mb = mbuf_alloc(256); if (!mb) return ENOMEM; mbuf_write_str(mb, str); if (sa_isset(&cons->udp_peer, SA_ALL)) { mb->pos = 0; err |= udp_send(cons->us, &cons->udp_peer, mb); } if (cons->tc) { mb->pos = 0; err |= tcp_send(cons->tc, mb); } mem_deref(mb); return err; } /* * Relay log-messages to all active UDP/TCP connections */ static void log_handler(uint32_t level, const char *msg) { (void)level; output_handler(msg); } static struct ui ui_cons = { .name = "cons", .outputh = output_handler }; static struct log lg = { .h = log_handler, }; static int cons_init(void) { struct sa laddr; int err; if (conf_get_sa(conf_cur(), "cons_listen", &laddr)) { sa_set_str(&laddr, "0.0.0.0", CONS_PORT); } err = cons_alloc(&cons, &laddr); if (err) return err; ui_register(baresip_uis(), &ui_cons); log_register_handler(&lg); return 0; } static int cons_close(void) { log_unregister_handler(&lg); ui_unregister(&ui_cons); cons = mem_deref(cons); return 0; } const struct mod_export DECL_EXPORTS(cons) = { "cons", "ui", cons_init, cons_close }; baresip-1.0.0/modules/cons/module.mk000066400000000000000000000001521372575704200173770ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # MOD := cons $(MOD)_SRCS += cons.c include mk/mod.mk baresip-1.0.0/modules/contact/000077500000000000000000000000001372575704200162545ustar00rootroot00000000000000baresip-1.0.0/modules/contact/contact.c000066400000000000000000000147621372575704200200650ustar00rootroot00000000000000/** * @file modules/contact/contact.c Contacts module * * Copyright (C) 2010 - 2015 Creytiv.com */ #include #include #include /** * @defgroup contact contact * * Contact module reading contacts from a file * * - read contact entries from ~/.baresip/contacts * - populate local database of contacts */ static int confline_handler(const struct pl *addr, void *arg) { struct contacts *contacts = arg; return contact_add(contacts, NULL, addr); } static int print_contacts(struct re_printf *pf, void *unused) { (void)unused; return contacts_print(pf, baresip_contacts()); } static int save_current(const struct contact *cnt) { char path[256] = "", file[256] = ""; FILE *f = NULL; int err; err = conf_path_get(path, sizeof(path)); if (err) return err; if (re_snprintf(file, sizeof(file), "%s/current_contact", path) < 0) return ENOMEM; f = fopen(file, "w"); if (!f) return errno; if (re_fprintf(f, "%s", contact_uri(cnt)) < 0) { err = errno; goto out; } out: if (f) (void)fclose(f); return err; } static void send_resp_handler(int err, const struct sip_msg *msg, void *arg) { (void)arg; if (err) { (void)re_fprintf(stderr, " \x1b[31m%m\x1b[;m\n", err); return; } if (msg->scode >= 300) { (void)re_fprintf(stderr, " \x1b[31m%u %r\x1b[;m\n", msg->scode, &msg->reason); } } static int cmd_dial_contact(struct re_printf *pf, void *arg) { struct contact *cnt; const char *uri; int err = 0; (void)arg; cnt = contacts_current(baresip_contacts()); if (!cnt) { return re_hprintf(pf, "contact: current contact not set\n"); } uri = contact_uri(cnt); err = ua_connect(uag_current(), NULL, NULL, uri, VIDMODE_ON); if (err) { warning("contact: ua_connect(%s) failed: %m\n", uri, err); } return 0; } static int cmd_message(struct re_printf *pf, void *arg) { const struct cmd_arg *carg = arg; struct contact *cnt; const char *uri; int err = 0; cnt = contacts_current(baresip_contacts()); if (!cnt) { return re_hprintf(pf, "contact: current contact not set\n"); } uri = contact_uri(cnt); err = message_send(uag_current(), uri, carg->prm, send_resp_handler, NULL); if (err) { (void)re_hprintf(pf, "contact: message_send(%s) failed (%m)\n", uri, err); } return err; } static int load_current_contact(struct contacts *contacts, const char *path) { char file[256] = ""; char buf[1024]; struct contact *cnt = NULL; struct sip_addr addr; struct pl pl; FILE *f = NULL; int err = 0; if (re_snprintf(file, sizeof(file), "%s/current_contact", path) < 0) return ENOMEM; if (conf_fileexist(file)) { f = fopen(file, "r"); if (!f) return errno; if (!fgets(buf, (int)sizeof(buf), f)) { err = errno; goto out; } pl_set_str(&pl, buf); if (0 == sip_addr_decode(&addr, &pl)) pl_strcpy(&addr.auri, buf, sizeof(buf)); cnt = contact_find(contacts, buf); if (!cnt) { info("contact from disk not found (%s)\n", buf); } } if (!cnt) { cnt = list_ledata(list_head(contact_list(contacts))); err = save_current(cnt); if (err) goto out; } if (cnt) contacts_set_current(contacts, cnt); out: if (f) (void)fclose(f); return err; } static int cycle_current(struct re_printf *pf, bool next) { struct contacts *contacts = baresip_contacts(); struct contact *cnt; struct le *le; int err; cnt = contacts_current(contacts); if (cnt) { le = contact_le(cnt); if (next) le = le->next ? le->next : le; else le = le->prev ? le->prev : le; } else { /* No current contact, set the first one */ le = list_head(contact_list(contacts)); if (!le) return re_hprintf(pf, "(no contacts)\n"); } cnt = list_ledata(le); contacts_set_current(contacts, cnt); re_hprintf(pf, "Current contact: %H\n", contact_print, cnt); err = save_current(cnt); if (err) { warning("contact: failed to save" " current contact (%m)\n", err); } return 0; } static int cmd_current_prev(struct re_printf *pf, void *arg) { (void)arg; return cycle_current(pf, false); } static int cmd_current_next(struct re_printf *pf, void *arg) { (void)arg; return cycle_current(pf, true); } static const struct cmd cmdv[] = { {"contacts", 'C', 0, "List contacts", print_contacts }, {"dialcontact", 'D', 0, "Dial current contact", cmd_dial_contact }, {"message", 'M', CMD_PRM, "Message current contact",cmd_message }, {"contact_prev", '<', 0, "Set previous contact", cmd_current_prev }, {"contact_next", '>', 0, "Set next contact", cmd_current_next }, }; static int write_template(const char *file) { const char *user, *domain; FILE *f = NULL; info("contact: creating contacts template %s\n", file); f = fopen(file, "w"); if (!f) return errno; user = sys_username(); if (!user) user = "user"; domain = net_domain(baresip_network()); if (!domain) domain = "domain"; (void)re_fprintf(f, "#\n" "# SIP contacts\n" "#\n" "# Displayname ;addr-params\n" "#\n" "# addr-params:\n" "# ;presence={none,p2p}\n" "# ;access={allow,block}\n" "#\n" "\n" "\n" "\"Echo Server\" \n" "\"%s\" ;presence=p2p\n" "\n" "# Access rules\n" "#\"Catch All\" ;access=block\n" "\"Good Friend\" ;access=allow\n" "\n" , user, user, domain); if (f) (void)fclose(f); return 0; } static int module_init(void) { struct contacts *contacts = baresip_contacts(); char path[256] = "", file[256] = ""; int err; err = conf_path_get(path, sizeof(path)); if (err) return err; if (re_snprintf(file, sizeof(file), "%s/contacts", path) < 0) return ENOMEM; if (!conf_fileexist(file)) { (void)fs_mkdir(path, 0700); err = write_template(file); if (err) return err; } err = conf_parse(file, confline_handler, contacts); if (err) return err; err = cmd_register(baresip_commands(), cmdv, ARRAY_SIZE(cmdv)); if (err) return err; info("Populated %u contacts\n", list_count(contact_list(contacts))); /* Load current contact after list was populated */ if (!list_isempty(contact_list(contacts))) { err = load_current_contact(contacts, path); if (err) { warning("could not load current contact (%m)\n", err); err = 0; } } return err; } static int module_close(void) { cmd_unregister(baresip_commands(), cmdv); list_flush(contact_list(baresip_contacts())); return 0; } const struct mod_export DECL_EXPORTS(contact) = { "contact", "application", module_init, module_close }; baresip-1.0.0/modules/contact/module.mk000066400000000000000000000001601372575704200200670ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # MOD := contact $(MOD)_SRCS += contact.c include mk/mod.mk baresip-1.0.0/modules/coreaudio/000077500000000000000000000000001372575704200165735ustar00rootroot00000000000000baresip-1.0.0/modules/coreaudio/coreaudio.c000066400000000000000000000107521372575704200207160ustar00rootroot00000000000000/** * @file coreaudio.c Apple Coreaudio sound driver * * Copyright (C) 2010 Creytiv.com */ #include #include #include #include #include "coreaudio.h" /** * @defgroup coreaudio coreaudio * * Audio driver module for OSX CoreAudio */ static struct auplay *auplay; static struct ausrc *ausrc; int coreaudio_enum_devices(const char *name, struct list *dev_list, CFStringRef *uid, Boolean is_input) { AudioObjectPropertyAddress propertyAddress = { kAudioHardwarePropertyDevices, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster }; AudioDeviceID *audioDevices = NULL; UInt32 dataSize = 0; UInt32 deviceCount; OSStatus status; int err = 0; if (!dev_list && !uid) return EINVAL; if (uid) { *uid = NULL; if (!str_isset(name)) return 0; } status = AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &propertyAddress, 0, NULL, &dataSize); if (kAudioHardwareNoError != status) { warning("AudioObjectGetPropertyDataSize" " (kAudioHardwarePropertyDevices) failed: %i\n", status); err = ENODEV; goto out; } deviceCount = dataSize / sizeof(AudioDeviceID); audioDevices = mem_zalloc(dataSize, NULL); if (NULL == audioDevices) { err = ENOMEM; goto out; } status = AudioObjectGetPropertyData(kAudioObjectSystemObject, &propertyAddress, 0, NULL, &dataSize, audioDevices); if (kAudioHardwareNoError != status) { warning("AudioObjectGetPropertyData" " (kAudioHardwarePropertyDevices) failed: %i\n", status); err = ENODEV; goto out; } if (is_input) propertyAddress.mScope = kAudioDevicePropertyScopeInput; else propertyAddress.mScope = kAudioDevicePropertyScopeOutput; for (UInt32 i = 0; i < deviceCount; ++i) { CFStringRef deviceUID = NULL; CFStringRef deviceName = NULL; const char *name_str; /* fallback if CFStringGetCStringPtr fails */ char name_buf[64]; propertyAddress.mSelector = kAudioDevicePropertyStreams; status = AudioObjectGetPropertyDataSize(audioDevices[i], &propertyAddress, 0, NULL, &dataSize); if (dataSize == 0) continue; dataSize = sizeof(deviceUID); propertyAddress.mSelector = kAudioDevicePropertyDeviceUID; status = AudioObjectGetPropertyData(audioDevices[i], &propertyAddress, 0, NULL, &dataSize, &deviceUID); if (kAudioHardwareNoError != status) { warning("AudioObjectGetPropertyData" " (kAudioDevicePropertyDeviceUID) " "failed: %i\n", status); continue; } dataSize = sizeof(deviceName); propertyAddress.mSelector = kAudioDevicePropertyDeviceNameCFString; status = AudioObjectGetPropertyData(audioDevices[i], &propertyAddress, 0, NULL, &dataSize, &deviceName); if (kAudioHardwareNoError != status) { warning("AudioObjectGetPropertyData" " (kAudioDevicePropertyDeviceNameCFString)" " failed: %i\n", status); continue; } name_str = CFStringGetCStringPtr(deviceName, kCFStringEncodingUTF8); /* CFStringGetCStringPtr can and does fail * (documented behavior) */ if (0 == name_str) { if (!CFStringGetCString(deviceName, name_buf, sizeof(name_buf), kCFStringEncodingUTF8)) { warning("CFStringGetCString " " failed: %i\n", status); continue; } name_str = name_buf; } if (uid) { if (0 == str_casecmp(name, name_str)) { *uid = deviceUID; break; } } else { err = mediadev_add(dev_list, name_str); if (err) break; } } out: mem_deref(audioDevices); return err; } uint32_t coreaudio_aufmt_to_formatflags(enum aufmt fmt) { switch (fmt) { case AUFMT_S16LE: return kLinearPCMFormatFlagIsSignedInteger; case AUFMT_S24_3LE:return kLinearPCMFormatFlagIsSignedInteger; case AUFMT_FLOAT: return kLinearPCMFormatFlagIsFloat; default: return 0; } } static int module_init(void) { int err; err = auplay_register(&auplay, baresip_auplayl(), "coreaudio", coreaudio_player_alloc); err |= ausrc_register(&ausrc, baresip_ausrcl(), "coreaudio", coreaudio_recorder_alloc); if (err) return err; err = coreaudio_player_init(auplay); err |= coreaudio_recorder_init(ausrc); return err; } static int module_close(void) { auplay = mem_deref(auplay); ausrc = mem_deref(ausrc); return 0; } EXPORT_SYM const struct mod_export DECL_EXPORTS(coreaudio) = { "coreaudio", "audio", module_init, module_close, }; baresip-1.0.0/modules/coreaudio/coreaudio.h000066400000000000000000000013661372575704200207240ustar00rootroot00000000000000/** * @file coreaudio.h Apple Coreaudio sound driver -- internal API * * Copyright (C) 2010 Creytiv.com */ int coreaudio_player_alloc(struct auplay_st **stp, const struct auplay *ap, struct auplay_prm *prm, const char *device, auplay_write_h *wh, void *arg); int coreaudio_recorder_alloc(struct ausrc_st **stp, const struct ausrc *as, struct media_ctx **ctx, struct ausrc_prm *prm, const char *device, ausrc_read_h *rh, ausrc_error_h *errh, void *arg); int coreaudio_enum_devices(const char *name, struct list *dev_list, CFStringRef *uid, Boolean is_input); uint32_t coreaudio_aufmt_to_formatflags(enum aufmt fmt); int coreaudio_player_init(struct auplay *ap); int coreaudio_recorder_init(struct ausrc *as); baresip-1.0.0/modules/coreaudio/module.mk000066400000000000000000000003441372575704200204120ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # MOD := coreaudio $(MOD)_SRCS += coreaudio.c $(MOD)_SRCS += player.c $(MOD)_SRCS += recorder.c $(MOD)_LFLAGS += -framework CoreAudio -framework AudioToolbox include mk/mod.mk baresip-1.0.0/modules/coreaudio/player.c000066400000000000000000000100621372575704200202320ustar00rootroot00000000000000/** * @file coreaudio/player.c Apple Coreaudio sound driver - player * * Copyright (C) 2010 Creytiv.com */ #include #include #include #include #include #include "coreaudio.h" /* This value can be tuned */ #define BUFC 6 struct auplay_st { const struct auplay *ap; /* inheritance */ AudioQueueRef queue; AudioQueueBufferRef buf[BUFC]; pthread_mutex_t mutex; uint32_t sampsz; auplay_write_h *wh; void *arg; }; static void auplay_destructor(void *arg) { struct auplay_st *st = arg; uint32_t i; pthread_mutex_lock(&st->mutex); st->wh = NULL; pthread_mutex_unlock(&st->mutex); if (st->queue) { AudioQueuePause(st->queue); AudioQueueStop(st->queue, true); for (i=0; ibuf); i++) if (st->buf[i]) AudioQueueFreeBuffer(st->queue, st->buf[i]); AudioQueueDispose(st->queue, true); } pthread_mutex_destroy(&st->mutex); } static void play_handler(void *userData, AudioQueueRef outQ, AudioQueueBufferRef outQB) { struct auplay_st *st = userData; auplay_write_h *wh; void *arg; pthread_mutex_lock(&st->mutex); wh = st->wh; arg = st->arg; pthread_mutex_unlock(&st->mutex); if (!wh) return; wh(outQB->mAudioData, outQB->mAudioDataByteSize/st->sampsz, arg); AudioQueueEnqueueBuffer(outQ, outQB, 0, NULL); } int coreaudio_player_alloc(struct auplay_st **stp, const struct auplay *ap, struct auplay_prm *prm, const char *device, auplay_write_h *wh, void *arg) { AudioStreamBasicDescription fmt; struct auplay_st *st; uint32_t sampc, bytc, i; OSStatus status; int err; if (!stp || !ap || !prm) return EINVAL; st = mem_zalloc(sizeof(*st), auplay_destructor); if (!st) return ENOMEM; st->ap = ap; st->wh = wh; st->arg = arg; st->sampsz = (uint32_t)aufmt_sample_size(prm->fmt); if (!st->sampsz) { err = ENOTSUP; goto out; } err = pthread_mutex_init(&st->mutex, NULL); if (err) goto out; fmt.mSampleRate = (Float64)prm->srate; fmt.mFormatID = kAudioFormatLinearPCM; fmt.mFormatFlags = coreaudio_aufmt_to_formatflags(prm->fmt) | kAudioFormatFlagIsPacked; #ifdef __BIG_ENDIAN__ fmt.mFormatFlags |= kAudioFormatFlagIsBigEndian; #endif fmt.mFramesPerPacket = 1; fmt.mBytesPerFrame = prm->ch * st->sampsz; fmt.mBytesPerPacket = prm->ch * st->sampsz; fmt.mChannelsPerFrame = prm->ch; fmt.mBitsPerChannel = 8 * st->sampsz; status = AudioQueueNewOutput(&fmt, play_handler, st, NULL, kCFRunLoopCommonModes, 0, &st->queue); if (status) { warning("coreaudio: AudioQueueNewOutput error: %i\n", status); err = ENODEV; goto out; } if (str_isset(device) && 0 != str_casecmp(device, "default")) { CFStringRef uid; info("coreaudio: player: using device '%s'\n", device); err = coreaudio_enum_devices(device, NULL, &uid, false); if (err) goto out; if (!uid) { warning("coreaudio: player: device not found: '%s'\n", device); err = ENODEV; goto out; } status = AudioQueueSetProperty(st->queue, kAudioQueueProperty_CurrentDevice, &uid, sizeof(uid)); CFRelease(uid); if (status) { warning("coreaudio: player: failed to" " set current device (%i)\n", status); err = ENODEV; goto out; } } sampc = prm->srate * prm->ch * prm->ptime / 1000; bytc = sampc * st->sampsz; for (i=0; ibuf); i++) { status = AudioQueueAllocateBuffer(st->queue, bytc, &st->buf[i]); if (status) { err = ENOMEM; goto out; } st->buf[i]->mAudioDataByteSize = bytc; memset(st->buf[i]->mAudioData, 0, st->buf[i]->mAudioDataByteSize); (void)AudioQueueEnqueueBuffer(st->queue, st->buf[i], 0, NULL); } status = AudioQueueStart(st->queue, NULL); if (status) { warning("coreaudio: AudioQueueStart error %i\n", status); err = ENODEV; goto out; } out: if (err) mem_deref(st); else *stp = st; return err; } int coreaudio_player_init(struct auplay *ap) { if (!ap) return EINVAL; list_init(&ap->dev_list); return coreaudio_enum_devices(NULL, &ap->dev_list, NULL, false); } baresip-1.0.0/modules/coreaudio/recorder.c000066400000000000000000000106041372575704200205450ustar00rootroot00000000000000/** * @file coreaudio/recorder.c Apple Coreaudio sound driver - recorder * * Copyright (C) 2010 Creytiv.com */ #include #include #include #include #include #include #include "coreaudio.h" #define BUFC 3 struct ausrc_st { const struct ausrc *as; /* inheritance */ AudioQueueRef queue; AudioQueueBufferRef buf[BUFC]; pthread_mutex_t mutex; struct ausrc_prm prm; uint32_t sampsz; int fmt; ausrc_read_h *rh; void *arg; }; static void ausrc_destructor(void *arg) { struct ausrc_st *st = arg; uint32_t i; pthread_mutex_lock(&st->mutex); st->rh = NULL; pthread_mutex_unlock(&st->mutex); if (st->queue) { AudioQueuePause(st->queue); AudioQueueStop(st->queue, true); for (i=0; ibuf); i++) if (st->buf[i]) AudioQueueFreeBuffer(st->queue, st->buf[i]); AudioQueueDispose(st->queue, true); } pthread_mutex_destroy(&st->mutex); } static void record_handler(void *userData, AudioQueueRef inQ, AudioQueueBufferRef inQB, const AudioTimeStamp *inStartTime, UInt32 inNumPackets, const AudioStreamPacketDescription *inPacketDesc) { struct ausrc_st *st = userData; struct auframe af; ausrc_read_h *rh; void *arg; (void)inStartTime; (void)inNumPackets; (void)inPacketDesc; pthread_mutex_lock(&st->mutex); rh = st->rh; arg = st->arg; pthread_mutex_unlock(&st->mutex); if (!rh) return; auframe_init(&af, st->fmt, inQB->mAudioData, inQB->mAudioDataByteSize/st->sampsz); af.timestamp = AUDIO_TIMEBASE*inStartTime->mSampleTime / st->prm.srate; rh(&af, arg); AudioQueueEnqueueBuffer(inQ, inQB, 0, NULL); } int coreaudio_recorder_alloc(struct ausrc_st **stp, const struct ausrc *as, struct media_ctx **ctx, struct ausrc_prm *prm, const char *device, ausrc_read_h *rh, ausrc_error_h *errh, void *arg) { AudioStreamBasicDescription fmt; struct ausrc_st *st; uint32_t sampc, bytc, i; OSStatus status; int err; (void)ctx; (void)errh; if (!stp || !as || !prm) return EINVAL; st = mem_zalloc(sizeof(*st), ausrc_destructor); if (!st) return ENOMEM; st->as = as; st->rh = rh; st->arg = arg; st->sampsz = (uint32_t)aufmt_sample_size(prm->fmt); if (!st->sampsz) { err = ENOTSUP; goto out; } sampc = prm->srate * prm->ch * prm->ptime / 1000; bytc = sampc * st->sampsz; st->fmt = prm->fmt; st->prm = *prm; err = pthread_mutex_init(&st->mutex, NULL); if (err) goto out; fmt.mSampleRate = (Float64)prm->srate; fmt.mFormatID = kAudioFormatLinearPCM; fmt.mFormatFlags = coreaudio_aufmt_to_formatflags(prm->fmt) | kAudioFormatFlagIsPacked; #ifdef __BIG_ENDIAN__ fmt.mFormatFlags |= kAudioFormatFlagIsBigEndian; #endif fmt.mFramesPerPacket = 1; fmt.mBytesPerFrame = prm->ch * st->sampsz; fmt.mBytesPerPacket = prm->ch * st->sampsz; fmt.mChannelsPerFrame = prm->ch; fmt.mBitsPerChannel = 8 * st->sampsz; status = AudioQueueNewInput(&fmt, record_handler, st, NULL, kCFRunLoopCommonModes, 0, &st->queue); if (status) { warning("coreaudio: AudioQueueNewInput error: %i\n", status); err = ENODEV; goto out; } if (str_isset(device) && 0 != str_casecmp(device, "default")) { CFStringRef uid; info("coreaudio: recorder: using device '%s'\n", device); err = coreaudio_enum_devices(device, NULL, &uid, true); if (err) goto out; if (!uid) { warning("coreaudio: recorder: device not found:" " '%s'\n", device); err = ENODEV; goto out; } status = AudioQueueSetProperty(st->queue, kAudioQueueProperty_CurrentDevice, &uid, sizeof(uid)); CFRelease(uid); if (status) { warning("coreaudio: recorder: failed to" " set current device (%i)\n", status); err = ENODEV; goto out; } } for (i=0; ibuf); i++) { status = AudioQueueAllocateBuffer(st->queue, bytc, &st->buf[i]); if (status) { err = ENOMEM; goto out; } AudioQueueEnqueueBuffer(st->queue, st->buf[i], 0, NULL); } status = AudioQueueStart(st->queue, NULL); if (status) { warning("coreaudio: AudioQueueStart error %i\n", status); err = ENODEV; goto out; } out: if (err) mem_deref(st); else *stp = st; return err; } int coreaudio_recorder_init(struct ausrc *as) { if (!as) return EINVAL; list_init(&as->dev_list); return coreaudio_enum_devices (NULL, &as->dev_list, NULL, true); } baresip-1.0.0/modules/ctrl_tcp/000077500000000000000000000000001372575704200164335ustar00rootroot00000000000000baresip-1.0.0/modules/ctrl_tcp/ctrl_tcp.c000066400000000000000000000165161372575704200204220ustar00rootroot00000000000000/** * @file ctrl_tcp.c TCP control interface using JSON payload * * Copyright (C) 2018 46 Labs LLC */ #include #include #include "tcp_netstring.h" /** * @defgroup ctrl_tcp ctrl_tcp * * Communication channel to control and monitor Baresip via JSON messages. * * It receives commands to be executed, sends back command responses and * notifies about events. * * Command message parameters: * * - command : Command to be executed. * - params : Command parameters. * - token : Optional. Included in the response if present. * * Command message example: * \verbatim { "command" : "dial", "params" : "sip:alice@atlanta.com", "token" : "qwerasdf" } \endverbatim * * * Response message parameters: * * - response : true. Identifies the message type. * - ok: : true/false. Indicates whether the command execution succeeded. * - data : Baresip response to the related command execution. * - token : Present if it was included in the related command request. * * Response message example: * \verbatim { "response" : true, "ok" : true, "data" : "", "token" : "qwerasdf" } \endverbatim * * * Event message parameters: * * - event : true. Identifies the message type. * - class : Event class. * - type : Event ID. * - param : Specific event information. * * Apart from the above, events may contain aditional parameters. * * Event message example: * \verbatim { "event" : "true", "class" : "call", "type" : "CALL_CLOSED", "param" : "Connection reset by peer", "accountaor" : "sip:alice@atlanta.com", "direction" : "incoming", "peeruri" : "sip:bob@biloxy.com", "id" : "73a12546589651f8" } \endverbatim * * * Sample config: * \verbatim ctrl_tcp_listen 0.0.0.0:4444 # IP-address and port to listen on \endverbatim */ enum {CTRL_PORT = 4444}; struct ctrl_st { struct tcp_sock *ts; struct tcp_conn *tc; struct netstring *ns; }; static struct ctrl_st *ctrl = NULL; /* allow only one instance */ static int print_handler(const char *p, size_t size, void *arg) { struct mbuf *mb = arg; return mbuf_write_mem(mb, (uint8_t *)p, size); } static int encode_response(int cmd_error, struct mbuf *resp, const char *token) { struct re_printf pf = {print_handler, resp}; struct odict *od = NULL; char *buf = NULL; char m[256]; int err; /* Empty response. */ if (resp->pos == NETSTRING_HEADER_SIZE) { buf = mem_alloc(1, NULL); buf[0] = '\0'; } else { resp->pos = NETSTRING_HEADER_SIZE; err = mbuf_strdup(resp, &buf, resp->end - NETSTRING_HEADER_SIZE); if (err) return err; } err = odict_alloc(&od, 8); if (err) return err; err |= odict_entry_add(od, "response", ODICT_BOOL, true); err |= odict_entry_add(od, "ok", ODICT_BOOL, (bool)!cmd_error); if (cmd_error && str_len(buf) == 0) err |= odict_entry_add(od, "data", ODICT_STRING, str_error(cmd_error, m, sizeof(m))); else err |= odict_entry_add(od, "data", ODICT_STRING, buf); if (token) err |= odict_entry_add(od, "token", ODICT_STRING, token); if (err) goto out; mbuf_reset(resp); mbuf_init(resp); resp->pos = NETSTRING_HEADER_SIZE; err = json_encode_odict(&pf, od); if (err) warning("ctrl_tcp: failed to encode response JSON (%m)\n", err); out: mem_deref(buf); mem_deref(od); return err; } static bool command_handler(struct mbuf *mb, void *arg) { struct ctrl_st *st = arg; struct mbuf *resp = mbuf_alloc(2048); struct re_printf pf = {print_handler, resp}; struct odict *od = NULL; const struct odict_entry *oe_cmd, *oe_prm, *oe_tok; char buf[1024]; int err; err = json_decode_odict(&od, 32, (const char*)mb->buf, mb->end, 16); if (err) { warning("ctrl_tcp: failed to decode JSON (%m)\n", err); goto out; } oe_cmd = odict_lookup(od, "command"); oe_prm = odict_lookup(od, "params"); oe_tok = odict_lookup(od, "token"); if (!oe_cmd) { warning("ctrl_tcp: missing json entries\n"); goto out; } debug("ctrl_tcp: handle_command: cmd='%s', params:'%s', token='%s'\n", oe_cmd->u.str, oe_prm ? oe_prm->u.str : "", oe_tok ? oe_tok->u.str : ""); re_snprintf(buf, sizeof(buf), "%s%s%s", oe_cmd->u.str, oe_prm ? " " : "", oe_prm ? oe_prm->u.str : ""); resp->pos = NETSTRING_HEADER_SIZE; /* Relay message to long commands */ err = cmd_process_long(baresip_commands(), buf, str_len(buf), &pf, NULL); if (err) { warning("ctrl_tcp: error processing command (%m)\n", err); } err = encode_response(err, resp, oe_tok ? oe_tok->u.str : NULL); if (err) { warning("ctrl_tcp: failed to encode response (%m)\n", err); goto out; } resp->pos = NETSTRING_HEADER_SIZE; err = tcp_send(st->tc, resp); if (err) { warning("ctrl_tcp: failed to send the message (%m)\n", err); } out: mem_deref(resp); mem_deref(od); return true; /* always handled */ } static void tcp_close_handler(int err, void *arg) { struct ctrl_st *st = arg; (void)err; st->tc = mem_deref(st->tc); } static void tcp_conn_handler(const struct sa *peer, void *arg) { struct ctrl_st *st = arg; (void)peer; /* only one connection allowed */ st->tc = mem_deref(st->tc); st->ns = mem_deref(st->ns); (void)tcp_accept(&st->tc, st->ts, NULL, NULL, tcp_close_handler, st); (void)netstring_insert(&st->ns, st->tc, 0, command_handler, st); } /* * Relay UA events */ static void ua_event_handler(struct ua *ua, enum ua_event ev, struct call *call, const char *prm, void *arg) { struct ctrl_st *st = arg; struct mbuf *buf = mbuf_alloc(1024); struct re_printf pf = {print_handler, buf}; struct odict *od = NULL; int err; buf->pos = NETSTRING_HEADER_SIZE; err = odict_alloc(&od, 8); if (err) return; err = odict_entry_add(od, "event", ODICT_BOOL, true); err |= event_encode_dict(od, ua, ev, call, prm); if (err) { warning("ctrl_tcp: failed to encode event (%m)\n", err); goto out; } err = json_encode_odict(&pf, od); if (err) { warning("ctrl_tcp: failed to encode json (%m)\n", err); goto out; } if (st->tc) { buf->pos = NETSTRING_HEADER_SIZE; err = tcp_send(st->tc, buf); if (err) { warning("ctrl_tcp: failed to send the message (%m)\n", err); } } out: mem_deref(buf); mem_deref(od); } static void ctrl_destructor(void *arg) { struct ctrl_st *st = arg; mem_deref(st->tc); mem_deref(st->ts); mem_deref(st->ns); } static int ctrl_alloc(struct ctrl_st **stp, const struct sa *laddr) { struct ctrl_st *st; int err; if (!stp) return EINVAL; st = mem_zalloc(sizeof(*st), ctrl_destructor); if (!st) return ENOMEM; err = tcp_listen(&st->ts, laddr, tcp_conn_handler, st); if (err) { warning("ctrl_tcp: failed to listen on TCP %J (%m)\n", laddr, err); goto out; } debug("ctrl_tcp: TCP socket listening on %J\n", laddr); out: if (err) mem_deref(st); else *stp = st; return err; } static int ctrl_init(void) { struct sa laddr; int err; if (conf_get_sa(conf_cur(), "ctrl_tcp_listen", &laddr)) { sa_set_str(&laddr, "0.0.0.0", CTRL_PORT); } err = ctrl_alloc(&ctrl, &laddr); if (err) return err; err = uag_event_register(ua_event_handler, ctrl); if (err) return err; return 0; } static int ctrl_close(void) { uag_event_unregister(ua_event_handler); ctrl = mem_deref(ctrl); return 0; } const struct mod_export DECL_EXPORTS(ctrl_tcp) = { "ctrl_tcp", "application", ctrl_init, ctrl_close }; baresip-1.0.0/modules/ctrl_tcp/module.mk000066400000000000000000000002321372575704200202460ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2018 46 Labs LLC # MOD := ctrl_tcp $(MOD)_SRCS += ctrl_tcp.c tcp_netstring.c ./netstring/netstring.c include mk/mod.mk baresip-1.0.0/modules/ctrl_tcp/netstring/000077500000000000000000000000001372575704200204505ustar00rootroot00000000000000baresip-1.0.0/modules/ctrl_tcp/netstring/netstring.c000066400000000000000000000110201372575704200226230ustar00rootroot00000000000000/** * @file netstring.c Streaming API for netstrings * * This file is public domain, * adapted from https://github.com/PeterScott/netstring-c/" */ #include #include #include #include #include #include #include "netstring.h" const char* netstring_error_str(netstring_error err) { switch (err) { case NETSTRING_ERROR_TOO_LONG: return "NETSTRING_ERROR_TOO_LONG"; case NETSTRING_ERROR_NO_COLON: return "NETSTRING_ERROR_NO_COLON"; case NETSTRING_ERROR_TOO_SHORT: return "NETSTRING_ERROR_TOO_SHORT"; case NETSTRING_ERROR_NO_COMMA: return "NETSTRING_ERROR_NO_COMMA"; case NETSTRING_ERROR_LEADING_ZERO: return "NETSTRING_ERROR_LEADING_ZERO"; case NETSTRING_ERROR_NO_LENGTH: return "NETSTRING_ERROR_NO_LENGTH"; default: return "NETSTRING_ERROR_UNKNOWN"; } } /** * Reads a netstring from a `buffer` of length `buffer_length`. Writes * to `netstring_start` a pointer to the beginning of the string in * the buffer, and to `netstring_length` the length of the * string. Does not allocate any memory. If it reads successfully, * then it returns 0. If there is an error, then the return value will * be negative. The error values are: * NETSTRING_ERROR_TOO_LONG More than 999999999 bytes in a field * NETSTRING_ERROR_NO_COLON No colon was found after the number * NETSTRING_ERROR_TOO_SHORT Number of bytes greater than buffer length * NETSTRING_ERROR_NO_COMMA No comma was found at the end * NETSTRING_ERROR_LEADING_ZERO Leading zeros are not allowed * NETSTRING_ERROR_NO_LENGTH Length not given at start of netstring * If you're sending messages with more than 999999999 bytes -- about * 2 GB -- then you probably should not be doing so in the form of a * single netstring. This restriction is in place partially to protect * from malicious or erroneous input, and partly to be compatible with * D. J. Bernstein's reference implementation. * Example: * if (netstring_read("3:foo,", 6, &str, &len) < 0) explode_and_die(); */ int netstring_read(char *buffer, size_t buffer_length, char **netstring_start, size_t *netstring_length) { size_t i; size_t len = 0; /* Write default values for outputs */ *netstring_start = NULL; *netstring_length = 0; /* Make sure buffer is big enough. Minimum size is 3. */ if (buffer_length < 3) return NETSTRING_ERROR_TOO_SHORT; /* No leading zeros allowed! */ if (buffer[0] == '0' && isdigit(buffer[1])) return NETSTRING_ERROR_LEADING_ZERO; /* The netstring must start with a number */ if (!isdigit(buffer[0])) return NETSTRING_ERROR_NO_LENGTH; /* Read the number of bytes */ for (i = 0; i < buffer_length && isdigit(buffer[i]); i++) { /* Error if more than 9 digits */ if (i >= 9) return NETSTRING_ERROR_TOO_LONG; /* Accumulate each digit, assuming ASCII. */ len = len*10 + (buffer[i] - '0'); } /** * Check buffer length. The buffer must be longer than the sum of: * - the number we've read. * - the length of the string itself. * - the colon. * - the comma. */ if (i + len + 1 >= buffer_length) return NETSTRING_ERROR_TOO_SHORT; /* Read the colon */ if (buffer[i++] != ':') return NETSTRING_ERROR_NO_COLON; /* Test for the trailing comma, and set the return values */ if (buffer[i + len] != ',') return NETSTRING_ERROR_NO_COMMA; *netstring_start = &buffer[i]; *netstring_length = len; return 0; } /** * Return the number of digits represented in the given number. * We are assuming that the input is not bigger than NETSTRING_MAX_SIZE. */ size_t netstring_num_len(size_t num) { char num_str[32]; re_snprintf(num_str, sizeof(num_str), "%zu", num); return strlen(num_str); } /** * Return the length, in ASCII characters, of a netstring containing * `data_length` bytes. */ size_t netstring_buffer_size(size_t data_length) { if (data_length == 0) return 3; return netstring_num_len(data_length) + data_length + 2; } /* * Allocate and create a netstring containing the first `len` bytes of `data`. * This must be manually freed by the client. * If `len` is 0 then no data will be read from `data`, and it may be NULL. */ size_t netstring_encode_new(char **netstring, char *data, size_t len) { char *ns; size_t num_len = 1; if (len == 0) { ns = malloc(3); ns[0] = '0'; ns[1] = ':'; ns[2] = ','; } else { num_len = netstring_num_len(len); ns = malloc(num_len + len + 2); sprintf(ns, "%lu:", (unsigned long)len); memcpy(ns + num_len + 1, data, len); ns[num_len + len + 1] = ','; } *netstring = ns; return num_len + len + 2; } baresip-1.0.0/modules/ctrl_tcp/netstring/netstring.h000066400000000000000000000015321372575704200226370ustar00rootroot00000000000000/** * @file netstring.h Streaming API for netstrings. * * This file is public domain, * adapted from https://github.com/PeterScott/netstring-c/" */ #ifndef __NETSTRING_STREAM_H #define __NETSTRING_STREAM_H #include const char* netstring_error_str(int err); int netstring_read(char *buffer, size_t buffer_length, char **netstring_start, size_t *netstring_length); size_t netstring_num_len(size_t num); size_t netstring_buffer_size(size_t data_length); size_t netstring_encode_new(char **netstring, char *data, size_t len); #define NETSTRING_MAX_SIZE 999999999 /* Errors that can occur during netstring parsing */ typedef enum { NETSTRING_ERROR_TOO_LONG = -100, NETSTRING_ERROR_NO_COLON, NETSTRING_ERROR_TOO_SHORT, NETSTRING_ERROR_NO_COMMA, NETSTRING_ERROR_LEADING_ZERO, NETSTRING_ERROR_NO_LENGTH } netstring_error; #endif baresip-1.0.0/modules/ctrl_tcp/tcp_netstring.c000066400000000000000000000100021372575704200214530ustar00rootroot00000000000000/** * @file tcp_netstring.c TCP netstring framing * * Copyright (C) 2018 46 Labs LLC */ #include #include #include #include #include #include #include #include #include "tcp_netstring.h" #include "netstring/netstring.h" #define DEBUG_MODULE "tcp_netstring" #define DEBUG_LEVEL 5 #include struct netstring { struct tcp_conn *tc; struct tcp_helper *th; struct mbuf *mb; netstring_frame_h *frameh; void *arg; uint64_t n_tx; uint64_t n_rx; }; /* responsible for adding the netstring header - assumes that the sent MBUF contains a complete packet */ static bool netstring_send_handler(int *err, struct mbuf *mb, void *arg) { struct netstring *netstring = arg; size_t num_len; char num_str[32]; if (mb->pos < NETSTRING_HEADER_SIZE) { DEBUG_WARNING("send: not enough space for netstring header\n"); *err = ENOMEM; return true; } if (mbuf_get_left(mb) > NETSTRING_MAX_SIZE) { DEBUG_WARNING("send: buffer exceeds max size\n"); *err = EMSGSIZE; return true; } /* Build the netstring. */ if (mbuf_get_left(mb) == 0) { mb->buf[0] = '0'; mb->buf[1] = ':'; mb->buf[2] = ','; mb->end += 3; return false; } re_snprintf(num_str, sizeof(num_str), "%zu", mbuf_get_left(mb)); num_len = strlen(num_str); mb->pos = NETSTRING_HEADER_SIZE - (num_len + 1); mbuf_write_mem(mb, (uint8_t*) num_str, num_len); mb->pos = NETSTRING_HEADER_SIZE - (num_len + 1); mb->buf[mb->pos + num_len] = ':'; mb->buf[mb->end] = ','; mb->end += 1; ++netstring->n_tx; return false; } static bool netstring_recv_handler(int *errp, struct mbuf *mbx, bool *estab, void *arg) { struct netstring *netstring = arg; int err = 0; size_t pos = 0; (void)estab; /* handle re-assembly */ if (!netstring->mb) { netstring->mb = mbuf_alloc(1024); if (!netstring->mb) { *errp = ENOMEM; return true; } } pos = netstring->mb->pos; netstring->mb->pos = netstring->mb->end; err = mbuf_write_mem(netstring->mb, mbuf_buf(mbx), mbuf_get_left(mbx)); if (err) { netstring->mb->pos = pos; goto out; } netstring->mb->pos = pos; /* extract all NETSTRING-frames in the TCP-stream */ for (;;) { size_t len; struct mbuf mb; if (mbuf_get_left(netstring->mb) < (3)) break; mbuf_init(&mb); err = netstring_read( (char*)netstring->mb->buf + netstring->mb->pos, netstring->mb->end, (char**)&mb.buf, &len); if (err) { if (err == NETSTRING_ERROR_TOO_SHORT) { DEBUG_INFO("receive: %s\n", netstring_error_str(err)); } else { DEBUG_WARNING("receive: %s\n", netstring_error_str(err)); netstring->mb = mem_deref(netstring->mb); } return false; } mb.end = len; ++netstring->n_rx; netstring->frameh(&mb, netstring->arg); netstring->mb->pos += netstring_buffer_size(len); if (netstring->mb->pos >= netstring->mb->end) { netstring->mb = mem_deref(netstring->mb); break; } continue; } out: if (err) *errp = err; return true; /* always handled */ } static void destructor(void *arg) { struct netstring *netstring = arg; mem_deref(netstring->th); mem_deref(netstring->tc); mem_deref(netstring->mb); } int netstring_insert(struct netstring **netstringp, struct tcp_conn *tc, int layer, netstring_frame_h *frameh, void *arg) { struct netstring *netstring; int err; if (!netstringp || !tc || !frameh) return EINVAL; netstring = mem_zalloc(sizeof(*netstring), destructor); if (!netstring) return ENOMEM; netstring->tc = mem_ref(tc); err = tcp_register_helper(&netstring->th, tc, layer, NULL, netstring_send_handler, netstring_recv_handler, netstring); if (err) goto out; netstring->frameh = frameh; netstring->arg = arg; out: if (err) mem_deref(netstring); else *netstringp = netstring; return err; } int netstring_debug(struct re_printf *pf, const struct netstring *netstring) { if (!netstring) return 0; return re_hprintf(pf, "tx=%llu, rx=%llu", netstring->n_tx, netstring->n_rx); } baresip-1.0.0/modules/ctrl_tcp/tcp_netstring.h000066400000000000000000000006401372575704200214670ustar00rootroot00000000000000/** * @file tcp_netstring.h TCP netstring framing * * Copyright (C) 2018 46 Labs LLC */ enum {NETSTRING_HEADER_SIZE = 10}; struct netstring; typedef bool (netstring_frame_h)(struct mbuf *mb, void *arg); int netstring_insert(struct netstring **netstringp, struct tcp_conn *tc, int layer, netstring_frame_h *frameh, void *arg); int netstring_debug(struct re_printf *pf, const struct netstring *netstring); baresip-1.0.0/modules/debug_cmd/000077500000000000000000000000001372575704200165325ustar00rootroot00000000000000baresip-1.0.0/modules/debug_cmd/debug_cmd.c000066400000000000000000000134421372575704200206130ustar00rootroot00000000000000/** * @file debug_cmd.c Debug commands * * Copyright (C) 2010 - 2016 Creytiv.com */ #include #include #ifdef USE_OPENSSL #include #endif #include #include /** * @defgroup debug_cmd debug_cmd * * Advanced debug commands */ static uint64_t start_ticks; /**< Ticks when app started */ static time_t start_time; /**< Start time of application */ static int cmd_net_debug(struct re_printf *pf, void *unused) { (void)unused; return net_debug(pf, baresip_network()); } static int print_system_info(struct re_printf *pf, void *arg) { uint32_t uptime; int err = 0; (void)arg; uptime = (uint32_t)((long long)(tmr_jiffies() - start_ticks)/1000); err |= re_hprintf(pf, "\n--- System info: ---\n"); err |= re_hprintf(pf, " Machine: %s/%s\n", sys_arch_get(), sys_os_get()); err |= re_hprintf(pf, " Version: %s (libre v%s)\n", BARESIP_VERSION, sys_libre_version_get()); err |= re_hprintf(pf, " Build: %H\n", sys_build_get, NULL); err |= re_hprintf(pf, " Kernel: %H\n", sys_kernel_get, NULL); err |= re_hprintf(pf, " Uptime: %H\n", fmt_human_time, &uptime); err |= re_hprintf(pf, " Started: %s", ctime(&start_time)); #ifdef __VERSION__ err |= re_hprintf(pf, " Compiler: %s\n", __VERSION__); #endif #if defined (USE_OPENSSL) && (OPENSSL_VERSION_NUMBER < 0x10100000L) err |= re_hprintf(pf, " OpenSSL: %s\n", SSLeay_version(SSLEAY_VERSION)); #endif #if defined (USE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10100000L) err |= re_hprintf(pf, " OpenSSL: %s\n", OpenSSL_version(OPENSSL_VERSION)); #endif return err; } static int cmd_config_print(struct re_printf *pf, void *unused) { (void)unused; return config_print(pf, conf_config()); } static int cmd_ua_debug(struct re_printf *pf, void *unused) { const struct ua *ua = uag_current(); (void)unused; if (ua) return ua_debug(pf, ua); else return re_hprintf(pf, "(no user-agent)\n"); } /** * Returns all the User-Agents and their general codec state. * Formatted as JSON, for use with TCP / MQTT API interface. * JSON object with 'cuser' as the key. * * @return All User-Agents available, NULL if none */ static int cmd_api_uastate(struct re_printf *pf, void *unused) { struct odict *od = NULL; struct le *le; int err; (void)unused; err = odict_alloc(&od, 8); if (err) return err; for (le = list_head(uag_list()); le && !err; le = le->next) { const struct ua *ua = le->data; struct odict *odua; err = odict_alloc(&odua, 8); err |= ua_state_json_api(odua, ua); err |= odict_entry_add(od, ua_aor(ua), ODICT_OBJECT, odua); mem_deref(odua); } err |= json_encode_odict(pf, od); if (err) warning("debug: failed to encode json (%m)\n", err); mem_deref(od); return re_hprintf(pf, "\n"); } static int cmd_play_file(struct re_printf *pf, void *arg) { static struct play *g_play; struct cmd_arg *carg = arg; struct config *cfg; const char *filename = carg->prm; int err = 0; cfg = conf_config(); /* Stop the current tone, if any */ g_play = mem_deref(g_play); if (str_isset(filename)) { err = re_hprintf(pf, "playing audio file \"%s\" ..\n", filename); if (err) return err; err = play_file(&g_play, baresip_player(), filename, 0, cfg->audio.alert_mod, cfg->audio.alert_dev); if (err) { warning("debug_cmd: play_file(%s) failed (%m)\n", filename, err); return err; } } return err; } static int cmd_sip_debug(struct re_printf *pf, void *unused) { (void)unused; return sip_debug(pf, uag_sip()); } static int reload_config(struct re_printf *pf, void *arg) { int err; (void)arg; err = re_hprintf(pf, "reloading config file ..\n"); if (err) return err; err = conf_configure(); if (err) { (void)re_hprintf(pf, "reload_config failed: %m\n", err); return err; } (void)re_hprintf(pf, "done\n"); return 0; } static int cmd_log_level(struct re_printf *pf, void *unused) { int level; (void)unused; level = log_level_get(); --level; if (level < LEVEL_DEBUG) level = LEVEL_ERROR; log_level_set(level); return re_hprintf(pf, "Log level '%s'\n", log_level_name(level)); } static int print_uuid(struct re_printf *pf, void *arg) { struct config *cfg = conf_config(); (void)arg; if (cfg) re_hprintf(pf, "UUID: %s\n", cfg->sip.uuid); return 0; } static const struct cmd debugcmdv[] = { {"conf_reload", 0, 0, "Reload config file", reload_config }, {"config", 0, 0, "Print configuration", cmd_config_print }, {"loglevel", 'v', 0, "Log level toggle", cmd_log_level }, {"main", 0, 0, "Main loop debug", re_debug }, {"memstat", 'y', 0, "Memory status", mem_status }, {"modules", 0, 0, "Module debug", mod_debug }, {"netstat", 'n', 0, "Network debug", cmd_net_debug }, {"play", 0, CMD_PRM, "Play audio file", cmd_play_file }, {"sipstat", 'i', 0, "SIP debug", cmd_sip_debug }, {"sysinfo", 's', 0, "System info", print_system_info }, {"timers", 0, 0, "Timer debug", tmr_status }, {"uastat", 'u', 0, "UA debug", cmd_ua_debug }, {"uuid", 0, 0, "Print UUID", print_uuid }, {"apistate", 0, 0, "User Agent state", cmd_api_uastate }, }; static int module_init(void) { int err; start_ticks = tmr_jiffies(); (void)time(&start_time); err = cmd_register(baresip_commands(), debugcmdv, ARRAY_SIZE(debugcmdv)); return err; } static int module_close(void) { cmd_unregister(baresip_commands(), debugcmdv); return 0; } const struct mod_export DECL_EXPORTS(debug_cmd) = { "debug_cmd", "application", module_init, module_close }; baresip-1.0.0/modules/debug_cmd/module.mk000066400000000000000000000001641372575704200203510ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # MOD := debug_cmd $(MOD)_SRCS += debug_cmd.c include mk/mod.mk baresip-1.0.0/modules/directfb/000077500000000000000000000000001372575704200164035ustar00rootroot00000000000000baresip-1.0.0/modules/directfb/directfb.c000066400000000000000000000070051372575704200203330ustar00rootroot00000000000000/** * @file directfb.c DirectFB video display module * * Copyright (C) 2010 Creytiv.com * Copyright (C) 2013 Andreas Shimokawa */ #include #include #include #include struct vidisp_st { const struct vidisp *vd; /**< Inheritance (1st) */ struct vidsz size; /**< Current size */ IDirectFBWindow *window; /**< DirectFB Window */ IDirectFBSurface *surface; /**< Surface for pixels */ IDirectFBDisplayLayer *layer; /**< Display layer */ }; static IDirectFB *dfb; static struct vidisp *vid; static void destructor(void *arg) { struct vidisp_st *st = arg; if (st->surface) st->surface->Release(st->surface); if (st->window) st->window->Release(st->window); if (st->layer) st->layer->Release(st->layer); } static int alloc(struct vidisp_st **stp, const struct vidisp *vd, struct vidisp_prm *prm, const char *dev, vidisp_resize_h *resizeh, void *arg) { struct vidisp_st *st; int err = 0; /* Not used by DirectFB */ (void) prm; (void) dev; (void) resizeh; (void) arg; st = mem_zalloc(sizeof(*st), destructor); if (!st) return ENOMEM; st->vd = vd; dfb->GetDisplayLayer(dfb, DLID_PRIMARY, &st->layer); if (err) mem_deref(st); else *stp = st; return err; } static int display(struct vidisp_st *st, const char *title, const struct vidframe *frame, uint64_t timestamp) { void *pixels; int pitch, i; unsigned h; uint8_t *p; (void) title; (void) timestamp; if (!vidsz_cmp(&st->size, &frame->size)) { if (st->size.w && st->size.h) { info("directfb: reset: %u x %u ---> %u x %u\n", st->size.w, st->size.h, frame->size.w, frame->size.h); } if (st->surface) { st->surface->Release(st->surface); st->surface = NULL; } if (st->window) { st->window->Release(st->window); st->window = NULL; } } if (!st->window) { DFBWindowDescription desc; desc.flags = DWDESC_WIDTH|DWDESC_HEIGHT|DWDESC_PIXELFORMAT; desc.width = frame->size.w; desc.height = frame->size.h; desc.pixelformat = DSPF_I420; st->layer->CreateWindow(st->layer, &desc, &st->window); st->size = frame->size; st->window->SetOpacity(st->window, 0xff); st->window->GetSurface(st->window, &st->surface); } st->surface->Lock(st->surface, DSLF_WRITE, &pixels, &pitch); p = pixels; for (i=0; i<3; i++) { const uint8_t *s = frame->data[i]; const unsigned stp = frame->linesize[0] / frame->linesize[i]; const unsigned sz = frame->size.w / stp; for (h = 0; h < frame->size.h; h += stp) { memcpy(p, s, sz); s += frame->linesize[i]; p += (pitch / stp); } } st->surface->Unlock(st->surface); /* Update the screen! */ st->surface->Flip(st->surface, 0, 0); return 0; } static void hide(struct vidisp_st *st) { if (!st || !st->window) return; st->window->SetOpacity(st->window, 0x00); } static int module_init(void) { int err = 0; DFBResult ret; ret = DirectFBInit(NULL, NULL); if (ret) { DirectFBError("DirectFBInit() failed", ret); return (int) ret; } ret = DirectFBCreate(&dfb); if (ret) { DirectFBError("DirectFBCreate() failed", ret); return (int) ret; } err = vidisp_register(&vid, baresip_vidispl(), "directfb", alloc, NULL, display, hide); if (err) return err; return 0; } static int module_close(void) { vid = mem_deref(vid); if (dfb) { dfb->Release(dfb); dfb = NULL; } return 0; } EXPORT_SYM const struct mod_export DECL_EXPORTS(directfb) = { "directfb", "vidisp", module_init, module_close }; baresip-1.0.0/modules/directfb/module.mk000066400000000000000000000005731372575704200202260ustar00rootroot00000000000000# # module.mk - DirectFB video display module # # Copyright (C) 2010 Creytiv.com # Copyright (C) 2013 Andreas Shimokawa . # MOD := directfb $(MOD)_SRCS += directfb.c $(MOD)_LFLAGS += $(shell pkg-config --libs directfb) $(MOD)_CFLAGS += $(shell pkg-config --cflags directfb \ | sed -e 's/-I/-isystem/g') include mk/mod.mk baresip-1.0.0/modules/dshow/000077500000000000000000000000001372575704200157455ustar00rootroot00000000000000baresip-1.0.0/modules/dshow/dshow.cpp000066400000000000000000000301411372575704200175740ustar00rootroot00000000000000/** * @file dshow.cpp Windows DirectShow video-source * * Copyright (C) 2010 Creytiv.com * Copyright (C) 2010 Dusan Stevanovic */ #include #include #include #include #include #include #pragma comment(lib, "strmiids.lib") /** * @defgroup dshow dshow * * Windows DirectShow video-source * * * References: * * http://www.alsa-project.org/main/index.php/Main_Page */ #ifndef __ISampleGrabberCB_INTERFACE_DEFINED__ #define __ISampleGrabberCB_INTERFACE_DEFINED__ /* interface ISampleGrabberCB */ /* [unique][helpstring][local][uuid][object] */ EXTERN_C const IID IID_ISampleGrabberCB; MIDL_INTERFACE("0579154A-2B53-4994-B0D0-E773148EFF85") ISampleGrabberCB : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE SampleCB( double SampleTime, IMediaSample *pSample) = 0; virtual HRESULT STDMETHODCALLTYPE BufferCB( double SampleTime, BYTE *pBuffer, long BufferLen) = 0; }; #endif /* __ISampleGrabberCB_INTERFACE_DEFINED__ */ #ifndef __ISampleGrabber_INTERFACE_DEFINED__ #define __ISampleGrabber_INTERFACE_DEFINED__ /* interface ISampleGrabber */ /* [unique][helpstring][local][uuid][object] */ EXTERN_C const IID IID_ISampleGrabber; MIDL_INTERFACE("6B652FFF-11FE-4fce-92AD-0266B5D7C78F") ISampleGrabber : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE SetOneShot( BOOL OneShot) = 0; virtual HRESULT STDMETHODCALLTYPE SetMediaType( const AM_MEDIA_TYPE *pType) = 0; virtual HRESULT STDMETHODCALLTYPE GetConnectedMediaType( AM_MEDIA_TYPE *pType) = 0; virtual HRESULT STDMETHODCALLTYPE SetBufferSamples( BOOL BufferThem) = 0; virtual HRESULT STDMETHODCALLTYPE GetCurrentBuffer( /* [out][in] */ long *pBufferSize, /* [out] */ long *pBuffer) = 0; virtual HRESULT STDMETHODCALLTYPE GetCurrentSample( /* [retval][out] */ IMediaSample **ppSample) = 0; virtual HRESULT STDMETHODCALLTYPE SetCallback( ISampleGrabberCB *pCallback, long WhichMethodToCallback) = 0; }; DEFINE_GUID(CLSID_SampleGrabber, 0xc1f400a0, 0x3f08, 0x11d3, 0x9f, 0x0b, 0x00, 0x60, 0x08, 0x03, 0x9e, 0x37); #endif /* __ISampleGrabber_INTERFACE_DEFINED__ */ class Grabber; struct vidsrc_st { const struct vidsrc *vs; /* inheritance */ ICaptureGraphBuilder2 *capture; IBaseFilter *grabber_filter; IBaseFilter *dev_filter; ISampleGrabber *grabber; IMoniker *dev_moniker; IGraphBuilder *graph; IMediaControl *mc; Grabber *grab; struct vidsz size; vidsrc_frame_h *frameh; void *arg; }; class Grabber : public ISampleGrabberCB { public: Grabber(struct vidsrc_st *st) : src(st) { } STDMETHOD(QueryInterface)(REFIID InterfaceIdentifier, VOID** ppvObject) throw() { if (InterfaceIdentifier == IID_ISampleGrabberCB) { *ppvObject = (ISampleGrabberCB**) this; return S_OK; } return E_NOINTERFACE; } STDMETHOD_(ULONG, AddRef)() throw() { return 2; } STDMETHOD_(ULONG, Release)() throw() { return 1; } STDMETHOD(BufferCB) (double sample_time, BYTE *buf, long buf_len) { int i, j = 0, k; int buf_len_RGB32 = src->size.h*src->size.w; uint32_t tmp_pix_RGB32; uint32_t *buf_RGB32; struct vidframe vidframe; uint64_t timestamp = (uint64_t)(sample_time * VIDEO_TIMEBASE); vidframe_init_buf(&vidframe, VID_FMT_RGB32, &src->size, buf); //By default in Dshow, RGB32 image orientation is bottom-up buf_RGB32 = (uint32_t *)buf; for (i = buf_len_RGB32-1 ; i > buf_len_RGB32/2; i-=1) { k = src->size.w*(j/src->size.w) + i%(src->size.w); tmp_pix_RGB32 = buf_RGB32[k]; buf_RGB32[k] = buf_RGB32[i]; buf_RGB32[i] = tmp_pix_RGB32; ++j; } if (src->frameh) src->frameh(&vidframe, timestamp, src->arg); return S_OK; } STDMETHOD(SampleCB) (double sample_time, IMediaSample *samp) { return S_OK; } private: struct vidsrc_st *src; }; static struct vidsrc *vsrc; static int enum_devices(struct vidsrc_st *st, const char *name, struct list *dev_list) { ICreateDevEnum *dev_enum; IEnumMoniker *enum_mon; IMoniker *mon; ULONG fetched; HRESULT res; int id = 0; int err = 0; res = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void**)&dev_enum); if (res != NOERROR) return ENOENT; res = dev_enum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &enum_mon, 0); if (res != NOERROR) return ENOENT; enum_mon->Reset(); while (enum_mon->Next(1, &mon, &fetched) == S_OK) { IPropertyBag *bag; VARIANT var; char dev_name[256]; int len = 0; res = mon->BindToStorage(0, 0, IID_IPropertyBag, (void **)&bag); if (!SUCCEEDED(res)) continue; var.vt = VT_BSTR; res = bag->Read(L"FriendlyName", &var, NULL); if (NOERROR != res) continue; len = WideCharToMultiByte(CP_ACP, 0, var.bstrVal, -1, dev_name, sizeof(dev_name), NULL, NULL); SysFreeString(var.bstrVal); bag->Release(); if (len > 0) { if (st) { if (!str_isset(name) || !str_casecmp(dev_name, name)) { info("dshow: got device '%s' id=%d\n", name, id); st->dev_moniker = mon; return 0; } } else { err = mediadev_add(dev_list, dev_name); if (err) { return err; } } } mon->Release(); ++id; } return err; } static int set_available_devices(struct list* dev_list) { return enum_devices(NULL, NULL, dev_list); } static int get_device(struct vidsrc_st *st, const char *name) { int err = 0; bool found = false; if (!st) return EINVAL; err = enum_devices(st, name, NULL); if (err) return err; if (st->dev_moniker) found = true; return found? 0 : ENOENT; } static int add_sample_grabber(struct vidsrc_st *st) { AM_MEDIA_TYPE mt; HRESULT hr; hr = CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**) &st->grabber_filter); if (FAILED(hr)) return ENOMEM; hr = st->graph->AddFilter(st->grabber_filter, L"Sample Grabber"); if (FAILED(hr)) return ENOMEM; hr = st->grabber_filter->QueryInterface(IID_ISampleGrabber, (void**)&st->grabber); if (FAILED(hr)) return ENODEV; hr = st->grabber->SetCallback(st->grab, 1); if (FAILED(hr)) return ENOSYS; memset(&mt, 0, sizeof(mt)); mt.majortype = MEDIATYPE_Video; mt.subtype = MEDIASUBTYPE_RGB32; hr = st->grabber->SetMediaType(&mt); if (FAILED(hr)) return ENODEV; st->grabber->SetOneShot(FALSE); st->grabber->SetBufferSamples(FALSE); return 0; } static AM_MEDIA_TYPE *free_mt(AM_MEDIA_TYPE *mt) { if (!mt) return NULL; if (mt->cbFormat) { CoTaskMemFree((PVOID)mt->pbFormat); } if (mt->pUnk != NULL) { mt->pUnk->Release(); mt->pUnk = NULL; } CoTaskMemFree((PVOID)mt); return NULL; } static int config_pin(struct vidsrc_st *st, IPin *pin) { AM_MEDIA_TYPE *mt; AM_MEDIA_TYPE *best_mt = NULL; IEnumMediaTypes *media_enum = NULL; IAMStreamConfig *stream_conf = NULL; VIDEOINFOHEADER *vih; HRESULT hr; int h = st->size.h; int w = st->size.w; int rh, rw; int wh, rwrh; int best_match = 0; int err = 0; if (!pin || !st) return EINVAL; hr = pin->EnumMediaTypes(&media_enum); if (FAILED(hr)) return ENODATA; while ((hr = media_enum->Next(1, &mt, NULL)) == S_OK) { if (mt->formattype != FORMAT_VideoInfo) continue; vih = (VIDEOINFOHEADER *) mt->pbFormat; rw = vih->bmiHeader.biWidth; rh = vih->bmiHeader.biHeight; wh = w * h; rwrh = rw * rh; if (wh == rwrh) { best_mt = free_mt(best_mt); break; } else { int diff = abs(rwrh - wh); if (best_match != 0 && diff >= best_match) mt = free_mt(mt); else { best_match = diff; free_mt(best_mt); best_mt = mt; } } } if (hr != S_OK) mt = free_mt(mt); if (mt == NULL && best_mt == NULL) { err = ENODATA; goto out; } if (mt == NULL) mt = best_mt; hr = pin->QueryInterface(IID_IAMStreamConfig, (void **) &stream_conf); if (FAILED(hr)) { err = EINVAL; goto out; } vih = (VIDEOINFOHEADER *) mt->pbFormat; hr = stream_conf->SetFormat(mt); mt = free_mt(mt); if (FAILED(hr)) { err = ERANGE; goto out; } hr = stream_conf->GetFormat(&mt); if (FAILED(hr)) { err = EINVAL; goto out; } if (mt->formattype != FORMAT_VideoInfo) { err = EINVAL; goto out; } vih = (VIDEOINFOHEADER *)mt->pbFormat; rw = vih->bmiHeader.biWidth; rh = vih->bmiHeader.biHeight; if (w != rw || h != rh) { warning("dshow: config_pin: picture size missmatch: " "wanted %d x %d, got %d x %d\n", w, h, rw, rh); } st->size.w = rw; st->size.h = rh; out: if (media_enum) media_enum->Release(); if (stream_conf) stream_conf->Release(); free_mt(mt); return err; } static void destructor(void *arg) { struct vidsrc_st *st = (struct vidsrc_st *)arg; if (st->mc) { st->mc->Stop(); st->mc->Release(); } if (st->grabber) { st->grabber->SetCallback(NULL, 1); st->grabber->Release(); } if (st->grabber_filter) st->grabber_filter->Release(); if (st->dev_moniker) st->dev_moniker->Release(); if (st->dev_filter) st->dev_filter->Release(); if (st->capture) { st->capture->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, NULL, NULL, NULL); st->capture->Release(); } if (st->graph) st->graph->Release(); delete st->grab; } static int alloc(struct vidsrc_st **stp, const struct vidsrc *vs, struct media_ctx **ctx, struct vidsrc_prm *prm, const struct vidsz *size, const char *fmt, const char *dev, vidsrc_frame_h *frameh, vidsrc_error_h *errorh, void *arg) { struct vidsrc_st *st; IEnumPins *pin_enum = NULL; IPin *pin = NULL; HRESULT hr; int err; (void)ctx; (void)errorh; if (!stp || !vs || !prm || !size) return EINVAL; st = (struct vidsrc_st *) mem_zalloc(sizeof(*st), destructor); if (!st) return ENOMEM; err = get_device(st, dev); if (err) goto out; st->vs = vs; st->size = *size; st->frameh = frameh; st->arg = arg; st->grab = new Grabber(st); if (!st->grab) { err = ENOMEM; goto out; } hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC, IID_IGraphBuilder, (void **) &st->graph); if (FAILED(hr)) { warning("dshow: alloc: IID_IGraphBuilder failed: %ld\n", hr); err = ENODEV; goto out; } hr = CoCreateInstance(CLSID_CaptureGraphBuilder2 , NULL, CLSCTX_INPROC, IID_ICaptureGraphBuilder2, (void **) &st->capture); if (FAILED(hr)) { warning("dshow: alloc: IID_ICaptureGraphBuilder2: %ld\n", hr); err = ENODEV; goto out; } hr = st->capture->SetFiltergraph(st->graph); if (FAILED(hr)) { warning("dshow: alloc: SetFiltergraph failed: %ld\n", hr); err = ENODEV; goto out; } hr = st->dev_moniker->BindToObject(NULL, NULL, IID_IBaseFilter, (void **) &st->dev_filter); if (FAILED(hr)) { warning("dshow: alloc: bind to base filter failed: %ld\n", hr); err = ENODEV; goto out; } hr = st->graph->AddFilter(st->dev_filter, L"Video Capture"); if (FAILED(hr)) { warning("dshow: alloc: VideoCapture failed: %ld\n", hr); err = ENODEV; goto out; } hr = st->dev_filter->EnumPins(&pin_enum); if (pin_enum) { pin_enum->Reset(); hr = pin_enum->Next(1, &pin, NULL); } add_sample_grabber(st); err = config_pin(st, pin); pin->Release(); if (err) goto out; hr = st->capture->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, st->dev_filter, NULL, st->grabber_filter); if (FAILED(hr)) { warning("dshow: alloc: RenderStream failed\n"); err = ENODEV; goto out; } hr = st->graph->QueryInterface(IID_IMediaControl, (void **) &st->mc); if (FAILED(hr)) { warning("dshow: alloc: IMediaControl failed\n"); err = ENODEV; goto out; } hr = st->mc->Run(); if (FAILED(hr)) { warning("dshow: alloc: Run failed\n"); err = ENODEV; goto out; } out: if (err) mem_deref(st); else *stp = st; return err; } static int module_init(void) { int err; if (CoInitialize(NULL) != S_OK) return ENODATA; err = vidsrc_register(&vsrc, baresip_vidsrcl(), "dshow", alloc, NULL); if (err) return err; list_init(&vsrc->dev_list); err = set_available_devices(&vsrc->dev_list); return err; } static int module_close(void) { vsrc = (struct vidsrc *) mem_deref(vsrc); CoUninitialize(); return 0; } extern "C" const struct mod_export DECL_EXPORTS(dshow) = { "dshow", "vidsrc", module_init, module_close }; baresip-1.0.0/modules/dshow/module.mk000066400000000000000000000002461372575704200175650ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # MOD := dshow $(MOD)_SRCS += dshow.cpp $(MOD)_LFLAGS += -lstrmiids -lole32 -loleaut32 -lstdc++ include mk/mod.mk baresip-1.0.0/modules/dtls_srtp/000077500000000000000000000000001372575704200166375ustar00rootroot00000000000000baresip-1.0.0/modules/dtls_srtp/dtls.c000066400000000000000000000007661372575704200177620ustar00rootroot00000000000000/** * @file dtls.c DTLS functions * * Copyright (C) 2010 Creytiv.com */ #include #include #include "dtls_srtp.h" int dtls_print_sha256_fingerprint(struct re_printf *pf, const struct tls *tls) { uint8_t md[32]; unsigned int i; int err = 0; if (!tls) return EINVAL; err = tls_fingerprint(tls, TLS_FINGERPRINT_SHA256, md, sizeof(md)); if (err) return err; for (i=0; i #include #include #include "dtls_srtp.h" /** * @defgroup dtls_srtp dtls_srtp * * DTLS-SRTP media encryption module * * This module implements end-to-end media encryption using DTLS-SRTP * which is now mandatory for WebRTC endpoints. * * DTLS-SRTP can be enabled in ~/.baresip/accounts: * \verbatim ;mediaenc=dtls_srtp \endverbatim * * * Internally the protocol stack diagram looks something like this: * \verbatim * application * | * | * [DTLS] [SRTP] * \ / * \ / * \ / * \/ * ( TURN/ICE ) * | * | * [socket] \endverbatim * */ struct menc_sess { struct sdp_session *sdp; bool offerer; menc_event_h *eventh; menc_error_h *errorh; void *arg; }; /* media */ struct dtls_srtp { struct comp compv[2]; const struct menc_sess *sess; struct sdp_media *sdpm; const struct stream *strm; /**< pointer to parent */ bool started; bool active; bool mux; }; static struct tls *tls; static const char* srtp_profiles = "SRTP_AES128_CM_SHA1_80:" "SRTP_AES128_CM_SHA1_32:" "SRTP_AEAD_AES_128_GCM:" "SRTP_AEAD_AES_256_GCM"; static void sess_destructor(void *arg) { struct menc_sess *sess = arg; mem_deref(sess->sdp); } static void destructor(void *arg) { struct dtls_srtp *st = arg; size_t i; for (i=0; i<2; i++) { struct comp *c = &st->compv[i]; mem_deref(c->uh_srtp); mem_deref(c->tls_conn); mem_deref(c->dtls_sock); mem_deref(c->app_sock); /* must be freed last */ mem_deref(c->tx); mem_deref(c->rx); } mem_deref(st->sdpm); } static bool verify_fingerprint(const struct sdp_session *sess, const struct sdp_media *media, struct tls_conn *tc) { struct pl hash; uint8_t md_sdp[32], md_dtls[32]; size_t sz_sdp = sizeof(md_sdp); size_t sz_dtls; enum tls_fingerprint type; int err; if (sdp_fingerprint_decode(sdp_media_session_rattr(media, sess, "fingerprint"), &hash, md_sdp, &sz_sdp)) return false; if (0 == pl_strcasecmp(&hash, "sha-256")) { type = TLS_FINGERPRINT_SHA256; sz_dtls = 32; } else { warning("dtls_srtp: unknown fingerprint '%r'\n", &hash); return false; } err = tls_peer_fingerprint(tc, type, md_dtls, sizeof(md_dtls)); if (err) { warning("dtls_srtp: could not get DTLS fingerprint (%m)\n", err); return false; } if (sz_sdp != sz_dtls || 0 != memcmp(md_sdp, md_dtls, sz_sdp)) { warning("dtls_srtp: %r fingerprint mismatch\n", &hash); info("SDP: %w\n", md_sdp, sz_sdp); info("DTLS: %w\n", md_dtls, sz_dtls); return false; } info("dtls_srtp: verified %r fingerprint OK\n", &hash); return true; } static int session_alloc(struct menc_sess **sessp, struct sdp_session *sdp, bool offerer, menc_event_h *eventh, menc_error_h *errorh, void *arg) { struct menc_sess *sess; int err; if (!sessp || !sdp) return EINVAL; sess = mem_zalloc(sizeof(*sess), sess_destructor); if (!sess) return ENOMEM; sess->sdp = mem_ref(sdp); sess->offerer = offerer; sess->eventh = eventh; sess->errorh = errorh; sess->arg = arg; /* RFC 4145 */ err = sdp_session_set_lattr(sdp, true, "setup", offerer ? "actpass" : "active"); if (err) goto out; /* RFC 4572 */ err = sdp_session_set_lattr(sdp, true, "fingerprint", "SHA-256 %H", dtls_print_sha256_fingerprint, tls); if (err) goto out; out: if (err) mem_deref(sess); else *sessp = sess; return err; } static size_t get_master_keylen(enum srtp_suite suite) { switch (suite) { case SRTP_AES_CM_128_HMAC_SHA1_32: return 16+14; case SRTP_AES_CM_128_HMAC_SHA1_80: return 16+14; case SRTP_AES_128_GCM: return 16+12; case SRTP_AES_256_GCM: return 32+12; default: return 0; } } static void dtls_estab_handler(void *arg) { struct comp *comp = arg; const struct dtls_srtp *ds = comp->ds; enum srtp_suite suite; uint8_t cli_key[32+12], srv_key[32+12]; char buf[32] = ""; size_t keylen; int err; if (!verify_fingerprint(ds->sess->sdp, ds->sdpm, comp->tls_conn)) { warning("dtls_srtp: could not verify remote fingerprint\n"); if (ds->sess->errorh) ds->sess->errorh(EPIPE, ds->sess->arg); return; } err = tls_srtp_keyinfo(comp->tls_conn, &suite, cli_key, sizeof(cli_key), srv_key, sizeof(srv_key)); if (err) { warning("dtls_srtp: could not get SRTP keyinfo (%m)\n", err); return; } comp->negotiated = true; info("dtls_srtp: ---> DTLS-SRTP complete (%s/%s) Profile=%s\n", sdp_media_name(ds->sdpm), comp->is_rtp ? "RTP" : "RTCP", srtp_suite_name(suite)); keylen = get_master_keylen(suite); err |= srtp_stream_add(&comp->tx, suite, ds->active ? cli_key : srv_key, keylen, true); err |= srtp_stream_add(&comp->rx, suite, ds->active ? srv_key : cli_key, keylen, false); if (err) return; err |= srtp_install(comp); if (err) { warning("dtls_srtp: srtp_install: %m\n", err); } if (ds->sess->eventh) { if (re_snprintf(buf, sizeof(buf), "%s,%s", sdp_media_name(ds->sdpm), comp->is_rtp ? "RTP" : "RTCP")) ds->sess->eventh(MENC_EVENT_SECURE, buf, (struct stream *)ds->strm, ds->sess->arg); else warning("dtls_srtp: failed to print secure" " event arguments\n"); } } static void dtls_close_handler(int err, void *arg) { struct comp *comp = arg; info("dtls_srtp: dtls-connection closed (%m)\n", err); comp->tls_conn = mem_deref(comp->tls_conn); if (!comp->negotiated) { if (comp->ds->sess->errorh) comp->ds->sess->errorh(err, comp->ds->sess->arg); } } static void dtls_conn_handler(const struct sa *peer, void *arg) { struct comp *comp = arg; int err; (void)peer; info("dtls_srtp: incoming DTLS connect from %J\n", peer); if (comp->tls_conn) { warning("dtls_srtp: dtls already accepted (peer = %J)\n", dtls_peer(comp->tls_conn)); return; } err = dtls_accept(&comp->tls_conn, tls, comp->dtls_sock, dtls_estab_handler, NULL, dtls_close_handler, comp); if (err) { warning("dtls_srtp: dtls_accept failed (%m)\n", err); return; } } static int component_start(struct comp *comp, const struct sa *raddr) { int err = 0; debug("dtls_srtp: component start: %s [raddr=%J]\n", comp->is_rtp ? "RTP" : "RTCP", raddr); if (!comp->app_sock || comp->negotiated || comp->dtls_sock) return 0; err = dtls_listen(&comp->dtls_sock, NULL, comp->app_sock, 2, LAYER_DTLS, dtls_conn_handler, comp); if (err) { warning("dtls_srtp: dtls_listen failed (%m)\n", err); return err; } if (sa_isset(raddr, SA_ALL)) { if (comp->ds->active && !comp->tls_conn) { info("dtls_srtp: '%s,%s' dtls connect to %J\n", sdp_media_name(comp->ds->sdpm), comp->is_rtp ? "RTP" : "RTCP", raddr); err = dtls_connect(&comp->tls_conn, tls, comp->dtls_sock, raddr, dtls_estab_handler, NULL, dtls_close_handler, comp); if (err) { warning("dtls_srtp: dtls_connect()" " failed (%m)\n", err); return err; } } } return err; } static int media_start(struct dtls_srtp *st, struct sdp_media *sdpm, const struct sa *raddr_rtp, const struct sa *raddr_rtcp) { int err = 0; if (st->started) return 0; info("dtls_srtp: media=%s -- start DTLS %s\n", sdp_media_name(sdpm), st->active ? "client" : "server"); if (!sdp_media_has_media(sdpm)) return 0; err = component_start(&st->compv[0], raddr_rtp); if (!st->mux) err |= component_start(&st->compv[1], raddr_rtcp); if (err) return err; st->started = true; return 0; } static int media_alloc(struct menc_media **mp, struct menc_sess *sess, struct rtp_sock *rtp, struct udp_sock *rtpsock, struct udp_sock *rtcpsock, const struct sa *raddr_rtp, const struct sa *raddr_rtcp, struct sdp_media *sdpm, const struct stream *strm) { struct dtls_srtp *st; const char *setup, *fingerprint; int err = 0; unsigned i; (void)rtp; if (!mp || !sess) return EINVAL; st = (struct dtls_srtp *)*mp; if (st) goto setup; st = mem_zalloc(sizeof(*st), destructor); if (!st) return ENOMEM; st->sess = sess; st->sdpm = mem_ref(sdpm); st->strm = strm; st->compv[0].app_sock = mem_ref(rtpsock); st->compv[1].app_sock = mem_ref(rtcpsock); for (i=0; i<2; i++) st->compv[i].ds = st; st->compv[0].is_rtp = true; st->compv[1].is_rtp = false; err = sdp_media_set_alt_protos(st->sdpm, 4, "RTP/SAVP", "RTP/SAVPF", "UDP/TLS/RTP/SAVP", "UDP/TLS/RTP/SAVPF"); if (err) goto out; out: if (err) { mem_deref(st); return err; } else *mp = (struct menc_media *)st; setup: st->mux = (rtpsock == rtcpsock) || (rtcpsock == NULL); setup = sdp_media_session_rattr(st->sdpm, st->sess->sdp, "setup"); if (setup) { st->active = !(0 == str_casecmp(setup, "active")); err = media_start(st, st->sdpm, raddr_rtp, raddr_rtcp); if (err) return err; } /* SDP offer/answer on fingerprint attribute */ fingerprint = sdp_media_session_rattr(st->sdpm, st->sess->sdp, "fingerprint"); if (fingerprint) { struct pl hash; err = sdp_fingerprint_decode(fingerprint, &hash, NULL, NULL); if (err) return err; if (0 == pl_strcasecmp(&hash, "SHA-256")) { err = sdp_media_set_lattr(st->sdpm, true, "fingerprint", "SHA-256 %H", dtls_print_sha256_fingerprint, tls); } else { info("dtls_srtp: unsupported fingerprint hash `%r'\n", &hash); return EPROTO; } } return err; } static struct menc dtls_srtp = { .id = "dtls_srtp", .sdp_proto = "UDP/TLS/RTP/SAVPF", .wait_secure = true, .sessh = session_alloc, .mediah = media_alloc }; static int module_init(void) { struct list *mencl = baresip_mencl(); int err; err = tls_alloc(&tls, TLS_METHOD_DTLSV1, NULL, NULL); if (err) { warning("dtls_srtp: failed to create DTLS context (%m)\n", err); return err; } err = tls_set_selfsigned_rsa(tls, "dtls@baresip", 2048); if (err) { warning("dtls_srtp: failed to self-sign certificate (%m)\n", err); return err; } tls_set_verify_client(tls); err = tls_set_srtp(tls, srtp_profiles); if (err) { warning("dtls_srtp: failed to enable SRTP profile (%m)\n", err); return err; } menc_register(mencl, &dtls_srtp); debug("DTLS-SRTP ready with profiles %s\n", srtp_profiles); return 0; } static int module_close(void) { menc_unregister(&dtls_srtp); tls = mem_deref(tls); return 0; } EXPORT_SYM const struct mod_export DECL_EXPORTS(dtls_srtp) = { "dtls_srtp", "menc", module_init, module_close }; baresip-1.0.0/modules/dtls_srtp/dtls_srtp.h000066400000000000000000000012461372575704200210310ustar00rootroot00000000000000/** * @file dtls_srtp.h DTLS-SRTP Internal api * * Copyright (C) 2010 Creytiv.com */ enum { LAYER_SRTP = 20, LAYER_DTLS = 20, /* must be above zero */ }; struct comp { const struct dtls_srtp *ds; /* parent */ struct dtls_sock *dtls_sock; struct tls_conn *tls_conn; struct srtp_stream *tx; struct srtp_stream *rx; struct udp_helper *uh_srtp; void *app_sock; bool negotiated; bool is_rtp; }; /* dtls.c */ int dtls_print_sha256_fingerprint(struct re_printf *pf, const struct tls *tls); /* srtp.c */ int srtp_stream_add(struct srtp_stream **sp, enum srtp_suite suite, const uint8_t *key, size_t key_size, bool tx); int srtp_install(struct comp *comp); baresip-1.0.0/modules/dtls_srtp/module.mk000066400000000000000000000002231372575704200204520ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # MOD := dtls_srtp $(MOD)_SRCS += dtls_srtp.c srtp.c dtls.c $(MOD)_LFLAGS += include mk/mod.mk baresip-1.0.0/modules/dtls_srtp/srtp.c000066400000000000000000000051231372575704200177740ustar00rootroot00000000000000/** * @file dtls_srtp/srtp.c Secure RTP * * Copyright (C) 2010 Creytiv.com */ #include #include #include "dtls_srtp.h" struct srtp_stream { struct srtp *srtp; }; /* * See RFC 5764 figure 3: * * +----------------+ * | 127 < B < 192 -+--> forward to RTP * | | * packet --> | 19 < B < 64 -+--> forward to DTLS * | | * | B < 2 -+--> forward to STUN * +----------------+ * */ static inline bool is_rtp_or_rtcp(const struct mbuf *mb) { uint8_t b; if (mbuf_get_left(mb) < 1) return false; b = mbuf_buf(mb)[0]; return 127 < b && b < 192; } static inline bool is_rtcp_packet(const struct mbuf *mb) { uint8_t pt; if (mbuf_get_left(mb) < 2) return false; pt = mbuf_buf(mb)[1] & 0x7f; return 64 <= pt && pt <= 95; } static void destructor(void *arg) { struct srtp_stream *s = arg; mem_deref(s->srtp); } static bool send_handler(int *err, struct sa *dst, struct mbuf *mb, void *arg) { struct comp *comp = arg; (void)dst; if (!is_rtp_or_rtcp(mb)) return false; if (is_rtcp_packet(mb)) { *err = srtcp_encrypt(comp->tx->srtp, mb); if (*err) { warning("srtp: srtcp_encrypt failed (%m)\n", *err); } } else { *err = srtp_encrypt(comp->tx->srtp, mb); if (*err) { warning("srtp: srtp_encrypt failed (%m)\n", *err); } } return *err ? true : false; /* continue processing */ } static bool recv_handler(struct sa *src, struct mbuf *mb, void *arg) { struct comp *comp = arg; int err; (void)src; if (!is_rtp_or_rtcp(mb)) return false; if (is_rtcp_packet(mb)) { err = srtcp_decrypt(comp->rx->srtp, mb); } else { err = srtp_decrypt(comp->rx->srtp, mb); } if (err) { warning("srtp: recv: failed to decrypt %s-packet (%m)\n", is_rtcp_packet(mb) ? "RTCP" : "RTP", err); return true; /* error - drop packet */ } return false; /* continue processing */ } int srtp_stream_add(struct srtp_stream **sp, enum srtp_suite suite, const uint8_t *key, size_t key_size, bool tx) { struct srtp_stream *s; int err = 0; (void)tx; if (!sp || !key) return EINVAL; s = mem_zalloc(sizeof(*s), destructor); if (!s) return ENOMEM; err = srtp_alloc(&s->srtp, suite, key, key_size, 0); if (err) { warning("srtp: srtp_alloc() failed (%m)\n", err); goto out; } out: if (err) mem_deref(s); else *sp = s; return err; } int srtp_install(struct comp *comp) { return udp_register_helper(&comp->uh_srtp, comp->app_sock, LAYER_SRTP, send_handler, recv_handler, comp); } baresip-1.0.0/modules/ebuacip/000077500000000000000000000000001372575704200162315ustar00rootroot00000000000000baresip-1.0.0/modules/ebuacip/ebuacip.c000066400000000000000000000075131372575704200200130ustar00rootroot00000000000000/** * @file ebuacip.c EBU ACIP (Audio Contribution over IP) Profile * * Copyright (C) 2010 Creytiv.com */ #include #include /** * @defgroup ebuacip ebuacip * * EBU ACIP (Audio Contribution over IP) Profile * * Ref: https://tech.ebu.ch/docs/tech/tech3368.pdf * * Example config: * \verbatim ebuacip_jb_type auto|fixed \endverbatim */ static char jb_type[16]; static int set_ebuacip_params(struct audio *au) { struct stream *strm = audio_strm(au); struct sdp_media *sdp = stream_sdpmedia(strm); struct config *cfg = conf_config(); const struct config_avt *avt = &cfg->avt; struct config_audio *audio = audio_config(au); const struct list *lst; struct le *le; int jb_id = 0; int err = 0; /* set ebuacip version fixed value 0 for now. */ err |= sdp_media_set_lattr(sdp, false, "ebuacip", "version %i", 0); /* set jb option, only one in our case */ err |= sdp_media_set_lattr(sdp, false, "ebuacip", "jb %i", jb_id); /* define jb value in option */ if (0 == str_casecmp(jb_type, "auto")) { err |= sdp_media_set_lattr(sdp, false, "ebuacip", "jbdef %i auto %d-%d", jb_id, audio->buffer.min, audio->buffer.max); } else if (0 == str_casecmp(jb_type, "fixed")) { /* define jb value in option from audio buffer min value */ err |= sdp_media_set_lattr(sdp, false, "ebuacip", "jbdef %i fixed %d", jb_id, audio->buffer.min); } /* set QOS recomendation use tos / 4 to set DSCP value */ err |= sdp_media_set_lattr(sdp, false, "ebuacip", "qosrec %u", avt->rtp_tos / 4); /* EBU ACIP FEC:: NOT SET IN BARESIP */ lst = sdp_media_format_lst(sdp, true); for (le = list_head(lst); le; le = le->next) { const struct sdp_format *fmt = le->data; struct aucodec *ac = fmt->data; if (!fmt->sup) continue; if (!fmt->data) continue; if (ac->ptime) { err |= sdp_media_set_lattr(sdp, false, "ebuacip", "plength %s %u", fmt->id, ac->ptime); } } return err; } static bool ebuacip_handler(const char *name, const char *value, void *arg) { struct audio *au = arg; struct config_audio *cfg = audio_config(au); struct sdp_media *sdp; struct pl val, val_min, val_max; (void)name; /* check type first, if not fixed or auto, return false */ if (0 == re_regex(value, str_len(value), "jbdef [0-9]+ auto [0-9]+-[0-9]+", NULL, &val_min, &val_max)) { /* set audio buffer from min and max value*/ cfg->buffer.min = pl_u32(&val_min); cfg->buffer.max = pl_u32(&val_max); } else if (0 == re_regex(value, str_len(value), "jbdef [0-9]+ fixed [0-9]+", NULL, &val)) { uint32_t v = pl_u32(&val); /* set both audio buffer min and max value to val*/ cfg->buffer.min = v; cfg->buffer.max = v; } else { return false; } sdp = stream_sdpmedia(audio_strm(au)); sdp_media_del_lattr(sdp, "ebuacip"); return true; } static void ua_event_handler(struct ua *ua, enum ua_event ev, struct call *call, const char *prm, void *arg) { struct audio *au; (void)prm; (void)arg; #if 1 debug(".... ebuacip: [ ua=%s call=%s ] event: %s (%s)\n", ua_aor(ua), call_id(call), uag_event_str(ev), prm); #endif switch (ev) { case UA_EVENT_CALL_LOCAL_SDP: if (0 == str_casecmp(prm, "offer")) set_ebuacip_params(call_audio(call)); break; case UA_EVENT_CALL_REMOTE_SDP: au = call_audio(call); sdp_media_rattr_apply(stream_sdpmedia(audio_strm(au)), "ebuacip", ebuacip_handler, au); break; default: break; } } static int module_init(void) { conf_get_str(conf_cur(), "ebuacip_jb_type", jb_type, sizeof(jb_type)); return uag_event_register(ua_event_handler, NULL); } static int module_close(void) { uag_event_unregister(ua_event_handler); return 0; } const struct mod_export DECL_EXPORTS(ebuacip) = { "ebuacip", "application", module_init, module_close }; baresip-1.0.0/modules/ebuacip/module.mk000066400000000000000000000001601372575704200200440ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # MOD := ebuacip $(MOD)_SRCS += ebuacip.c include mk/mod.mk baresip-1.0.0/modules/echo/000077500000000000000000000000001372575704200155375ustar00rootroot00000000000000baresip-1.0.0/modules/echo/echo.c000066400000000000000000000046331372575704200166270ustar00rootroot00000000000000/** * @file echo.c Echo module */ #include #include /** * * Multi Call Echo module * * REQUIRES: aubridge * NOTE: This module is experimental. * */ struct session { struct le le; struct call *call_in; }; static struct list sessionl; static void destructor(void *arg) { struct session *sess = arg; debug("echo: session destroyed\n"); list_unlink(&sess->le); } static void call_event_handler(struct call *call, enum call_event ev, const char *str, void *arg) { struct session *sess = arg; (void)call; switch (ev) { case CALL_EVENT_CLOSED: debug("echo: CALL_CLOSED: %s\n", str); mem_deref(sess->call_in); mem_deref(sess); break; default: break; } } static void call_dtmf_handler(struct call *call, char key, void *arg) { (void)arg; debug("echo: relaying DTMF event: key = '%c'\n", key ? key : '.'); call_send_digit(call, key); } static int new_session(struct ua *ua, struct call *call) { struct session *sess; char a[64]; int err = 0; sess = mem_zalloc(sizeof(*sess), destructor); if (!sess) return ENOMEM; sess->call_in = call; re_snprintf(a, sizeof(a), "A-%x", sess); audio_set_devicename(call_audio(sess->call_in), a, a); video_set_devicename(call_video(sess->call_in), a, a); call_set_handlers(sess->call_in, call_event_handler, call_dtmf_handler, sess); list_append(&sessionl, &sess->le, sess); err = ua_answer(ua, call, VIDMODE_ON); if (err) mem_deref(sess); return err; } static void ua_event_handler(struct ua *ua, enum ua_event ev, struct call *call, const char *prm, void *arg) { int err; (void)prm; (void)arg; switch (ev) { case UA_EVENT_CALL_INCOMING: info("echo: CALL_INCOMING: peer=%s --> local=%s\n", call_peeruri(call), call_localuri(call)); err = new_session(ua, call); if (err) { call_hangup(call, 500, "Server Error"); } break; default: break; } } static int module_init(void) { int err; list_init(&sessionl); err = uag_event_register(ua_event_handler, 0); if (err) return err; debug("echo: module loaded\n"); return 0; } static int module_close(void) { debug("echo: module closing..\n"); if (!list_isempty(&sessionl)) { info("echo: flushing %u sessions\n", list_count(&sessionl)); list_flush(&sessionl); } uag_event_unregister(ua_event_handler); return 0; } const struct mod_export DECL_EXPORTS(echo) = { "echo", "application", module_init, module_close }; baresip-1.0.0/modules/echo/module.mk000066400000000000000000000001111372575704200173460ustar00rootroot00000000000000# # module.mk # # MOD := echo $(MOD)_SRCS += echo.c include mk/mod.mk baresip-1.0.0/modules/evdev/000077500000000000000000000000001372575704200157325ustar00rootroot00000000000000baresip-1.0.0/modules/evdev/evdev.c000066400000000000000000000141031372575704200172060ustar00rootroot00000000000000/** * @file evdev.c Input event device UI module * * Copyright (C) 2010 Creytiv.com */ #include #include #include #include #include #include #include #include #include "print.h" /** * @defgroup evdev evdev * * User-Interface (UI) module using the Linux input subsystem. * * The following options can be configured: * \verbatim evdev_device /dev/input/event0 # Name of the input device to use \endverbatim */ struct ui_st { int fd; }; static struct ui_st *evdev; static char evdev_device[64] = "/dev/input/event0"; static void evdev_close(struct ui_st *st) { if (st->fd < 0) return; fd_close(st->fd); (void)close(st->fd); st->fd = -1; } static void evdev_destructor(void *arg) { struct ui_st *st = arg; evdev_close(st); } static int code2ascii(uint16_t modifier, uint16_t code) { switch (code) { case KEY_0: return '0'; case KEY_1: return '1'; case KEY_2: return '2'; case KEY_3: return KEY_LEFTSHIFT==modifier ? '#' : '3'; case KEY_4: return '4'; case KEY_5: return '5'; case KEY_6: return '6'; case KEY_7: return '7'; case KEY_8: return '8'; case KEY_9: return '9'; case KEY_BACKSPACE: return '\b'; case KEY_ENTER: return '\n'; case KEY_ESC: return 0x1b; case KEY_KPASTERISK: return '*'; #ifdef KEY_NUMERIC_0 case KEY_NUMERIC_0: return '0'; #endif #ifdef KEY_NUMERIC_1 case KEY_NUMERIC_1: return '1'; #endif #ifdef KEY_NUMERIC_2 case KEY_NUMERIC_2: return '2'; #endif #ifdef KEY_NUMERIC_3 case KEY_NUMERIC_3: return '3'; #endif #ifdef KEY_NUMERIC_4 case KEY_NUMERIC_4: return '4'; #endif #ifdef KEY_NUMERIC_5 case KEY_NUMERIC_5: return '5'; #endif #ifdef KEY_NUMERIC_6 case KEY_NUMERIC_6: return '6'; #endif #ifdef KEY_NUMERIC_7 case KEY_NUMERIC_7: return '7'; #endif #ifdef KEY_NUMERIC_8 case KEY_NUMERIC_8: return '8'; #endif #ifdef KEY_NUMERIC_9 case KEY_NUMERIC_9: return '9'; #endif #ifdef KEY_NUMERIC_STAR case KEY_NUMERIC_STAR: return '*'; #endif #ifdef KEY_NUMERIC_POUND case KEY_NUMERIC_POUND: return '#'; #endif #ifdef KEY_KP0 case KEY_KP0: return '0'; #endif #ifdef KEY_KP1 case KEY_KP1: return '1'; #endif #ifdef KEY_KP2 case KEY_KP2: return '2'; #endif #ifdef KEY_KP3 case KEY_KP3: return '3'; #endif #ifdef KEY_KP4 case KEY_KP4: return '4'; #endif #ifdef KEY_KP5 case KEY_KP5: return '5'; #endif #ifdef KEY_KP6 case KEY_KP6: return '6'; #endif #ifdef KEY_KP7 case KEY_KP7: return '7'; #endif #ifdef KEY_KP8 case KEY_KP8: return '8'; #endif #ifdef KEY_KP9 case KEY_KP9: return '9'; #endif #ifdef KEY_KPDOT case KEY_KPDOT: return 0x1b; #endif #ifdef KEY_KPENTER case KEY_KPENTER: return '\n'; #endif default: return -1; } } static int stderr_handler(const char *p, size_t sz, void *arg) { (void)arg; if (write(STDERR_FILENO, p, sz) < 0) return errno; return 0; } static void reportkey(struct ui_st *st, int ascii) { static struct re_printf pf_stderr = {stderr_handler, NULL}; (void)st; ui_input_key(baresip_uis(), ascii, &pf_stderr); } static void evdev_fd_handler(int flags, void *arg) { struct ui_st *st = arg; struct input_event evv[64]; /* the events (up to 64 at once) */ uint16_t modifier = 0; size_t n; int i; /* This might happen if you unplug a USB device */ if (flags & FD_EXCEPT) { warning("evdev: fd handler: FD_EXCEPT - device unplugged?\n"); evdev_close(st); return; } n = read(st->fd, evv, sizeof(evv)); if (n < (int) sizeof(struct input_event)) { warning("evdev: event: short read (%m)\n", errno); return; } for (i = 0; i < (int) (n / sizeof(struct input_event)); i++) { const struct input_event *ev = &evv[i]; if (EV_KEY != ev->type) continue; if (KEY_LEFTSHIFT == ev->code) { modifier = KEY_LEFTSHIFT; continue; } if (1 == ev->value) { const int ascii = code2ascii(modifier, ev->code); if (-1 == ascii) { warning("evdev: unhandled key code %u\n", ev->code); } else reportkey(st, ascii); modifier = 0; } else if (0 == ev->value) { reportkey(st, KEYCODE_REL); } } } static int evdev_alloc(struct ui_st **stp, const char *dev) { struct ui_st *st; int err = 0; if (!stp) return EINVAL; st = mem_zalloc(sizeof(*st), evdev_destructor); if (!st) return ENOMEM; st->fd = open(dev, O_RDWR); if (st->fd < 0) { err = errno; warning("evdev: failed to open device '%s' (%m)\n", dev, err); goto out; } #if 0 /* grab the event device to prevent it from propagating its events to the regular keyboard driver */ if (-1 == ioctl(st->fd, EVIOCGRAB, (void *)1)) { warning("evdev: ioctl EVIOCGRAB on %s (%m)\n", dev, errno); } #endif print_name(st->fd); print_events(st->fd); print_keys(st->fd); print_leds(st->fd); err = fd_listen(st->fd, FD_READ, evdev_fd_handler, st); if (err) goto out; out: if (err) mem_deref(st); else *stp = st; return err; } static int buzz(const struct ui_st *st, int value) { struct input_event ev; ssize_t n; ev.type = EV_SND; ev.code = SND_BELL; ev.value = value; n = write(st->fd, &ev, sizeof(ev)); if (n < 0) { warning("evdev: output: write fd=%d (%m)\n", st->fd, errno); } return errno; } static int evdev_output(const char *str) { struct ui_st *st = evdev; int err = 0; if (!st || !str) return EINVAL; while (*str) { switch (*str++) { case '\a': err |= buzz(st, 1); break; default: err |= buzz(st, 0); break; } } return err; } static struct ui ui_evdev = { .name = "evdev", .outputh = evdev_output }; static int module_init(void) { int err; conf_get_str(conf_cur(), "evdev_device", evdev_device, sizeof(evdev_device)); err = evdev_alloc(&evdev, evdev_device); if (err) return err; ui_register(baresip_uis(), &ui_evdev); return 0; } static int module_close(void) { ui_unregister(&ui_evdev); evdev = mem_deref(evdev); return 0; } const struct mod_export DECL_EXPORTS(evdev) = { "evdev", "ui", module_init, module_close }; baresip-1.0.0/modules/evdev/module.mk000066400000000000000000000002241372575704200175460ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # MOD := evdev $(MOD)_SRCS += evdev.c $(MOD)_SRCS += print.c $(MOD)_LFLAGS += include mk/mod.mk baresip-1.0.0/modules/evdev/print.c000066400000000000000000000422131372575704200172340ustar00rootroot00000000000000/** * @file print.c Input event device info * * Copyright (C) 2010 Creytiv.com */ #include #include #include #include #include #include #include #include #include #include "print.h" #define test_bit(bit, array) (array[bit/8] & (1<<(bit%8))) /** * Print the name information * * @param fd Device file descriptor */ void print_name(int fd) { char name[256]= "Unknown"; if (ioctl(fd, EVIOCGNAME(sizeof(name)), name) < 0) { perror("evdev ioctl"); } info("evdev: device name: %s\n", name); } /** * Print supported events * * @param fd Device file descriptor */ void print_events(int fd) { uint8_t evtype_bitmask[EV_MAX/8 + 1]; int i; memset(evtype_bitmask, 0, sizeof(evtype_bitmask)); if (ioctl(fd, EVIOCGBIT(0, EV_MAX), evtype_bitmask) < 0) { warning("evdev: ioctl EVIOCGBIT (%m)\n", errno); return; } printf("Supported event types:\n"); for (i = 0; i < EV_MAX; i++) { if (!test_bit(i, evtype_bitmask)) continue; printf(" Event type 0x%02x ", i); switch (i) { case EV_KEY : printf(" (Keys or Buttons)\n"); break; case EV_REL : printf(" (Relative Axes)\n"); break; case EV_ABS : printf(" (Absolute Axes)\n"); break; case EV_MSC : printf(" (Something miscellaneous)\n"); break; case EV_LED : printf(" (LEDs)\n"); break; case EV_SND : printf(" (Sounds)\n"); break; case EV_REP : printf(" (Repeat)\n"); break; case EV_FF : printf(" (Force Feedback)\n"); break; default: printf(" (Unknown event type: 0x%04x)\n", i); break; } } } /** * Print supported keys * * @param fd Device file descriptor */ void print_keys(int fd) { uint8_t key_bitmask[KEY_MAX/8 + 1]; int i; memset(key_bitmask, 0, sizeof(key_bitmask)); if (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(key_bitmask)), key_bitmask) < 0) { perror("evdev ioctl"); } printf("Supported Keys:\n"); for (i = 0; i < KEY_MAX; i++) { if (!test_bit(i, key_bitmask)) continue; printf(" Key 0x%02x ", i); switch (i) { case KEY_RESERVED : printf(" (Reserved)\n"); break; case KEY_ESC : printf(" (Escape)\n"); break; case KEY_1 : printf(" (1)\n"); break; case KEY_2 : printf(" (2)\n"); break; case KEY_3 : printf(" (3)\n"); break; case KEY_4 : printf(" (4)\n"); break; case KEY_5 : printf(" (5)\n"); break; case KEY_6 : printf(" (6)\n"); break; case KEY_7 : printf(" (7)\n"); break; case KEY_8 : printf(" (8)\n"); break; case KEY_9 : printf(" ()\n"); break; case KEY_0 : printf(" ()\n"); break; case KEY_MINUS : printf(" (-)\n"); break; case KEY_EQUAL : printf(" (=)\n"); break; case KEY_BACKSPACE : printf(" (Backspace)\n"); break; case KEY_TAB : printf(" (Tab)\n"); break; case KEY_Q : printf(" (Q)\n"); break; case KEY_W : printf(" (W)\n"); break; case KEY_E : printf(" (E)\n"); break; case KEY_R : printf(" (R)\n"); break; case KEY_T : printf(" (T)\n"); break; case KEY_Y : printf(" (Y)\n"); break; case KEY_U : printf(" (U)\n"); break; case KEY_I : printf(" (I)\n"); break; case KEY_O : printf(" (O)\n"); break; case KEY_P : printf(" (P)\n"); break; case KEY_LEFTBRACE : printf(" ([)\n"); break; case KEY_RIGHTBRACE : printf(" (])\n"); break; case KEY_ENTER : printf(" (Enter)\n"); break; case KEY_LEFTCTRL : printf(" (LH Control)\n"); break; case KEY_A : printf(" (A)\n"); break; case KEY_S : printf(" (S)\n"); break; case KEY_D : printf(" (D)\n"); break; case KEY_F : printf(" (F)\n"); break; case KEY_G : printf(" (G)\n"); break; case KEY_H : printf(" (H)\n"); break; case KEY_J : printf(" (J)\n"); break; case KEY_K : printf(" (K)\n"); break; case KEY_L : printf(" (L)\n"); break; case KEY_SEMICOLON : printf(" (;)\n"); break; case KEY_APOSTROPHE : printf(" (')\n"); break; case KEY_GRAVE : printf(" (`)\n"); break; case KEY_LEFTSHIFT : printf(" (LH Shift)\n"); break; case KEY_BACKSLASH : printf(" (\\)\n"); break; case KEY_Z : printf(" (Z)\n"); break; case KEY_X : printf(" (X)\n"); break; case KEY_C : printf(" (C)\n"); break; case KEY_V : printf(" (V)\n"); break; case KEY_B : printf(" (B)\n"); break; case KEY_N : printf(" (N)\n"); break; case KEY_M : printf(" (M)\n"); break; case KEY_COMMA : printf(" (,)\n"); break; case KEY_DOT : printf(" (.)\n"); break; case KEY_SLASH : printf(" (/)\n"); break; case KEY_RIGHTSHIFT : printf(" (RH Shift)\n"); break; case KEY_KPASTERISK : printf(" (*)\n"); break; case KEY_LEFTALT : printf(" (LH Alt)\n"); break; case KEY_SPACE : printf(" (Space)\n"); break; case KEY_CAPSLOCK : printf(" (CapsLock)\n"); break; case KEY_F1 : printf(" (F1)\n"); break; case KEY_F2 : printf(" (F2)\n"); break; case KEY_F3 : printf(" (F3)\n"); break; case KEY_F4 : printf(" (F4)\n"); break; case KEY_F5 : printf(" (F5)\n"); break; case KEY_F6 : printf(" (F6)\n"); break; case KEY_F7 : printf(" (F7)\n"); break; case KEY_F8 : printf(" (F8)\n"); break; case KEY_F9 : printf(" (F9)\n"); break; case KEY_F10 : printf(" (F10)\n"); break; case KEY_NUMLOCK : printf(" (NumLock)\n"); break; case KEY_SCROLLLOCK : printf(" (ScrollLock)\n"); break; case KEY_KP7 : printf(" (KeyPad 7)\n"); break; case KEY_KP8 : printf(" (KeyPad 8)\n"); break; case KEY_KP9 : printf(" (Keypad 9)\n"); break; case KEY_KPMINUS : printf(" (KeyPad Minus)\n"); break; case KEY_KP4 : printf(" (KeyPad 4)\n"); break; case KEY_KP5 : printf(" (KeyPad 5)\n"); break; case KEY_KP6 : printf(" (KeyPad 6)\n"); break; case KEY_KPPLUS : printf(" (KeyPad Plus)\n"); break; case KEY_KP1 : printf(" (KeyPad 1)\n"); break; case KEY_KP2 : printf(" (KeyPad 2)\n"); break; case KEY_KP3 : printf(" (KeyPad 3)\n"); break; case KEY_KPDOT : printf(" (KeyPad decimal point)\n"); break; /* case KEY_103RD : printf(" (Huh?)\n"); break; */ case KEY_F13 : printf(" (F13)\n"); break; case KEY_102ND : printf(" (Beats me...)\n"); break; case KEY_F11 : printf(" (F11)\n"); break; case KEY_F12 : printf(" (F12)\n"); break; case KEY_F14 : printf(" (F14)\n"); break; case KEY_F15 : printf(" (F15)\n"); break; case KEY_F16 : printf(" (F16)\n"); break; case KEY_F17 : printf(" (F17)\n"); break; case KEY_F18 : printf(" (F18)\n"); break; case KEY_F19 : printf(" (F19)\n"); break; case KEY_F20 : printf(" (F20)\n"); break; case KEY_KPENTER : printf(" (Keypad Enter)\n"); break; case KEY_RIGHTCTRL : printf(" (RH Control)\n"); break; case KEY_KPSLASH : printf(" (KeyPad Forward Slash)\n"); break; case KEY_SYSRQ : printf(" (System Request)\n"); break; case KEY_RIGHTALT : printf(" (RH Alternate)\n"); break; case KEY_LINEFEED : printf(" (Line Feed)\n"); break; case KEY_HOME : printf(" (Home)\n"); break; case KEY_UP : printf(" (Up)\n"); break; case KEY_PAGEUP : printf(" (Page Up)\n"); break; case KEY_LEFT : printf(" (Left)\n"); break; case KEY_RIGHT : printf(" (Right)\n"); break; case KEY_END : printf(" (End)\n"); break; case KEY_DOWN : printf(" (Down)\n"); break; case KEY_PAGEDOWN : printf(" (Page Down)\n"); break; case KEY_INSERT : printf(" (Insert)\n"); break; case KEY_DELETE : printf(" (Delete)\n"); break; case KEY_MACRO : printf(" (Macro)\n"); break; case KEY_MUTE : printf(" (Mute)\n"); break; case KEY_VOLUMEDOWN : printf(" (Volume Down)\n"); break; case KEY_VOLUMEUP : printf(" (Volume Up)\n"); break; case KEY_POWER : printf(" (Power)\n"); break; case KEY_KPEQUAL : printf(" (KeyPad Equal)\n"); break; case KEY_KPPLUSMINUS : printf(" (KeyPad +/-)\n"); break; case KEY_PAUSE : printf(" (Pause)\n"); break; case KEY_F21 : printf(" (F21)\n"); break; case KEY_F22 : printf(" (F22)\n"); break; case KEY_F23 : printf(" (F23)\n"); break; case KEY_F24 : printf(" (F24)\n"); break; case KEY_KPCOMMA : printf(" (KeyPad comma)\n"); break; case KEY_LEFTMETA : printf(" (LH Meta)\n"); break; case KEY_RIGHTMETA : printf(" (RH Meta)\n"); break; case KEY_COMPOSE : printf(" (Compose)\n"); break; case KEY_STOP : printf(" (Stop)\n"); break; case KEY_AGAIN : printf(" (Again)\n"); break; case KEY_PROPS : printf(" (Properties)\n"); break; case KEY_UNDO : printf(" (Undo)\n"); break; case KEY_FRONT : printf(" (Front)\n"); break; case KEY_COPY : printf(" (Copy)\n"); break; case KEY_OPEN : printf(" (Open)\n"); break; case KEY_PASTE : printf(" (Paste)\n"); break; case KEY_FIND : printf(" (Find)\n"); break; case KEY_CUT : printf(" (Cut)\n"); break; case KEY_HELP : printf(" (Help)\n"); break; case KEY_MENU : printf(" (Menu)\n"); break; case KEY_CALC : printf(" (Calculator)\n"); break; case KEY_SETUP : printf(" (Setup)\n"); break; case KEY_SLEEP : printf(" (Sleep)\n"); break; case KEY_WAKEUP : printf(" (Wakeup)\n"); break; case KEY_FILE : printf(" (File)\n"); break; case KEY_SENDFILE : printf(" (Send File)\n"); break; case KEY_DELETEFILE : printf(" (Delete File)\n"); break; case KEY_XFER : printf(" (Transfer)\n"); break; case KEY_PROG1 : printf(" (Program 1)\n"); break; case KEY_PROG2 : printf(" (Program 2)\n"); break; case KEY_WWW : printf(" (Web Browser)\n"); break; case KEY_MSDOS : printf(" (DOS mode)\n"); break; case KEY_COFFEE : printf(" (Coffee)\n"); break; case KEY_DIRECTION : printf(" (Direction)\n"); break; case KEY_CYCLEWINDOWS : printf(" (Window cycle)\n"); break; case KEY_MAIL : printf(" (Mail)\n"); break; case KEY_BOOKMARKS : printf(" (Book Marks)\n"); break; case KEY_COMPUTER : printf(" (Computer)\n"); break; case KEY_BACK : printf(" (Back)\n"); break; case KEY_FORWARD : printf(" (Forward)\n"); break; case KEY_CLOSECD : printf(" (Close CD)\n"); break; case KEY_EJECTCD : printf(" (Eject CD)\n"); break; case KEY_EJECTCLOSECD : printf(" (Eject / Close CD)\n"); break; case KEY_NEXTSONG : printf(" (Next Song)\n"); break; case KEY_PLAYPAUSE : printf(" (Play and Pause)\n"); break; case KEY_PREVIOUSSONG : printf(" (Previous Song)\n"); break; case KEY_STOPCD : printf(" (Stop CD)\n"); break; case KEY_RECORD : printf(" (Record)\n"); break; case KEY_REWIND : printf(" (Rewind)\n"); break; case KEY_PHONE : printf(" (Phone)\n"); break; case KEY_ISO : printf(" (ISO)\n"); break; case KEY_CONFIG : printf(" (Config)\n"); break; case KEY_HOMEPAGE : printf(" (Home)\n"); break; case KEY_REFRESH : printf(" (Refresh)\n"); break; case KEY_EXIT : printf(" (Exit)\n"); break; case KEY_MOVE : printf(" (Move)\n"); break; case KEY_EDIT : printf(" (Edit)\n"); break; case KEY_SCROLLUP : printf(" (Scroll Up)\n"); break; case KEY_SCROLLDOWN : printf(" (Scroll Down)\n"); break; case KEY_KPLEFTPAREN : printf(" (KeyPad LH paren)\n"); break; case KEY_KPRIGHTPAREN : printf(" (KeyPad RH paren)\n"); break; #if 0 case KEY_INTL1 : printf(" (Intl 1)\n"); break; case KEY_INTL2 : printf(" (Intl 2)\n"); break; case KEY_INTL3 : printf(" (Intl 3)\n"); break; case KEY_INTL4 : printf(" (Intl 4)\n"); break; case KEY_INTL5 : printf(" (Intl 5)\n"); break; case KEY_INTL6 : printf(" (Intl 6)\n"); break; case KEY_INTL7 : printf(" (Intl 7)\n"); break; case KEY_INTL8 : printf(" (Intl 8)\n"); break; case KEY_INTL9 : printf(" (Intl 9)\n"); break; case KEY_LANG1 : printf(" (Language 1)\n"); break; case KEY_LANG2 : printf(" (Language 2)\n"); break; case KEY_LANG3 : printf(" (Language 3)\n"); break; case KEY_LANG4 : printf(" (Language 4)\n"); break; case KEY_LANG5 : printf(" (Language 5)\n"); break; case KEY_LANG6 : printf(" (Language 6)\n"); break; case KEY_LANG7 : printf(" (Language 7)\n"); break; case KEY_LANG8 : printf(" (Language 8)\n"); break; case KEY_LANG9 : printf(" (Language 9)\n"); break; #endif case KEY_PLAYCD : printf(" (Play CD)\n"); break; case KEY_PAUSECD : printf(" (Pause CD)\n"); break; case KEY_PROG3 : printf(" (Program 3)\n"); break; case KEY_PROG4 : printf(" (Program 4)\n"); break; case KEY_SUSPEND : printf(" (Suspend)\n"); break; case KEY_CLOSE : printf(" (Close)\n"); break; case KEY_UNKNOWN : printf(" (Specifically unknown)\n"); break; #ifdef KEY_BRIGHTNESSDOWN case KEY_BRIGHTNESSDOWN: printf(" (Brightness Down)\n");break; #endif #ifdef KEY_BRIGHTNESSUP case KEY_BRIGHTNESSUP : printf(" (Brightness Up)\n"); break; #endif case BTN_0 : printf(" (Button 0)\n"); break; case BTN_1 : printf(" (Button 1)\n"); break; case BTN_2 : printf(" (Button 2)\n"); break; case BTN_3 : printf(" (Button 3)\n"); break; case BTN_4 : printf(" (Button 4)\n"); break; case BTN_5 : printf(" (Button 5)\n"); break; case BTN_6 : printf(" (Button 6)\n"); break; case BTN_7 : printf(" (Button 7)\n"); break; case BTN_8 : printf(" (Button 8)\n"); break; case BTN_9 : printf(" (Button 9)\n"); break; case BTN_LEFT : printf(" (Left Button)\n"); break; case BTN_RIGHT : printf(" (Right Button)\n"); break; case BTN_MIDDLE : printf(" (Middle Button)\n"); break; case BTN_SIDE : printf(" (Side Button)\n"); break; case BTN_EXTRA : printf(" (Extra Button)\n"); break; case BTN_FORWARD : printf(" (Forward Button)\n"); break; case BTN_BACK : printf(" (Back Button)\n"); break; case BTN_TRIGGER : printf(" (Trigger Button)\n"); break; case BTN_THUMB : printf(" (Thumb Button)\n"); break; case BTN_THUMB2 : printf(" (Second Thumb Button)\n"); break; case BTN_TOP : printf(" (Top Button)\n"); break; case BTN_TOP2 : printf(" (Second Top Button)\n"); break; case BTN_PINKIE : printf(" (Pinkie Button)\n"); break; case BTN_BASE : printf(" (Base Button)\n"); break; case BTN_BASE2 : printf(" (Second Base Button)\n"); break; case BTN_BASE3 : printf(" (Third Base Button)\n"); break; case BTN_BASE4 : printf(" (Fourth Base Button)\n"); break; case BTN_BASE5 : printf(" (Fifth Base Button)\n"); break; case BTN_BASE6 : printf(" (Sixth Base Button)\n"); break; case BTN_DEAD : printf(" (Dead Button)\n"); break; case BTN_A : printf(" (Button A)\n"); break; case BTN_B : printf(" (Button B)\n"); break; case BTN_C : printf(" (Button C)\n"); break; case BTN_X : printf(" (Button X)\n"); break; case BTN_Y : printf(" (Button Y)\n"); break; case BTN_Z : printf(" (Button Z)\n"); break; case BTN_TL : printf(" (Thumb Left Button)\n"); break; case BTN_TR : printf(" (Thumb Right Button )\n"); break; case BTN_TL2 : printf(" (Second Thumb Left Button)\n"); break; case BTN_TR2 : printf(" (Second Thumb Right Button )\n"); break; case BTN_SELECT : printf(" (Select Button)\n"); break; case BTN_MODE : printf(" (Mode Button)\n"); break; case BTN_THUMBL : printf(" (Another Left Thumb Button )\n"); break; case BTN_THUMBR : printf(" (Another Right Thumb Button )\n"); break; case BTN_TOOL_PEN : printf(" (Digitiser Pen Tool)\n"); break; case BTN_TOOL_RUBBER : printf(" (Digitiser Rubber Tool)\n"); break; case BTN_TOOL_BRUSH : printf(" (Digitiser Brush Tool)\n"); break; case BTN_TOOL_PENCIL : printf(" (Digitiser Pencil Tool)\n"); break; case BTN_TOOL_AIRBRUSH:printf(" (Digitiser Airbrush Tool)\n"); break; case BTN_TOOL_FINGER : printf(" (Digitiser Finger Tool)\n"); break; case BTN_TOOL_MOUSE : printf(" (Digitiser Mouse Tool)\n"); break; case BTN_TOOL_LENS : printf(" (Digitiser Lens Tool)\n"); break; case BTN_TOUCH : printf(" (Digitiser Touch Button )\n"); break; case BTN_STYLUS : printf(" (Digitiser Stylus Button )\n"); break; case BTN_STYLUS2: printf(" (Second Digitiser Stylus Btn)\n"); break; #ifdef KEY_NUMERIC_0 case KEY_NUMERIC_0: printf(" (Numeric 0)\n"); break; #endif #ifdef KEY_NUMERIC_1 case KEY_NUMERIC_1: printf(" (Numeric 1)\n"); break; #endif #ifdef KEY_NUMERIC_2 case KEY_NUMERIC_2: printf(" (Numeric 2)\n"); break; #endif #ifdef KEY_NUMERIC_3 case KEY_NUMERIC_3: printf(" (Numeric 3)\n"); break; #endif #ifdef KEY_NUMERIC_4 case KEY_NUMERIC_4: printf(" (Numeric 4)\n"); break; #endif #ifdef KEY_NUMERIC_5 case KEY_NUMERIC_5: printf(" (Numeric 5)\n"); break; #endif #ifdef KEY_NUMERIC_6 case KEY_NUMERIC_6: printf(" (Numeric 6)\n"); break; #endif #ifdef KEY_NUMERIC_7 case KEY_NUMERIC_7: printf(" (Numeric 7)\n"); break; #endif #ifdef KEY_NUMERIC_8 case KEY_NUMERIC_8: printf(" (Numeric 8)\n"); break; #endif #ifdef KEY_NUMERIC_9 case KEY_NUMERIC_9: printf(" (Numeric 9)\n"); break; #endif #ifdef KEY_NUMERIC_STAR case KEY_NUMERIC_STAR: printf(" (Numeric *)\n"); break; #endif #ifdef KEY_NUMERIC_POUND case KEY_NUMERIC_POUND: printf(" (Numeric #)\n"); break; #endif default: printf(" (Unknown key)\n"); } } } /** * Print supported LEDs * * @param fd Device file descriptor */ void print_leds(int fd) { uint8_t led_bitmask[LED_MAX/8 + 1]; int i; memset(led_bitmask, 0, sizeof(led_bitmask)); if (ioctl(fd, EVIOCGBIT(EV_LED, sizeof(led_bitmask)), led_bitmask) < 0) { perror("evdev ioctl"); } printf("Supported LEDs:\n"); for (i = 0; i < LED_MAX; i++) { if (!test_bit(i, led_bitmask)) continue; printf(" LED type 0x%02x ", i); switch (i) { case LED_NUML : printf(" (Num Lock)\n"); break; case LED_CAPSL : printf(" (Caps Lock)\n"); break; case LED_SCROLLL : printf(" (Scroll Lock)\n"); break; case LED_COMPOSE : printf(" (Compose)\n"); break; case LED_KANA : printf(" (Kana)\n"); break; case LED_SLEEP : printf(" (Sleep)\n"); break; case LED_SUSPEND : printf(" (Suspend)\n"); break; case LED_MUTE : printf(" (Mute)\n"); break; case LED_MISC : printf(" (Miscellaneous)\n"); break; default: printf(" (Unknown LED type: 0x%04x)\n", i); } } } baresip-1.0.0/modules/evdev/print.h000066400000000000000000000003131372575704200172340ustar00rootroot00000000000000/** * @file print.h Interface to Input event device info * * Copyright (C) 2010 Creytiv.com */ void print_name(int fd); void print_events(int fd); void print_keys(int fd); void print_leds(int fd); baresip-1.0.0/modules/fakevideo/000077500000000000000000000000001372575704200165565ustar00rootroot00000000000000baresip-1.0.0/modules/fakevideo/fakevideo.c000066400000000000000000000101001372575704200206470ustar00rootroot00000000000000/** * @file fakevideo.c Fake video source and video display * * Copyright (C) 2010 Creytiv.com */ #define _DEFAULT_SOURCE 1 #define _BSD_SOURCE 1 #include #include #include #include #include /** * @defgroup fakevideo fakevideo * * Fake video source and display module * * This module can be used to generate fake video input frames, and to * send output video frames to a fake non-existant display. * * Example config: \verbatim video_source fakevideo,nil video_display fakevideo,nil \endverbatim */ struct vidsrc_st { const struct vidsrc *vs; /* inheritance */ struct vidframe *frame; #ifdef HAVE_PTHREAD pthread_t thread; bool run; #else struct tmr tmr; #endif uint64_t ts; double fps; vidsrc_frame_h *frameh; void *arg; }; struct vidisp_st { const struct vidisp *vd; /* inheritance */ }; static struct vidsrc *vidsrc; static struct vidisp *vidisp; static void process_frame(struct vidsrc_st *st) { st->ts += (VIDEO_TIMEBASE / st->fps); st->frameh(st->frame, st->ts, st->arg); } #ifdef HAVE_PTHREAD static void *read_thread(void *arg) { struct vidsrc_st *st = arg; st->ts = tmr_jiffies_usec(); while (st->run) { if (tmr_jiffies_usec() < st->ts) { sys_msleep(4); continue; } process_frame(st); } return NULL; } #else static void tmr_handler(void *arg) { struct vidsrc_st *st = arg; const uint64_t now = tmr_jiffies_usec(); tmr_start(&st->tmr, 4, tmr_handler, st); if (!st->ts) st->ts = now; if (now >= st->ts) { process_frame(st); } } #endif static void src_destructor(void *arg) { struct vidsrc_st *st = arg; #ifdef HAVE_PTHREAD if (st->run) { st->run = false; pthread_join(st->thread, NULL); } #else tmr_cancel(&st->tmr); #endif mem_deref(st->frame); } static void disp_destructor(void *arg) { struct vidisp_st *st = arg; (void)st; } static int src_alloc(struct vidsrc_st **stp, const struct vidsrc *vs, struct media_ctx **ctx, struct vidsrc_prm *prm, const struct vidsz *size, const char *fmt, const char *dev, vidsrc_frame_h *frameh, vidsrc_error_h *errorh, void *arg) { struct vidsrc_st *st; unsigned x; int err; (void)ctx; (void)fmt; (void)dev; (void)errorh; if (!stp || !prm || !size || !frameh) return EINVAL; st = mem_zalloc(sizeof(*st), src_destructor); if (!st) return ENOMEM; st->vs = vs; st->fps = prm->fps; st->frameh = frameh; st->arg = arg; err = vidframe_alloc(&st->frame, prm->fmt, size); if (err) goto out; /* Pattern of three vertical bars in RGB */ for (x=0; xw; x++) { uint8_t r=0, g=0, b=0; if (x < size->w/3) r = 255; else if (x < size->w*2/3) g = 255; else b = 255; vidframe_draw_vline(st->frame, x, 0, size->h, r, g, b); } #ifdef HAVE_PTHREAD st->run = true; err = pthread_create(&st->thread, NULL, read_thread, st); if (err) { st->run = false; goto out; } #else tmr_start(&st->tmr, 1, tmr_handler, st); #endif out: if (err) mem_deref(st); else *stp = st; return err; } static int disp_alloc(struct vidisp_st **stp, const struct vidisp *vd, struct vidisp_prm *prm, const char *dev, vidisp_resize_h *resizeh, void *arg) { struct vidisp_st *st; (void)prm; (void)dev; (void)resizeh; (void)arg; if (!stp || !vd) return EINVAL; st = mem_zalloc(sizeof(*st), disp_destructor); if (!st) return ENOMEM; st->vd = vd; *stp = st; return 0; } static int display(struct vidisp_st *st, const char *title, const struct vidframe *frame, uint64_t timestamp) { (void)st; (void)title; (void)frame; (void)timestamp; return 0; } static int module_init(void) { int err = 0; err |= vidsrc_register(&vidsrc, baresip_vidsrcl(), "fakevideo", src_alloc, NULL); err |= vidisp_register(&vidisp, baresip_vidispl(), "fakevideo", disp_alloc, NULL, display, NULL); return err; } static int module_close(void) { vidsrc = mem_deref(vidsrc); vidisp = mem_deref(vidisp); return 0; } EXPORT_SYM const struct mod_export DECL_EXPORTS(fakevideo) = { "fakevideo", "fakevideo", module_init, module_close }; baresip-1.0.0/modules/fakevideo/module.mk000066400000000000000000000002051372575704200203710ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # MOD := fakevideo $(MOD)_SRCS += fakevideo.c $(MOD)_LFLAGS += include mk/mod.mk baresip-1.0.0/modules/g711/000077500000000000000000000000001372575704200153005ustar00rootroot00000000000000baresip-1.0.0/modules/g711/g711.c000066400000000000000000000047531372575704200161340ustar00rootroot00000000000000/** * @file g711.c G.711 Audio Codec * * Copyright (C) 2010 - 2015 Creytiv.com */ #include #include #include /** * @defgroup g711 g711 * * The G.711 audio codec */ static int pcmu_encode(struct auenc_state *aes, bool *marker, uint8_t *buf, size_t *len, int fmt, const void *sampv, size_t sampc) { const int16_t *p = sampv; (void)aes; (void)marker; if (!buf || !len || !sampv) return EINVAL; if (*len < sampc) return ENOMEM; if (fmt != AUFMT_S16LE) return ENOTSUP; *len = sampc; while (sampc--) *buf++ = g711_pcm2ulaw(*p++); return 0; } static int pcmu_decode(struct audec_state *ads, int fmt, void *sampv, size_t *sampc, bool marker, const uint8_t *buf, size_t len) { int16_t *p = sampv; (void)ads; (void)marker; if (!sampv || !sampc || !buf) return EINVAL; if (*sampc < len) return ENOMEM; if (fmt != AUFMT_S16LE) return ENOTSUP; *sampc = len; while (len--) *p++ = g711_ulaw2pcm(*buf++); return 0; } static int pcma_encode(struct auenc_state *aes, bool *marker, uint8_t *buf, size_t *len, int fmt, const void *sampv, size_t sampc) { const int16_t *p = sampv; (void)aes; (void)marker; if (!buf || !len || !sampv) return EINVAL; if (*len < sampc) return ENOMEM; if (fmt != AUFMT_S16LE) return ENOTSUP; *len = sampc; while (sampc--) *buf++ = g711_pcm2alaw(*p++); return 0; } static int pcma_decode(struct audec_state *ads, int fmt, void *sampv, size_t *sampc, bool marker, const uint8_t *buf, size_t len) { int16_t *p = sampv; (void)ads; (void)marker; if (!sampv || !sampc || !buf) return EINVAL; if (*sampc < len) return ENOMEM; if (fmt != AUFMT_S16LE) return ENOTSUP; *sampc = len; while (len--) *p++ = g711_alaw2pcm(*buf++); return 0; } static struct aucodec pcmu = { .pt = "0", .name = "PCMU", .srate = 8000, .crate = 8000, .ch = 1, .pch = 1, .ench = pcmu_encode, .dech = pcmu_decode, }; static struct aucodec pcma = { .pt = "8", .name = "PCMA", .srate = 8000, .crate = 8000, .ch = 1, .pch = 1, .ench = pcma_encode, .dech = pcma_decode, }; static int module_init(void) { aucodec_register(baresip_aucodecl(), &pcmu); aucodec_register(baresip_aucodecl(), &pcma); return 0; } static int module_close(void) { aucodec_unregister(&pcma); aucodec_unregister(&pcmu); return 0; } EXPORT_SYM const struct mod_export DECL_EXPORTS(g711) = { "g711", "audio codec", module_init, module_close, }; baresip-1.0.0/modules/g711/module.mk000066400000000000000000000001521372575704200171140ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # MOD := g711 $(MOD)_SRCS += g711.c include mk/mod.mk baresip-1.0.0/modules/g722/000077500000000000000000000000001372575704200153025ustar00rootroot00000000000000baresip-1.0.0/modules/g722/g722.c000066400000000000000000000066661372575704200161450ustar00rootroot00000000000000/** * @file g722.c G.722 audio codec * * Copyright (C) 2010 Creytiv.com */ #include #include #include #include #include #include #define SPANDSP_EXPOSE_INTERNAL_STRUCTURES 1 #include /** * @defgroup g722 g722 * * The G.722 audio codec * * ## From RFC 3551: 4.5.2 G722 G722 is specified in ITU-T Recommendation G.722, "7 kHz audio-coding within 64 kbit/s". The G.722 encoder produces a stream of octets, each of which SHALL be octet-aligned in an RTP packet. The first bit transmitted in the G.722 octet, which is the most significant bit of the higher sub-band sample, SHALL correspond to the most significant bit of the octet in the RTP packet. Even though the actual sampling rate for G.722 audio is 16,000 Hz, the RTP clock rate for the G722 payload format is 8,000 Hz because that value was erroneously assigned in RFC 1890 and must remain unchanged for backward compatibility. The octet rate or sample-pair rate is 8,000 Hz. ## Reference: http://www.soft-switch.org/spandsp-modules.html */ enum { G722_SAMPLE_RATE = 16000, G722_BITRATE_48k = 48000, G722_BITRATE_56k = 56000, G722_BITRATE_64k = 64000 }; struct auenc_state { g722_encode_state_t enc; }; struct audec_state { g722_decode_state_t dec; }; static int encode_update(struct auenc_state **aesp, const struct aucodec *ac, struct auenc_param *prm, const char *fmtp) { struct auenc_state *st; int err = 0; (void)prm; (void)fmtp; if (!aesp || !ac) return EINVAL; if (*aesp) return 0; st = mem_alloc(sizeof(*st), NULL); if (!st) return ENOMEM; if (!g722_encode_init(&st->enc, G722_BITRATE_64k, 0)) { err = EPROTO; goto out; } out: if (err) mem_deref(st); else *aesp = st; return err; } static int decode_update(struct audec_state **adsp, const struct aucodec *ac, const char *fmtp) { struct audec_state *st; int err = 0; (void)fmtp; if (!adsp || !ac) return EINVAL; if (*adsp) return 0; st = mem_alloc(sizeof(*st), NULL); if (!st) return ENOMEM; if (!g722_decode_init(&st->dec, G722_BITRATE_64k, 0)) { err = EPROTO; goto out; } out: if (err) mem_deref(st); else *adsp = st; return err; } static int encode(struct auenc_state *st, bool *marker, uint8_t *buf, size_t *len, int fmt, const void *sampv, size_t sampc) { int n; (void)marker; if (fmt != AUFMT_S16LE) return ENOTSUP; n = g722_encode(&st->enc, buf, sampv, (int)sampc); if (n <= 0) { return EPROTO; } else if (n > (int)*len) { return EOVERFLOW; } *len = n; return 0; } static int decode(struct audec_state *st, int fmt, void *sampv, size_t *sampc, bool marker, const uint8_t *buf, size_t len) { int n; (void)marker; if (!st || !sampv || !buf) return EINVAL; if (fmt != AUFMT_S16LE) return ENOTSUP; n = g722_decode(&st->dec, sampv, buf, (int)len); if (n < 0) return EPROTO; *sampc = n; return 0; } static struct aucodec g722 = { .pt = "9", .name = "G722", .srate = 16000, .crate = 8000, .ch = 1, .pch = 1, .encupdh = encode_update, .ench = encode, .decupdh = decode_update, .dech = decode, }; static int module_init(void) { aucodec_register(baresip_aucodecl(), &g722); return 0; } static int module_close(void) { aucodec_unregister(&g722); return 0; } EXPORT_SYM const struct mod_export DECL_EXPORTS(g722) = { "g722", "codec", module_init, module_close }; baresip-1.0.0/modules/g722/module.mk000066400000000000000000000002051372575704200171150ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # MOD := g722 $(MOD)_SRCS += g722.c $(MOD)_LFLAGS += -lspandsp include mk/mod.mk baresip-1.0.0/modules/g7221/000077500000000000000000000000001372575704200153635ustar00rootroot00000000000000baresip-1.0.0/modules/g7221/decode.c000066400000000000000000000023631372575704200167560ustar00rootroot00000000000000/** * @file g7221/decode.c G.722.1 Decode * * Copyright (C) 2010 Creytiv.com */ #include #include #include #define G722_1_EXPOSE_INTERNAL_STRUCTURES #include #include "g7221.h" struct audec_state { g722_1_decode_state_t dec; }; int g7221_decode_update(struct audec_state **adsp, const struct aucodec *ac, const char *fmtp) { const struct g7221_aucodec *g7221 = (struct g7221_aucodec *)ac; struct audec_state *ads; (void)fmtp; if (!adsp || !ac) return EINVAL; ads = *adsp; if (ads) return 0; ads = mem_alloc(sizeof(*ads), NULL); if (!ads) return ENOMEM; if (!g722_1_decode_init(&ads->dec, g7221->bitrate, ac->srate)) { mem_deref(ads); return EPROTO; } *adsp = ads; return 0; } int g7221_decode(struct audec_state *ads, int fmt, void *sampv, size_t *sampc, bool marker, const uint8_t *buf, size_t len) { size_t framec; (void)marker; if (!ads || !sampv || !sampc || !buf) return EINVAL; if (fmt != AUFMT_S16LE) return ENOTSUP; framec = len / ads->dec.bytes_per_frame; if (len != ads->dec.bytes_per_frame * framec) return EPROTO; if (*sampc < ads->dec.frame_size * framec) return ENOMEM; *sampc = g722_1_decode(&ads->dec, sampv, buf, (int)len); return 0; } baresip-1.0.0/modules/g7221/encode.c000066400000000000000000000024241372575704200167660ustar00rootroot00000000000000/** * @file g7221/encode.c G.722.1 Encode * * Copyright (C) 2010 Creytiv.com */ #include #include #include #define G722_1_EXPOSE_INTERNAL_STRUCTURES #include #include "g7221.h" struct auenc_state { g722_1_encode_state_t enc; }; int g7221_encode_update(struct auenc_state **aesp, const struct aucodec *ac, struct auenc_param *prm, const char *fmtp) { const struct g7221_aucodec *g7221 = (struct g7221_aucodec *)ac; struct auenc_state *aes; (void)prm; (void)fmtp; if (!aesp || !ac) return EINVAL; aes = *aesp; if (aes) return 0; aes = mem_alloc(sizeof(*aes), NULL); if (!aes) return ENOMEM; if (!g722_1_encode_init(&aes->enc, g7221->bitrate, ac->srate)) { mem_deref(aes); return EPROTO; } *aesp = aes; return 0; } int g7221_encode(struct auenc_state *aes, bool *marker, uint8_t *buf, size_t *len, int fmt, const void *sampv, size_t sampc) { size_t framec; (void)marker; if (!aes || !buf || !len || !sampv) return EINVAL; if (fmt != AUFMT_S16LE) return ENOTSUP; framec = sampc / aes->enc.frame_size; if (sampc != aes->enc.frame_size * framec) return EPROTO; if (*len < aes->enc.bytes_per_frame * framec) return ENOMEM; *len = g722_1_encode(&aes->enc, buf, sampv, (int)sampc); return 0; } baresip-1.0.0/modules/g7221/g7221.c000066400000000000000000000015041372575704200162710ustar00rootroot00000000000000/** * @file g7221.c G.722.1 Audio Codec * * Copyright (C) 2010 Creytiv.com */ #include #include #include "g7221.h" static struct g7221_aucodec g7221 = { .ac = { .name = "G7221", .srate = 16000, .crate = 16000, .ch = 1, .pch = 1, .encupdh = g7221_encode_update, .ench = g7221_encode, .decupdh = g7221_decode_update, .dech = g7221_decode, .fmtp_ench = g7221_fmtp_enc, .fmtp_cmph = g7221_fmtp_cmp, }, .bitrate = 32000, }; static int module_init(void) { aucodec_register(baresip_aucodecl(), (struct aucodec *)&g7221); return 0; } static int module_close(void) { aucodec_unregister((struct aucodec *)&g7221); return 0; } EXPORT_SYM const struct mod_export DECL_EXPORTS(g7221) = { "g7221", "audio codec", module_init, module_close, }; baresip-1.0.0/modules/g7221/g7221.h000066400000000000000000000015171372575704200163020ustar00rootroot00000000000000/** * @file g7221.h Private G.722.1 Interface * * Copyright (C) 2010 Creytiv.com */ struct g7221_aucodec { struct aucodec ac; uint32_t bitrate; }; /* Encode */ int g7221_encode_update(struct auenc_state **aesp, const struct aucodec *ac, struct auenc_param *prm, const char *fmtp); int g7221_encode(struct auenc_state *aes, bool *marker, uint8_t *buf, size_t *len, int fmt, const void *sampv, size_t sampc); /* Decode */ int g7221_decode_update(struct audec_state **adsp, const struct aucodec *ac, const char *fmtp); int g7221_decode(struct audec_state *ads, int fmt, void *sampv, size_t *sampc, bool marker, const uint8_t *buf, size_t len); /* SDP */ int g7221_fmtp_enc(struct mbuf *mb, const struct sdp_format *fmt, bool offer, void *arg); bool g7221_fmtp_cmp(const char *lfmtp, const char *rfmtp, void *arg); baresip-1.0.0/modules/g7221/module.mk000066400000000000000000000003131372575704200171760ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # MOD := g7221 $(MOD)_SRCS += decode.c $(MOD)_SRCS += encode.c $(MOD)_SRCS += g7221.c $(MOD)_SRCS += sdp.c $(MOD)_LFLAGS += -lg722_1 include mk/mod.mk baresip-1.0.0/modules/g7221/sdp.c000066400000000000000000000015561372575704200163240ustar00rootroot00000000000000/** * @file g7221/sdp.c G.722.1 SDP Functions * * Copyright (C) 2010 Creytiv.com */ #include #include #include "g7221.h" static uint32_t g7221_bitrate(const char *fmtp) { struct pl pl, bitrate; if (!fmtp) return 0; pl_set_str(&pl, fmtp); if (fmt_param_get(&pl, "bitrate", &bitrate)) return pl_u32(&bitrate); return 0; } int g7221_fmtp_enc(struct mbuf *mb, const struct sdp_format *fmt, bool offer, void *arg) { const struct g7221_aucodec *g7221 = arg; (void)offer; if (!mb || !fmt || !g7221) return 0; return mbuf_printf(mb, "a=fmtp:%s bitrate=%u\r\n", fmt->id, g7221->bitrate); } bool g7221_fmtp_cmp(const char *lfmtp, const char *rfmtp, void *arg) { const struct g7221_aucodec *g7221 = arg; (void)lfmtp; if (!g7221) return false; if (g7221->bitrate != g7221_bitrate(rfmtp)) return false; return true; } baresip-1.0.0/modules/g726/000077500000000000000000000000001372575704200153065ustar00rootroot00000000000000baresip-1.0.0/modules/g726/g726.c000066400000000000000000000073761372575704200161540ustar00rootroot00000000000000/** * @file g726.c G.726 Audio Codec * * Copyright (C) 2010 Creytiv.com */ #include #include #include #define SPANDSP_EXPOSE_INTERNAL_STRUCTURES 1 #include /** * @defgroup g726 g726 * * The G.726 audio codec */ enum { MAX_PACKET = 100 }; struct g726_aucodec { struct aucodec ac; int bitrate; }; struct auenc_state { g726_state_t st; }; struct audec_state { g726_state_t st; }; static void encode_destructor(void *arg) { struct auenc_state *st = arg; g726_release(&st->st); } static void decode_destructor(void *arg) { struct audec_state *st = arg; g726_release(&st->st); } static int encode_update(struct auenc_state **aesp, const struct aucodec *ac, struct auenc_param *prm, const char *fmtp) { struct g726_aucodec *gac = (struct g726_aucodec *)ac; struct auenc_state *st; int err = 0; (void)prm; (void)fmtp; if (!aesp || !ac) return EINVAL; if (*aesp) return 0; st = mem_zalloc(sizeof(*st), encode_destructor); if (!st) return ENOMEM; if (!g726_init(&st->st, gac->bitrate, G726_ENCODING_LINEAR, G726_PACKING_LEFT)) { err = ENOMEM; goto out; } out: if (err) mem_deref(st); else *aesp = st; return err; } static int decode_update(struct audec_state **adsp, const struct aucodec *ac, const char *fmtp) { struct g726_aucodec *gac = (struct g726_aucodec *)ac; struct audec_state *st; int err = 0; (void)fmtp; if (!adsp || !ac) return EINVAL; if (*adsp) return 0; st = mem_zalloc(sizeof(*st), decode_destructor); if (!st) return ENOMEM; if (!g726_init(&st->st, gac->bitrate, G726_ENCODING_LINEAR, G726_PACKING_LEFT)) { err = ENOMEM; goto out; } out: if (err) mem_deref(st); else *adsp = st; return err; } static int encode(struct auenc_state *st, bool *marker, uint8_t *buf, size_t *len, int fmt, const void *sampv, size_t sampc) { (void)marker; if (!buf || !len || !sampv) return EINVAL; if (fmt != AUFMT_S16LE) return ENOTSUP; if (*len < MAX_PACKET) return ENOMEM; *len = g726_encode(&st->st, buf, sampv, (int)sampc); return 0; } static int decode(struct audec_state *st, int fmt, void *sampv, size_t *sampc, bool marker, const uint8_t *buf, size_t len) { (void)marker; if (!sampv || !sampc || !buf) return EINVAL; if (fmt != AUFMT_S16LE) return ENOTSUP; *sampc = g726_decode(&st->st, sampv, buf, (int)len); return 0; } static struct g726_aucodec g726[4] = { { { .name = "G726-40", .srate = 8000, .crate = 8000, .ch = 1, .pch = 1, .encupdh = encode_update, .ench = encode, .decupdh = decode_update, .dech = decode, }, 40000 }, { { .name = "G726-32", .srate = 8000, .crate = 8000, .ch = 1, .pch = 1, .encupdh = encode_update, .ench = encode, .decupdh = decode_update, .dech = decode, }, 32000 }, { { .name = "G726-24", .srate = 8000, .crate = 8000, .ch = 1, .pch = 1, .encupdh = encode_update, .ench = encode, .decupdh = decode_update, .dech = decode, }, 24000 }, { { .name = "G726-16", .srate = 8000, .crate = 8000, .ch = 1, .pch = 1, .encupdh = encode_update, .ench = encode, .decupdh = decode_update, .dech = decode, }, 16000 } }; static int module_init(void) { struct list *aucodecl = baresip_aucodecl(); size_t i; for (i=0; i /* please report if you have problems finding this file */ #include #include #include /** * @defgroup gsm gsm * * The GSM audio codec */ enum { FRAME_SIZE = 160 }; struct auenc_state { gsm enc; }; struct audec_state { gsm dec; }; static void encode_destructor(void *arg) { struct auenc_state *st = arg; gsm_destroy(st->enc); } static void decode_destructor(void *arg) { struct audec_state *st = arg; gsm_destroy(st->dec); } static int encode_update(struct auenc_state **aesp, const struct aucodec *ac, struct auenc_param *prm, const char *fmtp) { struct auenc_state *st; int err = 0; (void)ac; (void)prm; (void)fmtp; if (!aesp) return EINVAL; if (*aesp) return 0; st = mem_zalloc(sizeof(*st), encode_destructor); if (!st) return ENOMEM; st->enc = gsm_create(); if (!st->enc) { err = EPROTO; goto out; } out: if (err) mem_deref(st); else *aesp = st; return err; } static int decode_update(struct audec_state **adsp, const struct aucodec *ac, const char *fmtp) { struct audec_state *st; int err = 0; (void)ac; (void)fmtp; if (!adsp) return EINVAL; if (*adsp) return 0; st = mem_zalloc(sizeof(*st), decode_destructor); if (!st) return ENOMEM; st->dec = gsm_create(); if (!st->dec) { err = EPROTO; goto out; } out: if (err) mem_deref(st); else *adsp = st; return err; } static int encode(struct auenc_state *st, bool *marker, uint8_t *buf, size_t *len, int fmt, const void *sampv, size_t sampc) { (void)marker; if (sampc != FRAME_SIZE) return EPROTO; if (*len < sizeof(gsm_frame)) return ENOMEM; if (fmt != AUFMT_S16LE) return ENOTSUP; gsm_encode(st->enc, (gsm_signal *)sampv, buf); *len = sizeof(gsm_frame); return 0; } static int decode(struct audec_state *st, int fmt, void *sampv, size_t *sampc, bool marker, const uint8_t *buf, size_t len) { int ret; (void)marker; if (*sampc < FRAME_SIZE) return ENOMEM; if (len < sizeof(gsm_frame)) return EBADMSG; if (fmt != AUFMT_S16LE) return ENOTSUP; ret = gsm_decode(st->dec, (gsm_byte *)buf, (gsm_signal *)sampv); if (ret) return EPROTO; *sampc = 160; return 0; } static struct aucodec ac_gsm = { .pt = "3", .name = "GSM", .srate = 8000, .crate = 8000, .ch = 1, .pch = 1, .encupdh = encode_update, .ench = encode, .decupdh = decode_update, .dech = decode, }; static int module_init(void) { debug("gsm: GSM v%u.%u.%u\n", GSM_MAJOR, GSM_MINOR, GSM_PATCHLEVEL); aucodec_register(baresip_aucodecl(), &ac_gsm); return 0; } static int module_close(void) { aucodec_unregister(&ac_gsm); return 0; } EXPORT_SYM const struct mod_export DECL_EXPORTS(gsm) = { "gsm", "codec", module_init, module_close }; baresip-1.0.0/modules/gsm/module.mk000066400000000000000000000003251372575704200172250ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # MOD := gsm $(MOD)_SRCS += gsm.c $(MOD)_LFLAGS += -L$(SYSROOT)/lib -lgsm $(MOD)_CFLAGS += -I$(SYSROOT)/include/gsm -I$(SYSROOT)/local/include include mk/mod.mk baresip-1.0.0/modules/gst/000077500000000000000000000000001372575704200154165ustar00rootroot00000000000000baresip-1.0.0/modules/gst/gst.c000066400000000000000000000235611372575704200163660ustar00rootroot00000000000000/** * @file gst/gst.c Gstreamer 1.0 playbin pipeline * * Copyright (C) 2010 - 2015 Creytiv.com */ #define _DEFAULT_SOURCE 1 #define _POSIX_C_SOURCE 199309L #include #include #include #include #include #include #include #include /** * @defgroup gst gst * * Audio source module using gstreamer 1.0 as input * * The module 'gst' is using the Gstreamer framework to play external * media and provide this as an internal audio source. * * Example config: \verbatim audio_source gst,http://relay.slayradio.org:8000/ \endverbatim */ /** * Defines the Gstreamer state * *
 *                ptime=variable             ptime=20ms
 *  .-----------. N kHz          .---------. N kHz
 *  |           | 1-2 channels   |         | 1-2 channels
 *  | Gstreamer |--------------->|Packetize|-------------> [read handler]
 *  |           |                |         |
 *  '-----------'                '---------'
 *
 * 
*/ struct ausrc_st { const struct ausrc *as; /**< Inheritance */ pthread_t tid; /**< Thread ID */ bool run; /**< Running flag */ ausrc_read_h *rh; /**< Read handler */ ausrc_error_h *errh; /**< Error handler */ void *arg; /**< Handler argument */ struct ausrc_prm prm; /**< Read parameters */ struct aubuf *aubuf; /**< Packet buffer */ size_t psize; /**< Packet size in bytes */ size_t sampc; /* Gstreamer */ char *uri; GstElement *pipeline, *bin, *source, *capsfilt, *sink; GMainLoop *loop; }; typedef struct _GstFakeSink GstFakeSink; static struct ausrc *ausrc; static void *thread(void *arg) { struct ausrc_st *st = arg; /* Now set to playing and iterate. */ gst_element_set_state(st->pipeline, GST_STATE_PLAYING); while (st->run) { g_main_loop_run(st->loop); } return NULL; } static gboolean bus_watch_handler(GstBus *bus, GstMessage *msg, gpointer data) { struct ausrc_st *st = data; GMainLoop *loop = st->loop; GstTagList *tag_list; gchar *title; GError *err; gchar *d; (void)bus; switch (GST_MESSAGE_TYPE(msg)) { case GST_MESSAGE_EOS: /* Re-start stream */ if (st->run) { gst_element_set_state(st->pipeline, GST_STATE_NULL); gst_element_set_state(st->pipeline, GST_STATE_PLAYING); } else { g_main_loop_quit(loop); } break; case GST_MESSAGE_ERROR: gst_message_parse_error(msg, &err, &d); warning("gst: Error: %d(%m) message=\"%s\"\n", err->code, err->code, err->message); warning("gst: Debug: %s\n", d); g_free(d); /* Call error handler */ if (st->errh) st->errh(err->code, err->message, st->arg); g_error_free(err); st->run = false; g_main_loop_quit(loop); break; case GST_MESSAGE_TAG: gst_message_parse_tag(msg, &tag_list); if (gst_tag_list_get_string(tag_list, GST_TAG_TITLE, &title)) { info("gst: title: %s\n", title); g_free(title); } break; default: break; } return TRUE; } static void format_check(struct ausrc_st *st, GstStructure *s) { int rate, channels, width; gboolean sign; if (!st || !s) return; gst_structure_get_int(s, "rate", &rate); gst_structure_get_int(s, "channels", &channels); gst_structure_get_int(s, "width", &width); gst_structure_get_boolean(s, "signed", &sign); if ((int)st->prm.srate != rate) { warning("gst: expected %u Hz (got %u Hz)\n", st->prm.srate, rate); } if (st->prm.ch != channels) { warning("gst: expected %d channels (got %d)\n", st->prm.ch, channels); } if (16 != width) { warning("gst: expected 16-bit width (got %d)\n", width); } if (!sign) { warning("gst: expected signed 16-bit format\n"); } } static void play_packet(struct ausrc_st *st) { int16_t buf[st->sampc]; struct auframe af = { .fmt = AUFMT_S16LE, .sampv = buf, .sampc = st->sampc }; /* timed read from audio-buffer */ if (aubuf_get_samp(st->aubuf, st->prm.ptime, buf, st->sampc)) return; /* call read handler */ if (st->rh) st->rh(&af, st->arg); } /* Expected format: 16-bit signed PCM */ static void packet_handler(struct ausrc_st *st, GstBuffer *buffer) { GstMapInfo info; int err; if (!st->run) return; /* NOTE: When streaming from files, the buffer will be filled up * pretty quickly.. */ if (!gst_buffer_map(buffer, &info, GST_MAP_READ)) { warning("gst: gst_buffer_map failed\n"); return; } err = aubuf_write(st->aubuf, info.data, info.size); if (err) { warning("gst: aubuf_write: %m\n", err); } gst_buffer_unmap(buffer, &info); /* Empty buffer now */ while (st->run) { const struct timespec delay = {0, st->prm.ptime*1000000/2}; play_packet(st); if (aubuf_cur_size(st->aubuf) < st->psize) break; (void)nanosleep(&delay, NULL); } } static void handoff_handler(GstFakeSink *fakesink, GstBuffer *buffer, GstPad *pad, gpointer user_data) { struct ausrc_st *st = user_data; GstCaps *caps; (void)fakesink; caps = gst_pad_get_current_caps(pad); format_check(st, gst_caps_get_structure(caps, 0)); packet_handler(st, buffer); } static void set_caps(struct ausrc_st *st) { GstCaps *caps; /* Set the capabilities we want */ caps = gst_caps_new_simple("audio/x-raw", "rate", G_TYPE_INT, st->prm.srate, "channels", G_TYPE_INT, st->prm.ch, "width", G_TYPE_INT, 16, "signed", G_TYPE_BOOLEAN,true, NULL); g_object_set(G_OBJECT(st->capsfilt), "caps", caps, NULL); } /** * Set up the Gstreamer pipeline. The playbin element is used to decode * all kinds of different formats. The capsfilter is used to deliver the * audio in a fixed format (X Hz, 1-2 channels, 16 bit signed) * * The pipeline looks like this: * *
 *  .--------------.    .------------------------------------------.
 *  |    playbin   |    |mybin    .------------.   .------------.  |
 *  |----.    .----|    |-----.   | capsfilter |   |  fakesink  |  |
 *  |sink|    |src |--->|ghost|   |----.   .---|   |----.   .---|  |    handoff
 *  |----'    '----|    |pad  |-->|sink|   |src|-->|sink|   |src|--+--> handler
 *  |              |    |-----'   '------------'   '------------'  |
 *  '--------------'    '------------------------------------------'
 * 
* * @param st Audio source state * * @return 0 if success, otherwise errorcode */ static int gst_setup(struct ausrc_st *st) { GstBus *bus; GstPad *pad; st->loop = g_main_loop_new(NULL, FALSE); st->pipeline = gst_pipeline_new("pipeline"); if (!st->pipeline) { warning("gst: failed to create pipeline element\n"); return ENOMEM; } /********************* Player BIN **************************/ st->source = gst_element_factory_make("playbin", "source"); if (!st->source) { warning("gst: failed to create playbin source element\n"); return ENOMEM; } /********************* My BIN **************************/ st->bin = gst_bin_new("mybin"); st->capsfilt = gst_element_factory_make("capsfilter", NULL); if (!st->capsfilt) { warning("gst: failed to create capsfilter element\n"); return ENOMEM; } set_caps(st); st->sink = gst_element_factory_make("fakesink", "sink"); if (!st->sink) { warning("gst: failed to create sink element\n"); return ENOMEM; } gst_bin_add_many(GST_BIN(st->bin), st->capsfilt, st->sink, NULL); gst_element_link_many(st->capsfilt, st->sink, NULL); /* add ghostpad */ pad = gst_element_get_static_pad(st->capsfilt, "sink"); gst_element_add_pad(st->bin, gst_ghost_pad_new("sink", pad)); gst_object_unref(GST_OBJECT(pad)); /* put all elements in a bin */ gst_bin_add_many(GST_BIN(st->pipeline), st->source, NULL); /* Override audio-sink handoff handler */ g_object_set(G_OBJECT(st->sink), "signal-handoffs", TRUE, NULL); g_signal_connect(st->sink, "handoff", G_CALLBACK(handoff_handler), st); g_object_set(G_OBJECT(st->source), "audio-sink", st->bin, NULL); /********************* Misc **************************/ /* Bus watch */ bus = gst_pipeline_get_bus(GST_PIPELINE(st->pipeline)); gst_bus_add_watch(bus, bus_watch_handler, st); gst_object_unref(bus); /* Set URI */ g_object_set(G_OBJECT(st->source), "uri", st->uri, NULL); return 0; } static void gst_destructor(void *arg) { struct ausrc_st *st = arg; if (st->run) { st->run = false; g_main_loop_quit(st->loop); pthread_join(st->tid, NULL); } gst_element_set_state(st->pipeline, GST_STATE_NULL); gst_object_unref(GST_OBJECT(st->pipeline)); mem_deref(st->uri); mem_deref(st->aubuf); } static int gst_alloc(struct ausrc_st **stp, const struct ausrc *as, struct media_ctx **ctx, struct ausrc_prm *prm, const char *device, ausrc_read_h *rh, ausrc_error_h *errh, void *arg) { struct ausrc_st *st; int err; (void)ctx; if (!stp || !as || !prm) return EINVAL; if (!str_isset(device)) return EINVAL; if (prm->fmt != AUFMT_S16LE) { warning("gst: unsupported sample format (%s)\n", aufmt_name(prm->fmt)); return ENOTSUP; } st = mem_zalloc(sizeof(*st), gst_destructor); if (!st) return ENOMEM; st->as = as; st->rh = rh; st->errh = errh; st->arg = arg; err = str_dup(&st->uri, device); if (err) goto out; st->prm = *prm; st->sampc = prm->srate * prm->ch * prm->ptime / 1000; st->psize = 2 * st->sampc; err = aubuf_alloc(&st->aubuf, st->psize, 0); if (err) goto out; err = gst_setup(st); if (err) goto out; st->run = true; err = pthread_create(&st->tid, NULL, thread, st); if (err) { st->run = false; goto out; } out: if (err) mem_deref(st); else *stp = st; return err; } static int mod_gst_init(void) { gchar *s; gst_init(0, NULL); s = gst_version_string(); info("gst: init: %s\n", s); g_free(s); return ausrc_register(&ausrc, baresip_ausrcl(), "gst", gst_alloc); } static int mod_gst_close(void) { gst_deinit(); ausrc = mem_deref(ausrc); return 0; } EXPORT_SYM const struct mod_export DECL_EXPORTS(gst) = { "gst", "sound", mod_gst_init, mod_gst_close }; baresip-1.0.0/modules/gst/module.mk000066400000000000000000000003771372575704200172430ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # MOD := gst $(MOD)_SRCS += gst.c $(MOD)_LFLAGS += $(shell pkg-config --libs gstreamer-1.0) $(MOD)_CFLAGS += $(shell pkg-config --cflags gstreamer-1.0) $(MOD)_CFLAGS += -Wno-cast-align include mk/mod.mk baresip-1.0.0/modules/gst_video/000077500000000000000000000000001372575704200166045ustar00rootroot00000000000000baresip-1.0.0/modules/gst_video/encode.c000066400000000000000000000335321372575704200202130ustar00rootroot00000000000000/** * @file gst_video/encode.c Video codecs using Gstreamer video pipeline * * Copyright (C) 2010 - 2013 Creytiv.com * Copyright (C) 2014 Fadeev Alexander * Copyright (C) 2015 Thomas Strobel */ #define __USE_POSIX199309 #define _DEFAULT_SOURCE 1 #include #include #include #include #include #include #include #include #include #include #include #include #include "gst_video.h" struct videnc_state { struct { struct vidsz size; unsigned fps; unsigned bitrate; unsigned pktsize; } encoder; struct { uint32_t packetization_mode; uint32_t profile_idc; uint32_t profile_iop; uint32_t level_idc; uint32_t max_fs; uint32_t max_smbps; } h264; videnc_packet_h *pkth; void *arg; /* Gstreamer */ struct { bool valid; GstElement *pipeline; GstAppSrc *source; GstAppSrcCallbacks appsrcCallbacks; GstAppSinkCallbacks appsinkCallbacks; struct { pthread_mutex_t mutex; pthread_cond_t cond; int flag; } eos; /* Thread synchronization. */ struct { pthread_mutex_t mutex; pthread_cond_t cond; /* 0: no-wait, 1: wait, -1: pipeline destroyed */ int flag; } wait; } streamer; }; static void appsrc_need_data_cb(GstAppSrc *src, guint size, gpointer user_data) { struct videnc_state *st = user_data; (void)src; (void)size; pthread_mutex_lock(&st->streamer.wait.mutex); if (st->streamer.wait.flag == 1){ st->streamer.wait.flag = 0; pthread_cond_signal(&st->streamer.wait.cond); } pthread_mutex_unlock(&st->streamer.wait.mutex); } static void appsrc_enough_data_cb(GstAppSrc *src, gpointer user_data) { struct videnc_state *st = user_data; (void)src; pthread_mutex_lock(&st->streamer.wait.mutex); if (st->streamer.wait.flag == 0) st->streamer.wait.flag = 1; pthread_mutex_unlock(&st->streamer.wait.mutex); } static void appsrc_destroy_notify_cb(struct videnc_state *st) { pthread_mutex_lock(&st->streamer.wait.mutex); st->streamer.wait.flag = -1; pthread_cond_signal(&st->streamer.wait.cond); pthread_mutex_unlock(&st->streamer.wait.mutex); } /* The appsink has received a sample */ static GstFlowReturn appsink_new_sample_cb(GstAppSink *sink, gpointer user_data) { struct videnc_state *st = user_data; GstSample *sample; GstBuffer *buffer; GstMapInfo info; guint8 *data; gsize size; /* Retrieve the sample */ sample = gst_app_sink_pull_sample(sink); if (sample) { GstClockTime ts; uint64_t rtp_ts; buffer = gst_sample_get_buffer(sample); gst_buffer_map( buffer, &info, (GstMapFlags)(GST_MAP_READ) ); data = info.data; size = info.size; ts = GST_BUFFER_PTS(buffer); if (ts == GST_CLOCK_TIME_NONE) { warning("gst_video: timestamp is unknown\n"); rtp_ts = 0; } else { /* convert from nanoseconds to RTP clock */ rtp_ts = (uint64_t)((90000ULL * ts) / 1000000000UL); } h264_packetize(rtp_ts, data, size, st->encoder.pktsize, st->pkth, st->arg); gst_buffer_unmap(buffer, &info); gst_sample_unref(sample); } return GST_FLOW_OK; } static void appsink_end_of_stream_cb(GstAppSink *src, gpointer user_data) { struct videnc_state *st = user_data; (void)src; pthread_mutex_lock(&st->streamer.eos.mutex); if (st->streamer.eos.flag == 0) { st->streamer.eos.flag = 1; pthread_cond_signal(&st->streamer.eos.cond); } pthread_mutex_unlock(&st->streamer.eos.mutex); } static void appsink_destroy_notify_cb(struct videnc_state *st) { pthread_mutex_lock(&st->streamer.eos.mutex); st->streamer.eos.flag = -1; pthread_cond_signal(&st->streamer.eos.cond); pthread_mutex_unlock(&st->streamer.eos.mutex); } static GstBusSyncReply bus_sync_handler_cb(GstBus *bus, GstMessage *msg, struct videnc_state *st) { (void)bus; if ((GST_MESSAGE_TYPE (msg)) == GST_MESSAGE_ERROR) { GError *err = NULL; gchar *dbg_info = NULL; gst_message_parse_error (msg, &err, &dbg_info); warning("gst_video: Error: %d(%m) message=%s\n", err->code, err->code, err->message); warning("gst_video: Debug: %s\n", dbg_info); g_error_free (err); g_free (dbg_info); /* mark pipeline as broked */ st->streamer.valid = false; } gst_message_unref(msg); return GST_BUS_DROP; } static void bus_destroy_notify_cb(struct videnc_state *st) { (void)st; } /** * Set up the Gstreamer pipeline. Appsrc gets raw frames, and appsink takes * encoded frames. * * The pipeline looks like this: * *
 *  .--------.   .-----------.   .----------.
 *  | appsrc |   |  x264enc  |   | appsink  |
 *  |   .----|   |----.  .---|   |----.     |
 *  |   |src |-->|sink|  |src|-->|sink|-----+-->handoff
 *  |   '----|   |----'  '---|   |----'     |   handler
 *  '--------'   '-----------'   '----------'
 * 
*/ static int pipeline_init(struct videnc_state *st, const struct vidsz *size) { GstAppSrc *source; GstAppSink *sink; GstBus *bus; GError* gerror = NULL; char pipeline[1024]; GstStateChangeReturn ret; int err = 0; if (!st || !size) return EINVAL; snprintf(pipeline, sizeof(pipeline), "appsrc name=source is-live=TRUE block=TRUE " "do-timestamp=TRUE max-bytes=1000000 ! " "videoparse width=%d height=%d format=i420 framerate=%d/1 ! " "x264enc byte-stream=TRUE rc-lookahead=0 " "tune=zerolatency speed-preset=ultrafast " "sync-lookahead=0 bitrate=%d ! " "appsink name=sink emit-signals=TRUE drop=TRUE", size->w, size->h, st->encoder.fps, st->encoder.bitrate / 1000 /* kbit/s */); /* Initialize pipeline. */ st->streamer.pipeline = gst_parse_launch(pipeline, &gerror); if (gerror) { warning("gst_video: launch error: %d: %s: %s\n", gerror->code, gerror->message, pipeline); err = gerror->code; g_error_free(gerror); return err; } /* Configure appsource */ source = GST_APP_SRC(gst_bin_get_by_name( GST_BIN(st->streamer.pipeline), "source")); gst_app_src_set_callbacks(source, &(st->streamer.appsrcCallbacks), st, (GDestroyNotify)appsrc_destroy_notify_cb); /* Configure appsink. */ sink = GST_APP_SINK(gst_bin_get_by_name( GST_BIN(st->streamer.pipeline), "sink")); gst_app_sink_set_callbacks(sink, &(st->streamer.appsinkCallbacks), st, (GDestroyNotify)appsink_destroy_notify_cb); gst_object_unref(GST_OBJECT(sink)); /* Bus watch */ bus = gst_pipeline_get_bus(GST_PIPELINE(st->streamer.pipeline)); gst_bus_set_sync_handler(bus, (GstBusSyncHandler)bus_sync_handler_cb, st, (GDestroyNotify)bus_destroy_notify_cb); gst_object_unref(GST_OBJECT(bus)); /* Set start values of locks */ pthread_mutex_lock(&st->streamer.wait.mutex); st->streamer.wait.flag = 0; pthread_mutex_unlock(&st->streamer.wait.mutex); pthread_mutex_lock(&st->streamer.eos.mutex); st->streamer.eos.flag = 0; pthread_mutex_unlock(&st->streamer.eos.mutex); /* Start pipeline */ ret = gst_element_set_state(st->streamer.pipeline, GST_STATE_PLAYING); if (GST_STATE_CHANGE_FAILURE == ret) { g_warning("set state returned GST_STATE_CHANGE_FAILURE\n"); err = EPROTO; goto out; } st->streamer.source = source; /* Mark pipeline as working */ st->streamer.valid = true; out: return err; } static void pipeline_close(struct videnc_state *st) { if (!st) return; st->streamer.valid = false; if (st->streamer.source) { gst_object_unref(GST_OBJECT(st->streamer.source)); st->streamer.source = NULL; } if (st->streamer.pipeline) { gst_element_set_state(st->streamer.pipeline, GST_STATE_NULL); /* pipeline */ gst_object_unref(GST_OBJECT(st->streamer.pipeline)); st->streamer.pipeline = NULL; } } static void destruct_resources(void *data) { struct videnc_state *st = data; /* close pipeline */ pipeline_close(st); /* destroy locks */ pthread_mutex_destroy(&st->streamer.eos.mutex); pthread_cond_destroy(&st->streamer.eos.cond); pthread_mutex_destroy(&st->streamer.wait.mutex); pthread_cond_destroy(&st->streamer.wait.cond); } static int allocate_resources(struct videnc_state **stp) { struct videnc_state *st; st = mem_zalloc(sizeof(*st), destruct_resources); if (!st) return ENOMEM; *stp = st; /* initialize locks */ pthread_mutex_init(&st->streamer.eos.mutex, NULL); pthread_cond_init(&st->streamer.eos.cond, NULL); pthread_mutex_init(&st->streamer.wait.mutex, NULL); pthread_cond_init(&st->streamer.wait.cond, NULL); /* Set appsource callbacks. */ st->streamer.appsrcCallbacks.need_data = &appsrc_need_data_cb; st->streamer.appsrcCallbacks.enough_data = &appsrc_enough_data_cb; /* Set appsink callbacks. */ st->streamer.appsinkCallbacks.new_sample = &appsink_new_sample_cb; st->streamer.appsinkCallbacks.eos = &appsink_end_of_stream_cb; return 0; } /* decode sdpparameter for h264 */ static void param_handler(const struct pl *name, const struct pl *val, void *arg) { struct videnc_state *st = arg; if (0 == pl_strcasecmp(name, "packetization-mode")) { st->h264.packetization_mode = pl_u32(val); if (st->h264.packetization_mode != 0) { warning("gst_video: illegal packetization-mode %u\n", st->h264.packetization_mode); return; } } else if (0 == pl_strcasecmp(name, "profile-level-id")) { struct pl prof = *val; if (prof.l != 6) { warning("gst_video: invalid profile-level-id (%r)\n", val); return; } prof.l = 2; st->h264.profile_idc = pl_x32(&prof); prof.p += 2; st->h264.profile_iop = pl_x32(&prof); prof.p += 2; st->h264.level_idc = pl_x32(&prof); } else if (0 == pl_strcasecmp(name, "max-fs")) { st->h264.max_fs = pl_u32(val); } else if (0 == pl_strcasecmp(name, "max-smbps")) { st->h264.max_smbps = pl_u32(val); } return; } int gst_video_encoder_set(struct videnc_state **stp, const struct vidcodec *vc, struct videnc_param *prm, const char *fmtp, videnc_packet_h *pkth, void *arg) { struct videnc_state *st; int err = 0; if (!stp || !vc || !prm || !pkth) return EINVAL; st = *stp; if (!st) { err = allocate_resources(stp); if (err) { warning("gst_video: resource allocation failed\n"); return err; } st = *stp; st->pkth = pkth; st->arg = arg; } else { if (!st->streamer.valid) { warning("gst_video codec: trying to work" " with invalid pipeline\n"); return EINVAL; } if ((st->encoder.bitrate != prm->bitrate || st->encoder.pktsize != prm->pktsize || st->encoder.fps != prm->fps)) { pipeline_close(st); } } st->encoder.bitrate = prm->bitrate; st->encoder.pktsize = prm->pktsize; st->encoder.fps = prm->fps; if (str_isset(fmtp)) { struct pl sdp_fmtp; pl_set_str(&sdp_fmtp, fmtp); /* store new parameters */ fmt_param_apply(&sdp_fmtp, param_handler, st); } info("gst_video: video encoder %s: %d fps, %d bit/s, pktsize=%u\n", vc->name, st->encoder.fps, st->encoder.bitrate, st->encoder.pktsize); return err; } /* * couple gstreamer tightly by lock-stepping */ static int pipeline_push(struct videnc_state *st, const struct vidframe *frame, uint64_t timestamp) { GstBuffer *buffer; uint8_t *data; size_t size; GstFlowReturn ret; int err = 0; /* * Wait "start feed". */ pthread_mutex_lock(&st->streamer.wait.mutex); if (st->streamer.wait.flag == 1) { pthread_cond_wait(&st->streamer.wait.cond, &st->streamer.wait.mutex); } if (st->streamer.eos.flag == -1) /* error */ err = ENODEV; pthread_mutex_unlock(&st->streamer.wait.mutex); if (err) return err; /* * Copy frame into buffer for gstreamer */ /* NOTE: I420 (YUV420P): hardcoded. */ size = frame->linesize[0] * frame->size.h + frame->linesize[1] * frame->size.h * 0.5 + frame->linesize[2] * frame->size.h * 0.5; /* allocate memory; memory is freed within callback of gst_memory_new_wrapped of gst_video_push */ data = g_try_malloc(size); if (!data) return ENOMEM; /* copy content of frame */ size = 0; memcpy(&data[size], frame->data[0], frame->linesize[0] * frame->size.h); size += frame->linesize[0] * frame->size.h; memcpy(&data[size], frame->data[1], frame->linesize[1] * frame->size.h * 0.5); size += frame->linesize[1] * frame->size.h * 0.5; memcpy(&data[size], frame->data[2], frame->linesize[2] * frame->size.h * 0.5); size += frame->linesize[2] * frame->size.h * 0.5; /* Wrap memory in a gstreamer buffer */ buffer = gst_buffer_new(); gst_buffer_insert_memory(buffer, -1, gst_memory_new_wrapped (0, data, size, 0, size, data, g_free)); /* convert timestamp to nanoseconds */ buffer->pts = timestamp * 1000000000ULL / VIDEO_TIMEBASE; /* * Push data and EOS into gstreamer. */ ret = gst_app_src_push_buffer(st->streamer.source, buffer); if (ret != GST_FLOW_OK) { warning("gst_video: pushing buffer failed\n"); err = EPROTO; goto out; } #if 0 ret = gst_app_src_end_of_stream(st->streamer.source); if (ret != GST_FLOW_OK) { warning("gst_video: pushing EOS failed\n"); err = EPROTO; goto out; } #endif #if 0 /* * Wait "processing done". */ pthread_mutex_lock(&st->streamer.eos.mutex); if (st->streamer.eos.flag == 0) /* will returns with EOS (1) or error (-1) */ pthread_cond_wait(&st->streamer.wait.cond, &st->streamer.wait.mutex); if (st->streamer.eos.flag == 1) /* reset eos */ st->streamer.eos.flag = 0; else /* error */ err = -1; pthread_mutex_unlock(&st->streamer.wait.mutex); #endif out: return err; } int gst_video_encode(struct videnc_state *st, bool update, const struct vidframe *frame, uint64_t timestamp) { int err; if (!st || !frame || frame->fmt != VID_FMT_YUV420P) return EINVAL; if (!st->streamer.valid || !vidsz_cmp(&st->encoder.size, &frame->size)) { pipeline_close(st); err = pipeline_init(st, &frame->size); if (err) { warning("gst_video: pipeline initialization failed\n"); return err; } st->encoder.size = frame->size; } if (update) { debug("gst_video: gstreamer picture update" ", it's not implemented...\n"); } /* * Push frame into pipeline. * Function call will return once frame has been processed completely. */ err = pipeline_push(st, frame, timestamp); return err; } baresip-1.0.0/modules/gst_video/gst_video.c000066400000000000000000000024061372575704200207350ustar00rootroot00000000000000/** * @file gst_video/gst_video.c Video codecs using Gstreamer 1.0 * * Copyright (C) 2010 Creytiv.com * Copyright (C) 2014 Fadeev Alexander */ #include #include #include #include #include "gst_video.h" /** * @defgroup gst_video gst_video * * This module implements video codecs using Gstreamer 1.0 * * Currently only H.264 encoding is supported, but this can be extended * if needed. No decoding is done by this module, so that must be done by * another video-codec module. * * Thanks to Victor Sergienko and Fadeev Alexander for the * initial version, which was based on avcodec module. */ static struct vidcodec h264 = { .name = "H264", .variant = "packetization-mode=0", .encupdh = gst_video_encoder_set, .ench = gst_video_encode, .fmtp_ench = gst_video_fmtp_enc, .fmtp_cmph = gst_video_fmtp_cmp, }; static int module_init(void) { gst_init(NULL, NULL); vidcodec_register(baresip_vidcodecl(), &h264); info("gst_video: using gstreamer (%s)\n", gst_version_string()); return 0; } static int module_close(void) { vidcodec_unregister(&h264); gst_deinit(); return 0; } EXPORT_SYM const struct mod_export DECL_EXPORTS(gst_video) = { "gst_video", "vidcodec", module_init, module_close }; baresip-1.0.0/modules/gst_video/gst_video.h000066400000000000000000000013601372575704200207400ustar00rootroot00000000000000/** * @file gst_video/gst_video.h Gstreamer video pipeline -- internal API * * Copyright (C) 2010 - 2014 Creytiv.com * Copyright (C) 2014 Fadeev Alexander */ /* Encode */ struct videnc_state; int gst_video_encoder_set(struct videnc_state **stp, const struct vidcodec *vc, struct videnc_param *prm, const char *fmtp, videnc_packet_h *pkth, void *arg); int gst_video_encode(struct videnc_state *st, bool update, const struct vidframe *frame, uint64_t timestamp); /* SDP */ uint32_t gst_video_h264_packetization_mode(const char *fmtp); int gst_video_fmtp_enc(struct mbuf *mb, const struct sdp_format *fmt, bool offer, void *arg); bool gst_video_fmtp_cmp(const char *fmtp1, const char *fmtp2, void *data); baresip-1.0.0/modules/gst_video/module.mk000066400000000000000000000005001372575704200204150ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # MOD := gst_video $(MOD)_SRCS += gst_video.c encode.c sdp.c $(MOD)_LFLAGS += $(shell pkg-config --libs gstreamer-1.0 gstreamer-app-1.0) $(MOD)_CFLAGS += $(shell pkg-config --cflags gstreamer-1.0 gstreamer-app-1.0) $(MOD)_CFLAGS += -Wno-cast-align include mk/mod.mk baresip-1.0.0/modules/gst_video/sdp.c000066400000000000000000000021151372575704200175350ustar00rootroot00000000000000/** * @file gst_video/sdp.c H.264 SDP Functions * * Copyright (C) 2010 Creytiv.com */ #include #include #include "gst_video.h" static const uint8_t gst_video_h264_level_idc = 0x0c; uint32_t gst_video_h264_packetization_mode(const char *fmtp) { struct pl pl, mode; if (!fmtp) return 0; pl_set_str(&pl, fmtp); if (fmt_param_get(&pl, "packetization-mode", &mode)) return pl_u32(&mode); return 0; } int gst_video_fmtp_enc(struct mbuf *mb, const struct sdp_format *fmt, bool offer, void *arg) { struct vidcodec *vc = arg; const uint8_t profile_idc = 0x42; /* baseline profile */ const uint8_t profile_iop = 0x80; (void)offer; if (!mb || !fmt || !vc) return 0; return mbuf_printf(mb, "a=fmtp:%s" " packetization-mode=0" ";profile-level-id=%02x%02x%02x" "\r\n", fmt->id, profile_idc, profile_iop, gst_video_h264_level_idc); } bool gst_video_fmtp_cmp(const char *fmtp1, const char *fmtp2, void *data) { (void)data; return gst_video_h264_packetization_mode(fmtp1) == gst_video_h264_packetization_mode(fmtp2); } baresip-1.0.0/modules/gtk/000077500000000000000000000000001372575704200154065ustar00rootroot00000000000000baresip-1.0.0/modules/gtk/call_window.c000066400000000000000000000314121372575704200200550ustar00rootroot00000000000000/** * @file gtk/call_window.c GTK+ call window * * Copyright (C) 2015 Charles E. Lehner */ #include #include #include #include "gtk_mod.h" struct call_window { struct gtk_mod *mod; struct call *call; /** for communicating from gtk thread to main thread */ struct mqueue *mq; struct { struct vumeter_dec *dec; struct vumeter_enc *enc; } vu; struct transfer_dialog *transfer_dialog; GtkWidget *window; GtkLabel *status; GtkLabel *duration; struct { GtkWidget *hangup, *transfer, *hold, *mute; } buttons; struct { GtkProgressBar *enc, *dec; } progress; guint duration_timer_tag; guint vumeter_timer_tag; bool closed; int cur_key; struct play *play_dtmf_tone; }; enum call_window_events { MQ_HANGUP, MQ_CLOSE, MQ_HOLD, MQ_MUTE, MQ_TRANSFER, }; static struct call_window *last_call_win = NULL; static struct vumeter_dec *last_dec = NULL; static struct vumeter_enc *last_enc = NULL; static void call_window_update_duration(struct call_window *win) { gchar buf[32]; const uint32_t dur = call_duration(win->call); const uint32_t sec = dur%60%60; const uint32_t min = dur/60%60; const uint32_t hrs = dur/60/60; re_snprintf(buf, sizeof buf, "%u:%02u:%02u", hrs, min, sec); gtk_label_set_text(win->duration, buf); } static void call_window_update_vumeters(struct call_window *win) { double value; if (win->vu.enc && win->vu.enc->started) { value = min((double)win->vu.enc->avg_rec / 0x4000, 1); gtk_progress_bar_set_fraction(win->progress.enc, value); } if (win->vu.dec && win->vu.dec->started) { value = min((double)win->vu.dec->avg_play / 0x4000, 1); gtk_progress_bar_set_fraction(win->progress.dec, value); } } static gboolean call_timer(gpointer arg) { struct call_window *win = arg; call_window_update_duration(win); return G_SOURCE_CONTINUE; } static gboolean vumeter_timer(gpointer arg) { struct call_window *win = arg; call_window_update_vumeters(win); return G_SOURCE_CONTINUE; } static void vumeter_timer_start(struct call_window *win) { if (!win->vumeter_timer_tag) win->vumeter_timer_tag = g_timeout_add(100, vumeter_timer, win); if (win->vu.enc) win->vu.enc->avg_rec = 0; if (win->vu.dec) win->vu.dec->avg_play = 0; } static void vumeter_timer_stop(struct call_window *win) { if (win->vumeter_timer_tag) { g_source_remove(win->vumeter_timer_tag); win->vumeter_timer_tag = 0; } gtk_progress_bar_set_fraction(win->progress.enc, 0); gtk_progress_bar_set_fraction(win->progress.dec, 0); } static void call_window_set_vu_dec(struct call_window *win, struct vumeter_dec *dec) { mem_deref(win->vu.dec); win->vu.dec = mem_ref(dec); vumeter_timer_start(win); } static void call_window_set_vu_enc(struct call_window *win, struct vumeter_enc *enc) { mem_deref(win->vu.enc); win->vu.enc = mem_ref(enc); vumeter_timer_start(win); } /* This is a hack to associate a call with its vumeters */ void call_window_got_vu_dec(struct vumeter_dec *dec) { if (last_call_win) call_window_set_vu_dec(last_call_win, dec); else last_dec = dec; } void call_window_got_vu_enc(struct vumeter_enc *enc) { if (last_call_win) call_window_set_vu_enc(last_call_win, enc); else last_enc = enc; } static void got_call_window(struct call_window *win) { if (last_enc) call_window_set_vu_enc(win, last_enc); if (last_dec) call_window_set_vu_dec(win, last_dec); if (!last_enc || !last_dec) last_call_win = win; } static void call_on_hangup(GtkToggleButton *btn, struct call_window *win) { (void)btn; mqueue_push(win->mq, MQ_CLOSE, win); } static void call_on_hold_toggle(GtkToggleButton *btn, struct call_window *win) { bool hold = gtk_toggle_button_get_active(btn); if (hold) vumeter_timer_stop(win); else vumeter_timer_start(win); mqueue_push(win->mq, MQ_HOLD, (void *)(size_t)hold); } static void call_on_mute_toggle(GtkToggleButton *btn, struct call_window *win) { bool mute = gtk_toggle_button_get_active(btn); mqueue_push(win->mq, MQ_MUTE, (void *)(size_t)mute); } static void call_on_transfer(GtkToggleButton *btn, struct call_window *win) { (void)btn; if (!win->transfer_dialog) win->transfer_dialog = transfer_dialog_alloc(win); else transfer_dialog_show(win->transfer_dialog); } static gboolean call_on_window_close(GtkWidget *widget, GdkEventAny *event, struct call_window *win) { (void)event; (void)widget; mqueue_push(win->mq, MQ_CLOSE, NULL); return TRUE; } static gboolean call_on_key_press(GtkWidget *window, GdkEvent *ev, struct call_window *win) { struct config *cfg = conf_config(); gchar key = ev->key.string[0]; char wavfile[32]; (void)window; switch (key) { case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '0': re_snprintf(wavfile, sizeof wavfile, "sound%c.wav", key); break; case '*': re_snprintf(wavfile, sizeof wavfile, "sound%s.wav", "star"); break; case '#': re_snprintf(wavfile, sizeof wavfile, "sound%s.wav", "route"); break; default: return FALSE; } (void)play_file(&win->play_dtmf_tone, baresip_player(), wavfile, -1, cfg->audio.alert_mod, cfg->audio.alert_dev); win->cur_key = key; call_send_digit(win->call, key); return TRUE; } static gboolean call_on_key_release(GtkWidget *window, GdkEvent *ev, struct call_window *win) { (void)window; if (win->cur_key && win->cur_key == ev->key.string[0]) { win->play_dtmf_tone = mem_deref(win->play_dtmf_tone); win->cur_key = KEYCODE_REL; call_send_digit(win->call, KEYCODE_REL); return TRUE; } return FALSE; } static void call_window_set_status(struct call_window *win, const char *status) { gtk_label_set_text(win->status, status); } static void mqueue_handler(int id, void *data, void *arg) { struct call_window *win = arg; switch ((enum call_window_events)id) { case MQ_HANGUP: ua_hangup(uag_current(), win->call, 0, NULL); break; case MQ_CLOSE: if (!win->closed) { ua_hangup(uag_current(), win->call, 0, NULL); win->closed = true; } mem_deref(win); break; case MQ_MUTE: audio_mute(call_audio(win->call), (size_t)data); break; case MQ_HOLD: call_hold(win->call, (size_t)data); break; case MQ_TRANSFER: call_transfer(win->call, data); break; } } static void call_window_destructor(void *arg) { struct call_window *window = arg; gdk_threads_enter(); gtk_mod_call_window_closed(window->mod, window); gtk_widget_destroy(window->window); mem_deref(window->transfer_dialog); gdk_threads_leave(); mem_deref(window->call); mem_deref(window->mq); mem_deref(window->vu.enc); mem_deref(window->vu.dec); if (window->duration_timer_tag) g_source_remove(window->duration_timer_tag); if (window->vumeter_timer_tag) g_source_remove(window->vumeter_timer_tag); /* TODO: avoid race conditions here */ last_call_win = NULL; } struct call_window *call_window_new(struct call *call, struct gtk_mod *mod) { struct call_window *win; GtkWidget *window, *label, *status, *button, *progress, *image; GtkWidget *button_box, *vbox, *hbox; GtkWidget *duration; int err = 0; win = mem_zalloc(sizeof(*win), call_window_destructor); if (!win) return NULL; err = mqueue_alloc(&win->mq, mqueue_handler, win); if (err) goto out; window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(window), call_peeruri(call)); gtk_window_set_type_hint(GTK_WINDOW(window), GDK_WINDOW_TYPE_HINT_DIALOG); vbox = gtk_vbox_new(FALSE, 0); gtk_container_add(GTK_CONTAINER(window), vbox); /* Peer name and URI */ label = gtk_label_new(call_peername(call)); gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0); label = gtk_label_new(call_peeruri(call)); gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0); /* Call duration */ duration = gtk_label_new(NULL); gtk_box_pack_start(GTK_BOX(vbox), duration, FALSE, FALSE, 0); /* Status */ status = gtk_label_new(NULL); gtk_box_pack_start(GTK_BOX(vbox), status, FALSE, FALSE, 0); /* Progress bars */ hbox = gtk_hbox_new(FALSE, 0); gtk_box_set_spacing(GTK_BOX(hbox), 6); gtk_container_set_border_width(GTK_CONTAINER(hbox), 5); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); /* Encoding vumeter */ image = gtk_image_new_from_icon_name("audio-input-microphone", GTK_ICON_SIZE_BUTTON); progress = gtk_progress_bar_new(); win->progress.enc = GTK_PROGRESS_BAR(progress); gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(hbox), progress, FALSE, FALSE, 0); /* Decoding vumeter */ image = gtk_image_new_from_icon_name("audio-headphones", GTK_ICON_SIZE_BUTTON); progress = gtk_progress_bar_new(); win->progress.dec = GTK_PROGRESS_BAR(progress); gtk_box_pack_end(GTK_BOX(hbox), progress, FALSE, FALSE, 0); gtk_box_pack_end(GTK_BOX(hbox), image, FALSE, FALSE, 0); /* Buttons */ button_box = gtk_hbutton_box_new(); gtk_button_box_set_layout(GTK_BUTTON_BOX(button_box), GTK_BUTTONBOX_END); gtk_box_set_spacing(GTK_BOX(button_box), 6); gtk_container_set_border_width(GTK_CONTAINER(button_box), 5); gtk_box_pack_end(GTK_BOX(vbox), button_box, FALSE, TRUE, 0); /* Hang up */ button = gtk_button_new_with_label("Hangup"); win->buttons.hangup = button; gtk_box_pack_end(GTK_BOX(button_box), button, FALSE, TRUE, 0); g_signal_connect(button, "clicked", G_CALLBACK(call_on_hangup), win); image = gtk_image_new_from_icon_name("call-stop", GTK_ICON_SIZE_BUTTON); gtk_button_set_image(GTK_BUTTON(button), image); /* Transfer */ button = gtk_button_new_with_label("Transfer"); win->buttons.transfer = button; gtk_box_pack_end(GTK_BOX(button_box), button, FALSE, TRUE, 0); g_signal_connect(button, "clicked", G_CALLBACK(call_on_transfer), win); image = gtk_image_new_from_icon_name("forward", GTK_ICON_SIZE_BUTTON); gtk_button_set_image(GTK_BUTTON(button), image); /* Hold */ button = gtk_toggle_button_new_with_label("Hold"); win->buttons.hold = button; gtk_box_pack_end(GTK_BOX(button_box), button, FALSE, TRUE, 0); g_signal_connect(button, "toggled", G_CALLBACK(call_on_hold_toggle), win); image = gtk_image_new_from_icon_name("player_pause", GTK_ICON_SIZE_BUTTON); gtk_button_set_image(GTK_BUTTON(button), image); /* Mute */ button = gtk_toggle_button_new_with_label("Mute"); win->buttons.mute = button; gtk_box_pack_end(GTK_BOX(button_box), button, FALSE, TRUE, 0); g_signal_connect(button, "toggled", G_CALLBACK(call_on_mute_toggle), win); image = gtk_image_new_from_icon_name("microphone-sensitivity-muted", GTK_ICON_SIZE_BUTTON); gtk_button_set_image(GTK_BUTTON(button), image); gtk_widget_show_all(window); gtk_window_present(GTK_WINDOW(window)); g_signal_connect(window, "delete_event", G_CALLBACK(call_on_window_close), win); g_signal_connect(window, "key-press-event", G_CALLBACK(call_on_key_press), win); g_signal_connect(window, "key-release-event", G_CALLBACK(call_on_key_release), win); win->call = mem_ref(call); win->mod = mod; win->window = window; win->transfer_dialog = NULL; win->status = GTK_LABEL(status); win->duration = GTK_LABEL(duration); win->closed = false; win->duration_timer_tag = 0; win->vumeter_timer_tag = 0; win->vu.enc = NULL; win->vu.dec = NULL; got_call_window(win); out: if (err) mem_deref(win); return win; } void call_window_transfer(struct call_window *win, const char *uri) { mqueue_push(win->mq, MQ_TRANSFER, (char *)uri); } void call_window_closed(struct call_window *win, const char *reason) { char buf[256]; const char *status; if (!win) return; vumeter_timer_stop(win); if (win->duration_timer_tag) { g_source_remove(win->duration_timer_tag); win->duration_timer_tag = 0; } gtk_widget_set_sensitive(win->buttons.transfer, FALSE); gtk_widget_set_sensitive(win->buttons.hold, FALSE); gtk_widget_set_sensitive(win->buttons.mute, FALSE); if (reason && reason[0]) { re_snprintf(buf, sizeof buf, "closed: %s", reason); status = buf; } else { status = "closed"; } call_window_set_status(win, status); win->transfer_dialog = mem_deref(win->transfer_dialog); win->closed = true; } void call_window_ringing(struct call_window *win) { call_window_set_status(win, "ringing"); } void call_window_progress(struct call_window *win) { if (!win) return; win->duration_timer_tag = g_timeout_add_seconds(1, call_timer, win); last_call_win = win; call_window_set_status(win, "progress"); } void call_window_established(struct call_window *win) { if (!win) return; call_window_update_duration(win); if (!win->duration_timer_tag) { win->duration_timer_tag = g_timeout_add_seconds(1, call_timer, win); } last_call_win = win; call_window_set_status(win, "established"); } void call_window_transfer_failed(struct call_window *win, const char *reason) { if (!win) return; if (win->transfer_dialog) { transfer_dialog_fail(win->transfer_dialog, reason); } } bool call_window_is_for_call(struct call_window *win, struct call *call) { if (!win) return false; return win->call == call; } baresip-1.0.0/modules/gtk/dial_dialog.c000066400000000000000000000064201372575704200200040ustar00rootroot00000000000000/** * @file gtk/dial_dialog.c GTK+ dial dialog * * Copyright (C) 2015 Charles E. Lehner */ #include #include #include #include #include #include "gtk_mod.h" struct dial_dialog { struct gtk_mod *mod; GtkWidget *dialog; GtkComboBox *uri_combobox; }; static int clean_number(char* str) { int i = 0, k = 0; /* only clean numeric numbers * In other cases trust the user input */ int err = re_regex(str, sizeof(str), "[A-Za-z]"); if (err == 0) return -1; /* remove (0) which is in some mal-formated numbers * but only if trailed by another character */ if (str[0] == '+' || (str[0] == '0' && str[1] == '0')) while (str[i]) { if (str[i] == '(' && str[i+1] == '0' && str[i+2] == ')' && (str[i+3] == ' ' || (str[i+3] >= '0' && str[i+3] <= '9') ) ) { str[i+1] = ' '; break; } ++i; } i = 0; while (str[i]) { if (str[i] == ' ' || str[i] == '.' || str[i] == '-' || str[i] == '/' || str[i] == '(' || str[i] == ')') ++i; else str[k++] = str[i++]; } str[k] = '\0'; return k; } static void dial_dialog_on_response(GtkDialog *dialog, gint response_id, gpointer arg) { struct dial_dialog *dd = arg; char *uri; if (response_id == GTK_RESPONSE_ACCEPT) { uri = (char *)uri_combo_box_get_text(dd->uri_combobox); if (gtk_mod_clean_number(dd->mod)) { int length = clean_number(uri); if (length >= 0) uri_combo_box_set_text(dd->uri_combobox, uri, length); } gtk_mod_connect(dd->mod, uri); } gtk_widget_hide(GTK_WIDGET(dialog)); } static void destructor(void *arg) { struct dial_dialog *dd = arg; gtk_widget_destroy(dd->dialog); } struct dial_dialog *dial_dialog_alloc(struct gtk_mod *mod) { struct dial_dialog *dd; GtkWidget *dial; GtkWidget *content, *button, *image; GtkWidget *uri_combobox; dd = mem_zalloc(sizeof(*dd), destructor); if (!dd) return NULL; dial = gtk_dialog_new_with_buttons("Dial", NULL, 0, NULL); /* Cancel */ button = gtk_button_new_with_label("Cancel"); image = gtk_image_new_from_icon_name("call-stop", GTK_ICON_SIZE_BUTTON); gtk_button_set_image(GTK_BUTTON(button), image); gtk_dialog_add_action_widget(GTK_DIALOG(dial), button, GTK_RESPONSE_REJECT); /* Call */ button = gtk_button_new_with_label("Call"); image = gtk_image_new_from_icon_name("call-start", GTK_ICON_SIZE_BUTTON); gtk_button_set_image(GTK_BUTTON(button), image); gtk_dialog_add_action_widget(GTK_DIALOG(dial), button, GTK_RESPONSE_ACCEPT); gtk_widget_set_can_default (button, TRUE); gtk_dialog_set_default_response(GTK_DIALOG(dial), GTK_RESPONSE_ACCEPT); uri_combobox = uri_combo_box_new(); content = gtk_dialog_get_content_area(GTK_DIALOG(dial)); gtk_box_pack_start(GTK_BOX(content), uri_combobox, FALSE, FALSE, 5); gtk_widget_show_all(content); g_signal_connect(G_OBJECT(dial), "response", G_CALLBACK(dial_dialog_on_response), dd); g_signal_connect(G_OBJECT(dial), "delete-event", G_CALLBACK(gtk_widget_hide_on_delete), dd); dd->dialog = dial; dd->uri_combobox = GTK_COMBO_BOX(uri_combobox); dd->mod = mod; return dd; } void dial_dialog_show(struct dial_dialog *dd) { if (!dd) return; gtk_window_present(GTK_WINDOW(dd->dialog)); gtk_widget_grab_focus(gtk_bin_get_child(GTK_BIN(dd->uri_combobox))); } baresip-1.0.0/modules/gtk/gtk_mod.c000066400000000000000000000605321372575704200172040ustar00rootroot00000000000000/** * @file gtk/gtk_mod.c GTK+ UI module * * Copyright (C) 2015 Charles E. Lehner * Copyright (C) 2010 - 2015 Creytiv.com */ #include #include #include #include #include #include #include #include "gtk_mod.h" #ifdef USE_LIBNOTIFY #include #endif #if GLIB_CHECK_VERSION(2,40,0) || defined(USE_LIBNOTIFY) #define USE_NOTIFICATIONS 1 #endif /* About */ #define COPYRIGHT " Copyright (C) 2010 - 2019 Alfred E. Heggestad et al." #define COMMENTS "A modular SIP User-Agent with audio and video support" #define WEBSITE "http://www.creytiv.com/baresip.html" #define LICENSE "BSD" /** * @defgroup gtk_mod gtk_mod * * GTK+ Menu-based User-Interface module * * Creates a tray icon with a menu for making calls. * */ struct gtk_mod { pthread_t thread; bool run; bool contacts_inited; struct mqueue *mq; GApplication *app; GtkStatusIcon *status_icon; GtkWidget *app_menu; GtkWidget *contacts_menu; GtkWidget *accounts_menu; GtkWidget *status_menu; GSList *accounts_menu_group; struct dial_dialog *dial_dialog; GSList *call_windows; GSList *incoming_call_menus; bool clean_number; }; static struct gtk_mod mod_obj; enum gtk_mod_events { MQ_POPUP, MQ_CONNECT, MQ_QUIT, MQ_ANSWER, MQ_HANGUP, MQ_SELECT_UA, }; static void answer_activated(GSimpleAction *, GVariant *, gpointer); static void reject_activated(GSimpleAction *, GVariant *, gpointer); static void denotify_incoming_call(struct gtk_mod *, struct call *); static GActionEntry app_entries[] = { {"answer", answer_activated, "s", NULL, NULL, {0} }, {"reject", reject_activated, "s", NULL, NULL, {0} }, }; static struct call *get_call_from_gvariant(GVariant *param) { struct list *calls = ua_calls(uag_current()); const gchar *call_ptr = g_variant_get_string(param, NULL); return call_find_id(calls, call_ptr); } static void menu_on_about(GtkMenuItem *menuItem, gpointer arg) { (void)menuItem; (void)arg; gtk_show_about_dialog(NULL, "program-name", "baresip", "version", BARESIP_VERSION, "logo-icon-name", "call-start", "copyright", COPYRIGHT, "comments", COMMENTS, "website", WEBSITE, "license", LICENSE, NULL); } static void menu_on_quit(GtkMenuItem *menuItem, gpointer arg) { struct gtk_mod *mod = arg; (void)menuItem; gtk_widget_destroy(GTK_WIDGET(mod->app_menu)); g_object_unref(G_OBJECT(mod->status_icon)); mqueue_push(mod->mq, MQ_QUIT, 0); info("quit from gtk\n"); } static void menu_on_dial(GtkMenuItem *menuItem, gpointer arg) { struct gtk_mod *mod = arg; (void)menuItem; if (!mod->dial_dialog) mod->dial_dialog = dial_dialog_alloc(mod); dial_dialog_show(mod->dial_dialog); } static void menu_on_dial_contact(GtkMenuItem *menuItem, gpointer arg) { struct gtk_mod *mod = arg; const char *uri = gtk_menu_item_get_label(menuItem); /* Queue dial from the main thread */ mqueue_push(mod->mq, MQ_CONNECT, (char *)uri); } static void init_contacts_menu(struct gtk_mod *mod) { struct contacts *contacts = baresip_contacts(); struct le *le; GtkWidget *item; GtkMenuShell *contacts_menu = GTK_MENU_SHELL(mod->contacts_menu); /* Add contacts to submenu */ for (le = list_head(contact_list(contacts)); le; le = le->next) { struct contact *c = le->data; item = gtk_menu_item_new_with_label(contact_str(c)); gtk_menu_shell_append(contacts_menu, item); g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(menu_on_dial_contact), mod); } } static void menu_on_account_toggled(GtkCheckMenuItem *menu_item, struct gtk_mod *mod) { struct ua *ua = g_object_get_data(G_OBJECT(menu_item), "ua"); if (menu_item->active) mqueue_push(mod->mq, MQ_SELECT_UA, ua); } static void menu_on_presence_set(GtkMenuItem *item, struct gtk_mod *mod) { struct le *le; void *type = g_object_get_data(G_OBJECT(item), "presence"); enum presence_status status = GPOINTER_TO_UINT(type); (void)mod; for (le = list_head(uag_list()); le; le = le->next) { struct ua *ua = le->data; ua_presence_status_set(ua, status); } } #ifdef USE_NOTIFICATIONS static void menu_on_incoming_call_answer(GtkMenuItem *menuItem, struct gtk_mod *mod) { struct call *call = g_object_get_data(G_OBJECT(menuItem), "call"); denotify_incoming_call(mod, call); mqueue_push(mod->mq, MQ_ANSWER, call); } static void menu_on_incoming_call_reject(GtkMenuItem *menuItem, struct gtk_mod *mod) { struct call *call = g_object_get_data(G_OBJECT(menuItem), "call"); denotify_incoming_call(mod, call); mqueue_push(mod->mq, MQ_HANGUP, call); } #endif static GtkMenuItem *accounts_menu_add_item(struct gtk_mod *mod, struct ua *ua) { GtkMenuShell *accounts_menu = GTK_MENU_SHELL(mod->accounts_menu); GtkWidget *item; GSList *group = mod->accounts_menu_group; struct ua *ua_current = uag_current(); char buf[256]; re_snprintf(buf, sizeof buf, "%s%s", ua_aor(ua), ua_isregistered(ua) ? " (OK)" : ""); item = gtk_radio_menu_item_new_with_label(group, buf); group = gtk_radio_menu_item_get_group( GTK_RADIO_MENU_ITEM (item)); if (ua == ua_current) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), TRUE); g_object_set_data(G_OBJECT(item), "ua", ua); g_signal_connect(item, "toggled", G_CALLBACK(menu_on_account_toggled), mod); gtk_menu_shell_append(accounts_menu, item); mod->accounts_menu_group = group; return GTK_MENU_ITEM(item); } static GtkMenuItem *accounts_menu_get_item(struct gtk_mod *mod, struct ua *ua) { GtkMenuItem *item; GtkMenuShell *accounts_menu = GTK_MENU_SHELL(mod->accounts_menu); GList *items = accounts_menu->children; for (; items; items = items->next) { item = items->data; if (ua == g_object_get_data(G_OBJECT(item), "ua")) return item; } /* Add new account not yet in menu */ return accounts_menu_add_item(mod, ua); } static void update_current_accounts_menu_item(struct gtk_mod *mod) { GtkMenuItem *item = accounts_menu_get_item(mod, uag_current()); gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), TRUE); } static void update_ua_presence(struct gtk_mod *mod) { GtkCheckMenuItem *item = 0; enum presence_status cur_status; void *status; GtkMenuShell *status_menu = GTK_MENU_SHELL(mod->status_menu); GList *items = status_menu->children; cur_status = ua_presence_status(uag_current()); for (; items; items = items->next) { item = items->data; status = g_object_get_data(G_OBJECT(item), "presence"); if (cur_status == GPOINTER_TO_UINT(status)) break; } if (!item) return; gtk_check_menu_item_set_active(item, TRUE); } static const char *ua_event_reg_str(enum ua_event ev) { switch (ev) { case UA_EVENT_REGISTERING: return "registering"; case UA_EVENT_REGISTER_OK: return "OK"; case UA_EVENT_REGISTER_FAIL: return "ERR"; case UA_EVENT_UNREGISTERING: return "unregistering"; default: return "?"; } } static void accounts_menu_set_status(struct gtk_mod *mod, struct ua *ua, enum ua_event ev) { GtkMenuItem *item = accounts_menu_get_item(mod, ua); char buf[256]; re_snprintf(buf, sizeof buf, "%s (%s)", ua_aor(ua), ua_event_reg_str(ev)); gtk_menu_item_set_label(item, buf); } #ifdef USE_NOTIFICATIONS static void notify_incoming_call(struct gtk_mod *mod, struct call *call) { char title[128]; const char *msg = call_peeruri(call); GtkWidget *call_menu; GtkWidget *menu_item; #if defined(USE_LIBNOTIFY) NotifyNotification *notification; #elif GLIB_CHECK_VERSION(2,40,0) char id[64]; GVariant *target; GNotification *notification; #endif re_snprintf(title, sizeof title, "Incoming call from %s", call_peername(call)); #if defined(USE_LIBNOTIFY) if (!notify_is_initted()) return; notification = notify_notification_new(title, msg, "baresip"); notify_notification_set_urgency(notification, NOTIFY_URGENCY_CRITICAL); notify_notification_show(notification, NULL); g_object_unref(notification); #elif GLIB_CHECK_VERSION(2,40,0) notification = g_notification_new(title); re_snprintf(id, sizeof id, "incoming-call-%p", call); id[sizeof id - 1] = '\0'; #if GLIB_CHECK_VERSION(2,42,0) g_notification_set_priority(notification, G_NOTIFICATION_PRIORITY_URGENT); #else g_notification_set_urgent(notification, TRUE); #endif target = g_variant_new_string(call_id(call)); g_notification_set_body(notification, msg); g_notification_add_button_with_target_value(notification, "Answer", "app.answer", target); g_notification_add_button_with_target_value(notification, "Reject", "app.reject", target); g_application_send_notification(mod->app, id, notification); g_object_unref(notification); #else (void)msg; (void)title; #endif /* Add incoming call to the app menu */ call_menu = gtk_menu_new(); menu_item = gtk_menu_item_new_with_mnemonic("_Incoming call"); g_object_set_data(G_OBJECT(menu_item), "call", call); gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item), call_menu); gtk_menu_shell_prepend(GTK_MENU_SHELL(mod->app_menu), menu_item); mod->incoming_call_menus = g_slist_append(mod->incoming_call_menus, menu_item); menu_item = gtk_menu_item_new_with_label(call_peeruri(call)); gtk_widget_set_sensitive(menu_item, FALSE); gtk_menu_shell_append(GTK_MENU_SHELL(call_menu), menu_item); menu_item = gtk_menu_item_new_with_mnemonic("_Accept"); g_object_set_data(G_OBJECT(menu_item), "call", call); g_signal_connect(G_OBJECT(menu_item), "activate", G_CALLBACK(menu_on_incoming_call_answer), mod); gtk_menu_shell_append(GTK_MENU_SHELL(call_menu), menu_item); menu_item = gtk_menu_item_new_with_mnemonic("_Reject"); g_object_set_data(G_OBJECT(menu_item), "call", call); g_signal_connect(G_OBJECT(menu_item), "activate", G_CALLBACK(menu_on_incoming_call_reject), mod); gtk_menu_shell_append(GTK_MENU_SHELL(call_menu), menu_item); } #endif static void denotify_incoming_call(struct gtk_mod *mod, struct call *call) { GSList *item, *next; #if GLIB_CHECK_VERSION(2,40,0) char id[64]; re_snprintf(id, sizeof id, "incoming-call-%p", call); id[sizeof id - 1] = '\0'; g_application_withdraw_notification(mod->app, id); #endif /* Remove call submenu */ for (item = mod->incoming_call_menus; item; item = next) { GtkWidget *menu_item = item->data; next = item->next; if (call == g_object_get_data(G_OBJECT(menu_item), "call")) { gtk_widget_destroy(menu_item); mod->incoming_call_menus = g_slist_delete_link(mod->incoming_call_menus, item); } } } static void answer_activated(GSimpleAction *action, GVariant *parameter, gpointer arg) { struct gtk_mod *mod = arg; struct call *call = get_call_from_gvariant(parameter); (void)action; if (call) { denotify_incoming_call(mod, call); mqueue_push(mod->mq, MQ_ANSWER, call); } } static void reject_activated(GSimpleAction *action, GVariant *parameter, gpointer arg) { struct gtk_mod *mod = arg; struct call *call = get_call_from_gvariant(parameter); (void)action; if (call) { denotify_incoming_call(mod, call); mqueue_push(mod->mq, MQ_HANGUP, call); } } static struct call_window *new_call_window(struct gtk_mod *mod, struct call *call) { struct call_window *win = call_window_new(call, mod); if (call) { mod->call_windows = g_slist_append(mod->call_windows, win); } return win; } static struct call_window *get_call_window(struct gtk_mod *mod, struct call *call) { GSList *wins; for (wins = mod->call_windows; wins; wins = wins->next) { struct call_window *win = wins->data; if (call_window_is_for_call(win, call)) return win; } return NULL; } static struct call_window *get_create_call_window(struct gtk_mod *mod, struct call *call) { struct call_window *win = get_call_window(mod, call); if (!win) win = new_call_window(mod, call); return win; } void gtk_mod_call_window_closed(struct gtk_mod *mod, struct call_window *win) { if (!mod) return; mod->call_windows = g_slist_remove(mod->call_windows, win); } static void ua_event_handler(struct ua *ua, enum ua_event ev, struct call *call, const char *prm, void *arg) { struct gtk_mod *mod = arg; struct call_window *win; gdk_threads_enter(); switch (ev) { case UA_EVENT_REGISTERING: case UA_EVENT_UNREGISTERING: case UA_EVENT_REGISTER_OK: case UA_EVENT_REGISTER_FAIL: accounts_menu_set_status(mod, ua, ev); break; #ifdef USE_NOTIFICATIONS case UA_EVENT_CALL_INCOMING: notify_incoming_call(mod, call); break; #endif case UA_EVENT_CALL_CLOSED: win = get_call_window(mod, call); if (win) call_window_closed(win, prm); else denotify_incoming_call(mod, call); break; case UA_EVENT_CALL_RINGING: win = get_create_call_window(mod, call); if (win) call_window_ringing(win); break; case UA_EVENT_CALL_PROGRESS: win = get_create_call_window(mod, call); if (win) call_window_progress(win); break; case UA_EVENT_CALL_ESTABLISHED: win = get_create_call_window(mod, call); if (win) call_window_established(win); break; case UA_EVENT_CALL_TRANSFER_FAILED: win = get_create_call_window(mod, call); if (win) call_window_transfer_failed(win, prm); break; default: break; } gdk_threads_leave(); } #ifdef USE_NOTIFICATIONS static void message_handler(struct ua *ua, const struct pl *peer, const struct pl *ctype, struct mbuf *body, void *arg) { struct gtk_mod *mod = arg; char title[128]; char msg[512]; #if GLIB_CHECK_VERSION(2,40,0) GNotification *notification; #elif defined(USE_LIBNOTIFY) NotifyNotification *notification; #endif (void)ua; (void)ctype; /* Display notification of chat */ re_snprintf(title, sizeof title, "Chat from %r", peer); title[sizeof title - 1] = '\0'; re_snprintf(msg, sizeof msg, "%b", mbuf_buf(body), mbuf_get_left(body)); #if GLIB_CHECK_VERSION(2,40,0) notification = g_notification_new(title); g_notification_set_body(notification, msg); g_application_send_notification(mod->app, NULL, notification); g_object_unref(notification); #elif defined(USE_LIBNOTIFY) (void)mod; if (!notify_is_initted()) return; notification = notify_notification_new(title, msg, "baresip"); notify_notification_show(notification, NULL); g_object_unref(notification); #endif } #endif static void popup_menu(struct gtk_mod *mod, GtkMenuPositionFunc position, gpointer position_arg, guint button, guint32 activate_time) { if (!mod->contacts_inited) { init_contacts_menu(mod); mod->contacts_inited = TRUE; } /* Update things that may have been changed through another UI */ update_current_accounts_menu_item(mod); update_ua_presence(mod); gtk_widget_show_all(mod->app_menu); gtk_menu_popup(GTK_MENU(mod->app_menu), NULL, NULL, position, position_arg, button, activate_time); } static gboolean status_icon_on_button_press(GtkStatusIcon *status_icon, GdkEventButton *event, struct gtk_mod *mod) { popup_menu(mod, gtk_status_icon_position_menu, status_icon, event->button, event->time); return TRUE; } void gtk_mod_connect(struct gtk_mod *mod, const char *uri) { if (!mod) return; mqueue_push(mod->mq, MQ_CONNECT, (char *)uri); } bool gtk_mod_clean_number(struct gtk_mod *mod) { if (!mod) return false; return mod->clean_number; } static void warning_dialog(const char *title, const char *fmt, ...) { va_list ap; char msg[512]; GtkWidget *dialog; va_start(ap, fmt); (void)re_vsnprintf(msg, sizeof msg, fmt, ap); va_end(ap); dialog = gtk_message_dialog_new(NULL, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "%s", title); gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog), "%s", msg); g_signal_connect_swapped(G_OBJECT(dialog), "response", G_CALLBACK(gtk_widget_destroy), dialog); gtk_window_set_title(GTK_WINDOW(dialog), title); gtk_widget_show(dialog); } static void mqueue_handler(int id, void *data, void *arg) { struct gtk_mod *mod = arg; const char *uri; struct call *call; int err; struct ua *ua = uag_current(); switch ((enum gtk_mod_events)id) { case MQ_POPUP: gdk_threads_enter(); popup_menu(mod, NULL, NULL, 0, GPOINTER_TO_UINT(data)); gdk_threads_leave(); break; case MQ_CONNECT: uri = data; err = ua_connect(ua, &call, NULL, uri, VIDMODE_ON); if (err) { gdk_threads_enter(); warning_dialog("Call failed", "Connecting to \"%s\" failed.\n" "Error: %m", uri, err); gdk_threads_leave(); break; } gdk_threads_enter(); err = new_call_window(mod, call) == NULL; gdk_threads_leave(); if (err) { ua_hangup(ua, call, 500, "Server Error"); } break; case MQ_HANGUP: call = data; ua_hangup(ua, call, 0, NULL); break; case MQ_QUIT: ua_stop_all(false); break; case MQ_ANSWER: call = data; err = ua_answer(ua, call, VIDMODE_ON); if (err) { gdk_threads_enter(); warning_dialog("Call failed", "Answering the call " "from \"%s\" failed.\n" "Error: %m", call_peername(call), err); gdk_threads_leave(); break; } gdk_threads_enter(); err = new_call_window(mod, call) == NULL; gdk_threads_leave(); if (err) { ua_hangup(ua, call, 500, "Server Error"); } break; case MQ_SELECT_UA: ua = data; uag_current_set(ua); break; } } static void *gtk_thread(void *arg) { struct gtk_mod *mod = arg; GtkMenuShell *app_menu; GtkWidget *item; GError *err = NULL; struct le *le; gdk_threads_init(); gtk_init(0, NULL); g_set_application_name("baresip"); mod->app = g_application_new("com.creytiv.baresip", G_APPLICATION_FLAGS_NONE); g_application_register(G_APPLICATION (mod->app), NULL, &err); if (err != NULL) { warning ("Unable to register GApplication: %s", err->message); g_error_free(err); err = NULL; } #ifdef USE_LIBNOTIFY notify_init("baresip"); #endif mod->status_icon = gtk_status_icon_new_from_icon_name("call-start"); gtk_status_icon_set_tooltip_text (mod->status_icon, "baresip"); g_signal_connect(G_OBJECT(mod->status_icon), "button_press_event", G_CALLBACK(status_icon_on_button_press), mod); gtk_status_icon_set_visible(mod->status_icon, TRUE); mod->contacts_inited = false; mod->dial_dialog = NULL; mod->call_windows = NULL; mod->incoming_call_menus = NULL; /* App menu */ mod->app_menu = gtk_menu_new(); app_menu = GTK_MENU_SHELL(mod->app_menu); /* Account submenu */ mod->accounts_menu = gtk_menu_new(); mod->accounts_menu_group = NULL; item = gtk_menu_item_new_with_mnemonic("_Account"); gtk_menu_shell_append(app_menu, item); gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), mod->accounts_menu); /* Add accounts to submenu */ for (le = list_head(uag_list()); le; le = le->next) { struct ua *ua = le->data; accounts_menu_add_item(mod, ua); } /* Status submenu */ mod->status_menu = gtk_menu_new(); item = gtk_menu_item_new_with_mnemonic("_Status"); gtk_menu_shell_append(GTK_MENU_SHELL(app_menu), item); gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), mod->status_menu); /* Open */ item = gtk_radio_menu_item_new_with_label(NULL, "Open"); g_object_set_data(G_OBJECT(item), "presence", GINT_TO_POINTER(PRESENCE_OPEN)); g_signal_connect(item, "activate", G_CALLBACK(menu_on_presence_set), mod); gtk_menu_shell_append(GTK_MENU_SHELL(mod->status_menu), item); gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), TRUE); /* Closed */ item = gtk_radio_menu_item_new_with_label_from_widget( GTK_RADIO_MENU_ITEM(item), "Closed"); g_object_set_data(G_OBJECT(item), "presence", GINT_TO_POINTER(PRESENCE_CLOSED)); g_signal_connect(item, "activate", G_CALLBACK(menu_on_presence_set), mod); gtk_menu_shell_append(GTK_MENU_SHELL(mod->status_menu), item); gtk_menu_shell_append(app_menu, gtk_separator_menu_item_new()); /* Dial */ item = gtk_menu_item_new_with_mnemonic("_Dial..."); gtk_menu_shell_append(app_menu, item); g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(menu_on_dial), mod); /* Dial contact */ mod->contacts_menu = gtk_menu_new(); item = gtk_menu_item_new_with_mnemonic("Dial _contact"); gtk_menu_shell_append(app_menu, item); gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), mod->contacts_menu); gtk_menu_shell_append(app_menu, gtk_separator_menu_item_new()); /* About */ item = gtk_menu_item_new_with_mnemonic("A_bout"); g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(menu_on_about), mod); gtk_menu_shell_append(app_menu, item); gtk_menu_shell_append(app_menu, gtk_separator_menu_item_new()); /* Quit */ item = gtk_menu_item_new_with_mnemonic("_Quit"); g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(menu_on_quit), mod); gtk_menu_shell_append(app_menu, item); g_action_map_add_action_entries(G_ACTION_MAP(mod->app), app_entries, G_N_ELEMENTS(app_entries), mod); info("gtk_menu starting\n"); uag_event_register(ua_event_handler, mod); mod->run = true; gtk_main(); mod->run = false; uag_event_unregister(ua_event_handler); mod->dial_dialog = mem_deref(mod->dial_dialog); return NULL; } static void vu_enc_destructor(void *arg) { struct vumeter_enc *st = arg; list_unlink(&st->af.le); } static void vu_dec_destructor(void *arg) { struct vumeter_dec *st = arg; list_unlink(&st->af.le); } static int16_t calc_avg_s16(const int16_t *sampv, size_t sampc) { int32_t v = 0; size_t i; if (!sampv || !sampc) return 0; for (i=0; ifmt != AUFMT_S16LE) { warning("vumeter: unsupported sample format (%s)\n", aufmt_name(prm->fmt)); return ENOTSUP; } st = mem_zalloc(sizeof(*st), vu_enc_destructor); if (!st) return ENOMEM; gdk_threads_enter(); call_window_got_vu_enc(st); gdk_threads_leave(); *stp = (struct aufilt_enc_st *)st; return 0; } static int vu_decode_update(struct aufilt_dec_st **stp, void **ctx, const struct aufilt *af, struct aufilt_prm *prm, const struct audio *au) { struct vumeter_dec *st; (void)ctx; (void)prm; (void)au; if (!stp || !af) return EINVAL; if (*stp) return 0; if (prm->fmt != AUFMT_S16LE) { warning("vumeter: unsupported sample format (%s)\n", aufmt_name(prm->fmt)); return ENOTSUP; } st = mem_zalloc(sizeof(*st), vu_dec_destructor); if (!st) return ENOMEM; gdk_threads_enter(); call_window_got_vu_dec(st); gdk_threads_leave(); *stp = (struct aufilt_dec_st *)st; return 0; } static int vu_encode(struct aufilt_enc_st *st, struct auframe *af) { struct vumeter_enc *vu = (struct vumeter_enc *)st; vu->avg_rec = calc_avg_s16(af->sampv, af->sampc); vu->started = true; return 0; } static int vu_decode(struct aufilt_dec_st *st, struct auframe *af) { struct vumeter_dec *vu = (struct vumeter_dec *)st; vu->avg_play = calc_avg_s16(af->sampv, af->sampc); vu->started = true; return 0; } static struct aufilt vumeter = { .name = "gtk_vumeter", .encupdh = vu_encode_update, .ench = vu_encode, .decupdh = vu_decode_update, .dech = vu_decode }; static int cmd_popup_menu(struct re_printf *pf, void *unused) { (void)pf; (void)unused; mqueue_push(mod_obj.mq, MQ_POPUP, GUINT_TO_POINTER(GDK_CURRENT_TIME)); return 0; } static const struct cmd cmdv[] = { {"gtk", 0, 0, "Pop up GTK+ menu", cmd_popup_menu }, }; static int module_init(void) { int err; mod_obj.clean_number = false; conf_get_bool(conf_cur(), "gtk_clean_number", &mod_obj.clean_number); err = mqueue_alloc(&mod_obj.mq, mqueue_handler, &mod_obj); if (err) return err; aufilt_register(baresip_aufiltl(), &vumeter); #ifdef USE_NOTIFICATIONS err = message_listen(baresip_message(), message_handler, &mod_obj); if (err) { warning("gtk: message_init failed (%m)\n", err); return err; } #endif err = cmd_register(baresip_commands(), cmdv, ARRAY_SIZE(cmdv)); if (err) return err; /* start the thread last */ err = pthread_create(&mod_obj.thread, NULL, gtk_thread, &mod_obj); if (err) return err; return err; } static int module_close(void) { cmd_unregister(baresip_commands(), cmdv); if (mod_obj.run) { gdk_threads_enter(); gtk_main_quit(); gdk_threads_leave(); } if (mod_obj.thread) pthread_join(mod_obj.thread, NULL); mod_obj.mq = mem_deref(mod_obj.mq); aufilt_unregister(&vumeter); message_unlisten(baresip_message(), message_handler); #ifdef USE_LIBNOTIFY if (notify_is_initted()) notify_uninit(); #endif g_slist_free(mod_obj.accounts_menu_group); g_slist_free(mod_obj.call_windows); g_slist_free(mod_obj.incoming_call_menus); uag_event_unregister(ua_event_handler); return 0; } EXPORT_SYM const struct mod_export DECL_EXPORTS(gtk) = { "gtk", "application", module_init, module_close, }; baresip-1.0.0/modules/gtk/gtk_mod.h000066400000000000000000000033701372575704200172060ustar00rootroot00000000000000/** * @file gtk/gtk_mod.h GTK+ UI module -- internal API * * Copyright (C) 2015 Charles E. Lehner */ struct gtk_mod; struct call_window; struct dial_dialog; struct transfer_dialog; struct vumeter_enc { struct aufilt_enc_st af; /* inheritance */ int16_t avg_rec; volatile bool started; }; struct vumeter_dec { struct aufilt_dec_st af; /* inheritance */ int16_t avg_play; volatile bool started; }; /* Main menu */ void gtk_mod_connect(struct gtk_mod *, const char *uri); void gtk_mod_call_window_closed(struct gtk_mod *, struct call_window *); /* Call Window */ struct call_window *call_window_new(struct call *call, struct gtk_mod *mod); void call_window_got_vu_dec(struct vumeter_dec *); void call_window_got_vu_enc(struct vumeter_enc *); void call_window_transfer(struct call_window *, const char *uri); void call_window_closed(struct call_window *, const char *reason); void call_window_ringing(struct call_window *); void call_window_progress(struct call_window *); void call_window_established(struct call_window *); void call_window_transfer_failed(struct call_window *, const char *reason); bool call_window_is_for_call(struct call_window *, struct call *); /* Dial Dialog */ struct dial_dialog *dial_dialog_alloc(struct gtk_mod *); void dial_dialog_show(struct dial_dialog *); /* Call transfer dialog */ struct transfer_dialog *transfer_dialog_alloc(struct call_window *); void transfer_dialog_show(struct transfer_dialog *); void transfer_dialog_fail(struct transfer_dialog *, const char *reason); /* URI entry combo box */ GtkWidget *uri_combo_box_new(void); void uri_combo_box_set_text(GtkComboBox *box, char* str, int length); const char *uri_combo_box_get_text(GtkComboBox *box); /* Helper functions */ bool gtk_mod_clean_number(struct gtk_mod *mod); baresip-1.0.0/modules/gtk/module.mk000066400000000000000000000010321372575704200172200ustar00rootroot00000000000000# # module.mk - GTK+ Menu-based UI # # Copyright (C) 2010 Creytiv.com # Copyright (C) 2015 Charles E. Lehner # MOD := gtk $(MOD)_SRCS += gtk_mod.c call_window.c dial_dialog.c transfer_dialog.c \ uri_entry.c $(MOD)_LFLAGS += $(shell pkg-config --libs gtk+-2.0 $($(MOD)_EXTRA)) $(MOD)_CFLAGS += \ $(shell pkg-config --cflags gtk+-2.0 $($(MOD)_EXTRA) | \ sed -e 's/-I/-isystem/g' ) $(MOD)_CFLAGS += -Wno-strict-prototypes ifneq ($(USE_LIBNOTIFY),) $(MOD)_EXTRA = libnotify $(MOD)_CFLAGS += -DUSE_LIBNOTIFY=1 endif include mk/mod.mk baresip-1.0.0/modules/gtk/transfer_dialog.c000066400000000000000000000066601372575704200207250ustar00rootroot00000000000000/** * @file transfer_dialog.c GTK+ call transfer dialog * * Copyright (C) 2015 Charles E. Lehner */ #include #include #include #include "gtk_mod.h" struct transfer_dialog { struct call_window *call_win; GtkWidget *dialog; GtkComboBox *uri_combobox; GtkLabel *status_label; GtkWidget *spinner; }; static const char *status_progress = "progress"; static void set_status(struct transfer_dialog *td, const char *status) { if (status == status_progress) { gtk_widget_show(td->spinner); gtk_spinner_start(GTK_SPINNER(td->spinner)); gtk_label_set_text(td->status_label, NULL); } else { gtk_widget_hide(td->spinner); gtk_spinner_stop(GTK_SPINNER(td->spinner)); gtk_label_set_text(td->status_label, status); } } static void on_dialog_response(GtkDialog *dialog, gint response_id, struct transfer_dialog *win) { char *uri; if (response_id == GTK_RESPONSE_ACCEPT) { uri = (char *)uri_combo_box_get_text(win->uri_combobox); set_status(win, status_progress); call_window_transfer(win->call_win, uri); } else { set_status(win, NULL); gtk_widget_hide(GTK_WIDGET(dialog)); } } static void destructor(void *arg) { struct transfer_dialog *td = arg; gtk_widget_destroy(td->dialog); } struct transfer_dialog *transfer_dialog_alloc(struct call_window *call_win) { struct transfer_dialog *win; GtkWidget *dialog, *content, *button, *image, *hbox, *spinner, *label; GtkWidget *uri_combobox; win = mem_zalloc(sizeof(*win), destructor); if (!win) return NULL; dialog = gtk_dialog_new_with_buttons("Transfer", NULL, 0, GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, NULL); /* Transfer button */ button = gtk_button_new_with_label("Transfer"); image = gtk_image_new_from_icon_name("forward", GTK_ICON_SIZE_BUTTON); gtk_button_set_image(GTK_BUTTON(button), image); gtk_dialog_add_action_widget(GTK_DIALOG(dialog), button, GTK_RESPONSE_ACCEPT); gtk_widget_set_can_default(button, TRUE); gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT); /* Label */ content = gtk_dialog_get_content_area(GTK_DIALOG(dialog)); label = gtk_label_new("Transfer call to:"); gtk_box_pack_start(GTK_BOX(content), label, FALSE, FALSE, 0); /* URI entry */ uri_combobox = uri_combo_box_new(); gtk_box_pack_start(GTK_BOX(content), uri_combobox, FALSE, FALSE, 5); g_signal_connect(dialog, "response", G_CALLBACK(on_dialog_response), win); g_signal_connect(dialog, "delete-event", G_CALLBACK(gtk_widget_hide_on_delete), win); /* Spinner and status */ hbox = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(content), hbox, FALSE, FALSE, 0); spinner = gtk_spinner_new(); gtk_box_pack_start(GTK_BOX(hbox), spinner, TRUE, TRUE, 0); label = gtk_label_new(NULL); gtk_box_pack_start(GTK_BOX(content), label, FALSE, FALSE, 0); win->status_label = GTK_LABEL(label); win->dialog = dialog; win->uri_combobox = GTK_COMBO_BOX(uri_combobox); win->call_win = call_win; win->spinner = spinner; gtk_widget_show_all(dialog); gtk_widget_hide(spinner); return win; } void transfer_dialog_show(struct transfer_dialog *td) { if (!td) return; gtk_window_present(GTK_WINDOW(td->dialog)); gtk_widget_grab_focus(gtk_bin_get_child(GTK_BIN(td->uri_combobox))); set_status(td, NULL); } void transfer_dialog_fail(struct transfer_dialog *td, const char *reason) { char buf[256]; if (!td) return; re_snprintf(buf, sizeof buf, "Transfer failed: %s", reason); set_status(td, buf); } baresip-1.0.0/modules/gtk/uri_entry.c000066400000000000000000000025151372575704200175750ustar00rootroot00000000000000/** * @file uri_entry.c GTK+ URI entry combo box * * Copyright (C) 2015 Charles E. Lehner */ #include #include #include #include "gtk_mod.h" /** * Create a URI combox box. * * The combo box has a menu of contacts, and a text entry for a URI. * * @return the combo box */ GtkWidget *uri_combo_box_new(void) { struct contacts *contacts = baresip_contacts(); struct le *le; GtkEntry *uri_entry; GtkWidget *uri_combobox; uri_combobox = gtk_combo_box_text_new_with_entry(); uri_entry = GTK_ENTRY(gtk_bin_get_child(GTK_BIN(uri_combobox))); gtk_entry_set_activates_default(uri_entry, TRUE); for (le = list_head(contact_list(contacts)); le; le = le->next) { struct contact *c = le->data; gtk_combo_box_text_append_text( GTK_COMBO_BOX_TEXT(uri_combobox), contact_str(c)); } return uri_combobox; } void uri_combo_box_set_text(GtkComboBox *box, char* str, int length) { gchar* number = g_strdup (str); GtkEntry *entry = GTK_ENTRY(gtk_bin_get_child(GTK_BIN(box))); GtkEntryBuffer *buf = gtk_entry_get_buffer(entry); gtk_entry_buffer_set_text(buf, number, length); } const char *uri_combo_box_get_text(GtkComboBox *box) { GtkEntry *entry = GTK_ENTRY(gtk_bin_get_child(GTK_BIN(box))); GtkEntryBuffer *buf = gtk_entry_get_buffer(entry); return gtk_entry_buffer_get_text(buf); } baresip-1.0.0/modules/gzrtp/000077500000000000000000000000001372575704200157675ustar00rootroot00000000000000baresip-1.0.0/modules/gzrtp/gzrtp.cpp000066400000000000000000000104571372575704200176500ustar00rootroot00000000000000/** * @file gzrtp.cpp GNU ZRTP: Media Path Key Agreement for Unicast Secure RTP * * Copyright (C) 2010 - 2017 Creytiv.com */ #include #include #include #include #include #include "session.h" #include "stream.h" /** * @defgroup gzrtp gzrtp * * ZRTP: Media Path Key Agreement for Unicast Secure RTP * * Experimental support for ZRTP * * See http://tools.ietf.org/html/rfc6189 * * * This module is using GNU ZRTP C++ library * * https://github.com/wernerd/ZRTPCPP * * Configuration options: * \verbatim zrtp_parallel {yes,no} # Start all streams at once \endverbatim * */ static ZRTPConfig *s_zrtp_config = NULL; struct menc_sess { Session *session; }; struct menc_media { Stream *stream; const struct stream *strm; /**< pointer to parent */ }; static void session_destructor(void *arg) { struct menc_sess *st = (struct menc_sess *)arg; delete st->session; } static void media_destructor(void *arg) { struct menc_media *st = (struct menc_media *)arg; delete st->stream; } static int session_alloc(struct menc_sess **sessp, struct sdp_session *sdp, bool offerer, menc_event_h *eventh, menc_error_h *errorh, void *arg) { struct menc_sess *st; (void)offerer; (void)eventh; (void)errorh; (void)arg; int err = 0; if (!sessp || !sdp) return EINVAL; st = (struct menc_sess *)mem_zalloc(sizeof(*st), session_destructor); if (!st) return ENOMEM; st->session = new Session(*s_zrtp_config); if (!st->session) err = ENOMEM; if (err) mem_deref(st); else *sessp = st; return err; } static int media_alloc(struct menc_media **stp, struct menc_sess *sess, struct rtp_sock *rtp, struct udp_sock *rtpsock, struct udp_sock *rtcpsock, const struct sa *raddr_rtp, const struct sa *raddr_rtcp, struct sdp_media *sdpm, const struct stream *strm) { struct menc_media *st; int err = 0; StreamMediaType med_type; const char *med_name; if (!stp || !sess || !sess->session) return EINVAL; st = *stp; if (st) goto start; st = (struct menc_media *)mem_zalloc(sizeof(*st), media_destructor); if (!st) return ENOMEM; med_name = sdp_media_name(sdpm); if (str_cmp(med_name, "audio") == 0) med_type = MT_AUDIO; else if (str_cmp(med_name, "video") == 0) med_type = MT_VIDEO; else if (str_cmp(med_name, "text") == 0) med_type = MT_TEXT; else if (str_cmp(med_name, "application") == 0) med_type = MT_APPLICATION; else if (str_cmp(med_name, "message") == 0) med_type = MT_MESSAGE; else med_type = MT_UNKNOWN; st->strm = strm; st->stream = sess->session->create_stream( *s_zrtp_config, (struct udp_sock *)rtpsock, (struct udp_sock *)rtcpsock, rtp_sess_ssrc(rtp), med_type); if (!st->stream) { err = ENOMEM; goto out; } st->stream->sdp_encode(sdpm); out: if (err) { mem_deref(st); return err; } else *stp = st; start: if (sa_isset(sdp_media_raddr(sdpm), SA_ALL)) { st->stream->sdp_decode(sdpm); err = sess->session->start_stream(st->stream); if (err) { warning("zrtp: stream start failed: %d\n", err); } } return err; } static struct menc menc_zrtp = { .id = "zrtp", .sdp_proto = "RTP/AVP", .sessh = session_alloc, .mediah = media_alloc }; static const struct cmd cmdv[] = { {"zrtp_verify", 0, CMD_PRM, "Verify ZRTP SAS ", Session::cmd_verify_sas }, {"zrtp_unverify", 0, CMD_PRM, "Unverify ZRTP SAS ", Session::cmd_unverify_sas }, }; static int module_init(void) { char config_path[256]; int err = 0; err = conf_path_get(config_path, sizeof(config_path)); if (err) { warning("zrtp: could not get config path: %m\n", err); return err; } s_zrtp_config = new ZRTPConfig(conf_cur(), config_path); if (!s_zrtp_config) return ENOMEM; menc_register(baresip_mencl(), &menc_zrtp); return cmd_register(baresip_commands(), cmdv, ARRAY_SIZE(cmdv)); } static int module_close(void) { delete s_zrtp_config; s_zrtp_config = NULL; cmd_unregister(baresip_commands(), cmdv); menc_unregister(&menc_zrtp); return 0; } extern "C" EXPORT_SYM const struct mod_export DECL_EXPORTS(gzrtp) = { "gzrtp", "menc", module_init, module_close }; baresip-1.0.0/modules/gzrtp/messages.cpp000066400000000000000000000133231372575704200203040ustar00rootroot00000000000000/** * @file messages.cpp GNU ZRTP: Engine messages * * Copyright (C) 2010 - 2017 Creytiv.com */ #include #include #include #include #include "stream.h" using namespace GnuZrtpCodes; #define NO_MESSAGE "NO MESSAGE DEFINED" static const char *info_msg(int32_t subcode) { const char *msg; switch (subcode) { case InfoHelloReceived: msg = "Hello received and prepared a Commit, " "ready to get peer's hello hash"; break; case InfoCommitDHGenerated: msg = "Commit: Generated a public DH key"; break; case InfoRespCommitReceived: msg = "Responder: Commit received, preparing DHPart1"; break; case InfoDH1DHGenerated: msg = "DH1Part: Generated a public DH key"; break; case InfoInitDH1Received: msg = "Initiator: DHPart1 received, preparing DHPart2"; break; case InfoRespDH2Received: msg = "Responder: DHPart2 received, preparing Confirm1"; break; case InfoInitConf1Received: msg = "Initiator: Confirm1 received, preparing Confirm2"; break; case InfoRespConf2Received: msg = "Responder: Confirm2 received, preparing Conf2Ack"; break; case InfoRSMatchFound: msg = "At least one retained secret matches - security OK"; break; case InfoSecureStateOn: msg = "Entered secure state"; break; case InfoSecureStateOff: msg = "No more security for this session"; break; default: msg = NO_MESSAGE; break; } return msg; } static const char *warning_msg(int32_t subcode) { const char *msg; switch (subcode) { case WarningDHAESmismatch: msg = "Commit contains an AES256 cipher but does not offer a " "Diffie-Helman 4096 - not used DH4096 was discarded"; break; case WarningGoClearReceived: msg = "Received a GoClear message"; break; case WarningDHShort: msg = "Hello offers an AES256 cipher but does not offer a " "Diffie-Helman 4096- not used DH4096 was discarded"; break; case WarningNoRSMatch: msg = "No retained shared secrets available - must verify SAS"; break; case WarningCRCmismatch: msg = "Internal ZRTP packet checksum mismatch - " "packet dropped"; break; case WarningSRTPauthError: msg = "Dropping packet because SRTP authentication failed!"; break; case WarningSRTPreplayError: msg = "Dropping packet because SRTP replay check failed!"; break; case WarningNoExpectedRSMatch: msg = "Valid retained shared secrets availabe but no matches " "found - must verify SAS"; break; case WarningNoExpectedAuxMatch: msg = "Our AUX secret was set but the other peer's AUX secret " "does not match ours"; break; default: msg = NO_MESSAGE; break; } return msg; } static const char *severe_msg(int32_t subcode) { const char *msg; switch (subcode) { case SevereHelloHMACFailed: msg = "Hash HMAC check of Hello failed!"; break; case SevereCommitHMACFailed: msg = "Hash HMAC check of Commit failed!"; break; case SevereDH1HMACFailed: msg = "Hash HMAC check of DHPart1 failed!"; break; case SevereDH2HMACFailed: msg = "Hash HMAC check of DHPart2 failed!"; break; case SevereCannotSend: msg = "Cannot send data - connection or peer down?"; break; case SevereProtocolError: msg = "Internal protocol error occured!"; break; case SevereNoTimer: msg = "Cannot start a timer - internal resources exhausted?"; break; case SevereTooMuchRetries: msg = "Too much retries during ZRTP negotiation - connection " "or peer down?"; break; default: msg = NO_MESSAGE; break; } return msg; } static const char *zrtp_msg(int32_t subcode) { const char *msg; switch (subcode) { case MalformedPacket: msg = "Malformed packet (CRC OK, but wrong structure)"; break; case CriticalSWError: msg = "Critical software error"; break; case UnsuppZRTPVersion: msg = "Unsupported ZRTP version"; break; case HelloCompMismatch: msg = "Hello components mismatch"; break; case UnsuppHashType: msg = "Hash type not supported"; break; case UnsuppCiphertype: msg = "Cipher type not supported"; break; case UnsuppPKExchange: msg = "Public key exchange not supported"; break; case UnsuppSRTPAuthTag: msg = "SRTP auth. tag not supported"; break; case UnsuppSASScheme: msg = "SAS scheme not supported"; break; case NoSharedSecret: msg = "No shared secret available, DH mode required"; break; case DHErrorWrongPV: msg = "DH Error: bad pvi or pvr ( == 1, 0, or p-1)"; break; case DHErrorWrongHVI: msg = "DH Error: hvi != hashed data"; break; case SASuntrustedMiTM: msg = "Received relayed SAS from untrusted MiTM"; break; case ConfirmHMACWrong: msg = "Auth. Error: Bad Confirm pkt HMAC"; break; case NonceReused: msg = "Nonce reuse"; break; case EqualZIDHello: msg = "Equal ZIDs in Hello"; break; case GoCleatNotAllowed: msg = "GoClear packet received, but not allowed"; break; default: msg = NO_MESSAGE; break; } return msg; } void Stream::print_message(GnuZrtpCodes::MessageSeverity severity, int32_t subcode) { switch (severity) { case Info: debug("zrtp: INFO<%s>: %s\n", media_name(), info_msg(subcode)); break; case Warning: warning("zrtp: WARNING<%s>: %s\n", media_name(), warning_msg(subcode)); break; case Severe: warning("zrtp: SEVERE<%s>: %s\n", media_name(), severe_msg(subcode)); break; case ZrtpError: warning("zrtp: ZRTP_ERR<%s>: %s\n", media_name(), zrtp_msg(subcode)); break; default: return; } } const char *Stream::media_name() const { switch (m_media_type) { case MT_AUDIO: return "audio"; case MT_VIDEO: return "video"; case MT_TEXT: return "text"; case MT_APPLICATION: return "application"; case MT_MESSAGE: return "message"; default: return "UNKNOWN"; } } baresip-1.0.0/modules/gzrtp/module.mk000066400000000000000000000016561372575704200176150ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 - 2017 Creytiv.com # # # To build libzrtpcppcore run the following commands: # # git clone https://github.com/wernerd/ZRTPCPP.git # cd ZRTPCPP # mkdir build # cd build # cmake -DCMAKE_POSITION_INDEPENDENT_CODE=1 -DCORE_LIB=1 -DSDES=1 \ # -DBUILD_STATIC=1 .. # make # # GNU ZRTP C++ library (ZRTPCPP) source directory ZRTP_PATH ?= ../ZRTPCPP ZRTP_LIB := $(shell find $(ZRTP_PATH) -name libzrtpcppcore.a) MOD := gzrtp $(MOD)_SRCS += gzrtp.cpp session.cpp stream.cpp messages.cpp srtp.cpp $(MOD)_LFLAGS += $(ZRTP_LIB) -lstdc++ $(MOD)_CXXFLAGS += \ -I$(ZRTP_PATH) \ -I$(ZRTP_PATH)/zrtp \ -I$(ZRTP_PATH)/srtp $(MOD)_CXXFLAGS += -O2 -Wall -fPIC # Uncomment this if you want to use libre SRTP facilities instead of the ones # provided by ZRTPCPP. In this case only standard ciphers (AES) are supported. #$(MOD)_CXXFLAGS += -DGZRTP_USE_RE_SRTP=1 include mk/mod.mk baresip-1.0.0/modules/gzrtp/session.cpp000066400000000000000000000104761372575704200201660ustar00rootroot00000000000000/** * @file session.cpp GNU ZRTP: Session class implementation * * Copyright (C) 2010 - 2017 Creytiv.com */ #include #include #include #include "session.h" std::vector Session::s_sessl; Session::Session(const ZRTPConfig& config) : m_start_parallel(config.start_parallel) , m_master(NULL) , m_encrypted(0) { int newid = 1; for (std::vector::iterator it = s_sessl.begin(); it != s_sessl.end(); ++it) { if ((*it)->id() >= newid) newid = (*it)->id() + 1; } m_id = newid; s_sessl.push_back(this); debug("zrtp: New session <%d>\n", id()); } Session::~Session() { for (std::vector::iterator it = s_sessl.begin(); it != s_sessl.end(); ++it) { if (*it == this) { s_sessl.erase(it); break; } } debug("zrtp: Session <%d> is destroyed\n", id()); } Stream *Session::create_stream(const ZRTPConfig& config, udp_sock *rtpsock, udp_sock *rtcpsock, uint32_t local_ssrc, StreamMediaType media_type) { int err = 0; Stream *st = new Stream (err, config, this, rtpsock, rtcpsock, local_ssrc, media_type); if (!st || err) { delete st; return NULL; } return st; } int Session::start_stream(Stream *stream) { if (stream->started()) return 0; m_streams.push_back(stream); // Start all streams in parallel using DH mode. This is a kind of // probing. The first stream to receive HelloACK will be the master // stream. If disabled, only the first stream starts in DH (master) // mode. if (m_start_parallel) { if (m_master && m_encrypted) // If we already have a master in secure state, // start in multistream mode return stream->start(m_master); else // Start a new stream in DH mode return stream->start(NULL); } else { if (!m_master) { // Start the first stream in DH mode m_master = stream; return stream->start(NULL); } else if (m_encrypted) { // Master is in secure state; multistream return stream->start(m_master); } } return 0; } bool Session::request_master(Stream *stream) { if (!m_start_parallel) return true; if (m_master) return false; // This is the first stream to receive HelloACK. It will be // used as the master for the other streams in the session. m_master = stream; // Stop other DH-mode streams. They will be started in the // multistream mode after the master enters secure state. for (std::vector::iterator it = m_streams.begin(); it != m_streams.end(); ++it) { if (*it != m_master) { (*it)->stop(); } } return true; } void Session::on_secure(Stream *stream) { ++m_encrypted; if (m_encrypted == m_streams.size() && m_master) { info("zrtp: All streams are encrypted (%s), " "SAS is [%s] (%s)\n", m_master->get_ciphers(), m_master->get_sas(), (m_master->sas_verified())? "verified" : "NOT VERIFIED"); return; } if (stream != m_master) return; // Master stream has just entered secure state. Start other // streams in the multistream mode. debug("zrtp: Starting other streams (%d)\n", m_streams.size() - 1); for (std::vector::iterator it = m_streams.begin(); it != m_streams.end(); ++it) { if (*it != m_master) { (*it)->start(m_master); } } } int Session::cmd_verify_sas(struct re_printf *pf, void *arg) { return cmd_sas(true, pf, arg); } int Session::cmd_unverify_sas(struct re_printf *pf, void *arg) { return cmd_sas(false, pf, arg); } int Session::cmd_sas(bool verify, struct re_printf *pf, void *arg) { const struct cmd_arg *carg = (struct cmd_arg *)arg; (void)pf; int id = -1; Session *sess = NULL; if (str_isset(carg->prm)) id = atoi(carg->prm); for (std::vector::iterator it = s_sessl.begin(); it != s_sessl.end(); ++it) { if ((*it)->id() == id) { sess = *it; break; } } if (!sess) { warning("zrtp: No session with id %d\n", id); return EINVAL; } if (!sess->m_master) { warning("zrtp: No master stream for the session with id %d\n", sess->id()); return EFAULT; } sess->m_master->verify_sas(verify); info("zrtp: Session <%d>: SAS [%s] is %s\n", sess->id(), sess->m_master->get_sas(), (sess->m_master->sas_verified())? "verified" : "NOT VERIFIED"); return 0; } baresip-1.0.0/modules/gzrtp/session.h000066400000000000000000000020071372575704200176220ustar00rootroot00000000000000/** * @file session.h GNU ZRTP: Session class * * Copyright (C) 2010 - 2017 Creytiv.com */ #ifndef __SESSION_H #define __SESSION_H #include "stream.h" class Stream; class ZRTPConfig; class Session { public: Session(const ZRTPConfig& config); ~Session(); Stream *create_stream(const ZRTPConfig& config, udp_sock *rtpsock, udp_sock *rtcpsock, uint32_t local_ssrc, StreamMediaType media_type); int start_stream(Stream *stream); int id() const { return m_id; } bool request_master(Stream *stream); void on_secure(Stream *stream); static int cmd_verify_sas(struct re_printf *pf, void *arg); static int cmd_unverify_sas(struct re_printf *pf, void *arg); static int cmd_sas(bool verify, struct re_printf *pf, void *arg); private: static std::vector s_sessl; const bool m_start_parallel; int m_id; std::vector m_streams; Stream *m_master; unsigned int m_encrypted; }; #endif // __SESSION_H baresip-1.0.0/modules/gzrtp/srtp.cpp000066400000000000000000000156301372575704200174700ustar00rootroot00000000000000/** * @file srtp.cpp GNU ZRTP: SRTP processing * * Copyright (C) 2010 - 2017 Creytiv.com */ #include #include #include #ifdef GZRTP_USE_RE_SRTP #include #else #include #include #include #endif #include "srtp.h" Srtp::Srtp(int& err, const SrtpSecret_t *secrets, EnableSecurity part) { const uint8_t *key, *salt; uint32_t key_len, salt_len; err = EPERM; #ifdef GZRTP_USE_RE_SRTP m_srtp = NULL; #else m_cc = NULL; m_cc_ctrl = NULL; #endif if (part == ForSender) { // To encrypt packets: intiator uses initiator keys, // responder uses responder keys if (secrets->role == Initiator) { key = secrets->keyInitiator; key_len = secrets->initKeyLen / 8; salt = secrets->saltInitiator; salt_len = secrets->initSaltLen / 8; } else { key = secrets->keyResponder; key_len = secrets->respKeyLen / 8; salt = secrets->saltResponder; salt_len = secrets->respSaltLen / 8; } } else if (part == ForReceiver) { // To decrypt packets: intiator uses responder keys, // responder initiator keys if (secrets->role == Initiator) { key = secrets->keyResponder; key_len = secrets->respKeyLen / 8; salt = secrets->saltResponder; salt_len = secrets->respSaltLen / 8; } else { key = secrets->keyInitiator; key_len = secrets->initKeyLen / 8; salt = secrets->saltInitiator; salt_len = secrets->initSaltLen / 8; } } else { err = EINVAL; return; } #ifdef GZRTP_USE_RE_SRTP uint8_t key_buf[32 + 14]; // max key + salt enum srtp_suite suite; struct srtp *st; if (secrets->symEncAlgorithm == Aes && secrets->authAlgorithm == Sha1) { if (key_len == 16 && secrets->srtpAuthTagLen == 32) suite = SRTP_AES_CM_128_HMAC_SHA1_32; else if (key_len == 16 && secrets->srtpAuthTagLen == 80) suite = SRTP_AES_CM_128_HMAC_SHA1_80; else if (key_len == 32 && secrets->srtpAuthTagLen == 32) suite = SRTP_AES_256_CM_HMAC_SHA1_32; else if (key_len == 32 && secrets->srtpAuthTagLen == 80) suite = SRTP_AES_256_CM_HMAC_SHA1_80; else { err = ENOTSUP; return; } } else { err = ENOTSUP; return; } if (salt_len != 14) { err = EINVAL; return; } memcpy(key_buf, key, key_len); memcpy(key_buf + key_len, salt, salt_len); err = srtp_alloc(&st, suite, key_buf, key_len + salt_len, 0); if (err) return; m_auth_tag_len = secrets->srtpAuthTagLen / 8; m_srtp = st; err = 0; #else CryptoContext *cc = NULL; CryptoContextCtrl *cc_ctrl = NULL; int cipher; int authn; int auth_key_len; switch (secrets->authAlgorithm) { case Sha1: authn = SrtpAuthenticationSha1Hmac; auth_key_len = 20; break; case Skein: authn = SrtpAuthenticationSkeinHmac; auth_key_len = 32; break; default: err = ENOTSUP; return; } switch (secrets->symEncAlgorithm) { case Aes: cipher = SrtpEncryptionAESCM; break; case TwoFish: cipher = SrtpEncryptionTWOCM; break; default: err = ENOTSUP; return; } cc = new CryptoContext( 0, // SSRC (used for lookup) 0, // Roll-Over-Counter (ROC) 0L, // keyderivation << 48, cipher, // encryption algo authn, // authtentication algo (uint8_t *)key, // Master Key key_len, // Master Key length (uint8_t *)salt, // Master Salt salt_len, // Master Salt length key_len, // encryption keyl auth_key_len, // authentication key len salt_len, // session salt len secrets->srtpAuthTagLen / 8); // authentication tag lenA cc_ctrl = new CryptoContextCtrl( 0, // SSRC (used for lookup) cipher, // encryption algo authn, // authtentication algo (uint8_t *)key, // Master Key key_len, // Master Key length (uint8_t *)salt, // Master Salt salt_len, // Master Salt length key_len, // encryption keyl auth_key_len, // authentication key len salt_len, // session salt len secrets->srtpAuthTagLen / 8); // authentication tag lenA if (!cc || !cc_ctrl) { delete cc; delete cc_ctrl; err = ENOMEM; return; } cc->deriveSrtpKeys(0L); cc_ctrl->deriveSrtcpKeys(); m_cc = cc; m_cc_ctrl = cc_ctrl; err = 0; #endif } Srtp::~Srtp() { #ifdef GZRTP_USE_RE_SRTP mem_deref(m_srtp); #else delete m_cc; delete m_cc_ctrl; #endif } int Srtp::protect_int(struct mbuf *mb, bool control) { size_t len = mbuf_get_left(mb); int32_t extra = (mbuf_get_space(mb) > len)? mbuf_get_space(mb) - len : 0; #ifdef GZRTP_USE_RE_SRTP if (m_auth_tag_len + (control? 4 : 0) > extra) return ENOMEM; if (control) return srtcp_encrypt(m_srtp, mb); else return srtp_encrypt(m_srtp, mb); #else if (control) { if (m_cc_ctrl->getTagLength() + 4 + m_cc_ctrl->getMkiLength() > extra) return ENOMEM; } else { if (m_cc->getTagLength() + m_cc->getMkiLength() > extra) return ENOMEM; } bool rc; if (control) rc = SrtpHandler::protectCtrl(m_cc_ctrl, mbuf_buf(mb), len, &len); else rc = SrtpHandler::protect(m_cc, mbuf_buf(mb), len, &len); if (!rc) return EPROTO; if (len > mbuf_get_space(mb)) { // this should never happen warning("zrtp: protect: length > space (%u > %u)\n", len, mbuf_get_space(mb)); abort(); } mb->end = mb->pos + len; return 0; #endif } int Srtp::protect(struct mbuf *mb) { return protect_int(mb, false); } int Srtp::protect_ctrl(struct mbuf *mb) { return protect_int(mb, true); } // return value: // 0 - OK // EBADMSG - SRTP/RTP packet decode error // EAUTH - SRTP authentication failed // EALREADY - SRTP replay check failed // other errors int Srtp::unprotect_int(struct mbuf *mb, bool control) { #ifdef GZRTP_USE_RE_SRTP if (control) return srtcp_decrypt(m_srtp, mb); else return srtp_decrypt(m_srtp, mb); #else size_t len = mbuf_get_left(mb); int rc, err; if (control) rc = SrtpHandler::unprotectCtrl(m_cc_ctrl, mbuf_buf(mb), len, &len); else rc = SrtpHandler::unprotect(m_cc, mbuf_buf(mb), len, &len, NULL); switch (rc) { case 1: err = 0; break; case 0: err = EBADMSG; break; case -1: err = EAUTH; break; case -2: err = EALREADY; break; default: err = EINVAL; } if (!err) mb->end = mb->pos + len; return err; #endif } int Srtp::unprotect(struct mbuf *mb) { return unprotect_int(mb, false); } int Srtp::unprotect_ctrl(struct mbuf *mb) { return unprotect_int(mb, true); } baresip-1.0.0/modules/gzrtp/srtp.h000066400000000000000000000014141372575704200171300ustar00rootroot00000000000000/** * @file srtp.h GNU ZRTP: SRTP processing * * Copyright (C) 2010 - 2017 Creytiv.com */ #ifndef __SRTP_H #define __SRTP_H #include #ifdef GZRTP_USE_RE_SRTP struct srtp; #else class CryptoContext; class CryptoContextCtrl; #endif class Srtp { public: Srtp(int& err, const SrtpSecret_t *secrets, EnableSecurity part); ~Srtp(); int protect(struct mbuf *mb); int protect_ctrl(struct mbuf *mb); int unprotect(struct mbuf *mb); int unprotect_ctrl(struct mbuf *mb); private: int protect_int(struct mbuf *mb, bool control); int unprotect_int(struct mbuf *mb, bool control); #ifdef GZRTP_USE_RE_SRTP int32_t m_auth_tag_len; struct srtp *m_srtp; #else CryptoContext *m_cc; CryptoContextCtrl *m_cc_ctrl; #endif }; #endif // __SRTP_H baresip-1.0.0/modules/gzrtp/stream.cpp000066400000000000000000000335101372575704200177700ustar00rootroot00000000000000/** * @file stream.cpp GNU ZRTP: Stream class implementation * * Copyright (C) 2010 - 2017 Creytiv.com */ #include #include #include #include #include #include #include "session.h" #include "stream.h" #include "srtp.h" // A burst of SRTP/SRTCP errors enough to display a warning // Set to 1 to display all warnings #define SRTP_ERR_BURST_THRESHOLD 20 enum { PRESZ = 36 /* Preamble size for TURN/STUN header */ }; enum pkt_type { PKT_TYPE_UNKNOWN = 0, PKT_TYPE_RTP = 1, PKT_TYPE_RTCP = 2, PKT_TYPE_ZRTP = 4 }; static enum pkt_type get_packet_type(const struct mbuf *mb) { uint8_t b, pt; uint32_t magic; if (mbuf_get_left(mb) < 8) return PKT_TYPE_UNKNOWN; b = mbuf_buf(mb)[0]; if (127 < b && b < 192) { pt = mbuf_buf(mb)[1] & 0x7f; if (72 <= pt && pt <= 76) return PKT_TYPE_RTCP; else return PKT_TYPE_RTP; } else { memcpy(&magic, &mbuf_buf(mb)[4], 4); magic = ntohl(magic); if (magic == ZRTP_MAGIC) return PKT_TYPE_ZRTP; } return PKT_TYPE_UNKNOWN; } ZRTPConfig::ZRTPConfig(const struct conf *conf, const char *conf_dir) { #ifdef GZRTP_USE_RE_SRTP // Standard ciphers only zrtp.clear(); zrtp.addAlgo(HashAlgorithm, zrtpHashes.getByName(s256)); zrtp.addAlgo(CipherAlgorithm, zrtpSymCiphers.getByName(aes3)); zrtp.addAlgo(CipherAlgorithm, zrtpSymCiphers.getByName(aes1)); zrtp.addAlgo(PubKeyAlgorithm, zrtpPubKeys.getByName(ec25)); zrtp.addAlgo(PubKeyAlgorithm, zrtpPubKeys.getByName(dh3k)); zrtp.addAlgo(PubKeyAlgorithm, zrtpPubKeys.getByName(ec38)); zrtp.addAlgo(PubKeyAlgorithm, zrtpPubKeys.getByName(dh2k)); zrtp.addAlgo(PubKeyAlgorithm, zrtpPubKeys.getByName(mult)); zrtp.addAlgo(SasType, zrtpSasTypes.getByName(b32)); zrtp.addAlgo(AuthLength, zrtpAuthLengths.getByName(hs32)); zrtp.addAlgo(AuthLength, zrtpAuthLengths.getByName(hs80)); #else zrtp.setStandardConfig(); #endif str_ncpy(client_id, "baresip/gzrtp", sizeof(client_id)); re_snprintf(zid_filename, sizeof(zid_filename), "%s/gzrtp.zid", conf_dir); start_parallel = true; (void)conf_get_bool(conf, "zrtp_parallel", &start_parallel); } SRTPStat::SRTPStat(const Stream *st, bool srtcp, uint64_t threshold) : m_stream(st) , m_control(srtcp) , m_threshold(threshold) { reset(); } void SRTPStat::update(int ret_code, bool quiet) { const char *err_msg; uint64_t *burst; // Srtp::unprotect/unprotect_ctrl return codes switch (ret_code) { case 0: ++m_ok; m_decode_burst = 0; m_auth_burst = 0; m_replay_burst = 0; return; case EBADMSG: ++m_decode; burst = &m_decode_burst; err_msg = "packet decode error"; break; case EAUTH: ++m_auth; burst = &m_auth_burst; err_msg = "authentication failed"; break; case EALREADY: ++m_replay; burst = &m_replay_burst; err_msg = "replay check failed"; break; default: warning("zrtp: %s unprotect failed: %m\n", (m_control)? "SRTCP" : "SRTP", ret_code); return; } ++(*burst); if (*burst == m_threshold) { *burst = 0; if (!quiet) warning("zrtp: Stream <%s>: %s %s, %d packets\n", m_stream->media_name(), (m_control)? "SRTCP" : "SRTP", err_msg, m_threshold); } } void SRTPStat::reset() { m_ok = 0; m_decode = 0; m_auth = 0; m_replay = 0; m_decode_burst = 0; m_auth_burst = 0; m_replay_burst = 0; } Stream::Stream(int& err, const ZRTPConfig& config, Session *session, udp_sock *rtpsock, udp_sock *rtcpsock, uint32_t local_ssrc, StreamMediaType media_type) : m_session(session) , m_zrtp(NULL) , m_started(false) , m_local_ssrc(local_ssrc) , m_peer_ssrc(0) , m_rtpsock(NULL) , m_rtcpsock(NULL) , m_uh_rtp(NULL) , m_uh_rtcp(NULL) , m_media_type(media_type) , m_send_srtp(NULL) , m_recv_srtp(NULL) , m_srtp_stat(this, false, SRTP_ERR_BURST_THRESHOLD) , m_srtcp_stat(this, true, SRTP_ERR_BURST_THRESHOLD) { err = 0; m_zrtp_seq = rand_u16() & 0x7fff; sa_init(&m_raddr, AF_INET); tmr_init(&m_zrtp_timer); pthread_mutexattr_t attr; err = pthread_mutexattr_init(&attr); err |= pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK); err |= pthread_mutex_init(&m_zrtp_mutex, &attr); err |= pthread_mutex_init(&m_send_mutex, &attr); if (err) return; int layer = 10; // above zero if (rtpsock) { m_rtpsock = (struct udp_sock *)mem_ref(rtpsock); err |= udp_register_helper(&m_uh_rtp, rtpsock, layer, Stream::udp_helper_send_cb, Stream::udp_helper_recv_cb, this); } if (rtcpsock && (rtcpsock != rtpsock)) { m_rtcpsock = (struct udp_sock *)mem_ref(rtcpsock); err |= udp_register_helper(&m_uh_rtcp, rtcpsock, layer, Stream::udp_helper_send_cb, Stream::udp_helper_recv_cb, this); } if (err) return; ZIDCache* zf = getZidCacheInstance(); if (!zf->isOpen()) { if (zf->open((char *)config.zid_filename) == -1) { warning("zrtp: Couldn't open/create ZID file %s\n", config.zid_filename); err = ENOENT; return; } } m_zrtp = new ZRtp((uint8_t *)zf->getZid(), this, config.client_id, (ZrtpConfigure *)&config.zrtp, false, false); if (!m_zrtp) { err = ENOMEM; return; } return; } Stream::~Stream() { stop(); delete m_zrtp; mem_deref(m_uh_rtp); mem_deref(m_uh_rtcp); mem_deref(m_rtpsock); mem_deref(m_rtcpsock); pthread_mutex_destroy(&m_zrtp_mutex); pthread_mutex_destroy(&m_send_mutex); tmr_cancel(&m_zrtp_timer); } int Stream::start(Stream *master) { if (started()) return EPERM; if (master) { ZRtp *zrtp_master; std::string params = master->m_zrtp->getMultiStrParams(&zrtp_master); if (params.empty()) return EPROTO; m_zrtp->setMultiStrParams(params, zrtp_master); } debug("zrtp: Starting <%s> stream%s\n", media_name(), (m_zrtp->isMultiStream())? " (multistream)" : ""); m_srtp_stat.reset(); m_srtcp_stat.reset(); m_sas.clear(); m_ciphers.clear(); m_started = true; m_zrtp->startZrtpEngine(); return 0; } void Stream::stop() { if (!started()) return; m_started = false; // If we got only a small amount of valid SRTP packets after ZRTP // negotiation then assume that our peer couldn't store the RS data, // thus make sure we have a second retained shared secret available. // Refer to RFC 6189bis, chapter 4.6.1 50 packets are about 1 second // of audio data if (!m_zrtp->isMultiStream() && m_recv_srtp && m_srtp_stat.ok() < 20) { debug("zrtp: Stream <%s>: received too few valid SRTP " "packets (%u), storing RS2\n", media_name(), m_srtp_stat.ok()); m_zrtp->setRs2Valid(); } debug("zrtp: Stopping <%s> stream\n", media_name()); m_zrtp->stopZrtp(); pthread_mutex_lock(&m_send_mutex); delete m_send_srtp; m_send_srtp = NULL; pthread_mutex_unlock(&m_send_mutex); delete m_recv_srtp; m_recv_srtp = NULL; debug("zrtp: Stream <%s> stopped\n", media_name()); } int Stream::sdp_encode(struct sdp_media *sdpm) { // NOTE: signaling hash return 0; } int Stream::sdp_decode(const struct sdp_media *sdpm) { if (sa_isset(sdp_media_raddr(sdpm), SA_ALL)) { m_raddr = *sdp_media_raddr(sdpm); } // NOTE: signaling hash return 0; } bool Stream::udp_helper_send_cb(int *err, struct sa *src, struct mbuf *mb, void *arg) { Stream *st = (Stream *)arg; if (st) return st->udp_helper_send(err, src, mb); return false; } bool Stream::udp_helper_send(int *err, struct sa *src, struct mbuf *mb) { bool ret = false; enum pkt_type ptype = get_packet_type(mb); size_t len = mbuf_get_left(mb); int rerr = 0; pthread_mutex_lock(&m_send_mutex); if (ptype == PKT_TYPE_RTCP && m_send_srtp && len > 8) { rerr = m_send_srtp->protect_ctrl(mb); } else if (ptype == PKT_TYPE_RTP && m_send_srtp && len > RTP_HEADER_SIZE) { rerr = m_send_srtp->protect(mb); } else goto out; if (rerr) { warning("zrtp: protect/protect_ctrl failed (len=%u): %m\n", len, rerr); if (rerr == ENOMEM) *err = rerr; // drop ret = true; } out: pthread_mutex_unlock(&m_send_mutex); return ret; } bool Stream::udp_helper_recv_cb(struct sa *src, struct mbuf *mb, void *arg) { Stream *st = (Stream *)arg; if (st) return st->udp_helper_recv(src, mb); return false; } bool Stream::udp_helper_recv(struct sa *src, struct mbuf *mb) { if (!started()) return false; enum pkt_type ptype = get_packet_type(mb); int err = 0; if (ptype == PKT_TYPE_RTCP && m_recv_srtp) { err = m_recv_srtp->unprotect_ctrl(mb); m_srtcp_stat.update(err); } else if (ptype == PKT_TYPE_RTP && m_recv_srtp) { err = m_recv_srtp->unprotect(mb); m_srtp_stat.update(err); if (!err) { // Got a good SRTP, check state and if in WaitConfAck // (an Initiator state) then simulate a conf2Ack, // refer to RFC 6189, chapter 4.6, last paragraph if (m_zrtp->inState(WaitConfAck)) m_zrtp->conf2AckSecure(); } } else if (ptype == PKT_TYPE_ZRTP) { return recv_zrtp(mb); } else return false; if (err) // drop return true; return false; } // + + + CRC32 #define ZRTP_MIN_PACKET_LENGTH (RTP_HEADER_SIZE + 4 + 8 + 4) bool Stream::recv_zrtp(struct mbuf *mb) { uint32_t crc32; uint8_t *buf = mbuf_buf(mb); size_t size = mbuf_get_left(mb); if (size < ZRTP_MIN_PACKET_LENGTH) { warning("zrtp: incoming packet size (%d) is too small\n", size); return false; } // check CRC memcpy(&crc32, buf + size - 4, 4); crc32 = ntohl(crc32); if (!zrtpCheckCksum(buf, size - 4, crc32)) { sendInfo(GnuZrtpCodes::Warning, GnuZrtpCodes::WarningCRCmismatch); return false; } // store peer's SSRC for creating the CryptoContext memcpy(&m_peer_ssrc, buf + 8, 4); m_peer_ssrc = ntohl(m_peer_ssrc); m_zrtp->processZrtpMessage(buf + RTP_HEADER_SIZE, m_peer_ssrc, size); return true; } void Stream::verify_sas(bool verify) { if (verify) m_zrtp->SASVerified(); else m_zrtp->resetSASVerified(); } bool Stream::sas_verified() { return m_zrtp->isSASVerified(); } // // callbacks // int32_t Stream::sendDataZRTP(const uint8_t* data, int32_t length) { struct mbuf *mb; uint8_t *crc_buf; uint32_t crc32; size_t start_pos = PRESZ; int err = 0; if (!sa_isset(&m_raddr, SA_ALL)) return 0; mb = mbuf_alloc(start_pos + RTP_HEADER_SIZE + length); if (!mb) return 0; mbuf_set_end(mb, start_pos); mbuf_set_pos(mb, start_pos); crc_buf = mbuf_buf(mb); // write RTP header err = mbuf_write_u8(mb, 0x10); err |= mbuf_write_u8(mb, 0x00); err |= mbuf_write_u16(mb, htons(m_zrtp_seq++)); err |= mbuf_write_u32(mb, htonl(ZRTP_MAGIC)); err |= mbuf_write_u32(mb, htonl(m_local_ssrc)); // copy ZRTP message data err |= mbuf_write_mem(mb, data, length - 4); // compute CRC crc32 = zrtpGenerateCksum(crc_buf, RTP_HEADER_SIZE + length - 4); crc32 = zrtpEndCksum(crc32); // store CRC err |= mbuf_write_u32(mb, htonl(crc32)); if (err) goto out; // send ZRTP packet using RTP socket mbuf_set_pos(mb, start_pos); err = udp_send_helper(m_rtpsock, &m_raddr, mb, m_uh_rtp); if (err) warning("zrtp: udp_send_helper: %m\n", err); out: mem_deref(mb); return (err == 0); } void Stream::zrtp_timer_cb(void *arg) { Stream *s = (Stream *)arg; s->m_zrtp->processTimeout(); } int32_t Stream::activateTimer(int32_t time) { tmr_start(&m_zrtp_timer, time, &Stream::zrtp_timer_cb, this); return 1; } int32_t Stream::cancelTimer() { tmr_cancel(&m_zrtp_timer); return 1; } void Stream::sendInfo(GnuZrtpCodes::MessageSeverity severity, int32_t subCode) { print_message(severity, subCode); if (severity == GnuZrtpCodes::Info) { if (subCode == GnuZrtpCodes::InfoSecureStateOn) { m_session->on_secure(this); } else if (subCode == GnuZrtpCodes::InfoHelloReceived && !m_zrtp->isMultiStream()) { m_session->request_master(this); } } } bool Stream::srtpSecretsReady(SrtpSecret_t* secrets, EnableSecurity part) { Srtp *s; int err = 0; debug("zrtp: Stream <%s>: secrets are ready for %s\n", media_name(), (part == ForSender)? "sender" : "receiver"); s = new Srtp(err, secrets, part); if (!s || err) { warning("zrtp: Stream <%s>: Srtp creation failed: %m\n", media_name(), err); delete s; return false; } if (part == ForSender) { pthread_mutex_lock(&m_send_mutex); m_send_srtp = s; pthread_mutex_unlock(&m_send_mutex); } else if (part == ForReceiver) m_recv_srtp = s; else return false; return true; } void Stream::srtpSecretsOff(EnableSecurity part) { debug("zrtp: Stream <%s>: secrets are off for %s\n", media_name(), (part == ForSender)? "sender" : "receiver"); if (part == ForSender) { pthread_mutex_lock(&m_send_mutex); delete m_send_srtp; m_send_srtp = NULL; pthread_mutex_unlock(&m_send_mutex); } if (part == ForReceiver) { delete m_recv_srtp; m_recv_srtp = NULL; } } void Stream::srtpSecretsOn(std::string c, std::string s, bool verified) { m_sas = s; m_ciphers = c; if (s.empty()) { info("zrtp: Stream <%s> is encrypted (%s)\n", media_name(), c.c_str()); } else { info("zrtp: Stream <%s> is encrypted (%s), " "SAS is [%s] (%s)\n", media_name(), c.c_str(), s.c_str(), (verified)? "verified" : "NOT VERIFIED"); if (!verified) warning("zrtp: SAS is not verified, type " "'/zrtp_verify %d' to verify\n", m_session->id()); } } void Stream::handleGoClear() { } void Stream::zrtpNegotiationFailed(GnuZrtpCodes::MessageSeverity severity, int32_t subCode) { } void Stream::zrtpNotSuppOther() { } void Stream::synchEnter() { pthread_mutex_lock(&m_zrtp_mutex); } void Stream::synchLeave() { pthread_mutex_unlock(&m_zrtp_mutex); } void Stream::zrtpAskEnrollment(GnuZrtpCodes::InfoEnrollment info) { } void Stream::zrtpInformEnrollment(GnuZrtpCodes::InfoEnrollment info) { } void Stream::signSAS(uint8_t* sasHash) { } bool Stream::checkSASSignature(uint8_t* sasHash) { return true; } baresip-1.0.0/modules/gzrtp/stream.h000066400000000000000000000070011372575704200174310ustar00rootroot00000000000000/** * @file stream.h GNU ZRTP: Stream class * * Copyright (C) 2010 - 2017 Creytiv.com */ #ifndef __STREAM_H #define __STREAM_H #include enum StreamMediaType { MT_UNKNOWN = 0, MT_AUDIO, MT_VIDEO, MT_TEXT, MT_APPLICATION, MT_MESSAGE }; class ZRTPConfig { public: ZRTPConfig(const struct conf *conf, const char *conf_dir); private: friend class Stream; friend class Session; ZrtpConfigure zrtp; char client_id[CLIENT_ID_SIZE + 1]; char zid_filename[256]; bool start_parallel; }; class Stream; class SRTPStat { public: SRTPStat(const Stream *st, bool srtcp, uint64_t threshold); void update(int ret_code, bool quiet = false); void reset(); uint64_t ok() { return m_ok; } private: const Stream *m_stream; const bool m_control; const uint64_t m_threshold; uint64_t m_ok, m_decode, m_auth, m_replay; uint64_t m_decode_burst, m_auth_burst, m_replay_burst; }; class Session; class Srtp; class Stream : public ZrtpCallback { public: Stream(int& err, const ZRTPConfig& config, Session *session, udp_sock *rtpsock, udp_sock *rtcpsock, uint32_t local_ssrc, StreamMediaType media_type); virtual ~Stream(); int start(Stream *master); void stop(); bool started() { return m_started; } int sdp_encode(struct sdp_media *sdpm); int sdp_decode(const struct sdp_media *sdpm); const char *media_name() const; const char *get_sas() const { return m_sas.c_str(); } const char *get_ciphers() const { return m_ciphers.c_str(); } bool sas_verified(); void verify_sas(bool verify); private: static void zrtp_timer_cb(void *arg); static bool udp_helper_send_cb(int *err, struct sa *src, struct mbuf *mb, void *arg); static bool udp_helper_recv_cb(struct sa *src, struct mbuf *mb, void *arg); bool udp_helper_send(int *err, struct sa *src, struct mbuf *mb); bool udp_helper_recv(struct sa *src, struct mbuf *mb); bool recv_zrtp(struct mbuf *mb); void print_message(GnuZrtpCodes::MessageSeverity severity, int32_t subcode); Session *m_session; ZRtp *m_zrtp; bool m_started; struct tmr m_zrtp_timer; pthread_mutex_t m_zrtp_mutex; uint16_t m_zrtp_seq; uint32_t m_local_ssrc, m_peer_ssrc; struct sa m_raddr; struct udp_sock *m_rtpsock, *m_rtcpsock; struct udp_helper *m_uh_rtp; struct udp_helper *m_uh_rtcp; StreamMediaType m_media_type; Srtp *m_send_srtp, *m_recv_srtp; pthread_mutex_t m_send_mutex; SRTPStat m_srtp_stat, m_srtcp_stat; std::string m_sas, m_ciphers; protected: virtual int32_t sendDataZRTP(const uint8_t* data, int32_t length); virtual int32_t activateTimer(int32_t time); virtual int32_t cancelTimer(); virtual void sendInfo(GnuZrtpCodes::MessageSeverity severity, int32_t subCode); virtual bool srtpSecretsReady(SrtpSecret_t* secrets, EnableSecurity part); virtual void srtpSecretsOff(EnableSecurity part); virtual void srtpSecretsOn(std::string c, std::string s, bool verified); virtual void handleGoClear(); virtual void zrtpNegotiationFailed( GnuZrtpCodes::MessageSeverity severity, int32_t subCode); virtual void zrtpNotSuppOther(); virtual void synchEnter(); virtual void synchLeave(); virtual void zrtpAskEnrollment(GnuZrtpCodes::InfoEnrollment info); virtual void zrtpInformEnrollment(GnuZrtpCodes::InfoEnrollment info); virtual void signSAS(uint8_t* sasHash); virtual bool checkSASSignature(uint8_t* sasHash); }; #endif // __STREAM_H baresip-1.0.0/modules/httpd/000077500000000000000000000000001372575704200157445ustar00rootroot00000000000000baresip-1.0.0/modules/httpd/httpd.c000066400000000000000000000072441372575704200172420ustar00rootroot00000000000000/** * @file httpd.c Webserver UI module * * Copyright (C) 2010 - 2015 Creytiv.com */ #include #include /** * @defgroup httpd httpd * * HTTP Server module for the User-Interface * * * Open your favourite web browser and point it to http://127.0.0.1:8000/ * Example URLs: * \verbatim http://127.0.0.1:8000?h -- Print the Help menu http://127.0.0.1:8000?d1234@target.com -- Make an outgoing call \endverbatim * * The following options can be configured: * \verbatim http_listen 0.0.0.0:8000 # IP-address and port to listen on \endverbatim */ enum {HTTP_PORT = 8000}; static struct http_sock *httpsock; static int handle_input(struct re_printf *pf, const struct pl *pl) { if (!pl) return 0; if (pl->l > 1 && pl->p[0] == '/') return ui_input_long_command(pf, pl); else return ui_input_pl(pf, pl); } static int html_print_head(struct re_printf *pf, void *unused) { (void)unused; return re_hprintf(pf, "\n" "\n" "Baresip v" BARESIP_VERSION "\n" "\n"); } static int html_print_cmd(struct re_printf *pf, const struct pl *prm) { struct pl params; if (!pf || !prm) return EINVAL; if (pl_isset(prm)) { params.p = prm->p + 1; params.l = prm->l - 1; } else { params.p = "h"; params.l = 1; } return re_hprintf(pf, "%H" "\n" "
\n"
			  "%H"
			  "
\n" "\n" "\n", html_print_head, NULL, handle_input, ¶ms); } static int html_print_raw(struct re_printf *pf, const struct pl *prm) { struct pl params; if (!pf || !prm) return EINVAL; if (pl_isset(prm)) { params.p = prm->p + 1; params.l = prm->l - 1; } else { params.p = "h"; params.l = 1; } return re_hprintf(pf, "%H", handle_input, ¶ms); } static void http_req_handler(struct http_conn *conn, const struct http_msg *msg, void *arg) { struct mbuf *mb; int err; char *buf = NULL; struct pl nprm; (void)arg; mb = mbuf_alloc(8192); if (!mb) return; err = re_sdprintf(&buf, "%H", uri_header_unescape, &msg->prm); if (err) goto error; pl_set_str(&nprm, buf); if (0 == pl_strcasecmp(&msg->path, "/")) { err = mbuf_printf(mb, "%H", html_print_cmd, &nprm); if (!err) { http_reply(conn, 200, "OK", "Content-Type: text/html;charset=UTF-8\r\n" "Content-Length: %zu\r\n" "Access-Control-Allow-Origin: *\r\n" "\r\n" "%b", mb->end, mb->buf, mb->end); } } else if (0 == pl_strcasecmp(&msg->path, "/raw/")) { err = mbuf_printf(mb, "%H", html_print_raw, &nprm); if (!err) { http_reply(conn, 200, "OK", "Content-Type: text/plain;charset=UTF-8\r\n" "Content-Length: %zu\r\n" "Access-Control-Allow-Origin: *\r\n" "\r\n" "%b", mb->end, mb->buf, mb->end); } } else { goto error; } mem_deref(mb); mem_deref(buf); return; error: mem_deref(mb); mem_deref(buf); http_ereply(conn, 404, "Not Found"); } static int output_handler(const char *str) { (void)str; return 0; } static struct ui ui_http = { .name = "http", .outputh = output_handler }; static int module_init(void) { struct sa laddr; int err; if (conf_get_sa(conf_cur(), "http_listen", &laddr)) { sa_set_str(&laddr, "0.0.0.0", HTTP_PORT); } err = http_listen(&httpsock, &laddr, http_req_handler, NULL); if (err) return err; ui_register(baresip_uis(), &ui_http); info("httpd: listening on %J\n", &laddr); return 0; } static int module_close(void) { ui_unregister(&ui_http); httpsock = mem_deref(httpsock); return 0; } EXPORT_SYM const struct mod_export DECL_EXPORTS(httpd) = { "httpd", "application", module_init, module_close, }; baresip-1.0.0/modules/httpd/module.mk000066400000000000000000000001541372575704200175620ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # MOD := httpd $(MOD)_SRCS += httpd.c include mk/mod.mk baresip-1.0.0/modules/i2s/000077500000000000000000000000001372575704200153165ustar00rootroot00000000000000baresip-1.0.0/modules/i2s/i2s.c000066400000000000000000000051141372575704200161600ustar00rootroot00000000000000/** * @file i2s.c freeRTOS I2S audio driver module * * Copyright (C) 2019 cspiel.at */ #include #include #include #include #include "freertos/FreeRTOS.h" #include #include #include #include "driver/i2s.h" #include "i2s.h" /** * @defgroup i2s i2s * * I2S audio driver module for freeRTOS (ESP32 Espressif) * * This module adds an audio source for I2S MEMs microphone (mono/stereo) and * an audio player for I2S class D amplifiers. It was tested with: * * - ESP32-WROOM from Espressif * - Sparkfun I2S Audio Breakout - MAX98357A SF14809 - CLASS D stereo amplifier * - Adafruit I2S MEMS Microphone Breakout - SPH0645LM4H */ static struct ausrc *ausrc = NULL; static struct auplay *auplay = NULL; static enum I2SOnMask _i2s_on = I2O_NONE; static int i2s_init(void) { int err; err = ausrc_register(&ausrc, baresip_ausrcl(), "i2s", i2s_src_alloc); err |= auplay_register(&auplay, baresip_auplayl(), "i2s", i2s_play_alloc); return err; } int i2s_start_bus(uint32_t srate, enum I2SOnMask playrec, uint8_t channels) { esp_err_t err; bool start = _i2s_on == I2O_NONE; _i2s_on = _i2s_on | playrec; if (srate * 4 % DMA_SIZE) { warning("i2s: srate*4 % DMA_SIZE != 0\n"); return EINVAL; } info("%s start with _i2s_on=%d", __func__, _i2s_on); if (start) { i2s_config_t i2s_config = { .mode = I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_TX, .sample_rate = srate, .bits_per_sample = 32, .communication_format = I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB, .channel_format = channels ? I2S_CHANNEL_FMT_ONLY_RIGHT : I2S_CHANNEL_FMT_RIGHT_LEFT, .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, .dma_buf_count = 2, .dma_buf_len = DMA_SIZE, .use_apll = 0 /* disables APLL */ }; /* install and start i2s driver */ err = i2s_driver_install(I2S_PORT, &i2s_config, 0, NULL); if (err) { warning("i2s: could not install i2s driver (%s)", esp_err_to_name(err)); return EINVAL; } i2s_pin_config_t pins = { .bck_io_num = 26, .ws_io_num = 25, .data_out_num = 22, .data_in_num = 23 }; i2s_set_pin(I2S_PORT, &pins); i2s_zero_dma_buffer(I2S_PORT); } return 0; } void i2s_stop_bus(enum I2SOnMask playrec) { _i2s_on &= (~playrec); info("%s _i2s_on=%d", __func__, _i2s_on); if (_i2s_on == I2O_NONE) i2s_driver_uninstall(I2S_PORT); } static int i2s_close(void) { ausrc = mem_deref(ausrc); auplay = mem_deref(auplay); return 0; } const struct mod_export DECL_EXPORTS(i2s) = { "i2s", "sound", i2s_init, i2s_close }; baresip-1.0.0/modules/i2s/i2s.h000066400000000000000000000013551372575704200161700ustar00rootroot00000000000000/** * @file i2s.h freeRTOS I2S audio driver module - internal interface * * Copyright (C) 2019 cspiel.at */ #define I2S_PORT (0) #define DMA_SIZE (640) enum I2SOnMask { I2O_NONE = 0, I2O_PLAY = 1, I2O_RECO = 2, I2O_BOTH = 3 }; int i2s_src_alloc(struct ausrc_st **stp, const struct ausrc *as, struct media_ctx **ctx, struct ausrc_prm *prm, const char *device, ausrc_read_h *rh, ausrc_error_h *errh, void *arg); int i2s_play_alloc(struct auplay_st **stp, const struct auplay *ap, struct auplay_prm *prm, const char *device, auplay_write_h *wh, void *arg); int i2s_start_bus(uint32_t srate, enum I2SOnMask playrec, uint8_t channels); void i2s_stop_bus(enum I2SOnMask playrec); baresip-1.0.0/modules/i2s/i2s_play.c000066400000000000000000000060471372575704200172130ustar00rootroot00000000000000/** * @file i2s_play.c freeRTOS I2S audio driver module - player * * Copyright (C) 2019 cspiel.at */ #include #include #include #include #include #include "freertos/FreeRTOS.h" #include "driver/i2s.h" #include #include #include #include "i2s.h" struct auplay_st { const struct auplay *ap; /* pointer to base-class (inheritance) */ pthread_t thread; bool run; void *sampv; size_t sampc; auplay_write_h *wh; void *arg; struct auplay_prm prm; uint32_t *pcm; }; static void auplay_destructor(void *arg) { struct auplay_st *st = arg; /* Wait for termination of other thread */ if (st->run) { info("i2s: stopping playback thread\n"); st->run = false; (void)pthread_join(st->thread, NULL); } mem_deref(st->sampv); mem_deref(st->pcm); } /** * Converts samples from int16_t to pcm 32 bit values ready for I2S bus. A * reasonable volume of the playback is achieved by left-shifting. * @param st The auplay_st. * @param i Offset for st->sampv. * @param n Number of samples that should be converted. */ static void convert_sampv(struct auplay_st *st, size_t i, size_t n) { uint32_t j; int16_t *sampv = st->sampv; for (j = 0; j < n; j++) { uint32_t v = sampv[i+j]; st->pcm[j] = v << 17; } } static void *write_thread(void *arg) { struct auplay_st *st = arg; i2s_set_clk(I2S_PORT, st->prm.srate, 32, st->prm.ch); while (st->run) { size_t i; st->wh(st->sampv, st->sampc, st->arg); for (i = 0; i + DMA_SIZE / 4 <= st->sampc;) { size_t n; convert_sampv(st, i, DMA_SIZE / 4); if (i2s_write(I2S_PORT, (const uint8_t*) st->pcm, DMA_SIZE, &n, portMAX_DELAY) != ESP_OK) break; if (n != DMA_SIZE) warning("i2s: written %lu bytes but expected" " %lu.", n, DMA_SIZE); if (n == 0) break; i += (n / 4); } } i2s_stop_bus(I2O_PLAY); info("i2s: stopped auplay thread\n"); return NULL; } int i2s_play_alloc(struct auplay_st **stp, const struct auplay *ap, struct auplay_prm *prm, const char *device, auplay_write_h *wh, void *arg) { struct auplay_st *st; int err; (void) device; if (!stp || !ap || !prm || !wh) return EINVAL; if (prm->fmt!=AUFMT_S16LE) { warning("i2s: unsupported sample format %s\n", aufmt_name(prm->fmt)); return EINVAL; } st = mem_zalloc(sizeof(*st), auplay_destructor); if (!st) return ENOMEM; st->prm = *prm; st->ap = ap; st->wh = wh; st->arg = arg; st->sampc = prm->srate * prm->ch * prm->ptime / 1000; st->sampv = mem_zalloc(aufmt_sample_size(st->prm.fmt)*st->sampc, NULL); if (!st->sampv) { err = ENOMEM; goto out; } st->pcm = mem_zalloc(DMA_SIZE, NULL); if (!st->pcm) { err = ENOMEM; goto out; } err = i2s_start_bus(st->prm.srate, I2O_PLAY, st->prm.ch); if (err) goto out; st->run = true; info("%s starting play thread\n", __func__); err = pthread_create(&st->thread, NULL, write_thread, st); if (err) { st->run = false; goto out; } debug("i2s: playback started\n"); out: if (err) mem_deref(st); else *stp = st; return err; } baresip-1.0.0/modules/i2s/i2s_src.c000066400000000000000000000062601372575704200170320ustar00rootroot00000000000000/** * @file i2s_src.c freeRTOS I2S audio driver module - recorder * * Copyright (C) 2019 cspiel.at */ #include #include #include #include #include #include "freertos/FreeRTOS.h" #include "driver/i2s.h" #include #include #include #include "i2s.h" struct ausrc_st { const struct ausrc *as; /* pointer to base-class (inheritance) */ pthread_t thread; bool run; void *sampv; size_t sampc; ausrc_read_h *rh; void *arg; struct ausrc_prm prm; uint32_t *pcm; }; static void ausrc_destructor(void *arg) { struct ausrc_st *st = arg; /* Wait for termination of other thread */ if (st->run) { info("i2s: stopping recording thread\n"); st->run = false; (void)pthread_join(st->thread, NULL); } mem_deref(st->sampv); mem_deref(st->pcm); } /** * Converts the pcm 32 bit I2S values to baresip 16-bit samples. A reasonable * volume for the microphone is achieved by right shifting. * @param st The ausrc_st. * @param i Offset for st->sampv. * @param n The number of samples that should be converted. */ static void convert_pcm(struct ausrc_st *st, size_t i, size_t n) { uint32_t j; uint16_t *sampv = st->sampv; for (j = 0; j < n; j++) { uint32_t v = st->pcm[j]; uint16_t *o = sampv + i + j; *o = v >> 15; /* if negative fill with ff */ if (v & 0x80000000) *o |= 0xfffe0000; } } static void *read_thread(void *arg) { struct ausrc_st *st = arg; while (st->run) { size_t i; for (i = 0; i + DMA_SIZE / 4 <= st->sampc;) { size_t n = 0; if (i2s_read(I2S_PORT, st->pcm, DMA_SIZE, &n, portMAX_DELAY) != ESP_OK) break; if (n == 0) break; convert_pcm(st, i, n / 4); i += (n / 4); } st->rh(st->sampv, st->sampc, st->arg); } i2s_stop_bus(I2O_RECO); info("i2s: stopped ausrc thread\n"); return NULL; } int i2s_src_alloc(struct ausrc_st **stp, const struct ausrc *as, struct media_ctx **ctx, struct ausrc_prm *prm, const char *device, ausrc_read_h *rh, ausrc_error_h *errh, void *arg) { struct ausrc_st *st; size_t sampc; int err; (void) ctx; (void) device; (void) errh; if (!stp || !as || !prm || !rh) return EINVAL; if (prm->fmt!=AUFMT_S16LE) { warning("i2s: unsupported sample format %s\n", aufmt_name(prm->fmt)); return EINVAL; } sampc = prm->srate * prm->ch * prm->ptime / 1000; if (sampc % (DMA_SIZE / 4)) { warning("i2s: sampc=%d has to be divisible by DMA_SIZE/4\n", sampc); return EINVAL; } st = mem_zalloc(sizeof(*st), ausrc_destructor); if (!st) return ENOMEM; st->prm = *prm; st->as = as; st->rh = rh; st->arg = arg; st->sampc = sampc; st->sampv = mem_zalloc(aufmt_sample_size(st->prm.fmt)*st->sampc, NULL); if (!st->sampv) { err = ENOMEM; goto out; } st->pcm = mem_zalloc(DMA_SIZE, NULL); if (!st->pcm) { err = ENOMEM; goto out; } err = i2s_start_bus(st->prm.srate, I2O_RECO, st->prm.ch); if (err) goto out; st->run = true; info("%s starting src thread\n", __func__); err = pthread_create(&st->thread, NULL, read_thread, st); if (err) { st->run = false; goto out; } debug("i2s: recording\n"); out: if (err) mem_deref(st); else *stp = st; return err; } baresip-1.0.0/modules/i2s/module.mk000066400000000000000000000001461372575704200171350ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2019 cspiel.at # MOD := i2s $(MOD)_SRCS += i2s.c include mk/mod.mk baresip-1.0.0/modules/ice/000077500000000000000000000000001372575704200153615ustar00rootroot00000000000000baresip-1.0.0/modules/ice/ice.c000066400000000000000000000450171372575704200162740ustar00rootroot00000000000000/** * @file ice.c ICE Module * * Copyright (C) 2010 Creytiv.com */ #include #include /** * @defgroup ice ice * * Interactive Connectivity Establishment (ICE) for media NAT traversal * * This module enables ICE for NAT traversal. You can enable ICE * in your accounts file with the parameter ;medianat=ice. * */ enum { ICE_LAYER = 0 }; struct mnat_sess { struct list medial; struct sa srv; struct stun_dns *dnsq; struct sdp_session *sdp; struct tmr tmr_async; char lufrag[8]; char lpwd[32]; uint64_t tiebrk; bool turn; bool offerer; char *user; char *pass; bool started; bool send_reinvite; mnat_estab_h *estabh; void *arg; }; struct mnat_media { struct comp { struct mnat_media *m; /* pointer to parent */ struct stun_ctrans *ct_gath; struct sa laddr; unsigned id; void *sock; } compv[2]; struct le le; struct mnat_sess *sess; struct sdp_media *sdpm; struct icem *icem; bool gathered; bool complete; bool terminated; int nstun; /**< Number of pending STUN candidates */ mnat_connected_h *connh; void *arg; }; static void gather_handler(int err, uint16_t scode, const char *reason, void *arg); static void call_gather_handler(int err, struct mnat_media *m, uint16_t scode, const char *reason) { /* No more pending requests? */ if (m->nstun != 0) return; debug("ice: all components gathered.\n"); if (err) goto out; /* Eliminate redundant local candidates */ icem_cand_redund_elim(m->icem); err = icem_comps_set_default_cand(m->icem); if (err) { warning("ice: set default cands failed (%m)\n", err); goto out; } out: gather_handler(err, scode, reason, m); } static void stun_resp_handler(int err, uint16_t scode, const char *reason, const struct stun_msg *msg, void *arg) { struct comp *comp = arg; struct mnat_media *m = comp->m; struct stun_attr *attr; struct ice_cand *lcand; if (m->terminated) return; --m->nstun; if (err || scode > 0) { warning("ice: comp %u: STUN Request failed: %m\n", comp->id, err); goto out; } debug("ice: srflx gathering for comp %u complete.\n", comp->id); /* base candidate */ lcand = icem_cand_find(icem_lcandl(m->icem), comp->id, NULL); if (!lcand) goto out; attr = stun_msg_attr(msg, STUN_ATTR_XOR_MAPPED_ADDR); if (!attr) attr = stun_msg_attr(msg, STUN_ATTR_MAPPED_ADDR); if (!attr) { warning("ice: no Mapped Address in Response\n"); err = EPROTO; goto out; } err = icem_lcand_add(m->icem, icem_lcand_base(lcand), ICE_CAND_TYPE_SRFLX, &attr->v.sa); out: call_gather_handler(err, m, scode, reason); } /** Gather Server Reflexive address */ static int send_binding_request(struct mnat_media *m, struct comp *comp) { int err; if (comp->ct_gath) return EALREADY; debug("ice: gathering srflx for comp %u ..\n", comp->id); err = stun_request(&comp->ct_gath, icem_stun(m->icem), IPPROTO_UDP, comp->sock, &m->sess->srv, 0, STUN_METHOD_BINDING, NULL, false, 0, stun_resp_handler, comp, 1, STUN_ATTR_SOFTWARE, stun_software); if (err) return err; ++m->nstun; return 0; } static void turnc_handler(int err, uint16_t scode, const char *reason, const struct sa *relay, const struct sa *mapped, const struct stun_msg *msg, void *arg) { struct comp *comp = arg; struct mnat_media *m = comp->m; struct ice_cand *lcand; (void)msg; --m->nstun; /* TURN failed, so we destroy the client */ if (err || scode) { icem_set_turn_client(m->icem, comp->id, NULL); } if (err) { warning("{%u} TURN Client error: %m\n", comp->id, err); goto out; } if (scode) { warning("{%u} TURN Client error: %u %s\n", comp->id, scode, reason); err = send_binding_request(m, comp); if (err) goto out; return; } debug("ice: relay gathered for comp %u (%u %s)\n", comp->id, scode, reason); lcand = icem_cand_find(icem_lcandl(m->icem), comp->id, NULL); if (!lcand) goto out; if (!sa_cmp(relay, icem_lcand_addr(icem_lcand_base(lcand)), SA_ALL)) { err = icem_lcand_add(m->icem, icem_lcand_base(lcand), ICE_CAND_TYPE_RELAY, relay); } if (mapped) { err |= icem_lcand_add(m->icem, icem_lcand_base(lcand), ICE_CAND_TYPE_SRFLX, mapped); } else { err |= send_binding_request(m, comp); } out: call_gather_handler(err, m, scode, reason); } static int cand_gather_relayed(struct mnat_media *m, struct comp *comp, const char *username, const char *password) { struct turnc *turnc = NULL; const int layer = ICE_LAYER - 10; /* below ICE stack */ int err; err = turnc_alloc(&turnc, stun_conf(icem_stun(m->icem)), IPPROTO_UDP, comp->sock, layer, &m->sess->srv, username, password, 60, turnc_handler, comp); if (err) return err; err = icem_set_turn_client(m->icem, comp->id, turnc); if (err) goto out; ++m->nstun; out: mem_deref(turnc); return err; } static int start_gathering(struct mnat_media *m, const char *username, const char *password) { unsigned i; int err = 0; /* for each component */ for (i=0; i<2; i++) { struct comp *comp = &m->compv[i]; if (!comp->sock) continue; if (m->sess->turn) { err |= cand_gather_relayed(m, comp, username, password); } else err |= send_binding_request(m, comp); } return err; } static int icem_gather_srflx(struct mnat_media *m) { if (!m) return EINVAL; return start_gathering(m, NULL, NULL); } static int icem_gather_relay(struct mnat_media *m, const char *username, const char *password) { if (!m || !username || !password) return EINVAL; return start_gathering(m, username, password); } static void ice_printf(struct mnat_media *m, const char *fmt, ...) { va_list ap; va_start(ap, fmt); debug("%s: %v", m ? sdp_media_name(m->sdpm) : "ICE", fmt, &ap); va_end(ap); } static void session_destructor(void *arg) { struct mnat_sess *sess = arg; tmr_cancel(&sess->tmr_async); list_flush(&sess->medial); mem_deref(sess->dnsq); mem_deref(sess->user); mem_deref(sess->pass); mem_deref(sess->sdp); } static void media_destructor(void *arg) { struct mnat_media *m = arg; unsigned i; m->terminated = true; list_unlink(&m->le); mem_deref(m->sdpm); mem_deref(m->icem); for (i=0; i<2; i++) { mem_deref(m->compv[i].ct_gath); mem_deref(m->compv[i].sock); } } static bool candidate_handler(struct le *le, void *arg) { return 0 != sdp_media_set_lattr(arg, false, ice_attr_cand, "%H", ice_cand_encode, le->data); } /** * Update the local SDP attributes, this can be called multiple times * when the state of the ICE machinery changes */ static int set_media_attributes(struct mnat_media *m) { int err = 0; if (icem_mismatch(m->icem)) { err = sdp_media_set_lattr(m->sdpm, true, ice_attr_mismatch, NULL); return err; } else { sdp_media_del_lattr(m->sdpm, ice_attr_mismatch); } /* Encode all my candidates */ sdp_media_del_lattr(m->sdpm, ice_attr_cand); if (list_apply(icem_lcandl(m->icem), true, candidate_handler, m->sdpm)) return ENOMEM; if (ice_remotecands_avail(m->icem)) { err |= sdp_media_set_lattr(m->sdpm, true, ice_attr_remote_cand, "%H", ice_remotecands_encode, m->icem); } return err; } static bool if_handler(const char *ifname, const struct sa *sa, void *arg) { struct mnat_media *m = arg; uint16_t lprio; unsigned i; int err = 0; /* Skip loopback and link-local addresses */ if (sa_is_loopback(sa) || sa_is_linklocal(sa)) return false; if (!net_af_enabled(baresip_network(), sa_af(sa))) return false; lprio = 0; ice_printf(m, "added interface: %s:%j (local prio %u)\n", ifname, sa, lprio); for (i=0; i<2; i++) { if (m->compv[i].sock) err |= icem_cand_add(m->icem, i+1, lprio, ifname, sa); } if (err) { warning("ice: %s:%j: icem_cand_add: %m\n", ifname, sa, err); } return false; } static int media_start(struct mnat_sess *sess, struct mnat_media *m) { int err = 0; net_if_apply(if_handler, m); if (sess->turn) { err = icem_gather_relay(m, sess->user, sess->pass); } else { err = icem_gather_srflx(m); } return err; } static void dns_handler(int err, const struct sa *srv, void *arg) { struct mnat_sess *sess = arg; struct le *le; if (err) goto out; debug("ice: resolved %s-server to address %J\n", sess->turn ? "TURN" : "STUN", srv); sess->srv = *srv; for (le=sess->medial.head; le; le=le->next) { struct mnat_media *m = le->data; err = media_start(sess, m); if (err) goto out; } return; out: sess->estabh(err, 0, NULL, sess->arg); } static void tmr_async_handler(void *arg) { struct mnat_sess *sess = arg; struct le *le; for (le = sess->medial.head; le; le = le->next) { struct mnat_media *m = le->data; net_if_apply(if_handler, m); call_gather_handler(0, m, 0, ""); } } static int session_alloc(struct mnat_sess **sessp, const struct mnat *mnat, struct dnsc *dnsc, int af, const struct stun_uri *srv, const char *user, const char *pass, struct sdp_session *ss, bool offerer, mnat_estab_h *estabh, void *arg) { struct mnat_sess *sess; const char *usage = NULL; int err = 0; (void)mnat; if (!sessp || !dnsc || !ss || !estabh) return EINVAL; if (srv) { info("ice: new session with %s-server at %s (username=%s)\n", srv->scheme == STUN_SCHEME_TURN ? "TURN" : "STUN", srv->host, user); switch (srv->scheme) { case STUN_SCHEME_STUN: usage = stun_usage_binding; break; case STUN_SCHEME_TURN: usage = stun_usage_relay; break; default: return ENOTSUP; } } sess = mem_zalloc(sizeof(*sess), session_destructor); if (!sess) return ENOMEM; sess->sdp = mem_ref(ss); sess->estabh = estabh; sess->arg = arg; if (user && pass) { err = str_dup(&sess->user, user); err |= str_dup(&sess->pass, pass); if (err) goto out; } rand_str(sess->lufrag, sizeof(sess->lufrag)); rand_str(sess->lpwd, sizeof(sess->lpwd)); sess->tiebrk = rand_u64(); sess->offerer = offerer; err |= sdp_session_set_lattr(ss, true, ice_attr_ufrag, sess->lufrag); err |= sdp_session_set_lattr(ss, true, ice_attr_pwd, sess->lpwd); if (err) goto out; if (srv) { sess->turn = (srv->scheme == STUN_SCHEME_TURN); err = stun_server_discover(&sess->dnsq, dnsc, usage, stun_proto_udp, af, srv->host, srv->port, dns_handler, sess); } else { tmr_start(&sess->tmr_async, 1, tmr_async_handler, sess); } out: if (err) mem_deref(sess); else *sessp = sess; return err; } static bool verify_peer_ice(struct mnat_sess *ms) { struct le *le; for (le = ms->medial.head; le; le = le->next) { struct mnat_media *m = le->data; struct sa raddr[2]; unsigned i; if (!sdp_media_has_media(m->sdpm)) { info("ice: stream '%s' is disabled -- ignore\n", sdp_media_name(m->sdpm)); continue; } raddr[0] = *sdp_media_raddr(m->sdpm); sdp_media_raddr_rtcp(m->sdpm, &raddr[1]); for (i=0; i<2; i++) { if (m->compv[i].sock && !icem_verify_support(m->icem, i+1, &raddr[i])) { warning("ice: %s.%u: no remote candidates" " found (address = %J)\n", sdp_media_name(m->sdpm), i+1, &raddr[i]); return false; } } } return true; } static bool refresh_comp_laddr(struct mnat_media *m, unsigned id, struct comp *comp, const struct sa *laddr) { bool changed = false; if (!m || !comp || !comp->sock || !laddr) return false; if (!sa_cmp(&comp->laddr, laddr, SA_ALL)) { changed = true; ice_printf(m, "comp%u setting local: %J\n", id, laddr); } sa_cpy(&comp->laddr, laddr); if (id == 1) sdp_media_set_laddr(m->sdpm, &comp->laddr); else if (id == 2) sdp_media_set_laddr_rtcp(m->sdpm, &comp->laddr); return changed; } /* * Update SDP Media with local addresses */ static bool refresh_laddr(struct mnat_media *m, const struct sa *laddr1, const struct sa *laddr2) { bool changed = false; changed |= refresh_comp_laddr(m, 1, &m->compv[0], laddr1); changed |= refresh_comp_laddr(m, 2, &m->compv[1], laddr2); return changed; } static bool all_gathered(const struct mnat_sess *sess) { struct le *le; for (le = sess->medial.head; le; le = le->next) { struct mnat_media *m = le->data; if (!m->gathered) return false; } return true; } static bool all_completed(const struct mnat_sess *sess) { struct le *le; /* Check all conncheck flags */ LIST_FOREACH(&sess->medial, le) { struct mnat_media *mx = le->data; if (!mx->complete) return false; } return true; } static void gather_handler(int err, uint16_t scode, const char *reason, void *arg) { struct mnat_media *m = arg; mnat_estab_h *estabh = m->sess->estabh; if (err || scode) { warning("ice: gather error: %m (%u %s)\n", err, scode, reason); } else { refresh_laddr(m, icem_cand_default(m->icem, 1), icem_cand_default(m->icem, 2)); info("ice: %s: Default local candidates: %J / %J\n", sdp_media_name(m->sdpm), &m->compv[0].laddr, &m->compv[1].laddr); (void)set_media_attributes(m); m->gathered = true; if (!all_gathered(m->sess)) return; } if (err || scode) m->sess->estabh = NULL; if (estabh) estabh(err, scode, reason, m->sess->arg); } static void conncheck_handler(int err, bool update, void *arg) { struct mnat_media *m = arg; struct mnat_sess *sess = m->sess; bool sess_complete = false; info("ice: %s: connectivity check is complete (update=%d)\n", sdp_media_name(m->sdpm), update); ice_printf(m, "Dumping media state: %H\n", icem_debug, m->icem); if (err) { warning("ice: connectivity check failed: %m\n", err); } else { const struct ice_cand *cand1, *cand2; bool changed; m->complete = true; changed = refresh_laddr(m, icem_selected_laddr(m->icem, 1), icem_selected_laddr(m->icem, 2)); if (changed) sess->send_reinvite = true; (void)set_media_attributes(m); cand1 = icem_selected_rcand(m->icem, 1); cand2 = icem_selected_rcand(m->icem, 2); sess_complete = all_completed(sess); if (m->connh) { m->connh(icem_lcand_addr(cand1), icem_lcand_addr(cand2), m->arg); } } /* call estab-handler and send re-invite */ if (sess_complete && sess->send_reinvite && update) { info("ice: %s: sending Re-INVITE with updated" " default candidates\n", sdp_media_name(m->sdpm)); sess->send_reinvite = false; sess->estabh(0, 0, NULL, sess->arg); } } static int ice_start(struct mnat_sess *sess) { struct le *le; int err = 0; /* Update SDP media */ if (sess->started) { LIST_FOREACH(&sess->medial, le) { struct mnat_media *m = le->data; ice_printf(NULL, "ICE Start: %H", icem_debug, m->icem); icem_update(m->icem); refresh_laddr(m, icem_selected_laddr(m->icem, 1), icem_selected_laddr(m->icem, 2)); err |= set_media_attributes(m); } return err; } /* Clear all conncheck flags */ LIST_FOREACH(&sess->medial, le) { struct mnat_media *m = le->data; if (sdp_media_has_media(m->sdpm)) { m->complete = false; err = icem_conncheck_start(m->icem); if (err) return err; /* set the pair states -- first media stream only */ if (sess->medial.head == le) { ice_candpair_set_states(m->icem); } } else { m->complete = true; } } sess->started = true; return 0; } static int media_alloc(struct mnat_media **mp, struct mnat_sess *sess, struct udp_sock *sock1, struct udp_sock *sock2, struct sdp_media *sdpm, mnat_connected_h *connh, void *arg) { struct mnat_media *m; enum ice_role role; unsigned i; int err = 0; if (!mp || !sess || !sdpm) return EINVAL; m = mem_zalloc(sizeof(*m), media_destructor); if (!m) return ENOMEM; list_append(&sess->medial, &m->le, m); m->sdpm = mem_ref(sdpm); m->sess = sess; m->compv[0].sock = mem_ref(sock1); m->compv[1].sock = mem_ref(sock2); if (sess->offerer) role = ICE_ROLE_CONTROLLING; else role = ICE_ROLE_CONTROLLED; err = icem_alloc(&m->icem, ICE_MODE_FULL, role, IPPROTO_UDP, ICE_LAYER, sess->tiebrk, sess->lufrag, sess->lpwd, conncheck_handler, m); if (err) goto out; icem_conf(m->icem)->debug = LEVEL_DEBUG==log_level_get(); icem_conf(m->icem)->rc = 4; icem_set_conf(m->icem, icem_conf(m->icem)); icem_set_name(m->icem, sdp_media_name(sdpm)); for (i=0; i<2; i++) { m->compv[i].m = m; m->compv[i].id = i+1; if (m->compv[i].sock) err |= icem_comp_add(m->icem, i+1, m->compv[i].sock); } m->connh = connh; m->arg = arg; if (sa_isset(&sess->srv, SA_ALL)) err |= media_start(sess, m); out: if (err) mem_deref(m); else { *mp = m; } return err; } static bool sdp_attr_handler(const char *name, const char *value, void *arg) { struct mnat_sess *sess = arg; struct le *le; for (le = sess->medial.head; le; le = le->next) { struct mnat_media *m = le->data; (void)ice_sdp_decode(m->icem, name, value); } return false; } static bool media_attr_handler(const char *name, const char *value, void *arg) { struct mnat_media *m = arg; return 0 != icem_sdp_decode(m->icem, name, value); } static int enable_turn_channels(struct mnat_sess *sess) { struct le *le; int err = 0; for (le = sess->medial.head; le; le = le->next) { struct mnat_media *m = le->data; struct sa raddr[2]; unsigned i; err |= set_media_attributes(m); raddr[0] = *sdp_media_raddr(m->sdpm); sdp_media_raddr_rtcp(m->sdpm, &raddr[1]); for (i=0; i<2; i++) { if (m->compv[i].sock && sa_isset(&raddr[i], SA_ALL)) err |= icem_add_chan(m->icem, i+1, &raddr[i]); } } return err; } /** This can be called several times */ static int update(struct mnat_sess *sess) { struct le *le; int err = 0; if (!sess) return EINVAL; /* SDP session */ (void)sdp_session_rattr_apply(sess->sdp, NULL, sdp_attr_handler, sess); /* SDP medialines */ for (le = sess->medial.head; le; le = le->next) { struct mnat_media *m = le->data; sdp_media_rattr_apply(m->sdpm, NULL, media_attr_handler, m); } /* 5.1. Verifying ICE Support */ if (verify_peer_ice(sess)) { err = ice_start(sess); } else if (sess->turn) { info("ice: ICE not supported by peer, fallback to TURN\n"); err = enable_turn_channels(sess); } else { info("ice: ICE not supported by peer\n"); LIST_FOREACH(&sess->medial, le) { struct mnat_media *m = le->data; err |= set_media_attributes(m); } } return err; } static struct mnat mnat_ice = { .id = "ice", .ftag = "+sip.ice", .wait_connected = true, .sessh = session_alloc, .mediah = media_alloc, .updateh = update, }; static int module_init(void) { mnat_register(baresip_mnatl(), &mnat_ice); return 0; } static int module_close(void) { mnat_unregister(&mnat_ice); return 0; } EXPORT_SYM const struct mod_export DECL_EXPORTS(ice) = { "ice", "mnat", module_init, module_close, }; baresip-1.0.0/modules/ice/module.mk000066400000000000000000000001501372575704200171730ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # MOD := ice $(MOD)_SRCS += ice.c include mk/mod.mk baresip-1.0.0/modules/ilbc/000077500000000000000000000000001372575704200155325ustar00rootroot00000000000000baresip-1.0.0/modules/ilbc/ilbc.c000066400000000000000000000147601372575704200166170ustar00rootroot00000000000000/** * @file ilbc.c Internet Low Bit Rate Codec (iLBC) audio codec * * Copyright (C) 2010 Creytiv.com */ #include #include #include #include #include #include /** * @defgroup ilbc ilbc * * iLBC audio codec * * This module implements the iLBC audio codec as defined in: * * RFC 3951 Internet Low Bit Rate Codec (iLBC) * RFC 3952 RTP Payload Format for iLBC Speech * * The iLBC source code is not included here, but can be downloaded from * http://ilbcfreeware.org/ * * You can also use the source distributed by the Freeswitch project, * see www.freeswitch.org, and then freeswitch/libs/codec/ilbc. * Or you can look in the asterisk source code ... * * mode=20 15.20 kbit/s 160samp 38bytes * mode=30 13.33 kbit/s 240samp 50bytes */ enum { DEFAULT_MODE = 20, /* 20ms or 30ms */ USE_ENHANCER = 1 }; struct auenc_state { iLBC_Enc_Inst_t enc; int mode; uint32_t enc_bytes; }; struct audec_state { iLBC_Dec_Inst_t dec; int mode; uint32_t nsamp; size_t dec_bytes; }; static char ilbc_fmtp[32]; static void set_encoder_mode(struct auenc_state *st, int mode) { if (st->mode == mode) return; info("ilbc: set iLBC encoder mode %dms\n", mode); st->mode = mode; switch (mode) { case 20: st->enc_bytes = NO_OF_BYTES_20MS; break; case 30: st->enc_bytes = NO_OF_BYTES_30MS; break; default: warning("ilbc: unknown encoder mode %d\n", mode); return; } st->enc_bytes = initEncode(&st->enc, mode); } static void set_decoder_mode(struct audec_state *st, int mode) { if (st->mode == mode) return; info("ilbc: set iLBC decoder mode %dms\n", mode); st->mode = mode; switch (mode) { case 20: st->nsamp = BLOCKL_20MS; break; case 30: st->nsamp = BLOCKL_30MS; break; default: warning("ilbc: unknown decoder mode %d\n", mode); return; } st->nsamp = initDecode(&st->dec, mode, USE_ENHANCER); } static void encoder_fmtp_decode(struct auenc_state *st, const char *fmtp) { struct pl mode; if (!fmtp) return; if (re_regex(fmtp, strlen(fmtp), "mode=[0-9]+", &mode)) return; set_encoder_mode(st, pl_u32(&mode)); } static void decoder_fmtp_decode(struct audec_state *st, const char *fmtp) { struct pl mode; if (!fmtp) return; if (re_regex(fmtp, strlen(fmtp), "mode=[0-9]+", &mode)) return; set_decoder_mode(st, pl_u32(&mode)); } static void encode_destructor(void *arg) { struct auenc_state *st = arg; (void)st; } static void decode_destructor(void *arg) { struct audec_state *st = arg; (void)st; } static int check_ptime(const struct auenc_param *prm) { if (!prm) return 0; switch (prm->ptime) { case 20: case 30: return 0; default: warning("ilbc: invalid ptime %u ms\n", prm->ptime); return EINVAL; } } static int encode_update(struct auenc_state **aesp, const struct aucodec *ac, struct auenc_param *prm, const char *fmtp) { struct auenc_state *st; if (!aesp || !ac || !prm) return EINVAL; if (check_ptime(prm)) return EINVAL; if (*aesp) return 0; st = mem_zalloc(sizeof(*st), encode_destructor); if (!st) return ENOMEM; set_encoder_mode(st, DEFAULT_MODE); if (str_isset(fmtp)) encoder_fmtp_decode(st, fmtp); /* update parameters after SDP was decoded */ if (prm) { prm->ptime = st->mode; } *aesp = st; return 0; } static int decode_update(struct audec_state **adsp, const struct aucodec *ac, const char *fmtp) { struct audec_state *st; if (!adsp || !ac) return EINVAL; if (*adsp) return 0; st = mem_zalloc(sizeof(*st), decode_destructor); if (!st) return ENOMEM; set_decoder_mode(st, DEFAULT_MODE); if (str_isset(fmtp)) decoder_fmtp_decode(st, fmtp); *adsp = st; return 0; } static int encode(struct auenc_state *st, bool *marker, uint8_t *buf, size_t *len, int fmt, const void *sampv, size_t sampc) { float float_buf[sampc]; uint32_t i; (void)marker; /* Make sure there is enough space */ if (*len < st->enc_bytes) { warning("ilbc: encode: buffer is too small (%u bytes)\n", *len); return ENOMEM; } if (fmt != AUFMT_S16LE) return ENOTSUP; /* Convert from 16-bit samples to float */ for (i=0; ienc); /* (i/o) the general encoder state */ *len = st->enc_bytes; return 0; } static int do_dec(struct audec_state *st, int16_t *sampv, size_t *sampc, const uint8_t *buf, size_t len) { float float_buf[st->nsamp]; const int mode = len ? 1 : 0; uint32_t i; /* Make sure there is enough space in the buffer */ if (*sampc < st->nsamp) return ENOMEM; iLBC_decode(float_buf, /* (o) decoded signal block */ (uint8_t *)buf, /* (i) encoded signal bits */ &st->dec, /* (i/o) the decoder state structure */ mode); /* (i) 0: bad packet, PLC, 1: normal */ /* Convert from float to 16-bit samples */ for (i=0; insamp; i++) { sampv[i] = (int16_t)float_buf[i]; } *sampc = st->nsamp; return 0; } static int decode(struct audec_state *st, int fmt, void *sampv, size_t *sampc, bool marker, const uint8_t *buf, size_t len) { (void)marker; if (fmt != AUFMT_S16LE) return ENOTSUP; /* Try to detect mode */ if (st->dec_bytes != len) { st->dec_bytes = len; switch (st->dec_bytes) { case NO_OF_BYTES_20MS: set_decoder_mode(st, 20); break; case NO_OF_BYTES_30MS: set_decoder_mode(st, 30); break; default: warning("ilbc: decode: expect %u, got %u\n", st->dec_bytes, len); return EINVAL; } } return do_dec(st, (int16_t *)sampv, sampc, buf, len); } static int pkloss(struct audec_state *st, int fmt, void *sampv, size_t *sampc, const uint8_t *buf, size_t len) { (void)buf; (void)len; if (fmt != AUFMT_S16LE) return ENOTSUP; return do_dec(st, (int16_t *)sampv, sampc, NULL, 0); } static struct aucodec ilbc = { .name = "iLBC", .srate = 8000, .crate = 8000, .ch = 1, .pch = 1, .fmtp = ilbc_fmtp, .encupdh = encode_update, .ench = encode, .decupdh = decode_update, .dech = decode, .plch = pkloss, }; static int module_init(void) { (void)re_snprintf(ilbc_fmtp, sizeof(ilbc_fmtp), "mode=%d", DEFAULT_MODE); aucodec_register(baresip_aucodecl(), &ilbc); return 0; } static int module_close(void) { aucodec_unregister(&ilbc); return 0; } EXPORT_SYM const struct mod_export DECL_EXPORTS(ilbc) = { "ilbc", "codec", module_init, module_close }; baresip-1.0.0/modules/ilbc/module.mk000066400000000000000000000002061372575704200173460ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # MOD := ilbc $(MOD)_SRCS += ilbc.c $(MOD)_LFLAGS += -lilbc -lm include mk/mod.mk baresip-1.0.0/modules/isac/000077500000000000000000000000001372575704200155405ustar00rootroot00000000000000baresip-1.0.0/modules/isac/isac.c000066400000000000000000000071351372575704200166310ustar00rootroot00000000000000/** * @file isac.c iSAC audio codec * * Copyright (C) 2010 Creytiv.com */ #include #include #include "isac.h" /** * @defgroup isac isac * * iSAC audio codec * * draft-ietf-avt-rtp-isac-04 */ struct auenc_state { ISACStruct *inst; }; struct audec_state { ISACStruct *inst; }; static void encode_destructor(void *arg) { struct auenc_state *st = arg; if (st->inst) WebRtcIsac_Free(st->inst); } static void decode_destructor(void *arg) { struct audec_state *st = arg; if (st->inst) WebRtcIsac_Free(st->inst); } static int encode_update(struct auenc_state **aesp, const struct aucodec *ac, struct auenc_param *prm, const char *fmtp) { struct auenc_state *st; int err = 0; (void)prm; (void)fmtp; if (!aesp || !ac) return EINVAL; if (*aesp) return 0; st = mem_alloc(sizeof(*st), encode_destructor); if (!st) return ENOMEM; if (WebRtcIsac_Create(&st->inst) < 0) { err = ENOMEM; goto out; } WebRtcIsac_EncoderInit(st->inst, 0); if (ac->srate == 32000) WebRtcIsac_SetEncSampRate(st->inst, kIsacSuperWideband); out: if (err) mem_deref(st); else *aesp = st; return err; } static int decode_update(struct audec_state **adsp, const struct aucodec *ac, const char *fmtp) { struct audec_state *st; int err = 0; (void)fmtp; if (!adsp || !ac) return EINVAL; if (*adsp) return 0; st = mem_alloc(sizeof(*st), decode_destructor); if (!st) return ENOMEM; if (WebRtcIsac_Create(&st->inst) < 0) { err = ENOMEM; goto out; } WebRtcIsac_DecoderInit(st->inst); if (ac->srate == 32000) WebRtcIsac_SetDecSampRate(st->inst, kIsacSuperWideband); out: if (err) mem_deref(st); else *adsp = st; return err; } static int encode(struct auenc_state *st, uint8_t *buf, size_t *len, const int16_t *sampv, size_t sampc) { WebRtc_Word16 len1, len2; size_t l; if (!st || !buf || !len || !sampv || !sampc) return EINVAL; /* 10 ms audio blocks */ len1 = WebRtcIsac_Encode(st->inst, sampv, (void *)buf); len2 = WebRtcIsac_Encode(st->inst, &sampv[sampc/2], (void *)buf); l = len1 ? len1 : len2; if (l > *len) return ENOMEM; *len = l; return 0; } static int decode(struct audec_state *st, int16_t *sampv, size_t *sampc, const uint8_t *buf, size_t len) { WebRtc_Word16 speechType; int n; if (!st || !sampv || !sampc || !buf || !len) return EINVAL; n = WebRtcIsac_Decode(st->inst, (void *)buf, len, (void *)sampv, &speechType); if (n < 0) return EPROTO; if ((size_t)n > *sampc) return ENOMEM; *sampc = n; return 0; } static int plc(struct audec_state *st, int16_t *sampv, size_t *sampc) { int n; if (!st || !sampv || !sampc) return EINVAL; n = WebRtcIsac_DecodePlc(st->inst, (void *)sampv, 1); if (n < 0) return EPROTO; *sampc = n; return 0; } static struct aucodec isacv[] = { { .name = "isac", .srate = 32000, .crate = 32000, .ch = 1, .pch = 1, .encupdh = encode_update, .ench = encode, .decupdh = decode_update, .dech = decode, .plch = plc, }, { .name = "isac", .srate = 16000, .crate = 16000, .ch = 1, .pch = 1, .encupdh = encode_update, .ench = encode, .decupdh = decode_update, .dech = decode, .plch = plc, } }; static int module_init(void) { unsigned i; for (i=0; i #include #include #include "mod_jack.h" static struct auplay *auplay; static struct ausrc *ausrc; static int module_init(void) { int err = 0; err |= auplay_register(&auplay, baresip_auplayl(), "jack", jack_play_alloc); err |= ausrc_register(&ausrc, baresip_ausrcl(), "jack", jack_src_alloc); return err; } static int module_close(void) { auplay = mem_deref(auplay); ausrc = mem_deref(ausrc); return 0; } const struct mod_export DECL_EXPORTS(jack) = { "jack", "sound", module_init, module_close }; baresip-1.0.0/modules/jack/jack_play.c000066400000000000000000000136541372575704200176430ustar00rootroot00000000000000/** * @file jack_play.c JACK audio driver -- player * * Copyright (C) 2010 Creytiv.com */ #include #include #include #include #include "mod_jack.h" struct auplay_st { const struct auplay *ap; /* pointer to base-class (inheritance) */ struct auplay_prm prm; float *sampv; size_t sampc; /* includes number of channels */ auplay_write_h *wh; void *arg; jack_client_t *client; jack_port_t **portv; jack_nframes_t nframes; /* num frames per port (channel) */ }; /** * The process callback for this JACK application is called in a * special realtime thread once for each audio cycle. * * This client does nothing more than copy data from its input * port to its output port. It will exit when stopped by * the user (e.g. using Ctrl-C on a unix-ish operating system) * * NOTE avoid memory allocations in this function */ static int process_handler(jack_nframes_t nframes, void *arg) { struct auplay_st *st = arg; size_t sampc = nframes * st->prm.ch; size_t ch, j; /* 1. read data from app (signed 16-bit) interleaved */ st->wh(st->sampv, sampc, st->arg); /* 2. convert from 16-bit to float and copy to Jack */ /* 3. de-interleave [LRLRLRLR] -> [LLLLL]+[RRRRR] */ for (ch = 0; ch < st->prm.ch; ch++) { jack_default_audio_sample_t *buffer; buffer = jack_port_get_buffer(st->portv[ch], st->nframes); for (j = 0; j < nframes; j++) { float samp = st->sampv[j*st->prm.ch + ch]; buffer[j] = samp; } } return 0; } static void auplay_destructor(void *arg) { struct auplay_st *st = arg; info("jack: destroy\n"); if (st->client) jack_client_close(st->client); mem_deref(st->sampv); mem_deref(st->portv); } static int start_jack(struct auplay_st *st) { struct conf *conf = conf_cur(); const char **ports; const char *client_name = "baresip"; const char *server_name = NULL; jack_options_t options = JackNullOption; jack_status_t status; unsigned ch; jack_nframes_t engine_srate; bool jack_connect_ports = true; (void)conf_get_bool(conf, "jack_connect_ports", &jack_connect_ports); /* open a client connection to the JACK server */ size_t len = jack_client_name_size(); char *conf_name = mem_alloc(len+1, NULL); if (!conf_get_str(conf, "jack_client_name", conf_name, len)) { st->client = jack_client_open(conf_name, options, &status, server_name); } else { st->client = jack_client_open(client_name, options, &status, server_name); } mem_deref(conf_name); if (st->client == NULL) { warning("jack: jack_client_open() failed, " "status = 0x%2.0x\n", status); if (status & JackServerFailed) { warning("jack: Unable to connect to JACK server\n"); } return ENODEV; } if (status & JackServerStarted) { info("jack: JACK server started\n"); } client_name = jack_get_client_name(st->client); info("jack: source unique name `%s' assigned\n", client_name); jack_set_process_callback(st->client, process_handler, st); engine_srate = jack_get_sample_rate(st->client); st->nframes = jack_get_buffer_size(st->client); info("jack: engine sample rate: %" PRIu32 " max_frames=%u\n", engine_srate, st->nframes); /* currently the application must use the same sample-rate as the jack server backend */ if (engine_srate != st->prm.srate) { warning("jack: samplerate %uHz expected\n", engine_srate); return EINVAL; } st->sampc = st->nframes * st->prm.ch; st->sampv = mem_alloc(st->sampc * sizeof(float), NULL); if (!st->sampv) return ENOMEM; /* create one port per channel */ for (ch=0; chprm.ch; ch++) { char buf[32]; re_snprintf(buf, sizeof(buf), "output_%u", ch+1); st->portv[ch] = jack_port_register (st->client, buf, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); if ( st->portv[ch] == NULL) { warning("jack: no more JACK ports available\n"); return ENODEV; } } /* Tell the JACK server that we are ready to roll. Our * process() callback will start running now. */ if (jack_activate (st->client)) { warning("jack: cannot activate client"); return ENODEV; } /* Connect the ports. You can't do this before the client is * activated, because we can't make connections to clients * that aren't running. Note the confusing (but necessary) * orientation of the driver backend ports: playback ports are * "input" to the backend, and capture ports are "output" from * it. */ if (jack_connect_ports) { info("jack: connecting default input ports\n"); ports = jack_get_ports (st->client, NULL, NULL, JackPortIsInput | JackPortIsPhysical); if (ports == NULL) { warning("jack: no physical playback ports\n"); return ENODEV; } /* Connect all physical ports. In case of for example mono * audio with 2 physical playback ports, connect the * single registered port to both physical port. */ ch = 0; for (unsigned i = 0; ports[i] != NULL; i++) { if (jack_connect (st->client, jack_port_name (st->portv[ch]), ports[i])) { warning("jack: cannot connect output ports\n"); } ++ch; if (ch >= st->prm.ch) { ch = 0; } } jack_free(ports); } return 0; } int jack_play_alloc(struct auplay_st **stp, const struct auplay *ap, struct auplay_prm *prm, const char *device, auplay_write_h *wh, void *arg) { struct auplay_st *st; int err = 0; (void)device; if (!stp || !ap || !prm || !wh) return EINVAL; info("jack: play %uHz,%uch\n", prm->srate, prm->ch); if (prm->fmt != AUFMT_FLOAT) { warning("jack: playback: unsupported sample format (%s)\n", aufmt_name(prm->fmt)); return ENOTSUP; } st = mem_zalloc(sizeof(*st), auplay_destructor); if (!st) return ENOMEM; st->prm = *prm; st->ap = ap; st->wh = wh; st->arg = arg; st->portv = mem_reallocarray(NULL, prm->ch, sizeof(*st->portv), NULL); if (!st->portv) { err = ENOMEM; goto out; } err = start_jack(st); if (err) goto out; info("jack: sampc=%zu\n", st->sampc); out: if (err) mem_deref(st); else *stp = st; return err; } baresip-1.0.0/modules/jack/jack_src.c000066400000000000000000000123301372575704200174530ustar00rootroot00000000000000/** * @file jack_src.c JACK audio driver -- source * * Copyright (C) 2010 Creytiv.com */ #include #include #include #include #include #include "mod_jack.h" struct ausrc_st { const struct ausrc *as; /* pointer to base-class (inheritance) */ struct ausrc_prm prm; float *sampv; size_t sampc; /* includes number of channels */ ausrc_read_h *rh; void *arg; jack_client_t *client; jack_port_t **portv; jack_nframes_t nframes; /* num frames per port (channel) */ }; static int process_handler(jack_nframes_t nframes, void *arg) { struct ausrc_st *st = arg; struct auframe af; size_t sampc = nframes * st->prm.ch; size_t ch, j; uint64_t ts; ts = jack_frames_to_time(st->client, jack_last_frame_time(st->client)); /* 2. convert from 16-bit to float and copy to Jack */ /* 3. de-interleave [LRLRLRLR] -> [LLLLL]+[RRRRR] */ for (ch = 0; ch < st->prm.ch; ch++) { const jack_default_audio_sample_t *buffer; buffer = jack_port_get_buffer(st->portv[ch], st->nframes); for (j = 0; j < nframes; j++) { float samp = buffer[j]; st->sampv[j*st->prm.ch + ch] = samp; } } af.fmt = st->prm.fmt; af.sampv = st->sampv; af.sampc = sampc; af.timestamp = ts; /* 1. read data from app (signed 16-bit) interleaved */ st->rh(&af, st->arg); return 0; } static void ausrc_destructor(void *arg) { struct ausrc_st *st = arg; info("jack: source destroy\n"); if (st->client) jack_client_close(st->client); mem_deref(st->sampv); mem_deref(st->portv); } static int start_jack(struct ausrc_st *st) { struct conf *conf = conf_cur(); const char **ports; const char *client_name = "baresip"; const char *server_name = NULL; jack_options_t options = JackNullOption; jack_status_t status; unsigned ch; jack_nframes_t engine_srate; bool jack_connect_ports = true; (void)conf_get_bool(conf, "jack_connect_ports", &jack_connect_ports); /* open a client connection to the JACK server */ size_t len = jack_client_name_size(); char *conf_name = mem_alloc(len+1, NULL); if (!conf_get_str(conf, "jack_client_name", conf_name, len)) { st->client = jack_client_open(conf_name, options, &status, server_name); } else { st->client = jack_client_open(client_name, options, &status, server_name); } mem_deref(conf_name); if (st->client == NULL) { warning("jack: jack_client_open() failed, " "status = 0x%2.0x\n", status); if (status & JackServerFailed) { warning("jack: Unable to connect to JACK server\n"); } return ENODEV; } if (status & JackServerStarted) { info("jack: JACK server started\n"); } client_name = jack_get_client_name(st->client); info("jack: destination unique name `%s' assigned\n", client_name); jack_set_process_callback(st->client, process_handler, st); engine_srate = jack_get_sample_rate(st->client); st->nframes = jack_get_buffer_size(st->client); info("jack: engine sample rate: %" PRIu32 " max_frames=%u\n", engine_srate, st->nframes); /* currently the application must use the same sample-rate as the jack server backend */ if (engine_srate != st->prm.srate) { warning("jack: samplerate %uHz expected\n", engine_srate); return EINVAL; } st->sampc = st->nframes * st->prm.ch; st->sampv = mem_alloc(st->sampc * sizeof(float), NULL); if (!st->sampv) return ENOMEM; /* create one port per channel */ for (ch=0; chprm.ch; ch++) { char buf[32]; re_snprintf(buf, sizeof(buf), "input_%u", ch+1); st->portv[ch] = jack_port_register(st->client, buf, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); if ( st->portv[ch] == NULL) { warning("jack: no more JACK ports available\n"); return ENODEV; } } /* Tell the JACK server that we are ready to roll. Our * process() callback will start running now. */ if (jack_activate (st->client)) { warning("jack: cannot activate client"); return ENODEV; } if (jack_connect_ports) { info("jack: connecting default output ports\n"); ports = jack_get_ports (st->client, NULL, NULL, JackPortIsOutput | JackPortIsPhysical); if (ports == NULL) { warning("jack: no physical playback ports\n"); return ENODEV; } for (ch=0; chprm.ch; ch++) { if (jack_connect(st->client, ports[ch], jack_port_name(st->portv[ch]))) { warning("jack: cannot connect output ports\n"); } } jack_free(ports); } return 0; } int jack_src_alloc(struct ausrc_st **stp, const struct ausrc *as, struct media_ctx **ctx, struct ausrc_prm *prm, const char *device, ausrc_read_h *rh, ausrc_error_h *errh, void *arg) { struct ausrc_st *st; int err = 0; (void)ctx; (void)device; (void)errh; if (!stp || !as || !prm || !rh) return EINVAL; if (prm->fmt != AUFMT_FLOAT) { warning("jack: source: unsupported sample format (%s)\n", aufmt_name(prm->fmt)); return ENOTSUP; } st = mem_zalloc(sizeof(*st), ausrc_destructor); if (!st) return ENOMEM; st->prm = *prm; st->as = as; st->rh = rh; st->arg = arg; st->portv = mem_reallocarray(NULL, prm->ch, sizeof(*st->portv), NULL); if (!st->portv) { err = ENOMEM; goto out; } err = start_jack(st); if (err) goto out; info("jack: source sampc=%zu\n", st->sampc); out: if (err) mem_deref(st); else *stp = st; return err; } baresip-1.0.0/modules/jack/mod_jack.h000066400000000000000000000007121372575704200174510ustar00rootroot00000000000000/** * @file mod_jack.h JACK audio driver -- internal api * * Copyright (C) 2010 Creytiv.com */ int jack_play_alloc(struct auplay_st **stp, const struct auplay *ap, struct auplay_prm *prm, const char *device, auplay_write_h *wh, void *arg); int jack_src_alloc(struct ausrc_st **stp, const struct ausrc *as, struct media_ctx **ctx, struct ausrc_prm *prm, const char *device, ausrc_read_h *rh, ausrc_error_h *errh, void *arg); baresip-1.0.0/modules/jack/module.mk000066400000000000000000000003451372575704200173510ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # MOD := jack $(MOD)_SRCS += jack.c jack_play.c jack_src.c $(MOD)_CFLAGS += $(shell pkg-config --cflags jack) $(MOD)_LFLAGS += $(shell pkg-config --libs jack) include mk/mod.mk baresip-1.0.0/modules/l16/000077500000000000000000000000001372575704200152235ustar00rootroot00000000000000baresip-1.0.0/modules/l16/l16.c000066400000000000000000000044661372575704200160030ustar00rootroot00000000000000/** * @file l16.c 16-bit linear codec * * Copyright (C) 2010 - 2015 Creytiv.com */ #include #include #include /** * @defgroup l16 l16 * * Linear 16-bit audio codec */ enum {NR_CODECS = 10}; static int encode(struct auenc_state *st, bool *marker, uint8_t *buf, size_t *len, int fmt, const void *sampv, size_t sampc) { int16_t *p = (void *)buf; const int16_t *sampv16 = sampv; (void)st; (void)marker; if (!buf || !len || !sampv) return EINVAL; if (*len < sampc*2) return ENOMEM; if (fmt != AUFMT_S16LE) return ENOTSUP; *len = sampc*2; while (sampc--) *p++ = htons(*sampv16++); return 0; } static int decode(struct audec_state *st, int fmt, void *sampv, size_t *sampc, bool marker, const uint8_t *buf, size_t len) { int16_t *p = (void *)buf; int16_t *sampv16 = sampv; (void)st; (void)marker; if (!buf || !len || !sampv) return EINVAL; if (*sampc < len/2) return ENOMEM; if (fmt != AUFMT_S16LE) return ENOTSUP; *sampc = len/2; len /= 2; while (len--) *sampv16++ = ntohs(*p++); return 0; } /* See RFC 3551 */ static struct aucodec l16v[NR_CODECS] = { {LE_INIT, 0, "L16", 48000, 48000, 2, 2, 4, 0, 0, encode, 0, decode, 0,0,0}, {LE_INIT, "10", "L16", 44100, 44100, 2, 2, 4, 0, 0, encode, 0, decode, 0,0,0}, {LE_INIT, 0, "L16", 32000, 32000, 2, 2, 10, 0, 0, encode, 0, decode, 0,0,0}, {LE_INIT, 0, "L16", 16000, 16000, 2, 2, 20, 0, 0, encode, 0, decode, 0,0,0}, {LE_INIT, 0, "L16", 8000, 8000, 2, 2, 20, 0, 0, encode, 0, decode, 0,0,0}, {LE_INIT, 0, "L16", 48000, 48000, 1, 1, 10, 0, 0, encode, 0, decode, 0,0,0}, {LE_INIT, "11", "L16", 44100, 44100, 1, 1, 10, 0, 0, encode, 0, decode, 0,0,0}, {LE_INIT, 0, "L16", 32000, 32000, 1, 1, 20, 0, 0, encode, 0, decode, 0,0,0}, {LE_INIT, 0, "L16", 16000, 16000, 1, 1, 20, 0, 0, encode, 0, decode, 0,0,0}, {LE_INIT, 0, "L16", 8000, 8000, 1, 1, 20, 0, 0, encode, 0, decode, 0,0,0}, }; static int module_init(void) { struct list *aucodecl = baresip_aucodecl(); size_t i; for (i=0; i #include #include #include /** * @defgroup menu menu * * Interactive menu * * This module must be loaded if you want to use the interactive menu * to control the Baresip application. */ /** Defines the status modes */ enum statmode { STATMODE_CALL = 0, STATMODE_OFF, }; static struct { struct tmr tmr_alert; /**< Incoming call alert timer */ struct tmr tmr_stat; /**< Call status timer */ struct play *play; /**< Current audio player state */ struct mbuf *dialbuf; /**< Buffer for dialled number */ struct le *le_cur; /**< Current User-Agent (struct ua) */ bool bell; /**< ANSI Bell alert enabled */ bool ringback_disabled; /**< no ringback on sip 180 respons */ struct tmr tmr_redial; /**< Timer for auto-reconnect */ uint32_t redial_delay; /**< Redial delay in [seconds] */ uint32_t redial_attempts; /**< Number of re-dial attempts */ uint32_t current_attempts; /**< Current number of re-dials */ uint64_t start_ticks; /**< Ticks when app started */ enum statmode statmode; /**< Status mode */ bool clean_number; /**< Remove -/() from diald numbers */ char redial_aor[128]; } menu; static int menu_set_incall(bool incall); static void update_callstatus(void); static void alert_stop(void); static int switch_audio_source(struct re_printf *pf, void *arg); static int switch_audio_player(struct re_printf *pf, void *arg); static int switch_video_source(struct re_printf *pf, void *arg); static void redial_reset(void) { tmr_cancel(&menu.tmr_redial); menu.current_attempts = 0; } static const char *translate_errorcode(uint16_t scode) { switch (scode) { case 404: return "notfound.wav"; case 486: return "busy.wav"; case 487: return NULL; /* ignore */ default: return "error.wav"; } } static void check_registrations(void) { static bool ual_ready = false; struct le *le; uint32_t n; if (ual_ready) return; for (le = list_head(uag_list()); le; le = le->next) { struct ua *ua = le->data; if (!ua_isregistered(ua)) return; } n = list_count(uag_list()); /* We are ready */ ui_output(baresip_uis(), "\x1b[32mAll %u useragent%s registered successfully!" " (%u ms)\x1b[;m\n", n, n==1 ? "" : "s", (uint32_t)(tmr_jiffies() - menu.start_ticks)); ual_ready = true; } /* Return TRUE if there are any active calls for any UAs */ static bool have_active_calls(void) { struct le *le; for (le = list_head(uag_list()); le; le = le->next) { struct ua *ua = le->data; if (ua_call(ua)) return true; } return false; } /** * Print the SIP Registration for all User-Agents * * @param pf Print handler for debug output * @param unused Unused parameter * * @return 0 if success, otherwise errorcode */ static int ua_print_reg_status(struct re_printf *pf, void *unused) { struct le *le; int err; (void)unused; err = re_hprintf(pf, "\n--- User Agents (%u) ---\n", list_count(uag_list())); for (le = list_head(uag_list()); le && !err; le = le->next) { const struct ua *ua = le->data; err = re_hprintf(pf, "%s ", ua == uag_current() ? ">" : " "); err |= ua_print_status(pf, ua); } err |= re_hprintf(pf, "\n"); return err; } static int cmd_set_answermode(struct re_printf *pf, void *arg) { enum answermode mode; const struct cmd_arg *carg = arg; int err; if (0 == str_cmp(carg->prm, "manual")) { mode = ANSWERMODE_MANUAL; } else if (0 == str_cmp(carg->prm, "early")) { mode = ANSWERMODE_EARLY; } else if (0 == str_cmp(carg->prm, "auto")) { mode = ANSWERMODE_AUTO; } else { (void)re_hprintf(pf, "Invalid answer mode: %s\n", carg->prm); return EINVAL; } err = account_set_answermode(ua_account(uag_current()), mode); if (err) return err; (void)re_hprintf(pf, "Answer mode changed to: %s\n", carg->prm); return 0; } /** * Print the current SIP Call status for the current User-Agent * * @param pf Print handler for debug output * @param unused Unused parameter * * @return 0 if success, otherwise errorcode */ static int ua_print_call_status(struct re_printf *pf, void *unused) { struct call *call; int err; (void)unused; call = ua_call(uag_current()); if (call) { err = re_hprintf(pf, "\n%H\n", call_debug, call); } else { err = re_hprintf(pf, "\n(no active calls)\n"); } return err; } static void clean_number(char *str) { int i = 0, k = 0; /* only clean numeric numbers * In other cases trust the user input */ int err = re_regex(str, sizeof(str), "[A-Za-z]"); if (err == 0) return; /* remove (0) which is in some mal-formated numbers * but only if trailed by another character */ if (str[0] == '+' || (str[0] == '0' && str[1] == '0')) while (str[i]) { if (str[i] == '(' && str[i+1] == '0' && str[i+2] == ')' && (str[i+3] == ' ' || (str[i+3] >= '0' && str[i+3] <= '9') ) ) { str[i+1] = ' '; break; } ++i; } i = 0; while (str[i]) { if (str[i] == ' ' || str[i] == '.' || str[i] == '-' || str[i] == '/' || str[i] == '(' || str[i] == ')') ++i; else str[k++] = str[i++]; } str[k] = '\0'; } static int dial_handler(struct re_printf *pf, void *arg) { const struct cmd_arg *carg = arg; int err = 0; (void)pf; if (str_isset(carg->prm)) { mbuf_rewind(menu.dialbuf); (void)mbuf_write_str(menu.dialbuf, carg->prm); if (menu.clean_number) clean_number(carg->prm); err = ua_connect(uag_current(), NULL, NULL, carg->prm, VIDMODE_ON); } else if (menu.dialbuf->end > 0) { char *uri; menu.dialbuf->pos = 0; err = mbuf_strdup(menu.dialbuf, &uri, menu.dialbuf->end); if (err) return err; if (menu.clean_number) clean_number(uri); err = ua_connect(uag_current(), NULL, NULL, uri, VIDMODE_ON); mem_deref(uri); } if (err) { warning("menu: ua_connect failed: %m\n", err); } return err; } static void options_resp_handler(int err, const struct sip_msg *msg, void *arg) { (void)arg; if (err) { warning("options reply error: %m\n", err); return; } if (msg->scode < 200) return; if (msg->scode < 300) { mbuf_set_pos(msg->mb, 0); info("----- OPTIONS of %r -----\n%b", &msg->to.auri, mbuf_buf(msg->mb), mbuf_get_left(msg->mb)); return; } info("%r: OPTIONS failed: %u %r\n", &msg->to.auri, msg->scode, &msg->reason); } static int options_command(struct re_printf *pf, void *arg) { const struct cmd_arg *carg = arg; int err = 0; (void)pf; err = ua_options_send(uag_current(), carg->prm, options_resp_handler, NULL); if (err) { warning("menu: ua_options failed: %m\n", err); } return err; } static int cmd_answer(struct re_printf *pf, void *unused) { struct ua *ua = uag_current(); int err; (void)unused; err = re_hprintf(pf, "%s: Answering incoming call\n", ua_aor(ua)); /* Stop any ongoing ring-tones */ menu.play = mem_deref(menu.play); ua_hold_answer(ua, NULL, VIDMODE_ON); return err; } static int cmd_hangup(struct re_printf *pf, void *unused) { (void)pf; (void)unused; /* Stop any ongoing ring-tones */ menu.play = mem_deref(menu.play); alert_stop(); ua_hangup(uag_current(), NULL, 0, NULL); /* note: must be called after ua_hangup() */ menu_set_incall(have_active_calls()); return 0; } static int create_ua(struct re_printf *pf, void *arg) { const struct cmd_arg *carg = arg; struct ua *ua = NULL; int err = 0; if (str_isset(carg->prm)) { (void)re_hprintf(pf, "Creating UA for %s ...\n", carg->prm); err = ua_alloc(&ua, carg->prm); if (err) goto out; } if (account_regint(ua_account(ua))) { (void)ua_register(ua); } err = ua_print_reg_status(pf, NULL); out: if (err) { (void)re_hprintf(pf, "menu: create_ua failed: %m\n", err); } return err; } static int cmd_ua_next(struct re_printf *pf, void *unused) { int err; (void)pf; (void)unused; if (!menu.le_cur) menu.le_cur = list_head(uag_list()); if (!menu.le_cur) return 0; menu.le_cur = menu.le_cur->next ? menu.le_cur->next : list_head(uag_list()); err = re_hprintf(pf, "ua: %s\n", ua_aor(list_ledata(menu.le_cur))); uag_current_set(list_ledata(menu.le_cur)); update_callstatus(); return err; } static int cmd_ua_find(struct re_printf *pf, void *arg) { const struct cmd_arg *carg = arg; struct ua *ua = NULL; if (str_isset(carg->prm)) { ua = uag_find_aor(carg->prm); } if (!ua) { warning("menu: ua_find failed: %s\n", carg->prm); return ENOENT; } re_hprintf(pf, "ua: %s\n", ua_aor(ua)); uag_current_set(ua); update_callstatus(); return 0; } static int cmd_ua_delete(struct re_printf *pf, void *arg) { const struct cmd_arg *carg = arg; struct ua *ua = NULL; if (str_isset(carg->prm)) { ua = uag_find_aor(carg->prm); } if (!ua) { return ENOENT; } if (ua == uag_current()) { (void)cmd_ua_next(pf, NULL); } (void)re_hprintf(pf, "deleting ua: %s\n", carg->prm); mem_deref(ua); (void)ua_print_reg_status(pf, NULL); return 0; } static int print_commands(struct re_printf *pf, void *unused) { (void)unused; return cmd_print(pf, baresip_commands()); } static int cmd_print_calls(struct re_printf *pf, void *unused) { (void)unused; return ua_print_calls(pf, uag_current()); } static const char about_fmt[] = ".------------------------------------------------------------.\n" "| " "\x1b[34;1m" "bare" "\x1b[31;1m" "sip" "\x1b[;m" " %-10s |\n" "| |\n" "| Baresip is a portable and modular SIP User-Agent |\n" "| with audio and video support |\n" "| |\n" "| License: BSD |\n" "| Homepage: https://github.com/baresip/baresip |\n" "| |\n" "'------------------------------------------------------------'\n" ; static int about_box(struct re_printf *pf, void *unused) { (void)unused; return re_hprintf(pf, about_fmt, BARESIP_VERSION); } static const struct cmd cmdv[] = { {"accept", 'a', 0, "Accept incoming call", cmd_answer }, {"hangup", 'b', 0, "Hangup call", cmd_hangup }, {"callstat", 'c', 0, "Call status", ua_print_call_status }, {"dial", 'd', CMD_PRM, "Dial", dial_handler }, {"help", 'h', 0, "Help menu", print_commands }, {"listcalls", 'l', 0, "List active calls", cmd_print_calls }, {"options", 'o', CMD_PRM, "Options", options_command }, {"reginfo", 'r', 0, "Registration info", ua_print_reg_status }, {"answermode",0, CMD_PRM, "Set answer mode", cmd_set_answermode }, {NULL, KEYCODE_ESC,0, "Hangup call", cmd_hangup }, {"uanext", 'T', 0, "Toggle UAs", cmd_ua_next }, {"uanew", 0, CMD_PRM, "Create User-Agent", create_ua }, {"uadel", 0, CMD_PRM, "Delete User-Agent", cmd_ua_delete }, {"uafind", 0, CMD_PRM, "Find User-Agent ", cmd_ua_find }, {"ausrc", 0, CMD_PRM, "Switch audio source", switch_audio_source }, {"auplay", 0, CMD_PRM, "Switch audio player", switch_audio_player }, {"about", 0, 0, "About box", about_box }, {"vidsrc", 0, CMD_PRM, "Switch video source", switch_video_source }, }; static const struct cmd dialcmdv[] = { /* Numeric keypad inputs: */ {NULL, '#', CMD_PRM, NULL, dial_handler }, {NULL, '*', CMD_PRM, NULL, dial_handler }, {NULL, '0', CMD_PRM, NULL, dial_handler }, {NULL, '1', CMD_PRM, NULL, dial_handler }, {NULL, '2', CMD_PRM, NULL, dial_handler }, {NULL, '3', CMD_PRM, NULL, dial_handler }, {NULL, '4', CMD_PRM, NULL, dial_handler }, {NULL, '5', CMD_PRM, NULL, dial_handler }, {NULL, '6', CMD_PRM, NULL, dial_handler }, {NULL, '7', CMD_PRM, NULL, dial_handler }, {NULL, '8', CMD_PRM, NULL, dial_handler }, {NULL, '9', CMD_PRM, NULL, dial_handler }, }; static int call_audio_debug(struct re_printf *pf, void *unused) { (void)unused; return audio_debug(pf, call_audio(ua_call(uag_current()))); } static int call_reinvite(struct re_printf *pf, void *unused) { (void)pf; (void)unused; return call_modify(ua_call(uag_current())); } static int call_mute(struct re_printf *pf, void *unused) { struct audio *audio = call_audio(ua_call(uag_current())); bool muted = !audio_ismuted(audio); (void)unused; (void)re_hprintf(pf, "\ncall %smuted\n", muted ? "" : "un-"); audio_mute(audio, muted); return 0; } static int call_xfer(struct re_printf *pf, void *arg) { const struct cmd_arg *carg = arg; (void)pf; return call_transfer(ua_call(uag_current()), carg->prm); } static int cmd_call_hold(struct re_printf *pf, void *arg) { (void)pf; (void)arg; return call_hold(ua_call(uag_current()), true); } static int cmd_call_resume(struct re_printf *pf, void *arg) { (void)pf; (void)arg; return call_hold(ua_call(uag_current()), false); } static int hold_prev_call(struct re_printf *pf, void *arg) { const struct cmd_arg *carg = arg; (void)pf; return call_hold(ua_prev_call(uag_current()), 'H' == carg->key); } static int switch_audio_player(struct re_printf *pf, void *arg) { const struct cmd_arg *carg = arg; struct pl pl_driver, pl_device; struct config_audio *aucfg; struct config *cfg; struct audio *a; const struct auplay *ap; struct le *le; char driver[16], device[128] = ""; int err = 0; if (re_regex(carg->prm, str_len(carg->prm), "[^,]+,[~]*", &pl_driver, &pl_device)) { return re_hprintf(pf, "\rFormat should be:" " driver,device\n"); } pl_strcpy(&pl_driver, driver, sizeof(driver)); pl_strcpy(&pl_device, device, sizeof(device)); ap = auplay_find(baresip_auplayl(), driver); if (!ap) { re_hprintf(pf, "no such audio-player: %s\n", driver); return 0; } else if (!list_isempty(&ap->dev_list)) { if (!mediadev_find(&ap->dev_list, device)) { re_hprintf(pf, "no such device for %s audio-player: %s\n", driver, device); mediadev_print(pf, &ap->dev_list); return 0; } } re_hprintf(pf, "switch audio player: %s,%s\n", driver, device); cfg = conf_config(); if (!cfg) { return re_hprintf(pf, "no config object\n"); } aucfg = &cfg->audio; str_ncpy(aucfg->play_mod, driver, sizeof(aucfg->play_mod)); str_ncpy(aucfg->play_dev, device, sizeof(aucfg->play_dev)); str_ncpy(aucfg->alert_mod, driver, sizeof(aucfg->alert_mod)); str_ncpy(aucfg->alert_dev, device, sizeof(aucfg->alert_dev)); for (le = list_tail(ua_calls(uag_current())); le; le = le->prev) { struct call *call = le->data; a = call_audio(call); err = audio_set_player(a, driver, device); if (err) { re_hprintf(pf, "failed to set audio-player" " (%m)\n", err); break; } } return 0; } static int switch_audio_source(struct re_printf *pf, void *arg) { const struct cmd_arg *carg = arg; struct pl pl_driver, pl_device; struct config_audio *aucfg; struct config *cfg; struct audio *a; const struct ausrc *as; struct le *le; char driver[16], device[128] = ""; int err = 0; if (re_regex(carg->prm, str_len(carg->prm), "[^,]+,[~]*", &pl_driver, &pl_device)) { return re_hprintf(pf, "\rFormat should be:" " driver,device\n"); } pl_strcpy(&pl_driver, driver, sizeof(driver)); pl_strcpy(&pl_device, device, sizeof(device)); as = ausrc_find(baresip_ausrcl(), driver); if (!as) { re_hprintf(pf, "no such audio-source: %s\n", driver); return 0; } else if (!list_isempty(&as->dev_list)) { if (!mediadev_find(&as->dev_list, device)) { re_hprintf(pf, "no such device for %s audio-source: %s\n", driver, device); mediadev_print(pf, &as->dev_list); return 0; } } re_hprintf(pf, "switch audio device: %s,%s\n", driver, device); cfg = conf_config(); if (!cfg) { return re_hprintf(pf, "no config object\n"); } aucfg = &cfg->audio; str_ncpy(aucfg->src_mod, driver, sizeof(aucfg->src_mod)); str_ncpy(aucfg->src_dev, device, sizeof(aucfg->src_dev)); for (le = list_tail(ua_calls(uag_current())); le; le = le->prev) { struct call *call = le->data; a = call_audio(call); err = audio_set_source(a, driver, device); if (err) { re_hprintf(pf, "failed to set audio-source" " (%m)\n", err); break; } } return 0; } static int switch_video_source(struct re_printf *pf, void *arg) { const struct cmd_arg *carg = arg; struct pl pl_driver, pl_device; struct config_video *vidcfg; struct config *cfg; struct video *v; const struct vidsrc *vs; struct le *le; char driver[16], device[128] = ""; int err = 0; if (re_regex(carg->prm, str_len(carg->prm), "[^,]+,[~]*", &pl_driver, &pl_device)) { return re_hprintf(pf, "\rFormat should be:" " driver,device\n"); } pl_strcpy(&pl_driver, driver, sizeof(driver)); pl_strcpy(&pl_device, device, sizeof(device)); vs = vidsrc_find(baresip_vidsrcl(), driver); if (!vs) { re_hprintf(pf, "no such video-source: %s\n", driver); return 0; } else if (!list_isempty(&vs->dev_list)) { if (!mediadev_find(&vs->dev_list, device)) { re_hprintf(pf, "no such device for %s video-source: %s\n", driver, device); mediadev_print(pf, &vs->dev_list); return 0; } } re_hprintf(pf, "switch video device: %s,%s\n", driver, device); cfg = conf_config(); if (!cfg) { return re_hprintf(pf, "no config object\n"); } vidcfg = &cfg->video; str_ncpy(vidcfg->src_mod, driver, sizeof(vidcfg->src_mod)); str_ncpy(vidcfg->src_dev, device, sizeof(vidcfg->src_dev)); for (le = list_tail(ua_calls(uag_current())); le; le = le->prev) { struct call *call = le->data; v = call_video(call); err = video_set_source(v, driver, device); if (err) { re_hprintf(pf, "failed to set video-source" " (%m)\n", err); break; } } return 0; } static int call_video_debug(struct re_printf *pf, void *unused) { (void)unused; return video_debug(pf, call_video(ua_call(uag_current()))); } static int set_video_dir(struct re_printf *pf, void *arg) { const struct cmd_arg *carg = arg; int err = 0; if (0 == str_cmp(carg->prm, sdp_dir_name(SDP_INACTIVE))) { err = call_set_video_dir(ua_call(uag_current()), SDP_INACTIVE); } else if (0 == str_cmp(carg->prm, sdp_dir_name(SDP_SENDONLY))) { err = call_set_video_dir(ua_call(uag_current()), SDP_SENDONLY); } else if (0 == str_cmp(carg->prm, sdp_dir_name(SDP_RECVONLY))) { err = call_set_video_dir(ua_call(uag_current()), SDP_RECVONLY); } else if (0 == str_cmp(carg->prm, sdp_dir_name(SDP_SENDRECV))) { err = call_set_video_dir(ua_call(uag_current()), SDP_SENDRECV); } else { (void)re_hprintf(pf, "Invalid video direction %s" " (inactive, sendonly, recvonly, sendrecv)\n", carg->prm); return EINVAL; } return err; } static int digit_handler(struct re_printf *pf, void *arg) { const struct cmd_arg *carg = arg; struct call *call; int err = 0; (void)pf; call = ua_call(uag_current()); if (call) err = call_send_digit(call, carg->key); return err; } static int send_code(struct re_printf *pf, void *arg) { const struct cmd_arg *carg = arg; struct call *call; size_t i; int err = 0; (void)pf; call = ua_call(uag_current()); if (call) { for (i = 0; i < str_len(carg->prm) && !err; i++) { err = call_send_digit(call, carg->prm[i]); } if (!err) { err = call_send_digit(call, KEYCODE_REL); } } return err; } static int toggle_statmode(struct re_printf *pf, void *arg) { (void)pf; (void)arg; if (menu.statmode == STATMODE_OFF) menu.statmode = STATMODE_CALL; else menu.statmode = STATMODE_OFF; return 0; } static int set_current_call(struct re_printf *pf, void *arg) { struct cmd_arg *carg = arg; struct call *call; uint32_t linenum = atoi(carg->prm); int err; call = call_find_linenum(ua_calls(uag_current()), linenum); if (call) { err = re_hprintf(pf, "setting current call: line %u\n", linenum); call_set_current(ua_calls(uag_current()), call); } else { err = re_hprintf(pf, "call not found\n"); } return err; } static int set_audio_bitrate(struct re_printf *pf, void *arg) { struct cmd_arg *carg = arg; struct call *call; uint32_t bitrate = str_isset(carg->prm) ? atoi(carg->prm) : 0; int err; call = ua_call(uag_current()); if (call) { err = re_hprintf(pf, "setting audio bitrate: %u bps\n", bitrate); audio_set_bitrate(call_audio(call), bitrate); } else { err = re_hprintf(pf, "call not found\n"); } return err; } static int cmd_find_call(struct re_printf *pf, void *arg) { struct cmd_arg *carg = arg; const char *id = carg->prm; struct list *calls = ua_calls(uag_current()); struct call *call; int err; call = call_find_id(calls, id); if (call) { err = re_hprintf(pf, "setting current call: %s\n", id); call_set_current(calls, call); } else { err = re_hprintf(pf, "call not found (id=%s)\n", id); } return err; } static const struct cmd callcmdv[] = { {"aubitrate", 0, CMD_PRM, "Set audio bitrate", set_audio_bitrate }, {"audio_debug", 'A', 0, "Audio stream", call_audio_debug }, {"callfind", 0, CMD_PRM, "Find call ", cmd_find_call }, {"hold", 'x', 0, "Call hold", cmd_call_hold }, {"line", '@', CMD_PRM, "Set current call ", set_current_call }, {"mute", 'm', 0, "Call mute/un-mute", call_mute }, {"prevhold", 'H', 0, "Hold previous call", hold_prev_call }, {"prevresume", 'L', 0, "Resume previous call", hold_prev_call }, {"reinvite", 'I', 0, "Send re-INVITE", call_reinvite }, {"resume", 'X', 0, "Call resume", cmd_call_resume }, {"sndcode", 0, CMD_PRM, "Send Code", send_code }, {"statmode", 'S', 0, "Statusmode toggle", toggle_statmode }, {"transfer", 't', CMD_PRM, "Transfer call", call_xfer }, {"video_debug", 'V', 0, "Video stream", call_video_debug }, {"video_dir", 0, CMD_PRM, "Set video direction", set_video_dir }, /* Numeric keypad for DTMF events: */ {NULL, '#', 0, NULL, digit_handler }, {NULL, '*', 0, NULL, digit_handler }, {NULL, '0', 0, NULL, digit_handler }, {NULL, '1', 0, NULL, digit_handler }, {NULL, '2', 0, NULL, digit_handler }, {NULL, '3', 0, NULL, digit_handler }, {NULL, '4', 0, NULL, digit_handler }, {NULL, '5', 0, NULL, digit_handler }, {NULL, '6', 0, NULL, digit_handler }, {NULL, '7', 0, NULL, digit_handler }, {NULL, '8', 0, NULL, digit_handler }, {NULL, '9', 0, NULL, digit_handler }, {NULL, KEYCODE_REL, 0, NULL, digit_handler }, }; static int menu_set_incall(bool incall) { struct commands *commands = baresip_commands(); int err = 0; /* Dynamic menus */ if (incall) { cmd_unregister(commands, dialcmdv); if (!cmds_find(commands, callcmdv)) { err = cmd_register(commands, callcmdv, ARRAY_SIZE(callcmdv)); } } else { cmd_unregister(commands, callcmdv); if (!cmds_find(commands, dialcmdv)) { err = cmd_register(baresip_commands(), dialcmdv, ARRAY_SIZE(dialcmdv)); } } if (err) { warning("menu: set_incall: cmd_register failed (%m)\n", err); } return err; } static void tmrstat_handler(void *arg) { struct call *call; (void)arg; /* the UI will only show the current active call */ call = ua_call(uag_current()); if (!call) return; tmr_start(&menu.tmr_stat, 100, tmrstat_handler, 0); if (ui_isediting(baresip_uis())) return; if (STATMODE_OFF != menu.statmode) { (void)re_fprintf(stderr, "%H\r", call_status, call); } } static void update_callstatus(void) { /* if there are any active calls, enable the call status view */ if (have_active_calls()) tmr_start(&menu.tmr_stat, 100, tmrstat_handler, 0); else tmr_cancel(&menu.tmr_stat); } static void alert_start(void *arg) { (void)arg; if (!menu.bell) return; ui_output(baresip_uis(), "\033[10;1000]\033[11;1000]\a"); tmr_start(&menu.tmr_alert, 1000, alert_start, NULL); } static void alert_stop(void) { if (!menu.bell) return; if (tmr_isrunning(&menu.tmr_alert)) ui_output(baresip_uis(), "\r"); tmr_cancel(&menu.tmr_alert); } static void redial_handler(void *arg) { char *uri = NULL; int err; (void)arg; info("now: redialing now. current_attempts=%u, max_attempts=%u\n", menu.current_attempts, menu.redial_attempts); if (menu.current_attempts > menu.redial_attempts) { info("menu: redial: too many attemptes -- giving up\n"); return; } if (menu.dialbuf->end == 0) { warning("menu: redial: dialbuf is empty\n"); return; } menu.dialbuf->pos = 0; err = mbuf_strdup(menu.dialbuf, &uri, menu.dialbuf->end); if (err) return; err = ua_connect(uag_find_aor(menu.redial_aor), NULL, NULL, uri, VIDMODE_ON); if (err) { warning("menu: redial: ua_connect failed (%m)\n", err); } mem_deref(uri); } static void ua_event_handler(struct ua *ua, enum ua_event ev, struct call *call, const char *prm, void *arg) { struct player *player = baresip_player(); struct call *call2 = NULL; struct config *cfg; int err; (void)prm; (void)arg; #if 0 debug("menu: [ ua=%s call=%s ] event: %s (%s)\n", ua_aor(ua), call_id(call), uag_event_str(ev), prm); #endif cfg = conf_config(); switch (ev) { case UA_EVENT_CALL_INCOMING: /* set the current User-Agent to the one with the call */ uag_current_set(ua); info("%s: Incoming call from: %s %s -" " (press 'a' to accept)\n", ua_aor(ua), call_peername(call), call_peeruri(call)); /* stop any ringtones */ menu.play = mem_deref(menu.play); /* Only play the ringtones if answermode is "Manual". * If the answermode is "auto" then be silent. */ if (ANSWERMODE_MANUAL == account_answermode(ua_account(ua))) { if (list_count(ua_calls(ua)) > 1) { (void)play_file(&menu.play, player, "callwaiting.wav", 3, cfg->audio.play_mod, cfg->audio.play_dev); } else { /* Alert user */ (void)play_file(&menu.play, player, "ring.wav", -1, cfg->audio.alert_mod, cfg->audio.alert_dev); } if (menu.bell) alert_start(0); } break; case UA_EVENT_CALL_RINGING: /* stop any ringtones */ menu.play = mem_deref(menu.play); if (menu.ringback_disabled) { info("\nRingback disabled\n"); } else { (void)play_file(&menu.play, player, "ringback.wav", -1, cfg->audio.play_mod, cfg->audio.play_dev); } break; case UA_EVENT_CALL_ESTABLISHED: /* stop any ringtones */ menu.play = mem_deref(menu.play); alert_stop(); /* We must stop the re-dialing if the call was established */ redial_reset(); break; case UA_EVENT_CALL_CLOSED: /* stop any ringtones */ menu.play = mem_deref(menu.play); if (call_scode(call)) { const char *tone; tone = translate_errorcode(call_scode(call)); if (tone) { (void)play_file(&menu.play, player, tone, 1, cfg->audio.play_mod, cfg->audio.play_dev); } } alert_stop(); /* Activate the re-dialing if: * * - redial_attempts must be enabled in config * - the closed call must be of outgoing direction * - the closed call must fail with special code 701 */ if (menu.redial_attempts) { if (menu.current_attempts || (call_is_outgoing(call) && call_scode(call) == 701)) { info("menu: call closed" " -- redialing in %u seconds\n", menu.redial_delay); ++menu.current_attempts; str_ncpy(menu.redial_aor, ua_aor(ua), sizeof(menu.redial_aor)); tmr_start(&menu.tmr_redial, menu.redial_delay*1000, redial_handler, NULL); } else { info("menu: call closed -- not redialing\n"); } } break; case UA_EVENT_CALL_TRANSFER: /* * Create a new call to transfer target. * * NOTE: we will automatically connect a new call to the * transfer target */ info("menu: transferring call %s to '%s'\n", call_id(call), prm); err = ua_call_alloc(&call2, ua, VIDMODE_ON, NULL, call, call_localuri(call), true); if (!err) { struct pl pl; pl_set_str(&pl, prm); err = call_connect(call2, &pl); if (err) { warning("ua: transfer: connect error: %m\n", err); } } if (err) { (void)call_notify_sipfrag(call, 500, "Call Error"); mem_deref(call2); } break; case UA_EVENT_CALL_TRANSFER_FAILED: info("menu: transfer failure: %s\n", prm); break; case UA_EVENT_REGISTER_OK: check_registrations(); break; case UA_EVENT_UNREGISTERING: return; case UA_EVENT_MWI_NOTIFY: info("----- MWI for %s -----\n", ua_aor(ua)); info("%s\n", prm); break; case UA_EVENT_AUDIO_ERROR: info("menu: audio error (%s)\n", prm); break; default: break; } menu_set_incall(have_active_calls()); update_callstatus(); } static void message_handler(struct ua *ua, const struct pl *peer, const struct pl *ctype, struct mbuf *body, void *arg) { struct config *cfg; (void)ua; (void)ctype; (void)arg; cfg = conf_config(); ui_output(baresip_uis(), "\r%r: \"%b\"\n", peer, mbuf_buf(body), mbuf_get_left(body)); (void)play_file(NULL, baresip_player(), "message.wav", 0, cfg->audio.alert_mod, cfg->audio.alert_dev); } static int module_init(void) { struct pl val; int err; menu.bell = true; menu.redial_attempts = 0; menu.redial_delay = 5; menu.ringback_disabled = false; menu.statmode = STATMODE_CALL; menu.clean_number = false; /* * Read the config values */ conf_get_bool(conf_cur(), "menu_bell", &menu.bell); conf_get_bool(conf_cur(), "ringback_disabled", &menu.ringback_disabled); conf_get_bool(conf_cur(), "menu_clean_number", &menu.clean_number); if (0 == conf_get(conf_cur(), "redial_attempts", &val) && 0 == pl_strcasecmp(&val, "inf")) { menu.redial_attempts = (uint32_t)-1; } else { conf_get_u32(conf_cur(), "redial_attempts", &menu.redial_attempts); } conf_get_u32(conf_cur(), "redial_delay", &menu.redial_delay); if (menu.redial_attempts) { info("menu: redial enabled with %u attempts and" " %u seconds delay\n", menu.redial_attempts, menu.redial_delay); } menu.dialbuf = mbuf_alloc(64); if (!menu.dialbuf) return ENOMEM; menu.start_ticks = tmr_jiffies(); tmr_init(&menu.tmr_alert); if (0 == conf_get(conf_cur(), "statmode_default", &val) && 0 == pl_strcasecmp(&val, "off")) { menu.statmode = STATMODE_OFF; } else { menu.statmode = STATMODE_CALL; } err = cmd_register(baresip_commands(), cmdv, ARRAY_SIZE(cmdv)); err |= cmd_register(baresip_commands(), dialcmdv, ARRAY_SIZE(dialcmdv)); if (err) return err; err = uag_event_register(ua_event_handler, NULL); if (err) return err; err = message_listen(baresip_message(), message_handler, NULL); if (err) return err; return err; } static int module_close(void) { debug("menu: close (redial current_attempts=%d)\n", menu.current_attempts); message_unlisten(baresip_message(), message_handler); uag_event_unregister(ua_event_handler); cmd_unregister(baresip_commands(), cmdv); cmd_unregister(baresip_commands(), dialcmdv); cmd_unregister(baresip_commands(), callcmdv); tmr_cancel(&menu.tmr_alert); tmr_cancel(&menu.tmr_stat); menu.dialbuf = mem_deref(menu.dialbuf); menu.le_cur = NULL; menu.play = mem_deref(menu.play); tmr_cancel(&menu.tmr_redial); return 0; } const struct mod_export DECL_EXPORTS(menu) = { "menu", "application", module_init, module_close }; baresip-1.0.0/modules/menu/module.mk000066400000000000000000000001521372575704200174010ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # MOD := menu $(MOD)_SRCS += menu.c include mk/mod.mk baresip-1.0.0/modules/mpa/000077500000000000000000000000001372575704200153765ustar00rootroot00000000000000baresip-1.0.0/modules/mpa/decode.c000066400000000000000000000110631372575704200167660ustar00rootroot00000000000000/** * @file mpa/decode.c mpa Decode * * Copyright (C) 2016 Symonics GmbH */ #include #include #include #include #include #include #include "mpa.h" struct audec_state { mpg123_handle *dec; SpeexResamplerState *resampler; int channels; int16_t intermediate_buffer[MPA_FRAMESIZE*2]; int start; }; static void destructor(void *arg) { struct audec_state *ads = arg; if (ads->resampler) speex_resampler_destroy(ads->resampler); mpg123_close(ads->dec); mpg123_delete(ads->dec); #ifdef DEBUG debug("MPA dec destroyed\n"); #endif } int mpa_decode_update(struct audec_state **adsp, const struct aucodec *ac, const char *fmtp) { struct audec_state *ads; int result, err=0; (void)fmtp; if (!adsp || !ac || !ac->ch) return EINVAL; ads = *adsp; #ifdef DEBUG debug("MPA dec created %s\n",fmtp); #endif if (!ads) { ads = mem_zalloc(sizeof(*ads), destructor); if (!ads) return ENOMEM; } else { memset(ads,0,sizeof(*ads)); } ads->channels = 0; ads->resampler = NULL; ads->start = 0; ads->dec = mpg123_new(NULL,&result); if (!ads->dec) { warning("MPA dec create: %s\n", mpg123_plain_strerror(result)); err = ENOMEM; goto out; } #ifdef DEBUG result = mpg123_param(ads->dec, MPG123_VERBOSE, 4, 4.); #else result = mpg123_param(ads->dec, MPG123_VERBOSE, 0, 0.); #endif if (result != MPG123_OK) { warning("MPA dec param error %s\n", mpg123_plain_strerror(result)); err = EINVAL; goto out; } result = mpg123_format_all(ads->dec); if (result != MPG123_OK) { warning("MPA dec format error %s\n", mpg123_plain_strerror(result)); err = EINVAL; goto out; } result = mpg123_open_feed(ads->dec); if (result != MPG123_OK) { warning("MPA dec open feed error %s\n", mpg123_plain_strerror(result)); err = EINVAL; goto out; } out: if (err) mem_deref(ads); else *adsp = ads; return err; } int mpa_decode_frm(struct audec_state *ads, int fmt, void *sampv_void, size_t *sampc, bool marker, const uint8_t *buf, size_t len) { int result, channels, encoding, i; long samplerate; size_t n; spx_uint32_t intermediate_len; spx_uint32_t out_len; int16_t *sampv = sampv_void; (void)marker; #ifdef DEBUG debug("MPA dec start %d %ld\n",len, *sampc); #endif if (!ads || !sampv || !sampc || !buf || len<=4) return EINVAL; if (*(uint32_t*)(void *)buf != 0) { warning("MPA dec header is not zero %08X, not supported yet\n", *(uint32_t*)(void *)buf); return EPROTO; } if (fmt != AUFMT_S16LE) return ENOTSUP; n = 0; result = mpg123_decode(ads->dec, buf+4, len-4, (unsigned char*)ads->intermediate_buffer, sizeof(ads->intermediate_buffer), &n); /* n counts bytes */ #ifdef DEBUG debug("MPA dec %d %d %d %d\n",result, len-4, n, ads->channels); #endif if (result == MPG123_NEW_FORMAT) { mpg123_getformat(ads->dec, &samplerate, &channels, &encoding); info("MPA dec format change %d %d %04X\n",samplerate ,channels,encoding); ads->channels = channels; ads->start = 0; if (ads->resampler) speex_resampler_destroy(ads->resampler); if (samplerate != MPA_IORATE) { ads->resampler = speex_resampler_init(channels, (uint32_t)samplerate, MPA_IORATE, 3, &result); if (result!=RESAMPLER_ERR_SUCCESS || ads->resampler==NULL) { warning("MPA dec upsampler failed %d\n", result); return EINVAL; } } else ads->resampler = NULL; } else if (result == MPG123_NEED_MORE) ; /* workaround: do nothing */ else if (result != MPG123_OK) { warning("MPA dec feed error %d %s\n", result, mpg123_plain_strerror(result)); return EPROTO; } if (ads->resampler) { intermediate_len = (uint32_t)(n / 2 / ads->channels); /* intermediate_len counts samples per channel */ out_len = (uint32_t)(*sampc / 2); result=speex_resampler_process_interleaved_int( ads->resampler, ads->intermediate_buffer, &intermediate_len, sampv, &out_len); if (result!=RESAMPLER_ERR_SUCCESS) { warning("MPA dec upsample error: %s %d %d\n", strerror(result), out_len, *sampc/2); return EPROTO; } if (ads->channels==1) { for (i=out_len-1;i>=0;i--) sampv[i+i+1]=sampv[i+i]=sampv[i]; *sampc = out_len * 2; } else *sampc = out_len * ads->channels; } else { n /= 2; if (ads->channels!=1) { for (i=0;(unsigned)iintermediate_buffer[i]; *sampc = n; } else { for (i=0;(unsigned)iintermediate_buffer[i]; *sampc = n * 2; } #ifdef DEBUG debug("MPA dec done %d\n",*sampc); #endif } return 0; } baresip-1.0.0/modules/mpa/encode.c000066400000000000000000000132501372575704200170000ustar00rootroot00000000000000/** * @file mpa/encode.c mpa Encode * * Copyright (C) 2016 Symonics GmbH */ #include #include #include #include #include #include #include #include "mpa.h" struct auenc_state { twolame_options *enc2; lame_global_flags *enc3; int channels, samplerate; SpeexResamplerState *resampler; int16_t intermediate_buffer[MPA_FRAMESIZE*6]; }; static void destructor(void *arg) { struct auenc_state *aes = arg; if (aes->resampler) { speex_resampler_destroy(aes->resampler); aes->resampler = NULL; } if (aes->enc2) twolame_close(&aes->enc2); if (aes->enc3) lame_close(aes->enc3); #ifdef DEBUG debug("MPA enc destroyed\n"); #endif } int mpa_encode_update(struct auenc_state **aesp, const struct aucodec *ac, struct auenc_param *param, const char *fmtp) { struct auenc_state *aes; struct mpa_param prm; int result,err=0; (void)param; if (!aesp || !ac || !ac->ch) return EINVAL; debug("mpa: encoder fmtp (%s)\n", fmtp); /* Save the incoming MPA parameters from SDP offer */ if (str_isset(fmtp)) { mpa_mirror_params(fmtp); } aes = *aesp; if (!aes) { aes = mem_zalloc(sizeof(*aes), destructor); if (!aes) return ENOMEM; } else memset(aes,0,sizeof(*aes)); prm.samplerate = 48000; prm.bitrate = 64000; prm.layer = 2; prm.mode = MONO; mpa_decode_fmtp(&prm, fmtp); if (prm.layer == 2) aes->enc2 = twolame_init(); if (prm.layer == 3) aes->enc3 = lame_init(); if (!aes->enc2 && !aes->enc3) { warning("MPA enc create failed\n"); mem_deref(aes); return ENOMEM; } #ifdef DEBUG debug("MPA enc created %s\n", fmtp); #endif aes->channels = ac->ch; aes->samplerate = prm.samplerate; result = 0; if (aes->enc2) { #ifdef DEBUG result |= twolame_set_verbosity(aes->enc2, 5); #else result |= twolame_set_verbosity(aes->enc2, 0); #endif result |= twolame_set_mode(aes->enc2, prm.mode); result |= twolame_set_version(aes->enc2, prm.samplerate < 32000 ? TWOLAME_MPEG2 : TWOLAME_MPEG1); result |= twolame_set_bitrate(aes->enc2, prm.bitrate/1000); result |= twolame_set_in_samplerate(aes->enc2, prm.samplerate); result |= twolame_set_out_samplerate(aes->enc2, prm.samplerate); result |= twolame_set_num_channels(aes->enc2, 2); } if (aes->enc3) { result |= lame_set_mode(aes->enc3, prm.mode); result |= lame_set_brate(aes->enc3, prm.bitrate/1000); result |= lame_set_in_samplerate(aes->enc3, prm.samplerate); result |= lame_set_out_samplerate(aes->enc3, prm.samplerate); result |= lame_set_num_channels(aes->enc3, 2); result |= lame_set_VBR(aes->enc3, vbr_off); result |= lame_set_bWriteVbrTag(aes->enc3, 0); result |= lame_set_strict_ISO(aes->enc3, 1); result |= lame_set_disable_reservoir(aes->enc3, 1); } if (result!=0) { warning("MPA enc set failed\n"); err=EINVAL; goto out; } if (aes->enc2) result = twolame_init_params(aes->enc2); if (aes->enc3) result = lame_init_params(aes->enc3); if (result!=0) { warning("MPA enc init params failed\n"); err=EINVAL; goto out; } #ifdef DEBUG if (aes->enc2) twolame_print_config(aes->enc2); if (aes->enc3) lame_print_config(aes->enc3); #endif if (prm.samplerate != MPA_IORATE) { aes->resampler = speex_resampler_init(2, MPA_IORATE, prm.samplerate, 3, &result); if (result!=RESAMPLER_ERR_SUCCESS) { warning("MPA enc resampler init failed %d\n",result); err=EINVAL; goto out; } } else aes->resampler = NULL; out: if (err) mem_deref(aes); else *aesp = aes; return err; } int mpa_encode_frm(struct auenc_state *aes, bool *marker, uint8_t *buf, size_t *len, int fmt, const void *sampv, size_t sampc) { int n = 0; spx_uint32_t intermediate_len,in_len; uint32_t ts_delta = 0; (void)marker; if (!aes || !buf || !len || !sampv) return EINVAL; if (fmt != AUFMT_S16LE) return ENOTSUP; if (aes->resampler) { in_len = (uint32_t)sampc/2; intermediate_len = sizeof(aes->intermediate_buffer) / sizeof(aes->intermediate_buffer[0]); n=speex_resampler_process_interleaved_int(aes->resampler, sampv, &in_len, aes->intermediate_buffer, &intermediate_len); if (n!=RESAMPLER_ERR_SUCCESS || in_len != sampc/2) { warning("MPA enc downsample error: %s %d %d\n", strerror(n), in_len, sampc/2); return EPROTO; } if (aes->enc2) { n = twolame_encode_buffer_interleaved(aes->enc2, aes->intermediate_buffer, intermediate_len, buf+4, (int)(*len)-4); #ifdef DEBUG debug("MPA enc %d %d %d %d %d %p\n",intermediate_len, sampc,aes->channels,*len,n,aes->enc2); #endif } if (aes->enc3) { n = lame_encode_buffer_interleaved(aes->enc3, aes->intermediate_buffer, intermediate_len, buf+4, (int)(*len)-4); #ifdef DEBUG debug("MPA enc %d %d %d %d %d %p\n",intermediate_len, sampc,aes->channels,*len,n,aes->enc3); #endif } } else { if (aes->enc2) n = twolame_encode_buffer_interleaved(aes->enc2, sampv, (int)(sampc/2), buf+4, (int)(*len)-4); if (aes->enc3) n = lame_encode_buffer_interleaved(aes->enc3, (int16_t *)sampv, (int)(sampc/2), buf+4, (int)(*len)-4); #ifdef DEBUG debug("MPA enc %d %d %d %d\n",sampc, aes->channels,*len,n); #endif } if (n < 0) { warning("MPA enc error %s\n", strerror((int)n)); return EPROTO; } if (n > 0) { *(uint32_t*)(void *)buf = 0; *len = n+4; ts_delta = ((MPA_FRAMESIZE*MPA_RTPRATE)<<4) / aes->samplerate; } else *len = 0; #ifdef DEBUG if (aes->enc2) debug("MPA enc done %d %d %d %d %p\n",sampc,aes->channels, *len,n,aes->enc2); if (aes->enc3) debug("MPA enc done %d %d %d %d %p\n",sampc,aes->channels, *len,n,aes->enc3); #endif return 0x00010000 | ((ts_delta>>4) & 0x0000ffff); } baresip-1.0.0/modules/mpa/module.mk000066400000000000000000000003541372575704200172160ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2016 Symonics GmbH # MOD := mpa $(MOD)_SRCS += mpa.c $(MOD)_SRCS += decode.c $(MOD)_SRCS += sdp.c $(MOD)_SRCS += encode.c $(MOD)_LFLAGS += -ltwolame -lmp3lame -lmpg123 -lspeexdsp -lm include mk/mod.mk baresip-1.0.0/modules/mpa/mpa.c000066400000000000000000000125201372575704200163170ustar00rootroot00000000000000/** * @file mpa.c mpa Audio Codec * * Copyright (C) 2016 Symonics GmbH */ #include #include #include #include #include "mpa.h" #include /** * @defgroup mpa mpa * * The mpa audio codec * * Supported version: * libmpg123 1.16.0 or later * libtwolame 0.3.13 or later * libmp3lame 3.100 or later * * References: * * RFC 2250 RTP Payload Format for the mpa Speech and Audio Codec * */ /* 4.1.17. Registration of MIME media type audio/MPA MIME media type name: audio MIME subtype name: MPA (MPEG audio) Required parameters: None Optional parameters: layer: which layer of MPEG audio encoding; permissible values are 1, 2, 3. samplerate: the rate at which audio is sampled. MPEG-1 audio supports sampling rates of 32, 44.1, and 48 kHz; MPEG-2 supports sampling rates of 16, 22.05 and 24 kHz. This parameter is separate from the RTP timestamp clock rate which is always 90000 Hz for MPA. mode: permissible values are "stereo", "joint_stereo", "single_channel", "dual_channel". The "channels" parameter does not apply to MPA. It is undefined to put a number of channels in the SDP rtpmap attribute for MPA. bitrate: the data rate for the audio bit stream. ptime: RECOMMENDED duration of each packet in milliseconds. maxptime: maximum duration of each packet in milliseconds. Parameters which are omitted are left to the encoder to choose based on the session bandwidth, configuration information, or other constraints. The selected layer as well as the sampling rate and mode are indicated in the payload so receivers can process the data without these parameters being specified externally. Encoding considerations: This type is only defined for transfer via RTP [RFC 3550]. Security considerations: See Section 5 of RFC 3555 Interoperability considerations: none Published specification: RFC 3551 Applications which use this media type: Audio and video streaming and conferencing tools. */ static bool mpa_mirror; static char fmtp[256] = ""; static char fmtp_mirror[256]; static int mpa_fmtp_enc(struct mbuf *mb, const struct sdp_format *fmt, bool offer, void *arg) { bool mirror; (void)arg; (void)offer; if (!mb || !fmt) return 0; mirror = !offer && str_isset(fmtp_mirror); return mbuf_printf(mb, "a=fmtp:%s %s\r\n", fmt->id, mirror ? fmtp_mirror : fmtp); } static struct aucodec mpa = { .pt = "14", .name = "MPA", .srate = MPA_IORATE, .crate = MPA_RTPRATE, .ch = 2, .pch = 1, /* MPA does not expect channels count, even those it is stereo */ .fmtp = "layer=2", .encupdh = mpa_encode_update, .ench = mpa_encode_frm, .decupdh = mpa_decode_update, .dech = mpa_decode_frm, }; void mpa_mirror_params(const char *x) { if (!mpa_mirror) return; info("mpa: mirror parameters: \"%s\"\n", x); str_ncpy(fmtp_mirror, x, sizeof(fmtp_mirror)); } static int module_init(void) { struct conf *conf = conf_cur(); uint32_t value; static char mode[30]; int res; /** generate fmtp string based on config file */ str_ncpy(mode, mpa.fmtp, sizeof(mode)); if (0 == conf_get_u32(conf, "mpa_layer", &value)) { if (value<2 || value>3) { warning("MPA layer 2 or 3 are allowed."); return EINVAL; } (void)re_snprintf(fmtp+strlen(fmtp), sizeof(fmtp)-strlen(fmtp), "layer=%d", value); } if (0 == conf_get_u32(conf, "mpa_samplerate", &value)) { switch (value) { case 32000: case 44100: case 48000: case 16000: case 22050: case 24000: break; default: warning("MPA samplerates of 16, 22.05, 24, 32," " 44.1, and 48 kHz are allowed.\n"); return EINVAL; } (void)re_snprintf(fmtp+strlen(fmtp), sizeof(fmtp)-strlen(fmtp), ";samplerate=%d", value); } if (0 == conf_get_u32(conf, "mpa_bitrate", &value)) { if (value<8000 || value>384000) { warning("MPA bitrate between 8000 and " "384000 are allowed.\n"); return EINVAL; } (void)re_snprintf(fmtp+strlen(fmtp), sizeof(fmtp)-strlen(fmtp), ";bitrate=%d", value); } if (0 == conf_get_str(conf, "mpa_mode", mode, sizeof(mode))) { char *p = mode; while (*p) { *p = tolower(*p); ++p; } if (strcmp(mode,"stereo") && strcmp(mode,"joint_stereo") && strcmp(mode,"single_channel") && strcmp(mode,"dual_channel")) { warning("MPA mode: Permissible values are stereo, " "joint_stereo, single_channel, dual_channel.\n"); return EINVAL; } (void)re_snprintf(fmtp+strlen(fmtp), sizeof(fmtp)-strlen(fmtp), ";mode=%s", mode); } if (fmtp[0]==';') mpa.fmtp = fmtp+1; else mpa.fmtp = fmtp; (void)conf_get_bool(conf, "mpa_mirror", &mpa_mirror); if (mpa_mirror) { mpa.fmtp = NULL; mpa.fmtp_ench = mpa_fmtp_enc; } /* init decoder library */ res = mpg123_init(); if (res != MPG123_OK) { warning("MPA libmpg123 init error %s\n", mpg123_plain_strerror(res)); return ENODEV; } aucodec_register(baresip_aucodecl(), &mpa); #ifdef DEBUG info("MPA init with %s\n",mpa.fmtp); #endif return 0; } static int module_close(void) { aucodec_unregister(&mpa); mpg123_exit(); return 0; } EXPORT_SYM const struct mod_export DECL_EXPORTS(mpa) = { "MPA", "audio codec", module_init, module_close, }; baresip-1.0.0/modules/mpa/mpa.h000066400000000000000000000017301372575704200163250ustar00rootroot00000000000000/** * @file mpa.h Private mpa Interface * * Copyright (C) 2016 Symonics GmbH */ #define MPA_FRAMESIZE 1152 #define MPA_IORATE 48000 #define MPA_RTPRATE 90000 #define BARESIP_FRAMESIZE (MPA_IORATE/50*2) #undef DEBUG struct mpa_param { unsigned samplerate; unsigned bitrate; unsigned layer; int mode; /* MPEG_mode */ }; /* Encode */ int mpa_encode_update(struct auenc_state **aesp, const struct aucodec *ac, struct auenc_param *prm, const char *fmtp); int mpa_encode_frm(struct auenc_state *aes, bool *marker, uint8_t *buf, size_t *len, int fmt, const void *sampv, size_t sampc); /* Decode */ int mpa_decode_update(struct audec_state **adsp, const struct aucodec *ac, const char *fmtp); int mpa_decode_frm(struct audec_state *ads, int fmt, void *sampv, size_t *sampc, bool marker, const uint8_t *buf, size_t len); /* SDP */ void mpa_decode_fmtp(struct mpa_param *prm, const char *fmtp); void mpa_mirror_params(const char *fmtp); baresip-1.0.0/modules/mpa/sdp.c000066400000000000000000000021631372575704200163320ustar00rootroot00000000000000/** * @file mpa/sdp.c mpa SDP Functions * * Copyright (C) 2016 Symonics GmbH */ #include #include #include #include #include #include "mpa.h" static void assign_if (uint32_t *v, const struct pl *pl, uint32_t min, uint32_t max) { const uint32_t val = pl_u32(pl); if (val < min || val > max) return; *v = val; } void mpa_decode_fmtp(struct mpa_param *prm, const char *fmtp) { struct pl pl, val; if (!prm || !fmtp) return; pl_set_str(&pl, fmtp); if (fmt_param_get(&pl, "bitrate", &val)) assign_if (&prm->bitrate, &val, 32000, 384000); if (fmt_param_get(&pl, "samplerate", &val)) assign_if (&prm->samplerate, &val, 32000, 48000); if (fmt_param_get(&pl, "layer", &val)) assign_if (&prm->layer, &val, 2, 3); if (fmt_param_get(&pl, "mode", &val)) { if (!strncmp("stereo",val.p,val.l)) prm->mode = STEREO; else if (!strncmp("joint_stereo",val.p,val.l)) prm->mode = JOINT_STEREO; else if (!strncmp("dual_channel",val.p,val.l)) prm->mode = DUAL_CHANNEL; else if (!strncmp("single_channel",val.p,val.l)) prm->mode = MONO; } } baresip-1.0.0/modules/mqtt/000077500000000000000000000000001372575704200156065ustar00rootroot00000000000000baresip-1.0.0/modules/mqtt/README.md000066400000000000000000000040641372575704200170710ustar00rootroot00000000000000README ------ This module implements an MQTT (Message Queue Telemetry Transport) client for publishing and subscribing to topics. The module is using libmosquitto. All messages are encoded in JSON format. Starting the MQTT broker: ``` $ /usr/local/sbin/mosquitto -v ``` Subscribing to all topics: ``` $ mosquitto_sub -v -t /baresip/# ``` Publishing to the topic: ``` $ mosquitto_pub -t /baresip/xxx -m foo=42 ``` ## Topic patterns (Outgoing direction is from baresip mqtt module to broker, incoming direction is from broker to baresip mqtt module) * /baresip/event Outgoing events from ua_event * /baresip/command Incoming long command request * /baresip/command_resp Outgoing long command response ## Examples ``` /baresip/event {"type":"REGISTERING","class":"register","accountaor":"sip:aeh@iptel.org"} /baresip/event {"type":"REGISTER_OK","class":"register","accountaor":"sip:aeh@iptel.org","param":"200 OK"} /baresip/event {"type":"SHUTDOWN","class":"application","accountaor":"sip:aeh@iptel.org"} ``` ``` mosquitto_pub -t /baresip/command/ -m '{"command":"sysinfo"}' /baresip/command {"command":"dial","params":"music","token":"123"} /baresip/command_resp/123 (null) ``` ## Outgoing call ``` /baresip/event {"type":"CALL_ESTABLISHED","class":"call","accountaor":"sip:aeh@iptel.org","direction":"outgoing","peeruri":"sip:music@iptel.org","id":"4d758140c42c5d55","param":"sip:music@iptel.org"} /baresip/event {"type":"CALL_CLOSED","class":"call","accountaor":"sip:aeh@iptel.org","direction":"outgoing","peeruri":"sip:music@iptel.org","id":"4d758140c42c5d55","param":"Connection reset by user"} ``` ## Incoming call ``` /baresip/event {"type":"CALL_ESTABLISHED","class":"call","accountaor":"sip:aeh@iptel.org","direction":"incoming","peeruri":"sip:music@iptel.org", "peerdisplayname":"MUSIC IP-TEL", "id":"4d758140c42c5d55","param":"sip:aeh@iptel.org"} /baresip/event {"type":"CALL_CLOSED","class":"call","accountaor":"sip:aeh@iptel.org","direction":"outgoing","peeruri":"sip:music@iptel.org","id":"4d758140c42c5d55","param":"Connection reset by user"} ``` baresip-1.0.0/modules/mqtt/module.mk000066400000000000000000000003201372575704200174170ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # MOD := mqtt $(MOD)_SRCS += mqtt.c $(MOD)_SRCS += publish.c $(MOD)_SRCS += subscribe.c $(MOD)_LFLAGS += -lmosquitto $(MOD)_CFLAGS += include mk/mod.mk baresip-1.0.0/modules/mqtt/mqtt.c000066400000000000000000000104551372575704200167440ustar00rootroot00000000000000/** * @file mqtt.c Message Queue Telemetry Transport (MQTT) client * * Copyright (C) 2017 Creytiv.com */ #include #include #include #include "mqtt.h" static char broker_host[256] = "127.0.0.1"; /* Authentication user name, default none */ static char mqttusername[256] = ""; /* Authentication password, default none */ static char mqttpassword[256] = ""; /* Client ID - default "baresip" */ static char mqttclientid[256] = "baresip"; /* Base topic for MQTT - default "baresip" - i.e. /baresip/event */ static char mqttbasetopic[128] = "baresip"; static char mqttpublishtopic[256]; static char mqttsubscribetopic[256]; static uint32_t broker_port = 1883; static struct mqtt s_mqtt; static void fd_handler(int flags, void *arg) { struct mqtt *mqtt = arg; (void)flags; mosquitto_loop_read(mqtt->mosq, 1); mosquitto_loop_write(mqtt->mosq, 1); } static void tmr_handler(void *data) { struct mqtt *mqtt = data; int ret; tmr_start(&mqtt->tmr, 500, tmr_handler, mqtt); ret = mosquitto_loop_misc(mqtt->mosq); if (ret != MOSQ_ERR_SUCCESS) { warning("mqtt: error in loop (%s)\n", mosquitto_strerror(ret)); } } /* * This is called when the broker sends a CONNACK message * in response to a connection. */ static void connect_callback(struct mosquitto *mosq, void *obj, int result) { struct mqtt *mqtt = obj; int err; (void)mosq; if (result != MOSQ_ERR_SUCCESS) { warning("mqtt: could not connect to broker (%s) \n", mosquitto_strerror(result)); return; } info("mqtt: connected to broker at %s:%d\n", broker_host, broker_port); err = mqtt_subscribe_start(mqtt); if (err) { warning("mqtt: subscribe_init failed (%m)\n", err); } } static int module_init(void) { const int keepalive = 60; int ret; int err = 0; tmr_init(&s_mqtt.tmr); mosquitto_lib_init(); /* Get configuration data */ conf_get_str(conf_cur(), "mqtt_broker_host", broker_host, sizeof(broker_host)); conf_get_str(conf_cur(), "mqtt_broker_user", mqttusername, sizeof(mqttusername)); conf_get_str(conf_cur(), "mqtt_broker_password", mqttpassword, sizeof(mqttpassword)); conf_get_str(conf_cur(), "mqtt_broker_clientid", mqttclientid, sizeof(mqttclientid)); conf_get_str(conf_cur(), "mqtt_basetopic", mqttbasetopic, sizeof(mqttbasetopic)); info("mqtt: connecting to broker at %s:%d as %s topic %s\n", broker_host, broker_port, mqttclientid, mqttbasetopic); re_snprintf(mqttsubscribetopic, sizeof(mqttsubscribetopic), "/%s/command/+", mqttbasetopic); re_snprintf(mqttpublishtopic, sizeof(mqttpublishtopic), "/%s/event", mqttbasetopic); info("mqtt: Publishing on %s, subscribing to %s\n", mqttpublishtopic, mqttsubscribetopic); s_mqtt.basetopic = mqttbasetopic; s_mqtt.subtopic = mqttsubscribetopic; s_mqtt.pubtopic = mqttpublishtopic; conf_get_u32(conf_cur(), "mqtt_broker_port", &broker_port); s_mqtt.mosq = mosquitto_new(mqttclientid, true, &s_mqtt); if (!s_mqtt.mosq) { warning("mqtt: failed to create client instance\n"); return ENOMEM; } err = mqtt_subscribe_init(&s_mqtt); if (err) return err; mosquitto_connect_callback_set(s_mqtt.mosq, connect_callback); if (*mqttusername != '\0') { ret = mosquitto_username_pw_set(s_mqtt.mosq, mqttusername, mqttpassword); if (ret != MOSQ_ERR_SUCCESS) return ret == MOSQ_ERR_ERRNO ? errno : EIO; } ret = mosquitto_connect(s_mqtt.mosq, broker_host, broker_port, keepalive); if (ret != MOSQ_ERR_SUCCESS) { err = ret == MOSQ_ERR_ERRNO ? errno : EIO; warning("mqtt: failed to connect to %s:%d (%s)\n", broker_host, broker_port, mosquitto_strerror(ret)); return err; } tmr_start(&s_mqtt.tmr, 1, tmr_handler, &s_mqtt); err = mqtt_publish_init(&s_mqtt); if (err) return err; s_mqtt.fd = mosquitto_socket(s_mqtt.mosq); err = fd_listen(s_mqtt.fd, FD_READ, fd_handler, &s_mqtt); if (err) return err; info("mqtt: module loaded\n"); return err; } static int module_close(void) { fd_close(s_mqtt.fd); mqtt_publish_close(); mqtt_subscribe_close(); tmr_cancel(&s_mqtt.tmr); if (s_mqtt.mosq) { mosquitto_disconnect(s_mqtt.mosq); mosquitto_destroy(s_mqtt.mosq); s_mqtt.mosq = NULL; } mosquitto_lib_cleanup(); info("mqtt: module unloaded\n"); return 0; } const struct mod_export DECL_EXPORTS(mqtt) = { "mqtt", "application", module_init, module_close }; baresip-1.0.0/modules/mqtt/mqtt.h000066400000000000000000000012611372575704200167440ustar00rootroot00000000000000/** * @file mqtt.h Message Queue Telemetry Transport (MQTT) client -- interface * * Copyright (C) 2017 Creytiv.com */ struct mqtt { struct mosquitto *mosq; char *pubtopic; /* Topic for publish */ char *subtopic; /* Topic for subscribe */ char *basetopic; /* Base topic */ struct tmr tmr; int fd; }; /* * Subscribe direction (incoming) */ int mqtt_subscribe_init(struct mqtt *mqtt); int mqtt_subscribe_start(struct mqtt *mqtt); void mqtt_subscribe_close(void); /* * Publish direction (outgoing) */ int mqtt_publish_init(struct mqtt *mqtt); void mqtt_publish_close(void); int mqtt_publish_message(struct mqtt *mqtt, const char *topic, const char *fmt, ...); baresip-1.0.0/modules/mqtt/publish.c000066400000000000000000000034721372575704200174260ustar00rootroot00000000000000/** * @file publish.c MQTT client -- publish * * Copyright (C) 2017 Creytiv.com */ #include #include #include #include "mqtt.h" /* * This file contains functions for sending outgoing messages * from baresip to broker (publish) */ /* * Relay UA events as publish messages to the Broker */ static void ua_event_handler(struct ua *ua, enum ua_event ev, struct call *call, const char *prm, void *arg) { struct mqtt *mqtt = arg; struct odict *od = NULL; int err; err = odict_alloc(&od, 8); if (err) return; err = event_encode_dict(od, ua, ev, call, prm); if (err) goto out; /* send audio jitter buffer values together with VU rx values. */ if (ev == UA_EVENT_VU_RX) { err = event_add_au_jb_stat(od,call); if (err) { info("Could not add audio jb value.\n"); } } err = mqtt_publish_message(mqtt, mqtt->pubtopic, "%H", json_encode_odict, od); if (err) { warning("mqtt: failed to publish message (%m)\n", err); goto out; } out: mem_deref(od); } int mqtt_publish_message(struct mqtt *mqtt, const char *topic, const char *fmt, ...) { char *message; va_list ap; int ret; int err = 0; if (!mqtt || !topic || !fmt) return EINVAL; va_start(ap, fmt); err = re_vsdprintf(&message, fmt, ap); va_end(ap); if (err) return err; ret = mosquitto_publish(mqtt->mosq, NULL, topic, (int)str_len(message), message, 0, false); if (ret != MOSQ_ERR_SUCCESS) { warning("mqtt: failed to publish (%s)\n", mosquitto_strerror(ret)); err = EINVAL; goto out; } out: mem_deref(message); return err; } int mqtt_publish_init(struct mqtt *mqtt) { int err; err = uag_event_register(ua_event_handler, mqtt); if (err) return err; return err; } void mqtt_publish_close(void) { uag_event_unregister(&ua_event_handler); } baresip-1.0.0/modules/mqtt/subscribe.c000066400000000000000000000075761372575704200177520ustar00rootroot00000000000000/** * @file subscribe.c MQTT client -- subscribe * * Copyright (C) 2017 Creytiv.com */ #include #include #include #include "mqtt.h" static int print_handler(const char *p, size_t size, void *arg) { struct mbuf *mb = arg; return mbuf_write_mem(mb, (void *)p, size); } static void handle_command(struct mqtt *mqtt, const struct pl *msg) { struct mbuf *resp = mbuf_alloc(1024); struct re_printf pf = {print_handler, resp}; struct odict *od = NULL, *od_resp = NULL; const struct odict_entry *oe_cmd, *oe_prm, *oe_tok; char buf[256], resp_topic[256]; const char *aor, *callid; int err; err = json_decode_odict(&od, 32, msg->p, msg->l, 16); if (err) { warning("mqtt: failed to decode JSON with %zu bytes (%m)\n", msg->l, err); return; } oe_cmd = odict_lookup(od, "command"); oe_prm = odict_lookup(od, "params"); oe_tok = odict_lookup(od, "token"); if (!oe_cmd) { warning("mqtt: missing json entries\n"); goto out; } aor = odict_string(od, "accountaor"); callid = odict_string(od, "callid"); if (aor) { struct ua *ua = uag_find_aor(aor); if (!ua) { warning("mqtt: ua not found (%s)\n", aor); goto out; } uag_current_set(ua); if (callid) { struct call *call; call = call_find_id(ua_calls(ua), callid); if (!call) { warning("mqtt: call not found (%s)\n", callid); goto out; } call_set_current(ua_calls(ua), call); } } debug("mqtt: handle_command: cmd='%s', token='%s'\n", oe_cmd->u.str, oe_tok ? oe_tok->u.str : ""); re_snprintf(buf, sizeof(buf), "%s%s%s", oe_cmd->u.str, oe_prm ? " " : "", oe_prm ? oe_prm->u.str : ""); /* Relay message to long commands */ err = cmd_process_long(baresip_commands(), buf, str_len(buf), &pf, NULL); if (err) { warning("mqtt: error processing command (%m)\n", err); } err = mbuf_write_u8(resp, '\0'); if (err) goto out; /* NOTE: the command will now write the response to the resp mbuf, send it back to broker */ re_snprintf(resp_topic, sizeof(resp_topic), "/%s/command_resp/%s", mqtt->basetopic, oe_tok ? oe_tok->u.str : "nil"); err = odict_alloc(&od_resp, 8); if (err) goto out; err = odict_entry_add(od_resp, "response", ODICT_BOOL, true); err |= odict_entry_add(od_resp, "ok", ODICT_BOOL, (bool)err==0); err |= odict_entry_add(od_resp, "data", ODICT_STRING, resp->buf); if (oe_tok) { err |= odict_entry_add(od_resp, "token", ODICT_STRING, oe_tok->u.str); } if (err) goto out; err = mqtt_publish_message(mqtt, resp_topic, "%H", json_encode_odict, od_resp); if (err) { warning("mqtt: failed to publish message (%m)\n", err); goto out; } out: mem_deref(resp); mem_deref(od_resp); mem_deref(od); } /* * This is called when a message is received from the broker. */ static void message_callback(struct mosquitto *mosq, void *obj, const struct mosquitto_message *message) { struct mqtt *mqtt = obj; struct pl msg; bool match = false; (void)mosq; info("mqtt: got message '%b' for topic '%s'\n", (char*) message->payload, (size_t)message->payloadlen, message->topic); msg.p = message->payload; msg.l = message->payloadlen; mosquitto_topic_matches_sub(mqtt->subtopic, message->topic, &match); if (match) { info("mqtt: got message for '%s' topic\n", message->topic); handle_command(mqtt, &msg); } } int mqtt_subscribe_init(struct mqtt *mqtt) { if (!mqtt) return EINVAL; mosquitto_message_callback_set(mqtt->mosq, message_callback); return 0; } int mqtt_subscribe_start(struct mqtt *mqtt) { int ret; ret = mosquitto_subscribe(mqtt->mosq, NULL, mqtt->subtopic, 0); if (ret != MOSQ_ERR_SUCCESS) { warning("mqtt: failed to subscribe (%s)\n", mosquitto_strerror(ret)); return EPROTO; } info("mqtt: subscribed to pattern '%s'\n", mqtt->subtopic); return 0; } void mqtt_subscribe_close(void) { } baresip-1.0.0/modules/mwi/000077500000000000000000000000001372575704200154155ustar00rootroot00000000000000baresip-1.0.0/modules/mwi/module.mk000066400000000000000000000001501372575704200172270ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # MOD := mwi $(MOD)_SRCS += mwi.c include mk/mod.mk baresip-1.0.0/modules/mwi/mwi.c000066400000000000000000000071371372575704200163650ustar00rootroot00000000000000/** * @file mwi.c Message Waiting Indication (RFC 3842) * * Copyright (C) 2010 - 2015 Creytiv.com */ #include #include #include /** * @defgroup mwi mwi * * Message Waiting Indication * */ struct mwi { struct le le; struct sipsub *sub; struct ua *ua; struct tmr tmr; bool shutdown; }; static struct tmr tmr; static struct list mwil; static void destructor(void *arg) { struct mwi *mwi = arg; tmr_cancel(&mwi->tmr); list_unlink(&mwi->le); mem_deref(mwi->sub); mem_deref(mwi->ua); } static void deref_handler(void *arg) { struct mwi *mwi = arg; mem_deref(mwi); } static int auth_handler(char **username, char **password, const char *realm, void *arg) { struct account *acc = arg; return account_auth(acc, username, password, realm); } static void notify_handler(struct sip *sip, const struct sip_msg *msg, void *arg) { struct mwi *mwi = arg; if (mbuf_get_left(msg->mb)) { ua_event(mwi->ua, UA_EVENT_MWI_NOTIFY, NULL, "%b", mbuf_buf(msg->mb), mbuf_get_left(msg->mb)); } (void)sip_treply(NULL, sip, msg, 200, "OK"); if (mwi->shutdown) mem_deref(mwi); } static void close_handler(int err, const struct sip_msg *msg, const struct sipevent_substate *substate, void *arg) { struct mwi *mwi = arg; (void)substate; info("mwi: subscription for %s closed: %s (%u %r)\n", ua_aor(mwi->ua), err ? strerror(err) : "", err ? 0 : msg->scode, err ? 0 : &msg->reason); mem_deref(mwi); } static int mwi_subscribe(struct ua *ua) { const char *routev[1]; struct mwi *mwi; int err; mwi = mem_zalloc(sizeof(*mwi), destructor); if (!mwi) return ENOMEM; list_append(&mwil, &mwi->le, mwi); mwi->ua = mem_ref(ua); routev[0] = ua_outbound(ua); info("mwi: subscribing to messages for %s\n", ua_aor(ua)); err = sipevent_subscribe(&mwi->sub, uag_sipevent_sock(), ua_aor(ua), NULL, ua_aor(ua), "message-summary", NULL, 600, ua_cuser(ua), routev, routev[0] ? 1 : 0, auth_handler, ua_account(ua), true, NULL, notify_handler, close_handler, mwi, "Accept:" " application/simple-message-summary\r\n"); if (err) { warning("mwi: subscribe ERROR: %m\n", err); } if (err) mem_deref(mwi); return err; } static struct mwi *mwi_find(const struct ua *ua) { struct le *le; for (le = mwil.head; le; le = le->next) { struct mwi *mwi = le->data; if (mwi->ua == ua) return mwi; } return NULL; } static void ua_event_handler(struct ua *ua, enum ua_event ev, struct call *call, const char *prm, void *arg) { (void)call; (void)prm; (void)arg; if (ev == UA_EVENT_REGISTER_OK) { if (!mwi_find(ua) && (str_casecmp(account_mwi(ua_account(ua)), "yes") == 0)) mwi_subscribe(ua); } else if (ev == UA_EVENT_SHUTDOWN) { struct mwi *mwi = mwi_find(ua); if (mwi) { info("mwi: shutdown of %s\n", ua_aor(ua)); mwi->shutdown = true; if (mwi->sub) { mwi->sub = mem_deref(mwi->sub); tmr_start(&mwi->tmr, 500, deref_handler, mwi); } else mem_deref(mwi); } } } static void tmr_handler(void *arg) { struct le *le; (void)arg; for (le = list_head(&mwil); le; le = le->next) { struct mwi *mwi = le->data; mwi_subscribe(mwi->ua); } } static int module_init(void) { list_init(&mwil); tmr_start(&tmr, 1, tmr_handler, 0); return uag_event_register(ua_event_handler, NULL); } static int module_close(void) { uag_event_unregister(ua_event_handler); tmr_cancel(&tmr); list_flush(&mwil); return 0; } EXPORT_SYM const struct mod_export DECL_EXPORTS(mwi) = { "mwi", "application", module_init, module_close, }; baresip-1.0.0/modules/natpmp/000077500000000000000000000000001372575704200161205ustar00rootroot00000000000000baresip-1.0.0/modules/natpmp/libnatpmp.c000066400000000000000000000077341372575704200202650ustar00rootroot00000000000000/** * @file libnatpmp.c NAT-PMP Client library * * Copyright (C) 2010 Creytiv.com */ #include #include #include #include "libnatpmp.h" enum { NATPMP_DELAY = 250, NATPMP_MAXTX = 9, }; struct natpmp_req { struct natpmp_req **npp; struct udp_sock *us; struct tmr tmr; struct mbuf *mb; struct sa srv; unsigned n; natpmp_resp_h *resph; void *arg; }; static void completed(struct natpmp_req *np, int err, const struct natpmp_resp *resp) { natpmp_resp_h *resph = np->resph; void *arg = np->arg; tmr_cancel(&np->tmr); if (np->npp) { *np->npp = NULL; np->npp = NULL; } np->resph = NULL; /* must be destroyed before calling handler */ mem_deref(np); if (resph) resph(err, resp, arg); } static void destructor(void *arg) { struct natpmp_req *np = arg; tmr_cancel(&np->tmr); mem_deref(np->us); mem_deref(np->mb); } static void timeout(void *arg) { struct natpmp_req *np = arg; int err; if (np->n > NATPMP_MAXTX) { completed(np, ETIMEDOUT, NULL); return; } tmr_start(&np->tmr, NATPMP_DELAY<n, timeout, arg); #if 1 debug("natpmp: {n=%u} tx %u bytes\n", np->n, np->mb->end); #endif np->n++; np->mb->pos = 0; err = udp_send(np->us, &np->srv, np->mb); if (err) { completed(np, err, NULL); } } static int resp_decode(struct natpmp_resp *resp, struct mbuf *mb) { resp->vers = mbuf_read_u8(mb); resp->op = mbuf_read_u8(mb); resp->result = ntohs(mbuf_read_u16(mb)); resp->epoch = ntohl(mbuf_read_u32(mb)); if (!(resp->op & 0x80)) return EPROTO; resp->op &= ~0x80; switch (resp->op) { case NATPMP_OP_EXTERNAL: resp->u.ext_addr = ntohl(mbuf_read_u32(mb)); break; case NATPMP_OP_MAPPING_UDP: case NATPMP_OP_MAPPING_TCP: resp->u.map.int_port = ntohs(mbuf_read_u16(mb)); resp->u.map.ext_port = ntohs(mbuf_read_u16(mb)); resp->u.map.lifetime = ntohl(mbuf_read_u32(mb)); break; default: warning("natmap: unknown opcode %d\n", resp->op); return EBADMSG; } return 0; } static void udp_recv(const struct sa *src, struct mbuf *mb, void *arg) { struct natpmp_req *np = arg; struct natpmp_resp resp; if (!sa_cmp(src, &np->srv, SA_ALL)) return; if (resp_decode(&resp, mb)) return; completed(np, 0, &resp); } static int natpmp_init(struct natpmp_req *np, const struct sa *srv, uint8_t opcode, natpmp_resp_h *resph, void *arg) { int err; if (!np || !srv) return EINVAL; /* a new UDP socket for each NAT-PMP request */ err = udp_listen(&np->us, NULL, udp_recv, np); if (err) return err; np->srv = *srv; np->resph = resph; np->arg = arg; udp_connect(np->us, srv); np->mb = mbuf_alloc(512); if (!np->mb) return ENOMEM; err |= mbuf_write_u8(np->mb, NATPMP_VERSION); err |= mbuf_write_u8(np->mb, opcode); return err; } int natpmp_external_request(struct natpmp_req **npp, const struct sa *srv, natpmp_resp_h *resph, void *arg) { struct natpmp_req *np; int err; np = mem_zalloc(sizeof(*np), destructor); if (!np) return ENOMEM; err = natpmp_init(np, srv, NATPMP_OP_EXTERNAL, resph, arg); if (err) goto out; timeout(np); out: if (err) mem_deref(np); else if (npp) { np->npp = npp; *npp = np; } else { /* Destroy the transaction now */ mem_deref(np); } return err; } int natpmp_mapping_request(struct natpmp_req **npp, const struct sa *srv, uint16_t int_port, uint16_t ext_port, uint32_t lifetime, natpmp_resp_h *resph, void *arg) { struct natpmp_req *np; int err; np = mem_zalloc(sizeof(*np), destructor); if (!np) return ENOMEM; err = natpmp_init(np, srv, NATPMP_OP_MAPPING_UDP, resph, arg); if (err) goto out; err |= mbuf_write_u16(np->mb, 0x0000); err |= mbuf_write_u16(np->mb, htons(int_port)); err |= mbuf_write_u16(np->mb, htons(ext_port)); err |= mbuf_write_u32(np->mb, htonl(lifetime)); if (err) goto out; timeout(np); out: if (err) mem_deref(np); else if (npp) { np->npp = npp; *npp = np; } else { /* Destroy the transaction now */ mem_deref(np); } return err; } baresip-1.0.0/modules/natpmp/libnatpmp.h000066400000000000000000000020771372575704200202650ustar00rootroot00000000000000/** * @file libnatpmp.h Interface to NAT-PMP Client library * * Copyright (C) 2010 Creytiv.com */ enum { NATPMP_VERSION = 0, NATPMP_PORT = 5351, }; enum natpmp_op { NATPMP_OP_EXTERNAL = 0, NATPMP_OP_MAPPING_UDP = 1, NATPMP_OP_MAPPING_TCP = 2, }; enum natpmp_result { NATPMP_SUCCESS = 0, NATPMP_UNSUP_VERSION = 1, NATPMP_REFUSED = 2, NATPMP_NETWORK_FAILURE = 3, NATPMP_OUT_OF_RESOURCES = 4, NATPMP_UNSUP_OPCODE = 5 }; struct natpmp_resp { uint8_t vers; uint8_t op; uint16_t result; uint32_t epoch; union { uint32_t ext_addr; struct { uint16_t int_port; uint16_t ext_port; uint32_t lifetime; } map; } u; }; struct natpmp_req; typedef void (natpmp_resp_h)(int err, const struct natpmp_resp *resp, void *arg); int natpmp_external_request(struct natpmp_req **npp, const struct sa *srv, natpmp_resp_h *h, void *arg); int natpmp_mapping_request(struct natpmp_req **natpmpp, const struct sa *srv, uint16_t int_port, uint16_t ext_port, uint32_t lifetime, natpmp_resp_h *resph, void *arg); baresip-1.0.0/modules/natpmp/module.mk000066400000000000000000000001721372575704200177360ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # MOD := natpmp $(MOD)_SRCS += natpmp.c libnatpmp.c include mk/mod.mk baresip-1.0.0/modules/natpmp/natpmp.c000066400000000000000000000160501372575704200175650ustar00rootroot00000000000000/** * @file natpmp.c NAT-PMP Module for Media NAT-traversal * * Copyright (C) 2010 Creytiv.com */ #include #include #include "libnatpmp.h" /** * @defgroup natpmp natpmp * * NAT Port Mapping Protocol (NAT-PMP) * * https://tools.ietf.org/html/rfc6886 */ enum { LIFETIME = 300 /* seconds */ }; struct mnat_sess { struct list medial; mnat_estab_h *estabh; void *arg; }; struct mnat_media { struct comp { struct natpmp_req *natpmp; struct mnat_media *media; /* pointer to parent */ struct tmr tmr; uint16_t int_port; uint32_t lifetime; unsigned id; bool granted; } compv[2]; unsigned compc; struct le le; struct mnat_sess *sess; struct sdp_media *sdpm; }; static struct sa natpmp_srv, natpmp_extaddr; static struct natpmp_req *natpmp_ext; static void natpmp_resp_handler(int err, const struct natpmp_resp *resp, void *arg); static void session_destructor(void *arg) { struct mnat_sess *sess = arg; list_flush(&sess->medial); } static void media_destructor(void *arg) { struct mnat_media *m = arg; unsigned i; list_unlink(&m->le); for (i=0; icompc; i++) { struct comp *comp = &m->compv[i]; /* Destroy the mapping */ if (comp->granted) { (void)natpmp_mapping_request(NULL, &natpmp_srv, comp->int_port, 0, 0, NULL, NULL); } tmr_cancel(&comp->tmr); mem_deref(comp->natpmp); } mem_deref(m->sdpm); } static void complete(struct mnat_sess *sess, int err) { mnat_estab_h *estabh = sess->estabh; if (sess->estabh) { sess->estabh = NULL; estabh(err, 0, "done", sess->arg); } } static bool all_components_granted(const struct mnat_media *m) { unsigned i; if (!m || !m->compc) return false; for (i=0; icompc; i++) { const struct comp *comp = &m->compv[i]; if (!comp->granted) return false; } return true; } static void is_complete(struct mnat_sess *sess) { struct le *le; for (le = sess->medial.head; le; le = le->next) { struct mnat_media *m = le->data; if (!all_components_granted(m)) return; } complete(sess, 0); } static void refresh_timeout(void *arg) { struct comp *comp = arg; comp->natpmp = mem_deref(comp->natpmp); (void)natpmp_mapping_request(&comp->natpmp, &natpmp_srv, comp->int_port, 0, comp->lifetime, natpmp_resp_handler, comp); } static void natpmp_resp_handler(int err, const struct natpmp_resp *resp, void *arg) { struct comp *comp = arg; struct mnat_media *m = comp->media; struct sa map_addr; if (err) { warning("natpmp: response error: %m\n", err); complete(m->sess, err); return; } if (resp->op != NATPMP_OP_MAPPING_UDP) return; if (resp->result != NATPMP_SUCCESS) { warning("natpmp: request failed with result code: %d\n", resp->result); complete(m->sess, EPROTO); return; } if (resp->u.map.int_port != comp->int_port) { info("natpmp: ignoring response for internal_port=%u\n", resp->u.map.int_port); return; } info("natpmp: mapping granted for comp %u:" " internal_port=%u, external_port=%u, lifetime=%u\n", comp->id, resp->u.map.int_port, resp->u.map.ext_port, resp->u.map.lifetime); map_addr = natpmp_extaddr; sa_set_port(&map_addr, resp->u.map.ext_port); comp->lifetime = resp->u.map.lifetime; /* Update SDP media with external IP-address mapping */ if (comp->id == 1) sdp_media_set_laddr(m->sdpm, &map_addr); else sdp_media_set_laddr_rtcp(m->sdpm, &map_addr); comp->granted = true; tmr_start(&comp->tmr, comp->lifetime * 1000 * 3/4, refresh_timeout, comp); is_complete(m->sess); } static int session_alloc(struct mnat_sess **sessp, const struct mnat *mnat, struct dnsc *dnsc, int af, const struct stun_uri *srv, const char *user, const char *pass, struct sdp_session *ss, bool offerer, mnat_estab_h *estabh, void *arg) { struct mnat_sess *sess; (void)mnat; (void)af; (void)srv; (void)user; (void)pass; (void)ss; (void)offerer; if (!sessp || !dnsc || !ss || !estabh) return EINVAL; sess = mem_zalloc(sizeof(*sess), session_destructor); if (!sess) return ENOMEM; sess->estabh = estabh; sess->arg = arg; *sessp = sess; return 0; } static int comp_alloc(struct comp *comp, void *sock) { struct sa laddr; int err; err = udp_local_get(sock, &laddr); if (err) goto out; comp->int_port = sa_port(&laddr); info("natpmp: `%s' stream comp %u local UDP port is %u\n", sdp_media_name(comp->media->sdpm), comp->id, comp->int_port); err = natpmp_mapping_request(&comp->natpmp, &natpmp_srv, comp->int_port, 0, comp->lifetime, natpmp_resp_handler, comp); if (err) goto out; out: return err; } static int media_alloc(struct mnat_media **mp, struct mnat_sess *sess, struct udp_sock *sock1, struct udp_sock *sock2, struct sdp_media *sdpm, mnat_connected_h *connh, void *arg) { struct mnat_media *m; unsigned i; int err = 0; (void)sock2; (void)connh; (void)arg; if (!mp || !sess || !sdpm) return EINVAL; if (!sock1) return EINVAL; m = mem_zalloc(sizeof(*m), media_destructor); if (!m) return ENOMEM; m->compc = sock2 ? 2 : 1; list_append(&sess->medial, &m->le, m); m->sess = sess; m->sdpm = mem_ref(sdpm); for (i=0; icompc; i++) { struct comp *comp = &m->compv[i]; comp->id = i+1; comp->media = m; comp->lifetime = LIFETIME; err = comp_alloc(comp, i==0 ? sock1 : sock2); if (err) goto out; } out: if (err) mem_deref(m); else { *mp = m; } return err; } static void extaddr_handler(int err, const struct natpmp_resp *resp, void *arg) { (void)arg; if (err) { warning("natpmp: external address ERROR: %m\n", err); return; } if (resp->result != NATPMP_SUCCESS) { warning("natpmp: external address failed" " with result code: %d\n", resp->result); return; } if (resp->op != NATPMP_OP_EXTERNAL) return; sa_set_in(&natpmp_extaddr, resp->u.ext_addr, 0); info("natpmp: discovered External address: %j\n", &natpmp_extaddr); } static bool net_rt_handler(const char *ifname, const struct sa *dst, int dstlen, const struct sa *gw, void *arg) { (void)dstlen; (void)arg; if (sa_af(dst) != AF_INET) return false; if (sa_in(dst) == 0) { natpmp_srv = *gw; sa_set_port(&natpmp_srv, NATPMP_PORT); info("natpmp: found default gateway %j on interface '%s'\n", gw, ifname); return true; } return false; } static struct mnat mnat_natpmp = { .id = "natpmp", .sessh = session_alloc, .mediah = media_alloc, }; static int module_init(void) { int err; sa_init(&natpmp_srv, AF_INET); sa_set_port(&natpmp_srv, NATPMP_PORT); net_rt_list(net_rt_handler, NULL); conf_get_sa(conf_cur(), "natpmp_server", &natpmp_srv); info("natpmp: using NAT-PMP server at %J\n", &natpmp_srv); err = natpmp_external_request(&natpmp_ext, &natpmp_srv, extaddr_handler, NULL); if (err) return err; mnat_register(baresip_mnatl(), &mnat_natpmp); return 0; } static int module_close(void) { mnat_unregister(&mnat_natpmp); natpmp_ext = mem_deref(natpmp_ext); return 0; } EXPORT_SYM const struct mod_export DECL_EXPORTS(natpmp) = { "natpmp", "mnat", module_init, module_close, }; baresip-1.0.0/modules/omx/000077500000000000000000000000001372575704200154245ustar00rootroot00000000000000baresip-1.0.0/modules/omx/README000066400000000000000000000004211372575704200163010ustar00rootroot00000000000000README ------ This module implements support for the VideoCore4 of the Raspberry Pi A/B/2/3. Currently it only does video playback. EXAMPLE CONFIG -------------- # Video video_display omx,nil # Video codec Modules (in order) module omx.so baresip-1.0.0/modules/omx/module.c000066400000000000000000000045701372575704200170630ustar00rootroot00000000000000/** * @file omx/module.c Raspberry Pi VideoCoreIV OpenMAX interface * * Copyright (C) 2016 - 2017 Creytiv.com * Copyright (C) 2016 - 2017 Jonathan Sieber */ #include "omx.h" #include #include #include #include struct vidisp_st { const struct vidisp *vd; /* inheritance */ struct vidsz size; struct omx_state* omx; }; static struct vidisp* vid; static struct omx_state omx; static void destructor(void *arg) { struct vidisp_st *st = arg; omx_display_disable(st->omx); } static int omx_vidisp_alloc(struct vidisp_st **vp, const struct vidisp *vd, struct vidisp_prm *prm, const char *dev, vidisp_resize_h *resizeh, void *arg) { struct vidisp_st *st; /* Not used by OMX */ (void) prm; (void) dev; (void) resizeh; (void) arg; info("omx: vidisp_alloc\n"); st = mem_zalloc(sizeof(*st), destructor); if (!st) return ENOMEM; st->vd = vd; *vp = st; st->omx = &omx; return 0; } static int omx_vidisp_display(struct vidisp_st *st, const char *title, const struct vidframe *frame, uint64_t timestamp) { int err = 0; void* buf; uint32_t len; struct vidframe omx_frame; (void)title; (void)timestamp; if (frame->fmt != VID_FMT_YUV420P) { return EINVAL; } if (!vidsz_cmp(&st->size, &frame->size)) { info("omx: new frame size: w=%d h=%d\n", frame->size.w, frame->size.h); info("omx: linesize[0]=%d\tlinesize[1]=%d\tlinesize[2]=%d\n", frame->linesize[0], frame->linesize[1], frame->linesize[2]); err = omx_display_enable(st->omx, frame->size.w, frame->size.h, frame->size.w); if (err) { warning("omx_display_enable failed"); return err; } st->size = frame->size; } /* Get Buffer Pointer */ omx_display_input_buffer(st->omx, &buf, &len); vidframe_init_buf(&omx_frame, VID_FMT_YUV420P, &frame->size, buf); vidconv(&omx_frame, frame, 0); omx_display_flush_buffer(st->omx); return 0; } static int module_init(void) { if (omx_init(&omx) != 0) { warning("Could not initialize OpenMAX"); return ENODEV; } return vidisp_register(&vid, baresip_vidispl(), "omx", omx_vidisp_alloc, NULL, omx_vidisp_display, NULL); } static int module_close(void) { /* HACK: not deinitializing OMX because of a hangup */ /* omx_deinit(&omx) */ vid = mem_deref(vid); return 0; } EXPORT_SYM const struct mod_export DECL_EXPORTS(omx) = { "omx", "vidisp", module_init, module_close }; baresip-1.0.0/modules/omx/module.mk000066400000000000000000000011041372575704200172360ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 - 2015 Creytiv.com # MOD := omx $(MOD)_SRCS += omx.c module.c ifneq ($(USE_OMX_RPI),) $(MOD)_CFLAGS := -DRASPBERRY_PI -DOMX_SKIP64BIT \ -isystem /usr/local/include/interface/vmcs_host/linux/ \ -isystem /usr/local/include/interface/vcos/pthreads/ \ -isystem /opt/vc/include \ -isystem /opt/vc/include/interface/vmcs_host/linux \ -isystem /opt/vc/include/interface/vcos/pthreads $(MOD)_LFLAGS += -lvcos -lbcm_host -lopenmaxil -L /opt/vc/lib endif ifneq ($(USE_OMX_BELLAGIO),) $(MOD)_LFLAGS += -lomxil-bellagio endif include mk/mod.mk baresip-1.0.0/modules/omx/omx.c000066400000000000000000000204141372575704200163740ustar00rootroot00000000000000/** * @file omx.c Raspberry Pi VideoCoreIV OpenMAX interface * * Copyright (C) 2016 - 2017 Creytiv.com * Copyright (C) 2016 - 2017 Jonathan Sieber */ #define _POSIX_C_SOURCE 199309L #include "omx.h" #include #include #include #include #include #include /* Avoids a VideoCore header warning about clock_gettime() */ #include #include #ifdef RASPBERRY_PI #include #endif /** * @defgroup omx omx * * Raspberry Pi VideoCoreIV OpenMAX interface * * TODO: * * Proper sync OMX events across threads, instead of busy waiting */ #ifdef RASPBERRY_PI static const int VIDEO_RENDER_PORT = 90; #else static const int VIDEO_RENDER_PORT = 0; #endif /* static void setHeader(OMX_PTR header, OMX_U32 size) { OMX_VERSIONTYPE* ver = (OMX_VERSIONTYPE*)(header + sizeof(OMX_U32)); *((OMX_U32*)header) = size; ver->s.nVersionMajor = VERSIONMAJOR; ver->s.nVersionMinor = VERSIONMINOR; ver->s.nRevision = VERSIONREVISION; ver->s.nStep = VERSIONSTEP; } * */ static OMX_ERRORTYPE EventHandler(OMX_HANDLETYPE hComponent, OMX_PTR pAppData, OMX_EVENTTYPE eEvent, OMX_U32 nData1, OMX_U32 nData2, OMX_PTR pEventData) { (void) hComponent; switch (eEvent) { case OMX_EventCmdComplete: debug("omx.EventHandler: Previous command completed\n" "d1=%x\td2=%x\teventData=%p\tappdata=%p\n", nData1, nData2, pEventData, pAppData); /* TODO: Put these event into a multithreaded queue, * properly wait for them in the issuing code */ break; case OMX_EventError: warning("omx.EventHandler: Error event type " "data1=%x\tdata2=%x\n", nData1, nData2); break; default: warning("omx.EventHandler: Unknown event type %d\t" "data1=%x data2=%x\n", eEvent, nData1, nData2); return -1; break; } return 0; } static OMX_ERRORTYPE EmptyBufferDone(OMX_HANDLETYPE hComponent, OMX_PTR pAppData, OMX_BUFFERHEADERTYPE* pBuffer) { (void) hComponent; (void) pAppData; (void) pBuffer; /* TODO: Wrap every call that can generate an event, * and panic if an unexpected event arrives */ return 0; } static OMX_ERRORTYPE FillBufferDone(OMX_HANDLETYPE hComponent, OMX_PTR pAppData, OMX_BUFFERHEADERTYPE* pBuffer) { (void) hComponent; (void) pAppData; (void) pBuffer; debug("FillBufferDone\n"); return 0; } static struct OMX_CALLBACKTYPE callbacks = { EventHandler, EmptyBufferDone, &FillBufferDone }; int omx_init(struct omx_state *st) { OMX_ERRORTYPE err; #ifdef RASPBERRY_PI bcm_host_init(); #endif st->buffers = NULL; err = OMX_Init(); #ifdef RASPBERRY_PI err |= OMX_GetHandle(&st->video_render, "OMX.broadcom.video_render", 0, &callbacks); #else err |= OMX_GetHandle(&st->video_render, "OMX.st.video.xvideosink", 0, &callbacks); #endif if (!st->video_render || err != 0) { warning("omx: Failed to create OMX video_render component\n"); return ENOENT; } else { info("omx: created video_render component\n"); return 0; } } /* Some busy loops to verify we're running in order */ static void block_until_state_changed(OMX_HANDLETYPE hComponent, OMX_STATETYPE wanted_eState) { OMX_STATETYPE eState; unsigned int i = 0; while (i++ == 0 || eState != wanted_eState) { OMX_GetState(hComponent, &eState); if (eState != wanted_eState) { sys_usleep(10000); } } } void omx_deinit(struct omx_state *st) { if (!st) return; info("omx_deinit"); OMX_SendCommand(st->video_render, OMX_CommandStateSet, OMX_StateIdle, NULL); block_until_state_changed(st->video_render, OMX_StateIdle); OMX_SendCommand(st->video_render, OMX_CommandStateSet, OMX_StateLoaded, NULL); block_until_state_changed(st->video_render, OMX_StateLoaded); OMX_FreeHandle(st->video_render); OMX_Deinit(); } void omx_display_disable(struct omx_state *st) { #ifdef RASPBERRY_PI OMX_ERRORTYPE err; OMX_CONFIG_DISPLAYREGIONTYPE config; if (!st) return; memset(&config, 0, sizeof(OMX_CONFIG_DISPLAYREGIONTYPE)); config.nSize = sizeof(OMX_CONFIG_DISPLAYREGIONTYPE); config.nVersion.nVersion = OMX_VERSION; config.nPortIndex = VIDEO_RENDER_PORT; config.fullscreen = 0; config.set = OMX_DISPLAY_SET_FULLSCREEN; err = OMX_SetParameter(st->video_render, OMX_IndexConfigDisplayRegion, &config); if (err != 0) { warning("omx_display_disable command failed"); } #else (void)st; #endif } static void block_until_port_changed(OMX_HANDLETYPE hComponent, OMX_U32 nPortIndex, OMX_BOOL bEnabled) { OMX_ERRORTYPE r; OMX_PARAM_PORTDEFINITIONTYPE portdef; OMX_U32 i = 0; memset(&portdef, 0, sizeof(OMX_PARAM_PORTDEFINITIONTYPE)); portdef.nSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE); portdef.nVersion.nVersion = OMX_VERSION; portdef.nPortIndex = nPortIndex; while (i++ == 0 || portdef.bEnabled != bEnabled) { r = OMX_GetParameter(hComponent, OMX_IndexParamPortDefinition, &portdef); if (r != OMX_ErrorNone) { warning("block_until_port_changed: OMX_GetParameter " " failed with Result=%d\n", r); } if (portdef.bEnabled != bEnabled) { sys_usleep(10000); } } } int omx_display_enable(struct omx_state* st, int width, int height, int stride) { unsigned int i; OMX_PARAM_PORTDEFINITIONTYPE portdef; #ifdef RASPBERRY_PI OMX_CONFIG_DISPLAYREGIONTYPE config; #endif OMX_ERRORTYPE err = 0; info("omx_update_size %d %d\n", width, height); #ifdef RASPBERRY_PI memset(&config, 0, sizeof(OMX_CONFIG_DISPLAYREGIONTYPE)); config.nSize = sizeof(OMX_CONFIG_DISPLAYREGIONTYPE); config.nVersion.nVersion = OMX_VERSION; config.nPortIndex = VIDEO_RENDER_PORT; config.fullscreen = 1; config.set = OMX_DISPLAY_SET_FULLSCREEN; err |= OMX_SetParameter(st->video_render, OMX_IndexConfigDisplayRegion, &config); #endif memset(&portdef, 0, sizeof(OMX_PARAM_PORTDEFINITIONTYPE)); portdef.nSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE); portdef.nVersion.nVersion = OMX_VERSION; portdef.nPortIndex = VIDEO_RENDER_PORT; /* specify buffer requirements */ err |= OMX_GetParameter(st->video_render, OMX_IndexParamPortDefinition, &portdef); if (err != 0) { warning("omx_display_enable: couldn't retrieve port def\n"); err = ENOMEM; goto exit; } info("omx port definition: h=%d w=%d s=%d sh=%d\n", portdef.format.video.nFrameWidth, portdef.format.video.nFrameHeight, portdef.format.video.nStride, portdef.format.video.nSliceHeight); portdef.format.video.nFrameWidth = width; portdef.format.video.nFrameHeight = height; portdef.format.video.nStride = stride; portdef.format.video.nSliceHeight = height; portdef.bEnabled = 1; err |= OMX_SetParameter(st->video_render, OMX_IndexParamPortDefinition, &portdef); if (err) { warning("omx_display_enable: could not set port definition\n"); } block_until_port_changed(st->video_render, VIDEO_RENDER_PORT, true); err |= OMX_GetParameter(st->video_render, OMX_IndexParamPortDefinition, &portdef); if (err != 0 || !portdef.bEnabled) { warning("omx_display_enable: failed to set up video port\n"); err = ENOMEM; goto exit; } /* HACK: This state-change sometimes hangs for unknown reasons, * so we just send the state command and wait 50 ms */ /* block_until_state_changed(st->video_render, OMX_StateIdle); */ OMX_SendCommand(st->video_render, OMX_CommandStateSet, OMX_StateIdle, NULL); sys_usleep(50000); if (!st->buffers) { st->buffers = malloc(portdef.nBufferCountActual * sizeof(void*)); st->num_buffers = portdef.nBufferCountActual; st->current_buffer = 0; for (i = 0; i < portdef.nBufferCountActual; i++) { err = OMX_AllocateBuffer(st->video_render, &st->buffers[i], VIDEO_RENDER_PORT, st, portdef.nBufferSize); if (err) { warning("OMX_AllocateBuffer failed: %d\n", err); err = ENOMEM; goto exit; } } } debug("omx_update_size: send to execute state"); OMX_SendCommand(st->video_render, OMX_CommandStateSet, OMX_StateExecuting, NULL); block_until_state_changed(st->video_render, OMX_StateExecuting); exit: return err; } int omx_display_input_buffer(struct omx_state* st, void** pbuf, uint32_t* plen) { if (!st->buffers) return EINVAL; *pbuf = st->buffers[0]->pBuffer; *plen = st->buffers[0]->nAllocLen; st->buffers[0]->nFilledLen = *plen; st->buffers[0]->nOffset = 0; return 0; } int omx_display_flush_buffer(struct omx_state* st) { if (OMX_EmptyThisBuffer(st->video_render, st->buffers[0]) != OMX_ErrorNone) { warning("OMX_EmptyThisBuffer error"); } return 0; } baresip-1.0.0/modules/omx/omx.h000066400000000000000000000020011372575704200163710ustar00rootroot00000000000000/** * @file omx.h Raspberry Pi VideoCoreIV OpenMAX interface * * Copyright (C) 2016 - 2017 Creytiv.com * Copyright (C) 2016 - 2017 Jonathan Sieber */ #ifdef RASPBERRY_PI #include #include #include #else #include #include #include #undef OMX_VERSION #define OMX_VERSION 0x01010101 #define OMX_ERROR_NONE 0 #endif #include #include #include /* Needed for usleep to appear */ #define _BSD_SOURCE #include struct omx_state { OMX_HANDLETYPE video_render; OMX_BUFFERHEADERTYPE** buffers; int num_buffers; int current_buffer; }; int omx_init(struct omx_state* st); void omx_deinit(struct omx_state* st); int omx_display_input_buffer(struct omx_state* st, void** pbuf, uint32_t* plen); int omx_display_flush_buffer(struct omx_state* st); int omx_display_enable(struct omx_state *st, int width, int height, int stride); void omx_display_disable(struct omx_state *st); baresip-1.0.0/modules/opengl/000077500000000000000000000000001372575704200161055ustar00rootroot00000000000000baresip-1.0.0/modules/opengl/module.mk000066400000000000000000000002511372575704200177210ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # MOD := opengl $(MOD)_SRCS += opengl.m $(MOD)_LFLAGS += -framework OpenGL -framework Cocoa -lobjc include mk/mod.mk baresip-1.0.0/modules/opengl/opengl.m000066400000000000000000000266411372575704200175600ustar00rootroot00000000000000/** * @file opengl.m Video driver for OpenGL on MacOSX * * Copyright (C) 2010 - 2015 Creytiv.com */ #include #include #include #include #include #include /** * @defgroup opengl opengl * * Video display module for OpenGL on MacOSX */ #if (MAC_OS_X_VERSION_MAX_ALLOWED >= 101200) #define NSTitledWindowMask NSWindowStyleMaskTitled #define NSClosableWindowMask NSWindowStyleMaskClosable #define NSMiniaturizableWindowMask NSWindowStyleMaskMiniaturizable #endif struct vidisp_st { const struct vidisp *vd; /**< Inheritance (1st) */ struct vidsz size; /**< Current size */ NSOpenGLContext *ctx; NSWindow *win; GLhandleARB PHandle; char *prog; }; static struct vidisp *vid; /**< OPENGL Video-display */ static const char *FProgram= "uniform sampler2DRect Ytex;\n" "uniform sampler2DRect Utex,Vtex;\n" "void main(void) {\n" " float nx,ny,r,g,b,y,u,v;\n" " vec4 txl,ux,vx;" " nx=gl_TexCoord[0].x;\n" " ny=%d.0-gl_TexCoord[0].y;\n" " y=texture2DRect(Ytex,vec2(nx,ny)).r;\n" " u=texture2DRect(Utex,vec2(nx/2.0,ny/2.0)).r;\n" " v=texture2DRect(Vtex,vec2(nx/2.0,ny/2.0)).r;\n" " y=1.1643*(y-0.0625);\n" " u=u-0.5;\n" " v=v-0.5;\n" " r=y+1.5958*v;\n" " g=y-0.39173*u-0.81290*v;\n" " b=y+2.017*u;\n" " gl_FragColor=vec4(r,g,b,1.0);\n" "}\n"; static void destructor(void *arg) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; struct vidisp_st *st = arg; if (st->ctx) { [st->ctx clearDrawable]; [st->ctx release]; } [st->win close]; if (st->PHandle) { glUseProgramObjectARB(0); glDeleteObjectARB(st->PHandle); } mem_deref(st->prog); [pool release]; } static int create_window(struct vidisp_st *st) { NSRect rect = NSMakeRect(0, 0, 100, 100); NSUInteger style; if (st->win) return 0; style = NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask; st->win = [[NSWindow alloc] initWithContentRect:rect styleMask:style backing:NSBackingStoreBuffered defer:FALSE]; if (!st->win) { warning("opengl: could not create NSWindow\n"); return ENOMEM; } [st->win setLevel:NSFloatingWindowLevel]; return 0; } static void opengl_reset(struct vidisp_st *st, const struct vidsz *sz) { if (st->PHandle) { glUseProgramObjectARB(0); glDeleteObjectARB(st->PHandle); st->PHandle = 0; st->prog = mem_deref(st->prog); } st->size = *sz; } static int setup_shader(struct vidisp_st *st, int width, int height) { GLhandleARB FSHandle, PHandle; const char *progv[1]; char buf[1024]; int err, i; if (st->PHandle) return 0; err = re_sdprintf(&st->prog, FProgram, height); if (err) return err; glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0, width, 0, height, -1, 1); glViewport(0, 0, width, height); glClearColor(0, 0, 0, 0); glColor3f(1.0f, 0.84f, 0.0f); glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST); /* Set up program objects. */ PHandle = glCreateProgramObjectARB(); FSHandle = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB); /* Compile the shader. */ progv[0] = st->prog; glShaderSourceARB(FSHandle, 1, progv, NULL); glCompileShaderARB(FSHandle); /* Print the compilation log. */ glGetObjectParameterivARB(FSHandle, GL_OBJECT_COMPILE_STATUS_ARB, &i); if (i != 1) { warning("opengl: shader compile failed\n"); return ENOSYS; } glGetInfoLogARB(FSHandle, sizeof(buf), NULL, buf); /* Create a complete program object. */ glAttachObjectARB(PHandle, FSHandle); glLinkProgramARB(PHandle); /* And print the link log. */ glGetInfoLogARB(PHandle, sizeof(buf), NULL, buf); /* Finally, use the program. */ glUseProgramObjectARB(PHandle); st->PHandle = PHandle; return 0; } static int alloc(struct vidisp_st **stp, const struct vidisp *vd, struct vidisp_prm *prm, const char *dev, vidisp_resize_h *resizeh, void *arg) { NSOpenGLPixelFormatAttribute attr[] = { NSOpenGLPFAColorSize, 32, NSOpenGLPFADepthSize, 16, NSOpenGLPFADoubleBuffer, 0 }; NSOpenGLPixelFormat *fmt; NSAutoreleasePool *pool; struct vidisp_st *st; GLint vsync = 1; int err = 0; (void)dev; (void)resizeh; (void)arg; pool = [[NSAutoreleasePool alloc] init]; if (!pool) return ENOMEM; st = mem_zalloc(sizeof(*st), destructor); if (!st) return ENOMEM; st->vd = vd; fmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:attr]; if (!fmt) { err = ENOMEM; warning("opengl: Failed creating OpenGL format\n"); goto out; } st->ctx = [[NSOpenGLContext alloc] initWithFormat:fmt shareContext:nil]; [fmt release]; if (!st->ctx) { err = ENOMEM; warning("opengl: Failed creating OpenGL context\n"); goto out; } /* create our own */ err = create_window(st); if (err) goto out; /* Enable vertical sync */ [st->ctx setValues:&vsync forParameter:NSOpenGLCPSwapInterval]; out: if (err) mem_deref(st); else *stp = st; [pool release]; return err; } static inline void draw_yuv(GLhandleARB PHandle, int width, int height, const uint8_t *Ytex, int linesizeY, const uint8_t *Utex, int linesizeU, const uint8_t *Vtex, int linesizeV) { int i; /* This might not be required, but should not hurt. */ glEnable(GL_TEXTURE_2D); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); /* Select texture unit 1 as the active unit and bind the U texture. */ glActiveTexture(GL_TEXTURE1); i = glGetUniformLocationARB(PHandle, "Utex"); glUniform1iARB(i,1); /* Bind Utex to texture unit 1 */ glBindTexture(GL_TEXTURE_RECTANGLE_EXT,1); glPixelStorei(GL_UNPACK_ROW_LENGTH, linesizeU); glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MIN_FILTER,GL_LINEAR); glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_DECAL); glTexImage2D(GL_TEXTURE_RECTANGLE_EXT,0,GL_LUMINANCE, width/2, height/2, 0, GL_LUMINANCE,GL_UNSIGNED_BYTE,Utex); /* Select texture unit 2 as the active unit and bind the V texture. */ glActiveTexture(GL_TEXTURE2); i = glGetUniformLocationARB(PHandle, "Vtex"); glBindTexture(GL_TEXTURE_RECTANGLE_EXT,2); glPixelStorei(GL_UNPACK_ROW_LENGTH, linesizeV); glUniform1iARB(i,2); /* Bind Vtext to texture unit 2 */ glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MIN_FILTER,GL_LINEAR); glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_DECAL); glTexImage2D(GL_TEXTURE_RECTANGLE_EXT,0,GL_LUMINANCE, width/2, height/2, 0, GL_LUMINANCE,GL_UNSIGNED_BYTE,Vtex); /* Select texture unit 0 as the active unit and bind the Y texture. */ glActiveTexture(GL_TEXTURE0); i = glGetUniformLocationARB(PHandle,"Ytex"); glUniform1iARB(i,0); /* Bind Ytex to texture unit 0 */ glBindTexture(GL_TEXTURE_RECTANGLE_EXT,3); glPixelStorei(GL_UNPACK_ROW_LENGTH, linesizeY); glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MIN_FILTER,GL_LINEAR); glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_DECAL); glTexImage2D(GL_TEXTURE_RECTANGLE_EXT, 0, GL_LUMINANCE, width, height, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, Ytex); } static inline void draw_blit(int width, int height) { glClear(GL_COLOR_BUFFER_BIT); /* Draw image */ glBegin(GL_QUADS); { glTexCoord2i(0, 0); glVertex2i(0, 0); glTexCoord2i(width, 0); glVertex2i(width, 0); glTexCoord2i(width, height); glVertex2i(width, height); glTexCoord2i(0, height); glVertex2i(0, height); } glEnd(); } static inline void draw_rgb(const uint8_t *pic, int w, int h) { glEnable(GL_TEXTURE_RECTANGLE_EXT); glBindTexture(GL_TEXTURE_RECTANGLE_EXT, 1); glTextureRangeAPPLE(GL_TEXTURE_RECTANGLE_EXT, w * h * 2, pic); glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_STORAGE_HINT_APPLE, GL_STORAGE_SHARED_APPLE); glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE); glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); glTexImage2D(GL_TEXTURE_RECTANGLE_EXT, 0, GL_RGBA, w, h, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, pic); /* draw */ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable(GL_TEXTURE_2D); glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho( (GLfloat)0, (GLfloat)w, (GLfloat)0, (GLfloat)h, -1.0, 1.0); glBindTexture(GL_TEXTURE_RECTANGLE_EXT, 1); glMatrixMode(GL_TEXTURE); glLoadIdentity(); glBegin(GL_QUADS); { glTexCoord2f(0.0f, 0.0f); glVertex2f(0.0f, h); glTexCoord2f(0.0f, h); glVertex2f(0.0f, 0.0f); glTexCoord2f(w, h); glVertex2f(w, 0.0f); glTexCoord2f(w, 0.0f); glVertex2f(w, h); } glEnd(); } static int display(struct vidisp_st *st, const char *title, const struct vidframe *frame, uint64_t timestamp) { NSAutoreleasePool *pool; bool upd = false; int err = 0; (void)timestamp; pool = [[NSAutoreleasePool alloc] init]; if (!pool) return ENOMEM; if (!vidsz_cmp(&st->size, &frame->size)) { if (st->size.w && st->size.h) { info("opengl: reset: %u x %u ---> %u x %u\n", st->size.w, st->size.h, frame->size.w, frame->size.h); } opengl_reset(st, &frame->size); upd = true; } if (upd && st->win) { const NSSize size = {frame->size.w, frame->size.h}; char capt[256]; [st->win setContentSize:size]; if (title) { re_snprintf(capt, sizeof(capt), "%s - %u x %u", title, frame->size.w, frame->size.h); } else { re_snprintf(capt, sizeof(capt), "%u x %u", frame->size.w, frame->size.h); } [st->win setTitle:[NSString stringWithUTF8String:capt]]; [st->win makeKeyAndOrderFront:nil]; [st->win display]; [st->win center]; [st->ctx clearDrawable]; [st->ctx setView:[st->win contentView]]; } [st->ctx makeCurrentContext]; if (frame->fmt == VID_FMT_YUV420P) { if (!st->PHandle) { debug("opengl: using Vertex shader with YUV420P\n"); err = setup_shader(st, frame->size.w, frame->size.h); if (err) goto out; } draw_yuv(st->PHandle, frame->size.w, frame->size.h, frame->data[0], frame->linesize[0], frame->data[1], frame->linesize[1], frame->data[2], frame->linesize[2]); draw_blit(frame->size.w, frame->size.h); } else if (frame->fmt == VID_FMT_RGB32) { glClearColor(0, 0, 0, 0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glViewport(0, 0, frame->size.w, frame->size.h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); draw_rgb(frame->data[0], frame->size.w, frame->size.h); } else { warning("opengl: unknown pixel format %s\n", vidfmt_name(frame->fmt)); err = EINVAL; } [st->ctx flushBuffer]; out: [pool release]; return err; } static void hide(struct vidisp_st *st) { if (!st) return; [st->win orderOut:nil]; } static int module_init(void) { NSApplication *app; int err; app = [NSApplication sharedApplication]; if (!app) return ENOSYS; err = vidisp_register(&vid, baresip_vidispl(), "opengl", alloc, NULL, display, hide); if (err) return err; return 0; } static int module_close(void) { vid = mem_deref(vid); return 0; } EXPORT_SYM const struct mod_export DECL_EXPORTS(opengl) = { "opengl", "vidisp", module_init, module_close, }; baresip-1.0.0/modules/opensles/000077500000000000000000000000001372575704200164515ustar00rootroot00000000000000baresip-1.0.0/modules/opensles/module.mk000066400000000000000000000003001372575704200202600ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # MOD := opensles $(MOD)_SRCS += opensles.c $(MOD)_SRCS += player.c $(MOD)_SRCS += recorder.c $(MOD)_LFLAGS += -lOpenSLES include mk/mod.mk baresip-1.0.0/modules/opensles/opensles.c000066400000000000000000000027471372575704200204570ustar00rootroot00000000000000/** * @file opensles.c OpenSLES audio driver * * Copyright (C) 2010 - 2015 Creytiv.com */ #include #include #include #include "SLES/OpenSLES_Android.h" #include "opensles.h" /** * @defgroup opensles opensles * * Audio driver module for Android OpenSLES */ SLObjectItf engineObject = NULL; SLEngineItf engineEngine; static struct auplay *auplay; static struct ausrc *ausrc; static int module_init(void) { SLEngineOption engineOption[] = { { (SLuint32) SL_ENGINEOPTION_THREADSAFE, (SLuint32) SL_BOOLEAN_TRUE }, }; SLresult r; int err; r = slCreateEngine(&engineObject, 1, engineOption, 0, NULL, NULL); if (SL_RESULT_SUCCESS != r) return ENODEV; r = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE); if (SL_RESULT_SUCCESS != r) return ENODEV; r = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine); if (SL_RESULT_SUCCESS != r) return ENODEV; err = auplay_register(&auplay, baresip_auplayl(), "opensles", opensles_player_alloc); err |= ausrc_register(&ausrc, baresip_ausrcl(), "opensles", opensles_recorder_alloc); return err; } static int module_close(void) { auplay = mem_deref(auplay); ausrc = mem_deref(ausrc); if (engineObject != NULL) { (*engineObject)->Destroy(engineObject); engineObject = NULL; engineEngine = NULL; } return 0; } EXPORT_SYM const struct mod_export DECL_EXPORTS(opensles) = { "opensles", "audio", module_init, module_close, }; baresip-1.0.0/modules/opensles/opensles.h000066400000000000000000000010451372575704200204520ustar00rootroot00000000000000/** * @file opensles.h OpenSLES audio driver -- internal API * * Copyright (C) 2010 Creytiv.com */ extern SLObjectItf engineObject; extern SLEngineItf engineEngine; int opensles_player_alloc(struct auplay_st **stp, const struct auplay *ap, struct auplay_prm *prm, const char *device, auplay_write_h *wh, void *arg); int opensles_recorder_alloc(struct ausrc_st **stp, const struct ausrc *as, struct media_ctx **ctx, struct ausrc_prm *prm, const char *device, ausrc_read_h *rh, ausrc_error_h *errh, void *arg); baresip-1.0.0/modules/opensles/player.c000066400000000000000000000111331372575704200201100ustar00rootroot00000000000000/** * @file opensles/player.c OpenSLES audio driver -- playback * * Copyright (C) 2010 Creytiv.com */ #include #include #include #include #include "SLES/OpenSLES_Android.h" #include "opensles.h" #define N_PLAY_QUEUE_BUFFERS 2 #define PTIME 10 struct auplay_st { const struct auplay *ap; /* inheritance */ auplay_write_h *wh; void *arg; int16_t *sampv[N_PLAY_QUEUE_BUFFERS]; size_t sampc; uint8_t bufferId; SLObjectItf outputMixObject; SLObjectItf bqPlayerObject; SLPlayItf bqPlayerPlay; SLAndroidSimpleBufferQueueItf BufferQueue; }; static void auplay_destructor(void *arg) { struct auplay_st *st = arg; if (st->bqPlayerObject != NULL) (*st->bqPlayerObject)->Destroy(st->bqPlayerObject); if (st->outputMixObject != NULL) (*st->outputMixObject)->Destroy(st->outputMixObject); st->bufferId = 0; for (int i=0; isampv[i]); } } static void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void *context) { struct auplay_st *st = context; st->wh(st->sampv[st->bufferId], st->sampc, st->arg); (*st->BufferQueue)->Enqueue(bq /*st->BufferQueue*/, st->sampv[st->bufferId], st->sampc * 2); st->bufferId = ( st->bufferId + 1 ) % N_PLAY_QUEUE_BUFFERS; } static int createOutput(struct auplay_st *st) { const SLInterfaceID ids[1] = {SL_IID_ENVIRONMENTALREVERB}; const SLboolean req[1] = {SL_BOOLEAN_FALSE}; SLresult r; r = (*engineEngine)->CreateOutputMix(engineEngine, &st->outputMixObject, 1, ids, req); if (SL_RESULT_SUCCESS != r) return ENODEV; r = (*st->outputMixObject)->Realize(st->outputMixObject, SL_BOOLEAN_FALSE); if (SL_RESULT_SUCCESS != r) return ENODEV; return 0; } static int createPlayer(struct auplay_st *st, struct auplay_prm *prm) { SLDataLocator_AndroidSimpleBufferQueue loc_bufq = { SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2 }; uint32_t ch_mask = prm->ch == 2 ? SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT : SL_SPEAKER_FRONT_CENTER; SLDataFormat_PCM format_pcm = {SL_DATAFORMAT_PCM, prm->ch, prm->srate * 1000, SL_PCMSAMPLEFORMAT_FIXED_16, SL_PCMSAMPLEFORMAT_FIXED_16, ch_mask, SL_BYTEORDER_LITTLEENDIAN}; SLDataSource audioSrc = {&loc_bufq, &format_pcm}; SLDataLocator_OutputMix loc_outmix = { SL_DATALOCATOR_OUTPUTMIX, st->outputMixObject }; SLDataSink audioSnk = {&loc_outmix, NULL}; const SLInterfaceID ids[2] = {SL_IID_BUFFERQUEUE, SL_IID_EFFECTSEND}; const SLboolean req[2] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE}; SLresult r; r = (*engineEngine)->CreateAudioPlayer(engineEngine, &st->bqPlayerObject, &audioSrc, &audioSnk, ARRAY_SIZE(ids), ids, req); if (SL_RESULT_SUCCESS != r) { warning("opensles: CreateAudioPlayer error: r = %d\n", r); return ENODEV; } r = (*st->bqPlayerObject)->Realize(st->bqPlayerObject, SL_BOOLEAN_FALSE); if (SL_RESULT_SUCCESS != r) return ENODEV; r = (*st->bqPlayerObject)->GetInterface(st->bqPlayerObject, SL_IID_PLAY, &st->bqPlayerPlay); if (SL_RESULT_SUCCESS != r) return ENODEV; r = (*st->bqPlayerObject)->GetInterface(st->bqPlayerObject, SL_IID_BUFFERQUEUE, &st->BufferQueue); if (SL_RESULT_SUCCESS != r) return ENODEV; r = (*st->BufferQueue)->RegisterCallback(st->BufferQueue, bqPlayerCallback, st); if (SL_RESULT_SUCCESS != r) return ENODEV; r = (*st->bqPlayerPlay)->SetPlayState(st->bqPlayerPlay, SL_PLAYSTATE_PLAYING); if (SL_RESULT_SUCCESS != r) return ENODEV; return 0; } int opensles_player_alloc(struct auplay_st **stp, const struct auplay *ap, struct auplay_prm *prm, const char *device, auplay_write_h *wh, void *arg) { struct auplay_st *st; int err; (void)device; if (!stp || !ap || !prm || !wh) return EINVAL; if (prm->fmt != AUFMT_S16LE) { warning("opensles: player: unsupported sample format (%s)\n", aufmt_name(prm->fmt)); return ENOTSUP; } debug("opensles: opening player %uHz, %uchannels\n", prm->srate, prm->ch); st = mem_zalloc(sizeof(*st), auplay_destructor); if (!st) return ENOMEM; st->ap = ap; st->wh = wh; st->arg = arg; st->sampc = prm->srate * prm->ch * PTIME / 1000; st->bufferId = 0; for (int i=0; isampv[i] = mem_zalloc(2 * st->sampc, NULL); if (!st->sampv[i]) { err = ENOMEM; goto out; } } err = createOutput(st); if (err) goto out; err = createPlayer(st, prm); if (err) goto out; /* kick-start the buffer callback */ bqPlayerCallback(st->BufferQueue, st); out: if (err) mem_deref(st); else *stp = st; return err; } baresip-1.0.0/modules/opensles/recorder.c000066400000000000000000000114511372575704200204240ustar00rootroot00000000000000/** * @file opensles/recorder.c OpenSLES audio driver -- recording * * Copyright (C) 2010 Creytiv.com */ #include #include #include #include #include #include "SLES/OpenSLES_Android.h" #include "opensles.h" #define N_REC_QUEUE_BUFFERS 2 #define PTIME 10 struct ausrc_st { const struct ausrc *as; /* inheritance */ int16_t *sampv[N_REC_QUEUE_BUFFERS]; size_t sampc; uint8_t bufferId; ausrc_read_h *rh; void *arg; SLObjectItf recObject; SLRecordItf recRecord; SLAndroidSimpleBufferQueueItf recBufferQueue; }; static void ausrc_destructor(void *arg) { struct ausrc_st *st = arg; if (st->recObject != NULL) { SLuint32 state; if (SL_RESULT_SUCCESS == (*st->recObject)->GetState(st->recObject, &state) && SL_OBJECT_STATE_UNREALIZED != state) { (*st->recObject)->Destroy(st->recObject); } } st->bufferId = 0; for (int i=0; isampv[i]); } } static void bqRecorderCallback(SLAndroidSimpleBufferQueueItf bq, void *context) { struct ausrc_st *st = context; struct auframe af = { .fmt = AUFMT_S16LE, .sampv = st->sampv[st->bufferId], .sampc = st->sampc, .timestamp = tmr_jiffies_usec() }; (void)bq; st->rh(&af, st->arg); st->bufferId = ( st->bufferId + 1 ) % N_REC_QUEUE_BUFFERS; memset(st->sampv[st->bufferId], 0, st->sampc * 2); (*st->recBufferQueue)->Enqueue(st->recBufferQueue, st->sampv[st->bufferId], st->sampc * 2); } static int createAudioRecorder(struct ausrc_st *st, struct ausrc_prm *prm) { SLDataLocator_IODevice loc_dev = {SL_DATALOCATOR_IODEVICE, SL_IODEVICE_AUDIOINPUT, SL_DEFAULTDEVICEID_AUDIOINPUT, NULL}; SLDataSource audioSrc = {&loc_dev, NULL}; SLDataLocator_AndroidSimpleBufferQueue loc_bq = { SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2 }; int speakers = prm->ch > 1 ? SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT : SL_SPEAKER_FRONT_CENTER; SLDataFormat_PCM format_pcm = {SL_DATAFORMAT_PCM, prm->ch, prm->srate * 1000, SL_PCMSAMPLEFORMAT_FIXED_16, SL_PCMSAMPLEFORMAT_FIXED_16, speakers, SL_BYTEORDER_LITTLEENDIAN}; SLDataSink audioSnk = {&loc_bq, &format_pcm}; const SLInterfaceID id[1] = {SL_IID_ANDROIDSIMPLEBUFFERQUEUE}; const SLboolean req[1] = {SL_BOOLEAN_TRUE}; SLresult r; r = (*engineEngine)->CreateAudioRecorder(engineEngine, &st->recObject, &audioSrc, &audioSnk, 1, id, req); if (SL_RESULT_SUCCESS != r) { warning("opensles: CreateAudioRecorder failed: r = %d\n", r); return ENODEV; } r = (*st->recObject)->Realize(st->recObject, SL_BOOLEAN_FALSE); if (SL_RESULT_SUCCESS != r) return ENODEV; r = (*st->recObject)->GetInterface(st->recObject, SL_IID_RECORD, &st->recRecord); if (SL_RESULT_SUCCESS != r) return ENODEV; r = (*st->recObject)->GetInterface(st->recObject, SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &st->recBufferQueue); if (SL_RESULT_SUCCESS != r) return ENODEV; r = (*st->recBufferQueue)->RegisterCallback(st->recBufferQueue, bqRecorderCallback, st); if (SL_RESULT_SUCCESS != r) return ENODEV; return 0; } static int startRecording(struct ausrc_st *st) { SLresult r; (*st->recRecord)->SetRecordState(st->recRecord, SL_RECORDSTATE_STOPPED); (*st->recBufferQueue)->Clear(st->recBufferQueue); st->bufferId = 0; r = (*st->recBufferQueue)->Enqueue(st->recBufferQueue, st->sampv[st->bufferId], st->sampc * 2); if (SL_RESULT_SUCCESS != r) return ENODEV; r = (*st->recRecord)->SetRecordState(st->recRecord, SL_RECORDSTATE_RECORDING); if (SL_RESULT_SUCCESS != r) return ENODEV; return 0; } int opensles_recorder_alloc(struct ausrc_st **stp, const struct ausrc *as, struct media_ctx **ctx, struct ausrc_prm *prm, const char *device, ausrc_read_h *rh, ausrc_error_h *errh, void *arg) { struct ausrc_st *st; int err; (void)ctx; (void)device; (void)errh; if (!stp || !as || !prm || !rh) return EINVAL; if (prm->fmt != AUFMT_S16LE) { warning("opensles: record: unsupported sample format (%s)\n", aufmt_name(prm->fmt)); return ENOTSUP; } debug("opensles: opening recorder %uHz, %uchannels\n", prm->srate, prm->ch); st = mem_zalloc(sizeof(*st), ausrc_destructor); if (!st) return ENOMEM; st->as = as; st->rh = rh; st->arg = arg; st->sampc = prm->srate * prm->ch * PTIME / 1000; st->bufferId = 0; for (int i=0; isampv[i] = mem_zalloc(2 * st->sampc, NULL); if (!st->sampv[i]) { err = ENOMEM; goto out; } } err = createAudioRecorder(st, prm); if (err) goto out; err = startRecording(st); if (err) { warning("opensles: failed to start recorder\n"); goto out; } out: if (err) mem_deref(st); else *stp = st; return err; } baresip-1.0.0/modules/opus/000077500000000000000000000000001372575704200156075ustar00rootroot00000000000000baresip-1.0.0/modules/opus/decode.c000066400000000000000000000054141372575704200172020ustar00rootroot00000000000000/** * @file opus/decode.c Opus Decode * * Copyright (C) 2010 Creytiv.com */ #include #include #include #include #include "opus.h" struct audec_state { OpusDecoder *dec; unsigned ch; }; static void destructor(void *arg) { struct audec_state *ads = arg; if (ads->dec) opus_decoder_destroy(ads->dec); } int opus_decode_update(struct audec_state **adsp, const struct aucodec *ac, const char *fmtp) { struct audec_state *ads; int opuserr, err = 0; (void)fmtp; if (!adsp || !ac || !ac->ch) return EINVAL; ads = *adsp; if (ads) return 0; ads = mem_zalloc(sizeof(*ads), destructor); if (!ads) return ENOMEM; ads->ch = ac->ch; ads->dec = opus_decoder_create(ac->srate, ac->ch, &opuserr); if (!ads->dec) { warning("opus: decoder create: %s\n", opus_strerror(opuserr)); err = ENOMEM; goto out; } out: if (err) mem_deref(ads); else *adsp = ads; return err; } int opus_decode_frm(struct audec_state *ads, int fmt, void *sampv, size_t *sampc, bool marker, const uint8_t *buf, size_t len) { int n; (void)marker; if (!ads || !sampv || !sampc || !buf) return EINVAL; switch (fmt) { case AUFMT_S16LE: n = opus_decode(ads->dec, buf, (opus_int32)len, sampv, (int)(*sampc/ads->ch), 0); if (n < 0) { warning("opus: decode error: %s\n", opus_strerror(n)); return EPROTO; } break; case AUFMT_FLOAT: n = opus_decode_float(ads->dec, buf, (opus_int32)len, sampv, (int)(*sampc/ads->ch), 0); if (n < 0) { warning("opus: float decode error: %s\n", opus_strerror(n)); return EPROTO; } break; default: return ENOTSUP; } *sampc = n * ads->ch; return 0; } int opus_decode_pkloss(struct audec_state *ads, int fmt, void *sampv, size_t *sampc, const uint8_t *buf, size_t len) { int n; opus_int32 frame_size; size_t nsamp = 0; bool fec; if (!ads || !sampv || !sampc) return EINVAL; /* * FEC=0 -> use PLC * FEC=1 -> use inband FEC */ fec = opus_packet_loss > 0; opus_decoder_ctl(ads->dec, OPUS_GET_LAST_PACKET_DURATION(&frame_size)); switch (fmt) { case AUFMT_S16LE: n = opus_decode(ads->dec, fec ? buf : NULL, fec ? (opus_int32)len : 0, sampv, (int)(frame_size), fec); if (n < 0) { warning("opus: decode error: %s\n", opus_strerror(n)); return EPROTO; } break; case AUFMT_FLOAT: n = opus_decode_float(ads->dec, fec ? buf : NULL, fec ? (opus_int32)len : 0, sampv, (int)(frame_size), fec); if (n < 0) { warning("opus: decode error: %s\n", opus_strerror(n)); return EPROTO; } break; default: return ENOTSUP; } nsamp = (n * ads->ch); if (nsamp > *sampc) { warning("opus: pkloss: buffer too small.\n"); return ENOMEM; } *sampc = nsamp; return 0; } baresip-1.0.0/modules/opus/encode.c000066400000000000000000000112501372575704200172070ustar00rootroot00000000000000/** * @file opus/encode.c Opus Encode * * Copyright (C) 2010 Creytiv.com */ #include #include #include #include #include "opus.h" struct auenc_state { OpusEncoder *enc; unsigned ch; }; static void destructor(void *arg) { struct auenc_state *aes = arg; if (aes->enc) opus_encoder_destroy(aes->enc); } static opus_int32 srate2bw(opus_int32 srate) { if (srate >= 48000) return OPUS_BANDWIDTH_FULLBAND; else if (srate >= 24000) return OPUS_BANDWIDTH_SUPERWIDEBAND; else if (srate >= 16000) return OPUS_BANDWIDTH_WIDEBAND; else if (srate >= 12000) return OPUS_BANDWIDTH_MEDIUMBAND; else return OPUS_BANDWIDTH_NARROWBAND; } #if 0 static const char *bwname(opus_int32 bw) { switch (bw) { case OPUS_BANDWIDTH_FULLBAND: return "full"; case OPUS_BANDWIDTH_SUPERWIDEBAND: return "superwide"; case OPUS_BANDWIDTH_WIDEBAND: return "wide"; case OPUS_BANDWIDTH_MEDIUMBAND: return "medium"; case OPUS_BANDWIDTH_NARROWBAND: return "narrow"; default: return "???"; } } static const char *chname(opus_int32 ch) { switch (ch) { case OPUS_AUTO: return "auto"; case 1: return "mono"; case 2: return "stereo"; default: return "???"; } } #endif int opus_encode_update(struct auenc_state **aesp, const struct aucodec *ac, struct auenc_param *param, const char *fmtp) { struct auenc_state *aes; struct opus_param prm, conf_prm; opus_int32 fch, vbr; const struct aucodec *auc = ac; (void)param; if (!aesp || !ac || !ac->ch) return EINVAL; debug("opus: encoder fmtp (%s)\n", fmtp); /* Save the incoming OPUS parameters from SDP offer */ if (str_isset(fmtp)) { opus_mirror_params(fmtp); } aes = *aesp; if (!aes) { const opus_int32 complex = opus_complexity; int opuserr; aes = mem_zalloc(sizeof(*aes), destructor); if (!aes) return ENOMEM; aes->ch = ac->ch; aes->enc = opus_encoder_create(ac->srate, ac->ch, opus_application, &opuserr); if (!aes->enc) { warning("opus: encoder create: %s\n", opus_strerror(opuserr)); mem_deref(aes); return ENOMEM; } (void)opus_encoder_ctl(aes->enc, OPUS_SET_COMPLEXITY(complex)); *aesp = aes; } prm.srate = 48000; prm.bitrate = OPUS_AUTO; prm.stereo = 1; prm.cbr = 0; prm.inband_fec = 0; prm.dtx = 0; opus_decode_fmtp(&prm, fmtp); conf_prm.bitrate = OPUS_AUTO; opus_decode_fmtp(&conf_prm, auc->fmtp); if ((prm.bitrate == OPUS_AUTO) || ((conf_prm.bitrate != OPUS_AUTO) && (conf_prm.bitrate < prm.bitrate))) prm.bitrate = conf_prm.bitrate; fch = prm.stereo ? OPUS_AUTO : 1; vbr = prm.cbr ? 0 : 1; /* override local bitrate */ if (param && param->bitrate) prm.bitrate = param->bitrate; (void)opus_encoder_ctl(aes->enc, OPUS_SET_MAX_BANDWIDTH(srate2bw(prm.srate))); (void)opus_encoder_ctl(aes->enc, OPUS_SET_BITRATE(prm.bitrate)); (void)opus_encoder_ctl(aes->enc, OPUS_SET_FORCE_CHANNELS(fch)); (void)opus_encoder_ctl(aes->enc, OPUS_SET_VBR(vbr)); (void)opus_encoder_ctl(aes->enc, OPUS_SET_INBAND_FEC(prm.inband_fec)); (void)opus_encoder_ctl(aes->enc, OPUS_SET_DTX(prm.dtx)); if (opus_packet_loss) { opus_encoder_ctl(aes->enc, OPUS_SET_PACKET_LOSS_PERC(opus_packet_loss)); } #if 0 { opus_int32 bw, complex; (void)opus_encoder_ctl(aes->enc, OPUS_GET_MAX_BANDWIDTH(&bw)); (void)opus_encoder_ctl(aes->enc, OPUS_GET_BITRATE(&prm.bitrate)); (void)opus_encoder_ctl(aes->enc, OPUS_GET_FORCE_CHANNELS(&fch)); (void)opus_encoder_ctl(aes->enc, OPUS_GET_VBR(&vbr)); (void)opus_encoder_ctl(aes->enc, OPUS_GET_INBAND_FEC(&prm.inband_fec)); (void)opus_encoder_ctl(aes->enc, OPUS_GET_DTX(&prm.dtx)); (void)opus_encoder_ctl(aes->enc, OPUS_GET_COMPLEXITY(&complex)); debug("opus: encode bw=%s bitrate=%i fch=%s " "vbr=%i fec=%i dtx=%i complex=%i\n", bwname(bw), prm.bitrate, chname(fch), vbr, prm.inband_fec, prm.dtx, complex); } #endif return 0; } int opus_encode_frm(struct auenc_state *aes, bool *marker, uint8_t *buf, size_t *len, int fmt, const void *sampv, size_t sampc) { opus_int32 n; (void)marker; if (!aes || !buf || !len || !sampv) return EINVAL; switch (fmt) { case AUFMT_S16LE: n = opus_encode(aes->enc, sampv, (int)(sampc/aes->ch), buf, (opus_int32)(*len)); if (n < 0) { warning("opus: encode error: %s\n", opus_strerror((int)n)); return EPROTO; } break; case AUFMT_FLOAT: n = opus_encode_float(aes->enc, sampv, (int)(sampc/aes->ch), buf, (opus_int32)(*len)); if (n < 0) { warning("opus: float encode error: %s\n", opus_strerror((int)n)); return EPROTO; } break; default: return ENOTSUP; } *len = n; return 0; } baresip-1.0.0/modules/opus/module.mk000066400000000000000000000003131372575704200174220ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # MOD := opus $(MOD)_SRCS += decode.c $(MOD)_SRCS += encode.c $(MOD)_SRCS += opus.c $(MOD)_SRCS += sdp.c $(MOD)_LFLAGS += -lopus -lm include mk/mod.mk baresip-1.0.0/modules/opus/opus.c000066400000000000000000000107541372575704200167500ustar00rootroot00000000000000/** * @file opus.c Opus Audio Codec * * Copyright (C) 2010 Creytiv.com */ #include #include #include #include "opus.h" /** * @defgroup opus opus * * The OPUS audio codec * * Supported version: libopus 1.0.0 or later * * Configuration options: * \verbatim opus_stereo yes # Request peer to send stereo opus_sprop_stereo yes # Sending stereo opus_bitrate 128000 # Average bitrate in [bps] opus_cbr {yes,no} # Constant Bitrate (inverse of VBR) opus_inbandfec {yes,no} # Enable inband Forward Error Correction (FEC) opus_dtx {yes,no} # Enable Discontinuous Transmission (DTX) opus_complexity {0-10} # Encoder's computational complexity (10 max) opus_application {audio, voip} # Encoder's intended application opus_packet_loss {0-100} # Expected packet loss for FEC \endverbatim * * References: * * RFC 6716 Definition of the Opus Audio Codec * RFC 7587 RTP Payload Format for the Opus Speech and Audio Codec * * http://opus-codec.org/downloads/ */ static bool opus_mirror; static char fmtp[256] = ""; static char fmtp_mirror[256]; uint32_t opus_complexity = 10; opus_int32 opus_application = OPUS_APPLICATION_AUDIO; opus_int32 opus_packet_loss = 0; static int opus_fmtp_enc(struct mbuf *mb, const struct sdp_format *fmt, bool offer, void *arg) { bool mirror; (void)arg; (void)offer; if (!mb || !fmt) return 0; mirror = !offer && str_isset(fmtp_mirror); return mbuf_printf(mb, "a=fmtp:%s %s\r\n", fmt->id, mirror ? fmtp_mirror : fmtp); } static struct aucodec opus = { .name = "opus", .srate = 48000, .crate = 48000, .ch = 2, .pch = 2, .fmtp = fmtp, .encupdh = opus_encode_update, .ench = opus_encode_frm, .decupdh = opus_decode_update, .dech = opus_decode_frm, .plch = opus_decode_pkloss, }; void opus_mirror_params(const char *x) { if (!opus_mirror) return; info("opus: mirror parameters: \"%s\"\n", x); str_ncpy(fmtp_mirror, x, sizeof(fmtp_mirror)); } static int module_init(void) { struct conf *conf = conf_cur(); uint32_t value; char *p = fmtp + str_len(fmtp); bool b, stereo = true, sprop_stereo = true; struct pl pl; int n = 0; conf_get_bool(conf, "opus_stereo", &stereo); conf_get_bool(conf, "opus_sprop_stereo", &sprop_stereo); if (!stereo || !sprop_stereo) opus.ch = 1; /* always set stereo parameter first */ n = re_snprintf(p, sizeof(fmtp) - str_len(p), "stereo=%d;sprop-stereo=%d", stereo, sprop_stereo); if (n <= 0) return ENOMEM; p += n; if (0 == conf_get_u32(conf, "opus_bitrate", &value)) { n = re_snprintf(p, sizeof(fmtp) - str_len(p), ";maxaveragebitrate=%d", value); if (n <= 0) return ENOMEM; p += n; } if (0 == conf_get_u32(conf, "opus_samplerate", &value)) { if ((value != 8000) && (value != 12000) && (value != 16000) && (value != 24000) && (value != 48000)) { warning("opus: invalid samplerate: %d\n", value); return EINVAL; } opus.srate = value; } if (0 == conf_get_bool(conf, "opus_cbr", &b)) { n = re_snprintf(p, sizeof(fmtp) - str_len(p), ";cbr=%d", b); if (n <= 0) return ENOMEM; p += n; } if (0 == conf_get_bool(conf, "opus_inbandfec", &b)) { n = re_snprintf(p, sizeof(fmtp) - str_len(p), ";useinbandfec=%d", b); if (n <= 0) return ENOMEM; p += n; } if (0 == conf_get_bool(conf, "opus_dtx", &b)) { n = re_snprintf(p, sizeof(fmtp) - str_len(p), ";usedtx=%d", b); if (n <= 0) return ENOMEM; p += n; } (void)conf_get_bool(conf, "opus_mirror", &opus_mirror); if (opus_mirror) { opus.fmtp = NULL; opus.fmtp_ench = opus_fmtp_enc; } (void)conf_get_u32(conf, "opus_complexity", &opus_complexity); if (opus_complexity > 10) opus_complexity = 10; if (!conf_get(conf, "opus_application", &pl)) { if (!pl_strcasecmp(&pl, "audio")) opus_application = OPUS_APPLICATION_AUDIO; else if (!pl_strcasecmp(&pl, "voip")) opus_application = OPUS_APPLICATION_VOIP; else { warning("opus: unknown encoder application: %r\n", &pl); return EINVAL; } } if (0 == conf_get_u32(conf, "opus_packet_loss", &value)) { if (value > 100) opus_packet_loss = 100; else opus_packet_loss = value; } debug("opus: fmtp=\"%s\"\n", fmtp); aucodec_register(baresip_aucodecl(), &opus); return 0; } static int module_close(void) { aucodec_unregister(&opus); return 0; } EXPORT_SYM const struct mod_export DECL_EXPORTS(opus) = { "opus", "audio codec", module_init, module_close, }; baresip-1.0.0/modules/opus/opus.h000066400000000000000000000021551372575704200167510ustar00rootroot00000000000000/** * @file opus.h Private Opus Interface * * Copyright (C) 2010 Creytiv.com */ struct opus_param { opus_int32 srate; opus_int32 bitrate; opus_int32 stereo; opus_int32 cbr; opus_int32 inband_fec; opus_int32 dtx; }; /* Encode */ int opus_encode_update(struct auenc_state **aesp, const struct aucodec *ac, struct auenc_param *prm, const char *fmtp); int opus_encode_frm(struct auenc_state *aes, bool *marker, uint8_t *buf, size_t *len, int fmt, const void *sampv, size_t sampc); extern uint32_t opus_complexity; extern opus_int32 opus_application; extern opus_int32 opus_packet_loss; /* Decode */ int opus_decode_update(struct audec_state **adsp, const struct aucodec *ac, const char *fmtp); int opus_decode_frm(struct audec_state *ads, int fmt, void *sampv, size_t *sampc, bool marker, const uint8_t *buf, size_t len); int opus_decode_pkloss(struct audec_state *st, int fmt, void *sampv, size_t *sampc, const uint8_t *buf, size_t len); /* SDP */ void opus_decode_fmtp(struct opus_param *prm, const char *fmtp); void opus_mirror_params(const char *fmtp); baresip-1.0.0/modules/opus/sdp.c000066400000000000000000000017711372575704200165470ustar00rootroot00000000000000/** * @file opus/sdp.c Opus SDP Functions * * Copyright (C) 2010 Creytiv.com */ #include #include #include #include "opus.h" static void assign_if(opus_int32 *v, const struct pl *pl, uint32_t min, uint32_t max) { const uint32_t val = pl_u32(pl); if (val < min || val > max) return; *v = val; } void opus_decode_fmtp(struct opus_param *prm, const char *fmtp) { struct pl pl, val; if (!prm || !fmtp) return; pl_set_str(&pl, fmtp); if (fmt_param_get(&pl, "maxplaybackrate", &val)) assign_if(&prm->srate, &val, 8000, 48000); if (fmt_param_get(&pl, "maxaveragebitrate", &val)) assign_if(&prm->bitrate, &val, 6000, 510000); if (fmt_param_get(&pl, "stereo", &val)) assign_if(&prm->stereo, &val, 0, 1); if (fmt_param_get(&pl, "cbr", &val)) assign_if(&prm->cbr, &val, 0, 1); if (fmt_param_get(&pl, "useinbandfec", &val)) assign_if(&prm->inband_fec, &val, 0, 1); if (fmt_param_get(&pl, "usedtx", &val)) assign_if(&prm->dtx, &val, 0, 1); } baresip-1.0.0/modules/opus_multistream/000077500000000000000000000000001372575704200202355ustar00rootroot00000000000000baresip-1.0.0/modules/opus_multistream/decode.c000066400000000000000000000054301372575704200216260ustar00rootroot00000000000000/** * @file opus_multistream/decode.c Opus Multistream Decode * * Copyright (C) 2019 Creytiv.com */ #include #include #include #include #include "opus_multistream.h" struct audec_state { OpusMSDecoder *dec; unsigned ch; }; static void destructor(void *arg) { struct audec_state *ads = arg; if (ads->dec) opus_multistream_decoder_destroy(ads->dec); } int opus_multistream_decode_update(struct audec_state **adsp, const struct aucodec *ac, const char *fmtp) { struct audec_state *ads; unsigned ch; unsigned char mapping[256]; int opuserr, err = 0; (void)fmtp; if (!adsp || !ac || !ac->ch) return EINVAL; ads = *adsp; if (ads) return 0; /* create one mapping per channel */ for (ch=0; chch; ch++) { if (ch >= 256) { warning("opus: Exceeding the acceptable" " 255 channel-mappings\n"); return EINVAL; } else { mapping[ch] = ch; } } ads = mem_zalloc(sizeof(*ads), destructor); if (!ads) return ENOMEM; ads->ch = ac->ch; ads->dec = opus_multistream_decoder_create(ac->srate, ac->ch, opus_ms_streams, opus_ms_c_streams, mapping, &opuserr); if (!ads->dec) { warning("opus_multistream: decoder create: %s\n", opus_strerror(opuserr)); err = ENOMEM; goto out; } out: if (err) mem_deref(ads); else *adsp = ads; return err; } int opus_multistream_decode_frm(struct audec_state *ads, int fmt, void *sampv, size_t *sampc, bool marker, const uint8_t *buf, size_t len) { int n; (void)marker; if (!ads || !sampv || !sampc || !buf) return EINVAL; switch (fmt) { case AUFMT_S16LE: n = opus_multistream_decode(ads->dec, buf, (opus_int32)len, sampv, (int)(*sampc/ads->ch), 0); if (n < 0) { warning("opus_multistream: decode error: %s\n", opus_strerror(n)); return EPROTO; } break; case AUFMT_FLOAT: n = opus_multistream_decode_float(ads->dec, buf, (opus_int32)len, sampv, (int)(*sampc/ads->ch), 0); if (n < 0) { warning("opus_multistream: float decode error: %s\n", opus_strerror(n)); return EPROTO; } break; default: return ENOTSUP; } *sampc = n * ads->ch; return 0; } int opus_multistream_decode_pkloss(struct audec_state *ads, int fmt, void *sampv, size_t *sampc, const uint8_t *buf, size_t len) { int n; (void)buf; (void)len; if (!ads || !sampv || !sampc) return EINVAL; switch (fmt) { case AUFMT_S16LE: n = opus_multistream_decode(ads->dec, NULL, 0, sampv, (int)(*sampc/ads->ch), 0); if (n < 0) return EPROTO; break; case AUFMT_FLOAT: n = opus_multistream_decode_float(ads->dec, NULL, 0, sampv, (int)(*sampc/ads->ch), 0); if (n < 0) return EPROTO; break; default: return ENOTSUP; } *sampc = n * ads->ch; return 0; } baresip-1.0.0/modules/opus_multistream/encode.c000066400000000000000000000126341372575704200216440ustar00rootroot00000000000000/** * @file opus_multistream/encode.c Opus Multistream Encode * * Copyright (C) 2019 Creytiv.com */ #include #include #include #include #include "opus_multistream.h" struct auenc_state { OpusMSEncoder *enc; unsigned ch; }; static void destructor(void *arg) { struct auenc_state *aes = arg; if (aes->enc) opus_multistream_encoder_destroy(aes->enc); } static opus_int32 srate2bw(opus_int32 srate) { if (srate >= 48000) return OPUS_BANDWIDTH_FULLBAND; else if (srate >= 24000) return OPUS_BANDWIDTH_SUPERWIDEBAND; else if (srate >= 16000) return OPUS_BANDWIDTH_WIDEBAND; else if (srate >= 12000) return OPUS_BANDWIDTH_MEDIUMBAND; else return OPUS_BANDWIDTH_NARROWBAND; } #if 0 static const char *bwname(opus_int32 bw) { switch (bw) { case OPUS_BANDWIDTH_FULLBAND: return "full"; case OPUS_BANDWIDTH_SUPERWIDEBAND: return "superwide"; case OPUS_BANDWIDTH_WIDEBAND: return "wide"; case OPUS_BANDWIDTH_MEDIUMBAND: return "medium"; case OPUS_BANDWIDTH_NARROWBAND: return "narrow"; default: return "???"; } } static const char *chname(opus_int32 ch) { switch (ch) { case OPUS_AUTO: return "auto"; case 1: return "mono"; case 2: return "stereo"; default: return "???"; } } #endif int opus_multistream_encode_update(struct auenc_state **aesp, const struct aucodec *ac, struct auenc_param *param, const char *fmtp) { struct auenc_state *aes; unsigned ch; unsigned char mapping[256]; struct opus_multistream_param prm, conf_prm; opus_int32 fch, vbr; const struct aucodec *auc = ac; (void)param; if (!aesp || !ac || !ac->ch) return EINVAL; debug("opus_multistream: encoder fmtp (%s)\n", fmtp); /* Save the incoming OPUS parameters from SDP offer */ if (str_isset(fmtp)) { opus_multistream_mirror_params(fmtp); } /* create one mapping per channel */ for (ch=0; chch; ch++) { if (ch >= 256) { warning("opus: Exceeding the acceptable" " 255 channel-mappings"); return EINVAL; } else { mapping[ch] = ch; } } aes = *aesp; if (!aes) { const opus_int32 complex = opus_ms_complexity; int opuserr; aes = mem_zalloc(sizeof(*aes), destructor); if (!aes) return ENOMEM; aes->ch = ac->ch; aes->enc = opus_multistream_encoder_create(ac->srate, ac->ch, opus_ms_streams, opus_ms_c_streams, mapping, opus_ms_application, &opuserr); if (!aes->enc) { warning("opus_multistream: encoder create: %s\n", opus_strerror(opuserr)); mem_deref(aes); return ENOMEM; } (void)opus_multistream_encoder_ctl(aes->enc, OPUS_SET_COMPLEXITY(complex)); *aesp = aes; } prm.srate = 48000; prm.bitrate = OPUS_AUTO; prm.stereo = 1; prm.cbr = 0; prm.inband_fec = 0; prm.dtx = 0; opus_multistream_decode_fmtp(&prm, fmtp); conf_prm.bitrate = OPUS_AUTO; opus_multistream_decode_fmtp(&conf_prm, auc->fmtp); if ((prm.bitrate == OPUS_AUTO) || ((conf_prm.bitrate != OPUS_AUTO) && (conf_prm.bitrate < prm.bitrate))) prm.bitrate = conf_prm.bitrate; fch = prm.stereo ? OPUS_AUTO : 1; vbr = prm.cbr ? 0 : 1; /* override local bitrate */ if (param && param->bitrate) prm.bitrate = param->bitrate; (void)opus_multistream_encoder_ctl(aes->enc, OPUS_SET_MAX_BANDWIDTH(srate2bw(prm.srate))); (void)opus_multistream_encoder_ctl(aes->enc, OPUS_SET_BITRATE(prm.bitrate)); (void)opus_multistream_encoder_ctl(aes->enc, OPUS_SET_FORCE_CHANNELS(fch)); (void)opus_multistream_encoder_ctl(aes->enc, OPUS_SET_VBR(vbr)); (void)opus_multistream_encoder_ctl(aes->enc, OPUS_SET_INBAND_FEC(prm.inband_fec)); (void)opus_multistream_encoder_ctl(aes->enc, OPUS_SET_DTX(prm.dtx)); #if 0 { opus_int32 bw, complex; (void)opus_multistream_encoder_ctl(aes->enc, OPUS_GET_MAX_BANDWIDTH(&bw)); (void)opus_multistream_encoder_ctl(aes->enc, OPUS_GET_BITRATE(&prm.bitrate)); (void)opus_multistream_encoder_ctl(aes->enc, OPUS_GET_FORCE_CHANNELS(&fch)); (void)opus_multistream_encoder_ctl(aes->enc, OPUS_GET_VBR(&vbr)); (void)opus_multistream_encoder_ctl(aes->enc, OPUS_GET_INBAND_FEC(&prm.inband_fec)); (void)opus_multistream_encoder_ctl(aes->enc, OPUS_GET_DTX(&prm.dtx)); (void)opus_multistream_encoder_ctl(aes->enc, OPUS_GET_COMPLEXITY(&complex)); debug("opus_multistream: encode bw=%s bitrate=%i fch=%s " "vbr=%i fec=%i dtx=%i complex=%i\n", bwname(bw), prm.bitrate, chname(fch), vbr, prm.inband_fec, prm.dtx, complex); } #endif return 0; } int opus_multistream_encode_frm(struct auenc_state *aes, bool *marker, uint8_t *buf, size_t *len, int fmt, const void *sampv, size_t sampc) { opus_int32 n; (void)marker; if (!aes || !buf || !len || !sampv) return EINVAL; switch (fmt) { case AUFMT_S16LE: n = opus_multistream_encode(aes->enc, sampv, (int)(sampc/aes->ch), buf, (opus_int32)(*len)); if (n < 0) { warning("opus_multistream: encode error: %s\n", opus_strerror((int)n)); return EPROTO; } break; case AUFMT_FLOAT: n = opus_multistream_encode_float(aes->enc, sampv, (int)(sampc/aes->ch), buf, (opus_int32)(*len)); if (n < 0) { warning("opus_multistream: float encode error: %s\n", opus_strerror((int)n)); return EPROTO; } break; default: return ENOTSUP; } *len = n; return 0; } baresip-1.0.0/modules/opus_multistream/module.mk000066400000000000000000000003431372575704200220530ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2019 Creytiv.com # MOD := opus_multistream $(MOD)_SRCS += decode.c $(MOD)_SRCS += encode.c $(MOD)_SRCS += opus_multistream.c $(MOD)_SRCS += sdp.c $(MOD)_LFLAGS += -lopus -lm include mk/mod.mk baresip-1.0.0/modules/opus_multistream/opus_multistream.c000066400000000000000000000112111372575704200240110ustar00rootroot00000000000000/** * @file opus_multistream.c Opus Multistream Audio Codec * * Copyright (C) 2019 Creytiv.com */ #include #include #include #include "opus_multistream.h" /** * @defgroup opus opus * * The OPUS multistream audio codec * * Supported version: libopus 1.0.0 or later * * Configuration options: * \verbatim opus_stereo yes # Request peer to send stereo opus_sprop_stereo yes # Sending stereo opus_bitrate 128000 # Average bitrate in [bps] opus_cbr {yes,no} # Constant Bitrate (inverse of VBR) opus_inbandfec {yes,no} # Enable inband Forward Error Correction (FEC) opus_dtx {yes,no} # Enable Discontinuous Transmission (DTX) opus_complexity {0-10} # Encoder's computational complexity (10 max) opus_application {audio, voip} # Encoder's intended application \endverbatim * * References: * * RFC 6716 Definition of the Opus Audio Codec * RFC 7587 RTP Payload Format for the Opus Speech and Audio Codec * * http://opus-codec.org/downloads/ */ static bool opus_mirror; static char fmtp[256] = ""; static char fmtp_mirror[256]; uint32_t opus_ms_complexity = 10; opus_int32 opus_ms_application = OPUS_APPLICATION_AUDIO; uint32_t opus_ms_channels = 2; uint32_t opus_ms_streams = 2; uint32_t opus_ms_c_streams = 2; static int opus_multistream_fmtp_enc(struct mbuf *mb, const struct sdp_format *fmt, bool offer, void *arg) { bool mirror; (void)arg; (void)offer; if (!mb || !fmt) return 0; mirror = !offer && str_isset(fmtp_mirror); return mbuf_printf(mb, "a=fmtp:%s %s\r\n", fmt->id, mirror ? fmtp_mirror : fmtp); } static struct aucodec opus_multistream = { .name = "opus_multistream", /* NOTE: not standard */ .srate = 48000, .crate = 48000, .ch = 2, /* NOTE: configurable */ .pch = 2, .fmtp = fmtp, .encupdh = opus_multistream_encode_update, .ench = opus_multistream_encode_frm, .decupdh = opus_multistream_decode_update, .dech = opus_multistream_decode_frm, .plch = opus_multistream_decode_pkloss, }; void opus_multistream_mirror_params(const char *x) { if (!opus_mirror) return; info("opus_multistream: mirror parameters: \"%s\"\n", x); str_ncpy(fmtp_mirror, x, sizeof(fmtp_mirror)); } static int module_init(void) { struct conf *conf = conf_cur(); uint32_t value; char *p = fmtp + str_len(fmtp); bool b, stereo = true, sprop_stereo = true; struct pl pl; int n = 0; conf_get_bool(conf, "opus_stereo", &stereo); conf_get_bool(conf, "opus_sprop_stereo", &sprop_stereo); /* always set stereo parameter first */ n = re_snprintf(p, sizeof(fmtp) - str_len(p), "stereo=%d;sprop-stereo=%d", stereo, sprop_stereo); if (n <= 0) return ENOMEM; p += n; if (0 == conf_get_u32(conf, "opus_bitrate", &value)) { n = re_snprintf(p, sizeof(fmtp) - str_len(p), ";maxaveragebitrate=%d", value); if (n <= 0) return ENOMEM; p += n; } if (0 == conf_get_bool(conf, "opus_cbr", &b)) { n = re_snprintf(p, sizeof(fmtp) - str_len(p), ";cbr=%d", b); if (n <= 0) return ENOMEM; p += n; } if (0 == conf_get_bool(conf, "opus_inbandfec", &b)) { n = re_snprintf(p, sizeof(fmtp) - str_len(p), ";useinbandfec=%d", b); if (n <= 0) return ENOMEM; p += n; } if (0 == conf_get_bool(conf, "opus_dtx", &b)) { n = re_snprintf(p, sizeof(fmtp) - str_len(p), ";usedtx=%d", b); if (n <= 0) return ENOMEM; p += n; } (void)conf_get_bool(conf, "opus_mirror", &opus_mirror); if (opus_mirror) { opus_multistream.fmtp = NULL; opus_multistream.fmtp_ench = opus_multistream_fmtp_enc; } (void)conf_get_u32(conf, "opus_complexity", &opus_ms_complexity); if (opus_ms_complexity > 10) opus_ms_complexity = 10; if (!conf_get(conf, "opus_application", &pl)) { if (!pl_strcasecmp(&pl, "audio")) opus_ms_application = OPUS_APPLICATION_AUDIO; else if (!pl_strcasecmp(&pl, "voip")) opus_ms_application = OPUS_APPLICATION_VOIP; else { warning("opus: unknown encoder application: %r\n", &pl); return EINVAL; } } (void)conf_get_u32(conf, "opus_ms_channels", &opus_ms_channels); opus_multistream.ch = opus_ms_channels; (void)conf_get_u32(conf, "opus_ms_streams", &opus_ms_streams); (void)conf_get_u32(conf, "opus_ms_c_streams", &opus_ms_c_streams); debug("opus_multistream: fmtp=\"%s\"\n", fmtp); aucodec_register(baresip_aucodecl(), &opus_multistream); return 0; } static int module_close(void) { aucodec_unregister(&opus_multistream); return 0; } EXPORT_SYM const struct mod_export DECL_EXPORTS(opus_multistream) = { "opus_multistream", "audio codec", module_init, module_close, }; baresip-1.0.0/modules/opus_multistream/opus_multistream.h000066400000000000000000000024431372575704200240250ustar00rootroot00000000000000/** * @file opus_multistream.h Private Opus Multistream Interface * * Copyright (C) 2019 Creytiv.com */ struct opus_multistream_param { opus_int32 srate; opus_int32 bitrate; opus_int32 stereo; opus_int32 cbr; opus_int32 inband_fec; opus_int32 dtx; }; /* Encode */ int opus_multistream_encode_update(struct auenc_state **aesp, const struct aucodec *ac, struct auenc_param *prm, const char *fmtp); int opus_multistream_encode_frm(struct auenc_state *aes, bool *marker, uint8_t *buf, size_t *len, int fmt, const void *sampv, size_t sampc); extern uint32_t opus_ms_complexity; extern opus_int32 opus_ms_application; extern uint32_t opus_ms_streams; extern uint32_t opus_ms_c_streams; /* Decode */ int opus_multistream_decode_update(struct audec_state **adsp, const struct aucodec *ac, const char *fmtp); int opus_multistream_decode_frm(struct audec_state *ads, int fmt, void *sampv, size_t *sampc, bool marker, const uint8_t *buf, size_t len); int opus_multistream_decode_pkloss(struct audec_state *st, int fmt, void *sampv, size_t *sampc, const uint8_t *buf, size_t len); /* SDP */ void opus_multistream_decode_fmtp(struct opus_multistream_param *prm, const char *fmtp); void opus_multistream_mirror_params(const char *fmtp); baresip-1.0.0/modules/opus_multistream/sdp.c000066400000000000000000000021071372575704200211670ustar00rootroot00000000000000/** * @file opus_multistream/sdp.c Opus Multistream SDP Functions * * Copyright (C) 2019 Creytiv.com */ #include #include #include #include "opus_multistream.h" static void assign_if(opus_int32 *v, const struct pl *pl, uint32_t min, uint32_t max) { const uint32_t val = pl_u32(pl); if (val < min || val > max) return; *v = val; } void opus_multistream_decode_fmtp(struct opus_multistream_param *prm, const char *fmtp) { struct pl pl, val; if (!prm || !fmtp) return; pl_set_str(&pl, fmtp); if (fmt_param_get(&pl, "maxplaybackrate", &val)) assign_if(&prm->srate, &val, 8000, 48000); if (fmt_param_get(&pl, "maxaveragebitrate", &val)) assign_if(&prm->bitrate, &val, 6000, 510000); if (fmt_param_get(&pl, "stereo", &val)) assign_if(&prm->stereo, &val, 0, 1); if (fmt_param_get(&pl, "cbr", &val)) assign_if(&prm->cbr, &val, 0, 1); if (fmt_param_get(&pl, "useinbandfec", &val)) assign_if(&prm->inband_fec, &val, 0, 1); if (fmt_param_get(&pl, "usedtx", &val)) assign_if(&prm->dtx, &val, 0, 1); } baresip-1.0.0/modules/oss/000077500000000000000000000000001372575704200154255ustar00rootroot00000000000000baresip-1.0.0/modules/oss/module.mk000066400000000000000000000003511372575704200172420ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # MOD := oss $(MOD)_SRCS += oss.c $(MOD)_LFLAGS += ifeq ($(OS), openbsd) $(MOD)_LFLAGS += -lossaudio endif ifeq ($(OS), netbsd) $(MOD)_LFLAGS += -lossaudio endif include mk/mod.mk baresip-1.0.0/modules/oss/oss.c000066400000000000000000000146601372575704200164040ustar00rootroot00000000000000/** * @file oss.c Open Sound System (OSS) driver * * Copyright (C) 2010 Creytiv.com */ #include #include #include #include #include #include #include #include #if defined(NETBSD) || defined(OPENBSD) #include #elif defined (LINUX) #include #else #include #endif #ifdef SOLARIS #include #endif /** * @defgroup oss oss * * Open Sound System (OSS) audio driver module * * * References: * * http://www.4front-tech.com/linux.html */ struct ausrc_st { const struct ausrc *as; /* inheritance */ pthread_t thread; bool run; int fd; struct ausrc_prm prm; int16_t *sampv; size_t sampc; ausrc_read_h *rh; ausrc_error_h *errh; void *arg; }; struct auplay_st { const struct auplay *ap; /* inheritance */ pthread_t thread; bool run; int fd; int16_t *sampv; size_t sampc; auplay_write_h *wh; void *arg; }; static struct ausrc *ausrc; static struct auplay *auplay; static char oss_dev[64] = "/dev/dsp"; /* * Automatically calculate the fragment size depending on sampling rate * and number of channels. More entries can be added to the table below. * * NOTE. Powermac 8200 and linux 2.4.18 gives: * SNDCTL_DSP_SETFRAGMENT: Invalid argument */ static int set_fragment(int fd, uint32_t sampc) { static const struct { uint16_t max; uint16_t size; } fragv[] = { {10, 7}, /* 10 x 2^7 = 1280 = 4 x 320 */ {15, 7}, /* 15 x 2^7 = 1920 = 6 x 320 */ {20, 7}, /* 20 x 2^7 = 2560 = 8 x 320 */ {25, 7}, /* 25 x 2^7 = 3200 = 10 x 320 */ {15, 8}, /* 15 x 2^8 = 3840 = 12 x 320 */ {20, 8}, /* 20 x 2^8 = 5120 = 16 x 320 */ {25, 8} /* 25 x 2^8 = 6400 = 20 x 320 */ }; size_t i; const uint32_t buf_size = 2 * sampc; for (i=0; irun) { st->run = false; pthread_join(st->thread, NULL); } if (-1 != st->fd) { (void)close(st->fd); } mem_deref(st->sampv); } static void ausrc_destructor(void *arg) { struct ausrc_st *st = arg; if (st->run) { st->run = false; pthread_join(st->thread, NULL); } if (-1 != st->fd) { (void)close(st->fd); } mem_deref(st->sampv); } static void *record_thread(void *arg) { struct ausrc_st *st = arg; struct auframe af; uint64_t sampc = 0; int n; while (st->run) { n = read(st->fd, st->sampv, st->sampc*2); if (n <= 0) continue; af.fmt = AUFMT_S16LE; af.sampv = st->sampv; af.sampc = n/2; af.timestamp = sampc * AUDIO_TIMEBASE / st->prm.srate; sampc += n/2; st->rh(&af, st->arg); } return NULL; } static void *play_thread(void *arg) { struct auplay_st *st = arg; int n; while (st->run) { st->wh(st->sampv, st->sampc, st->arg); n = write(st->fd, st->sampv, st->sampc*2); if (n < 0) { warning("oss: write: %m\n", errno); break; } } return NULL; } static int src_alloc(struct ausrc_st **stp, const struct ausrc *as, struct media_ctx **ctx, struct ausrc_prm *prm, const char *device, ausrc_read_h *rh, ausrc_error_h *errh, void *arg) { struct ausrc_st *st; int err; (void)ctx; (void)errh; if (!stp || !as || !prm || prm->fmt != AUFMT_S16LE || !rh) return EINVAL; st = mem_zalloc(sizeof(*st), ausrc_destructor); if (!st) return ENOMEM; st->fd = -1; st->rh = rh; st->errh = errh; st->arg = arg; if (!device) device = oss_dev; st->prm = *prm; st->sampc = prm->srate * prm->ch * prm->ptime / 1000; st->sampv = mem_alloc(2 * st->sampc, NULL); if (!st->sampv) { err = ENOMEM; goto out; } st->fd = open(device, O_RDONLY); if (st->fd < 0) { err = errno; goto out; } err = oss_reset(st->fd, prm->srate, prm->ch, st->sampc, 0); if (err) goto out; st->as = as; st->run = true; err = pthread_create(&st->thread, NULL, record_thread, st); if (err) { st->run = false; goto out; } out: if (err) mem_deref(st); else *stp = st; return err; } static int play_alloc(struct auplay_st **stp, const struct auplay *ap, struct auplay_prm *prm, const char *device, auplay_write_h *wh, void *arg) { struct auplay_st *st; int err; if (!stp || !ap || !prm || prm->fmt != AUFMT_S16LE || !wh) return EINVAL; st = mem_zalloc(sizeof(*st), auplay_destructor); if (!st) return ENOMEM; st->fd = -1; st->wh = wh; st->arg = arg; if (!device) device = oss_dev; st->sampc = prm->srate * prm->ch * prm->ptime / 1000; st->sampv = mem_alloc(st->sampc * 2, NULL); if (!st->sampv) { err = ENOMEM; goto out; } st->fd = open(device, O_WRONLY); if (st->fd < 0) { err = errno; goto out; } err = oss_reset(st->fd, prm->srate, prm->ch, st->sampc, 0); if (err) goto out; st->ap = ap; st->run = true; err = pthread_create(&st->thread, NULL, play_thread, st); if (err) { st->run = false; goto out; } out: if (err) mem_deref(st); else *stp = st; return err; } static int module_init(void) { int err; err = ausrc_register(&ausrc, baresip_ausrcl(), "oss", src_alloc); err |= auplay_register(&auplay, baresip_auplayl(), "oss", play_alloc); return err; } static int module_close(void) { ausrc = mem_deref(ausrc); auplay = mem_deref(auplay); return 0; } EXPORT_SYM const struct mod_export DECL_EXPORTS(oss) = { "oss", "audio", module_init, module_close, }; baresip-1.0.0/modules/pcp/000077500000000000000000000000001372575704200154035ustar00rootroot00000000000000baresip-1.0.0/modules/pcp/listener.c000066400000000000000000000037261372575704200174040ustar00rootroot00000000000000/** * @file listener.c Port Control Protocol module -- multicast listener * * Copyright (C) 2010 - 2016 Creytiv.com */ #include #include #include #include "pcp.h" /* * Listen for incoming notifications on unicast/multicast port 5350 */ struct pcp_listener { struct udp_sock *us; struct sa srv; struct sa group; pcp_msg_h *msgh; void *arg; }; static void destructor(void *arg) { struct pcp_listener *pl = arg; if (sa_isset(&pl->group, SA_ADDR)) (void)udp_multicast_leave(pl->us, &pl->group); mem_deref(pl->us); } static void udp_recv(const struct sa *src, struct mbuf *mb, void *arg) { struct pcp_listener *pl = arg; struct pcp_msg *msg; int err; #if 0 if (!sa_cmp(src, &pl->srv, SA_ADDR)) { debug("pcp: listener: ignore %zu bytes from non-server %J\n", mb->end, src); return; } #endif err = pcp_msg_decode(&msg, mb); if (err) return; /* Validate PCP request */ if (!msg->hdr.resp) { info("pcp: listener: ignore request from %J\n", src); goto out; } if (pl->msgh) pl->msgh(msg, pl->arg); out: mem_deref(msg); } int pcp_listen(struct pcp_listener **plp, const struct sa *srv, pcp_msg_h *msgh, void *arg) { struct pcp_listener *pl; struct sa laddr; int err; if (!plp || !srv || !msgh) return EINVAL; pl = mem_zalloc(sizeof(*pl), destructor); if (!pl) return ENOMEM; pl->srv = *srv; pl->msgh = msgh; pl->arg = arg; /* note: must listen on ANY to get multicast working */ sa_init(&laddr, sa_af(srv)); sa_set_port(&laddr, PCP_PORT_CLI); err = udp_listen(&pl->us, &laddr, udp_recv, pl); if (err) goto out; switch (sa_af(&laddr)) { case AF_INET: err = sa_set_str(&pl->group, "224.0.0.1", 0); break; case AF_INET6: err = sa_set_str(&pl->group, "ff02::1", 0); break; default: err = EAFNOSUPPORT; break; } if (err) goto out; err = udp_multicast_join(pl->us, &pl->group); if (err) goto out; out: if (err) mem_deref(pl); else *plp = pl; return err; } baresip-1.0.0/modules/pcp/module.mk000066400000000000000000000002721372575704200172220ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # MOD := pcp $(MOD)_SRCS += pcp.c listener.c $(MOD)_CFLAGS += -I$(SYSROOT)/local/include/rew $(MOD)_LFLAGS += -lrew include mk/mod.mk baresip-1.0.0/modules/pcp/pcp.c000066400000000000000000000150351372575704200163350ustar00rootroot00000000000000/** * @file pcp.c Port Control Protocol for Media NAT-traversal * * Copyright (C) 2010 - 2016 Creytiv.com */ #include #include #include #include "pcp.h" /** * @defgroup pcp pcp * * Port Control Protocol (PCP) * * This module implements the medianat interface with PCP, which is * the successor of the NAT-PMP protocol. */ enum { LIFETIME = 120 /* seconds */ }; struct mnat_sess { struct le le; struct list medial; mnat_estab_h *estabh; void *arg; }; struct mnat_media { struct comp { struct pcp_request *pcp; struct mnat_media *media; /* pointer to parent */ unsigned id; bool granted; } compv[2]; unsigned compc; struct le le; struct mnat_sess *sess; struct sdp_media *sdpm; uint32_t srv_epoch; }; static struct sa pcp_srv; static struct list sessl; static struct pcp_listener *lsnr; static void session_destructor(void *arg) { struct mnat_sess *sess = arg; list_unlink(&sess->le); list_flush(&sess->medial); } static void media_destructor(void *arg) { struct mnat_media *m = arg; unsigned i; list_unlink(&m->le); for (i=0; icompc; i++) { struct comp *comp = &m->compv[i]; mem_deref(comp->pcp); } mem_deref(m->sdpm); } static void complete(struct mnat_sess *sess, int err, const char *reason) { mnat_estab_h *estabh = sess->estabh; void *arg = sess->arg; sess->estabh = NULL; if (estabh) { estabh(err, 0, reason, arg); } } static bool all_components_granted(const struct mnat_media *m) { unsigned i; if (!m || !m->compc) return false; for (i=0; icompc; i++) { const struct comp *comp = &m->compv[i]; if (!comp->granted) return false; } return true; } static void is_complete(struct mnat_sess *sess) { struct le *le; for (le = sess->medial.head; le; le = le->next) { struct mnat_media *m = le->data; if (!all_components_granted(m)) return; } complete(sess, 0, "done"); } static void pcp_resp_handler(int err, struct pcp_msg *msg, void *arg) { struct comp *comp = arg; struct mnat_media *m = comp->media; const struct pcp_map *map; if (err) { warning("pcp: mapping error: %m\n", err); complete(m->sess, err, NULL); return; } else if (msg->hdr.result != PCP_SUCCESS) { warning("pcp: mapping error: %s\n", pcp_result_name(msg->hdr.result)); re_printf("%H\n", pcp_msg_print, msg); complete(m->sess, EPROTO, "pcp error"); return; } map = pcp_msg_payload(msg); info("pcp: %s: mapping for %s:" " internal_port=%u, external_addr=%J\n", sdp_media_name(m->sdpm), comp->id==1 ? "RTP" : "RTCP", map->int_port, &map->ext_addr); /* Update SDP media with external IP-address mapping */ if (comp->id == 1) sdp_media_set_laddr(m->sdpm, &map->ext_addr); else sdp_media_set_laddr_rtcp(m->sdpm, &map->ext_addr); comp->granted = true; m->srv_epoch = msg->hdr.epoch; is_complete(m->sess); } static int session_alloc(struct mnat_sess **sessp, const struct mnat *mnat, struct dnsc *dnsc, int af, const struct stun_uri *srv, const char *user, const char *pass, struct sdp_session *ss, bool offerer, mnat_estab_h *estabh, void *arg) { struct mnat_sess *sess; int err = 0; (void)mnat; (void)af; (void)user; (void)pass; (void)ss; (void)offerer; if (!sessp || !dnsc || !srv || !ss || !estabh) return EINVAL; sess = mem_zalloc(sizeof(*sess), session_destructor); if (!sess) return ENOMEM; sess->estabh = estabh; sess->arg = arg; list_append(&sessl, &sess->le, sess); if (err) mem_deref(sess); else *sessp = sess; return err; } static int media_alloc(struct mnat_media **mp, struct mnat_sess *sess, struct udp_sock *sock1, struct udp_sock *sock2, struct sdp_media *sdpm, mnat_connected_h *connh, void *arg) { struct mnat_media *m; struct sa laddr; struct pcp_map map; unsigned i; int err = 0; (void)connh; (void)arg; if (!mp || !sess || !sdpm) return EINVAL; m = mem_zalloc(sizeof(*m), media_destructor); if (!m) return ENOMEM; m->compc = sock2 ? 2 : 1; list_append(&sess->medial, &m->le, m); m->sess = sess; m->sdpm = mem_ref(sdpm); for (i=0; icompc; i++) { struct comp *comp = &m->compv[i]; comp->id = i+1; comp->media = m; err = udp_local_get(i==0 ? sock1 : sock2, &laddr); if (err) goto out; rand_bytes(map.nonce, sizeof(map.nonce)); map.proto = IPPROTO_UDP; map.int_port = sa_port(&laddr); /* note: using same address-family as the PCP server */ sa_init(&map.ext_addr, sa_af(&pcp_srv)); info("pcp: %s: internal port for %s is %u\n", sdp_media_name(sdpm), i==0 ? "RTP" : "RTCP", map.int_port); err = pcp_request(&comp->pcp, NULL, &pcp_srv, PCP_MAP, LIFETIME, &map, pcp_resp_handler, comp, 0); if (err) goto out; } out: if (err) mem_deref(m); else if (mp) { *mp = m; } return err; } static void media_refresh(struct mnat_media *media) { unsigned i; for (i=0; icompc; i++) { struct comp *comp = &media->compv[i]; pcp_force_refresh(comp->pcp); } } static void refresh_session(struct mnat_sess *sess, uint32_t epoch_time) { struct le *le; for (le = sess->medial.head; le; le = le->next) { struct mnat_media *m = le->data; if (epoch_time < m->srv_epoch) { info("pcp: detected PCP Server reboot!\n"); media_refresh(m); } m->srv_epoch = epoch_time; } } static void pcp_msg_handler(const struct pcp_msg *msg, void *arg) { struct le *le; (void)arg; info("pcp: received notification: %H\n", pcp_msg_print, msg); if (msg->hdr.opcode == PCP_ANNOUNCE) { for (le = sessl.head; le; le = le->next) { struct mnat_sess *sess = le->data; refresh_session(sess, msg->hdr.epoch); } } } static struct mnat mnat_pcp = { .id = "pcp", .sessh = session_alloc, .mediah = media_alloc, }; static int module_init(void) { struct pl pl; int err; if (0 == conf_get(conf_cur(), "pcp_server", &pl)) { err = sa_decode(&pcp_srv, pl.p, pl.l); if (err) return err; } else { err = net_default_gateway_get(AF_INET, &pcp_srv); if (err) return err; sa_set_port(&pcp_srv, PCP_PORT_SRV); } info("pcp: using PCP server at %J\n", &pcp_srv); /* NOTE: if multiple applications are listening on port 5350 then this will not work */ err = pcp_listen(&lsnr, &pcp_srv, pcp_msg_handler, 0); if (err) { info("pcp: could not enable listener: %m\n", err); err = 0; } mnat_register(baresip_mnatl(), &mnat_pcp); return 0; } static int module_close(void) { lsnr = mem_deref(lsnr); mnat_unregister(&mnat_pcp); return 0; } EXPORT_SYM const struct mod_export DECL_EXPORTS(pcp) = { "pcp", "mnat", module_init, module_close, }; baresip-1.0.0/modules/pcp/pcp.h000066400000000000000000000005041372575704200163350ustar00rootroot00000000000000/** * @file pcp.h Port Control Protocol module -- internal interface * * Copyright (C) 2010 - 2016 Creytiv.com */ /* listener */ struct pcp_listener; typedef void (pcp_msg_h)(const struct pcp_msg *msg, void *arg); int pcp_listen(struct pcp_listener **plp, const struct sa *srv, pcp_msg_h *msgh, void *arg); baresip-1.0.0/modules/plc/000077500000000000000000000000001372575704200153775ustar00rootroot00000000000000baresip-1.0.0/modules/plc/module.mk000066400000000000000000000002051372575704200172120ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # MOD := plc $(MOD)_SRCS += plc.c $(MOD)_LFLAGS += "-lspandsp" include mk/mod.mk baresip-1.0.0/modules/plc/plc.c000066400000000000000000000037521372575704200163300ustar00rootroot00000000000000/** * @file plc.c PLC -- Packet Loss Concealment * * Copyright (C) 2010 Creytiv.com */ #define SPANDSP_EXPOSE_INTERNAL_STRUCTURES #include #include #include #include /** * @defgroup plc plc * * Packet Loss Concealment (PLC) audio-filter using spandsp * */ struct plc_st { struct aufilt_dec_st af; /* base class */ plc_state_t plc; size_t sampc; }; static void destructor(void *arg) { struct plc_st *st = arg; list_unlink(&st->af.le); } static int update(struct aufilt_dec_st **stp, void **ctx, const struct aufilt *af, struct aufilt_prm *prm, const struct audio *au) { struct plc_st *st; int err = 0; (void)ctx; (void)af; (void)au; if (!stp || !prm) return EINVAL; if (*stp) return 0; if (prm->ch != 1) { warning("plc: only mono supported (ch=%u)\n", prm->ch); return ENOSYS; } if (prm->fmt != AUFMT_S16LE) { warning("plc: unsupported sample format (%s)\n", aufmt_name(prm->fmt)); return ENOTSUP; } st = mem_zalloc(sizeof(*st), destructor); if (!st) return ENOMEM; if (!plc_init(&st->plc)) { err = ENOMEM; goto out; } out: if (err) mem_deref(st); else *stp = (struct aufilt_dec_st *)st; return err; } /* * PLC is only valid for Decoding (RX) * * NOTE: sampc == 0 , means Packet loss */ static int decode(struct aufilt_dec_st *st, struct auframe *af) { struct plc_st *plc = (struct plc_st *)st; if (!st || !af) return EINVAL; if (af->sampc) { plc_rx(&plc->plc, af->sampv, (int)af->sampc); plc->sampc = af->sampc; } else if (plc->sampc) af->sampc = plc_fillin(&plc->plc, af->sampv, (int)plc->sampc); return 0; } static struct aufilt plc = { .name = "plc", .decupdh = update, .dech = decode }; static int module_init(void) { aufilt_register(baresip_aufiltl(), &plc); return 0; } static int module_close(void) { aufilt_unregister(&plc); return 0; } EXPORT_SYM const struct mod_export DECL_EXPORTS(plc) = { "plc", "filter", module_init, module_close }; baresip-1.0.0/modules/portaudio/000077500000000000000000000000001372575704200166275ustar00rootroot00000000000000baresip-1.0.0/modules/portaudio/module.mk000066400000000000000000000002211372575704200204400ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # MOD := portaudio $(MOD)_SRCS += portaudio.c $(MOD)_LFLAGS += -lportaudio include mk/mod.mk baresip-1.0.0/modules/portaudio/portaudio.c000066400000000000000000000151101372575704200207770ustar00rootroot00000000000000/** * @file portaudio.c Portaudio sound driver * * Copyright (C) 2010 Creytiv.com */ #include #include #include #include #include #include /** * @defgroup portaudio portaudio * * Portaudio audio driver * * (portaudio v19 is required) * * * References: * * http://www.portaudio.com/ */ struct ausrc_st { const struct ausrc *as; /* inheritance */ PaStream *stream_rd; ausrc_read_h *rh; void *arg; volatile bool ready; unsigned ch; enum aufmt fmt; }; struct auplay_st { const struct auplay *ap; /* inheritance */ PaStream *stream_wr; auplay_write_h *wh; void *arg; volatile bool ready; unsigned ch; }; static struct ausrc *ausrc; static struct auplay *auplay; /* * This routine will be called by the PortAudio engine when audio is needed. * It may called at interrupt level on some machines so don't do anything * that could mess up the system like calling malloc() or free(). */ static int read_callback(const void *inputBuffer, void *outputBuffer, unsigned long frameCount, const PaStreamCallbackTimeInfo *timeInfo, PaStreamCallbackFlags statusFlags, void *userData) { struct ausrc_st *st = userData; struct auframe af; size_t sampc; (void)outputBuffer; (void)timeInfo; (void)statusFlags; if (!st->ready) return paAbort; sampc = frameCount * st->ch; af.fmt = st->fmt; af.sampv = (void *)inputBuffer; af.sampc = sampc; af.timestamp = Pa_GetStreamTime(st->stream_rd) * AUDIO_TIMEBASE; st->rh(&af, st->arg); return paContinue; } static int write_callback(const void *inputBuffer, void *outputBuffer, unsigned long frameCount, const PaStreamCallbackTimeInfo *timeInfo, PaStreamCallbackFlags statusFlags, void *userData) { struct auplay_st *st = userData; size_t sampc; (void)inputBuffer; (void)timeInfo; (void)statusFlags; if (!st->ready) return paAbort; sampc = frameCount * st->ch; st->wh(outputBuffer, sampc, st->arg); return paContinue; } static PaSampleFormat aufmt_to_pasampleformat(enum aufmt fmt) { switch (fmt) { case AUFMT_S16LE: return paInt16; case AUFMT_FLOAT: return paFloat32; default: return 0; } } static int read_stream_open(struct ausrc_st *st, const struct ausrc_prm *prm, uint32_t dev) { PaStreamParameters prm_in; PaError err; unsigned long frames_per_buffer = prm->srate * prm->ptime / 1000; memset(&prm_in, 0, sizeof(prm_in)); prm_in.device = dev; prm_in.channelCount = prm->ch; prm_in.sampleFormat = aufmt_to_pasampleformat(prm->fmt); prm_in.suggestedLatency = 0.100; st->stream_rd = NULL; err = Pa_OpenStream(&st->stream_rd, &prm_in, NULL, prm->srate, frames_per_buffer, paNoFlag, read_callback, st); if (paNoError != err) { warning("portaudio: read: Pa_OpenStream: %s\n", Pa_GetErrorText(err)); return EINVAL; } err = Pa_StartStream(st->stream_rd); if (paNoError != err) { warning("portaudio: read: Pa_StartStream: %s\n", Pa_GetErrorText(err)); return EINVAL; } return 0; } static int write_stream_open(struct auplay_st *st, const struct auplay_prm *prm, uint32_t dev) { PaStreamParameters prm_out; PaError err; unsigned long frames_per_buffer = prm->srate * prm->ptime / 1000; memset(&prm_out, 0, sizeof(prm_out)); prm_out.device = dev; prm_out.channelCount = prm->ch; prm_out.sampleFormat = aufmt_to_pasampleformat(prm->fmt); prm_out.suggestedLatency = 0.100; st->stream_wr = NULL; err = Pa_OpenStream(&st->stream_wr, NULL, &prm_out, prm->srate, frames_per_buffer, paNoFlag, write_callback, st); if (paNoError != err) { warning("portaudio: write: Pa_OpenStream: %s\n", Pa_GetErrorText(err)); return EINVAL; } err = Pa_StartStream(st->stream_wr); if (paNoError != err) { warning("portaudio: write: Pa_StartStream: %s\n", Pa_GetErrorText(err)); return EINVAL; } return 0; } static void ausrc_destructor(void *arg) { struct ausrc_st *st = arg; st->ready = false; if (st->stream_rd) { Pa_AbortStream(st->stream_rd); Pa_CloseStream(st->stream_rd); } } static void auplay_destructor(void *arg) { struct auplay_st *st = arg; st->ready = false; if (st->stream_wr) { Pa_AbortStream(st->stream_wr); Pa_CloseStream(st->stream_wr); } } static int src_alloc(struct ausrc_st **stp, const struct ausrc *as, struct media_ctx **ctx, struct ausrc_prm *prm, const char *device, ausrc_read_h *rh, ausrc_error_h *errh, void *arg) { struct ausrc_st *st; PaDeviceIndex dev_index; int err; (void)ctx; (void)device; (void)errh; if (!stp || !as || !prm) return EINVAL; if (str_isset(device)) dev_index = atoi(device); else dev_index = Pa_GetDefaultInputDevice(); st = mem_zalloc(sizeof(*st), ausrc_destructor); if (!st) return ENOMEM; st->as = as; st->rh = rh; st->arg = arg; st->ch = prm->ch; st->fmt = prm->fmt; st->ready = true; err = read_stream_open(st, prm, dev_index); if (err) goto out; out: if (err) mem_deref(st); else *stp = st; return err; } static int play_alloc(struct auplay_st **stp, const struct auplay *ap, struct auplay_prm *prm, const char *device, auplay_write_h *wh, void *arg) { struct auplay_st *st; PaDeviceIndex dev_index; int err; (void)device; if (!stp || !ap || !prm) return EINVAL; if (str_isset(device)) dev_index = atoi(device); else dev_index = Pa_GetDefaultOutputDevice(); st = mem_zalloc(sizeof(*st), auplay_destructor); if (!st) return ENOMEM; st->ap = ap; st->wh = wh; st->arg = arg; st->ch = prm->ch; st->ready = true; err = write_stream_open(st, prm, dev_index); if (err) goto out; out: if (err) mem_deref(st); else *stp = st; return err; } static int pa_init(void) { PaError paerr; int i, n, err = 0; paerr = Pa_Initialize(); if (paNoError != paerr) { warning("portaudio: init: %s\n", Pa_GetErrorText(paerr)); return ENODEV; } n = Pa_GetDeviceCount(); info("portaudio: device count is %d\n", n); for (i=0; iname); (void)devinfo; } if (paNoDevice != Pa_GetDefaultInputDevice()) err |= ausrc_register(&ausrc, baresip_ausrcl(), "portaudio", src_alloc); if (paNoDevice != Pa_GetDefaultOutputDevice()) err |= auplay_register(&auplay, baresip_auplayl(), "portaudio", play_alloc); return err; } static int pa_close(void) { ausrc = mem_deref(ausrc); auplay = mem_deref(auplay); Pa_Terminate(); return 0; } EXPORT_SYM const struct mod_export DECL_EXPORTS(portaudio) = { "portaudio", "sound", pa_init, pa_close }; baresip-1.0.0/modules/presence/000077500000000000000000000000001372575704200164255ustar00rootroot00000000000000baresip-1.0.0/modules/presence/module.mk000066400000000000000000000002471372575704200202460ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # MOD := presence $(MOD)_SRCS += presence.c subscriber.c notifier.c publisher.c $(MOD)_LFLAGS += include mk/mod.mk baresip-1.0.0/modules/presence/notifier.c000066400000000000000000000100621372575704200204070ustar00rootroot00000000000000/** * @file notifier.c Presence notifier * * Copyright (C) 2010 Creytiv.com */ #include #include #include "presence.h" /* * Notifier - other people are subscribing to the status of our AOR. * we must maintain a list of active notifications. we receive a SUBSCRIBE * message from peer, and send NOTIFY to all peers when the Status changes */ struct notifier { struct le le; struct sipnot *not; struct ua *ua; }; static struct list notifierl; static const char *presence_status_str(enum presence_status st) { switch (st) { case PRESENCE_OPEN: return "open"; case PRESENCE_CLOSED: return "closed"; default: return "?"; } } static int notify(struct notifier *not, enum presence_status status) { const char *aor = ua_aor(not->ua); struct mbuf *mb; int err; mb = mbuf_alloc(1024); if (!mb) return ENOMEM; err = mbuf_printf(mb, "\r\n" "\r\n" " \r\n" " \r\n" " \r\n" " %s\r\n" " \r\n" " %s\r\n" " \r\n" "\r\n" ,aor, presence_status_str(status), aor); if (err) goto out; mb->pos = 0; err = sipevent_notify(not->not, mb, SIPEVENT_ACTIVE, 0, 0); if (err) { warning("presence: notify to %s failed (%m)\n", aor, err); } out: mem_deref(mb); return err; } static void sipnot_close_handler(int err, const struct sip_msg *msg, void *arg) { struct notifier *not = arg; if (err) { info("presence: notifier closed (%m)\n", err); } else if (msg) { info("presence: notifier closed (%u %r)\n", msg->scode, &msg->reason); } mem_deref(not); } static void destructor(void *arg) { struct notifier *not = arg; list_unlink(¬->le); mem_deref(not->not); mem_deref(not->ua); } static int auth_handler(char **username, char **password, const char *realm, void *arg) { return account_auth(arg, username, password, realm); } static int notifier_alloc(struct notifier **notp, const struct sip_msg *msg, const struct sipevent_event *se, struct ua *ua) { struct notifier *not; int err; if (!msg || !se) return EINVAL; not = mem_zalloc(sizeof(*not), destructor); if (!not) return ENOMEM; not->ua = mem_ref(ua); err = sipevent_accept(¬->not, uag_sipevent_sock(), msg, NULL, se, 200, "OK", 600, 600, 600, ua_cuser(not->ua), "application/pidf+xml", auth_handler, ua_account(not->ua), true, sipnot_close_handler, not, NULL); if (err) { warning("presence: sipevent_accept failed: %m\n", err); goto out; } list_append(¬ifierl, ¬->le, not); out: if (err) mem_deref(not); else if (notp) *notp = not; return err; } static int notifier_add(const struct sip_msg *msg, struct ua *ua) { const struct sip_hdr *hdr; struct sipevent_event se; struct notifier *not; int err; hdr = sip_msg_hdr(msg, SIP_HDR_EVENT); if (!hdr) return EPROTO; err = sipevent_event_decode(&se, &hdr->val); if (err) return err; if (pl_strcasecmp(&se.event, "presence")) { info("presence: unexpected event '%r'\n", &se.event); return EPROTO; } err = notifier_alloc(¬, msg, &se, ua); if (err) return err; (void)notify(not, ua_presence_status(ua)); return 0; } void notifier_update_status(struct ua *ua) { struct le *le; for (le = notifierl.head; le; le = le->next) { struct notifier *not = le->data; if (not->ua == ua) (void)notify(not, ua_presence_status(not->ua)); } } static bool sub_handler(const struct sip_msg *msg, void *arg) { struct ua *ua = arg; if (notifier_add(msg, ua)) (void)sip_treply(NULL, uag_sip(), msg, 400, "Bad Presence"); return true; } int notifier_init(void) { uag_set_sub_handler(sub_handler); return 0; } void notifier_close(void) { list_flush(¬ifierl); uag_set_sub_handler(NULL); } baresip-1.0.0/modules/presence/presence.c000066400000000000000000000040701372575704200203760ustar00rootroot00000000000000/** * @file presence.c Presence module * * Copyright (C) 2010 Creytiv.com */ #include #include #include "presence.h" static int status_update(struct ua *current_ua, const enum presence_status new_status) { if (ua_presence_status(current_ua) == new_status) return 0; info("presence: update status of '%s' from '%s' to '%s'\n", ua_aor(current_ua), contact_presence_str(ua_presence_status(current_ua)), contact_presence_str(new_status)); ua_presence_status_set(current_ua, new_status); publisher_update_status(current_ua); notifier_update_status(current_ua); return 0; } static int cmd_online(struct re_printf *pf, void *arg) { (void)pf; (void)arg; return status_update(uag_current(), PRESENCE_OPEN); } static int cmd_offline(struct re_printf *pf, void *arg) { (void)pf; (void)arg; return status_update(uag_current(), PRESENCE_CLOSED); } static const struct cmd cmdv[] = { {"presence_online", '[', 0, "Set presence online", cmd_online }, {"presence_offline", ']', 0, "Set presence offline", cmd_offline }, }; static void event_handler(struct ua *ua, enum ua_event ev, struct call *call, const char *prm, void *arg) { (void)call; (void)prm; (void)arg; debug("presence: ua=%p got event %d (%s)\n", ua, ev, uag_event_str(ev)); if (ev == UA_EVENT_SHUTDOWN) { publisher_close(); notifier_close(); subscriber_close_all(); } } static int module_init(void) { int err; err = subscriber_init(); if (err) return err; err = publisher_init(); if (err) return err; err = notifier_init(); if (err) return err; err = cmd_register(baresip_commands(), cmdv, ARRAY_SIZE(cmdv)); if (err) return err; err = uag_event_register(event_handler, NULL); if (err) return err; return err; } static int module_close(void) { uag_event_unregister(event_handler); cmd_unregister(baresip_commands(), cmdv); publisher_close(); notifier_close(); subscriber_close(); return 0; } const struct mod_export DECL_EXPORTS(presence) = { "presence", "application", module_init, module_close }; baresip-1.0.0/modules/presence/presence.h000066400000000000000000000005771372575704200204130ustar00rootroot00000000000000/** * @file presence.h Presence module interface * * Copyright (C) 2010 Creytiv.com */ int subscriber_init(void); void subscriber_close(void); void subscriber_close_all(void); int notifier_init(void); void notifier_close(void); void notifier_update_status(struct ua *ua); int publisher_init(void); void publisher_close(void); void publisher_update_status(struct ua *ua); baresip-1.0.0/modules/presence/publisher.c000066400000000000000000000123011372575704200205630ustar00rootroot00000000000000/** * @file publisher.c Presence Publisher (RFC 3903) * * Copyright (C) 2010 Creytiv.com * Copyright (C) 2014 Juha Heinanen */ #include #include #include #include "presence.h" struct publisher { struct le le; struct tmr tmr; unsigned failc; char *etag; unsigned int expires; unsigned int refresh; struct ua *ua; }; static struct list publ = LIST_INIT; static void tmr_handler(void *arg); static int publish(struct publisher *pub); static void response_handler(int err, const struct sip_msg *msg, void *arg) { struct publisher *pub = arg; const struct sip_hdr *etag_hdr; if (err) return; if (msg->scode < 200) { return; } if (msg->scode < 300) { if (pub->expires == 0) return; etag_hdr = sip_msg_xhdr(msg, "SIP-ETag"); if (etag_hdr) { mem_deref(pub->etag); pl_strdup(&(pub->etag), &(etag_hdr->val)); pub->refresh = 1; tmr_start(&pub->tmr, pub->expires * 900, tmr_handler, pub); } else { warning("%s: publisher got 200 OK without etag\n", ua_aor(pub->ua)); } } else if (msg->scode == 412) { mem_deref(pub->etag); pub->etag = NULL; pub->refresh = 0; publish(pub); } else { warning("%s: publisher got error response %u %r\n", ua_aor(pub->ua), msg->scode, &msg->reason); } return; } /* move this to presence.c */ static const char *presence_status_str(enum presence_status st) { switch (st) { case PRESENCE_OPEN: return "open"; case PRESENCE_CLOSED: return "closed"; case PRESENCE_UNKNOWN: return "unknown"; default: return "?"; } } static int print_etag_header(struct re_printf *pf, const char *etag) { if (!etag) return 0; return re_hprintf(pf, "SIP-If-Match: %s\r\n", etag); } static int publish(struct publisher *pub) { int err; const char *aor = ua_aor(pub->ua); struct mbuf *mb; mb = mbuf_alloc(1024); if (!mb) return ENOMEM; if (pub->expires && !pub->refresh) err = mbuf_printf(mb, "\r\n" "\r\n" " \r\n" " \r\n" " \r\n" " %s\r\n" " \r\n" " %s\r\n" " \r\n" "\r\n" ,aor, presence_status_str(ua_presence_status(pub->ua)), aor); else err = mbuf_printf(mb, ""); if (err) goto out; mb->pos = 0; err = sip_req_send(pub->ua, "PUBLISH", aor, pub->expires ? response_handler : NULL, pub, "%s" "Event: presence\r\n" "Expires: %u\r\n" "%H" "Content-Length: %zu\r\n" "\r\n" "%b", pub->expires ? "Content-Type: application/pidf+xml\r\n" : "", pub->expires, print_etag_header, pub->etag, mbuf_get_left(mb), mbuf_buf(mb), mbuf_get_left(mb)); if (err) { warning("publisher: send PUBLISH: (%m)\n", err); } out: mem_deref(mb); return err; } /* move to presence.c */ static uint32_t wait_fail(unsigned failc) { switch (failc) { case 1: return 30; case 2: return 300; case 3: return 3600; default: return 86400; } } static void tmr_handler(void *arg) { struct publisher *pub = arg; if (publish(pub)) tmr_start(&pub->tmr, wait_fail(++pub->failc) * 1000, tmr_handler, pub); else pub->failc = 0; } static void destructor(void *arg) { struct publisher *pub = arg; list_unlink(&pub->le); tmr_cancel(&pub->tmr); mem_deref(pub->ua); mem_deref(pub->etag); } void publisher_update_status(struct ua *ua) { struct le *le; for (le = publ.head; le; le = le->next) { struct publisher *pub = le->data; if (pub->ua == ua) { pub->refresh = 0; publish(pub); } } } static int publisher_alloc(struct ua *ua) { struct publisher *pub; pub = mem_zalloc(sizeof(*pub), destructor); if (!pub) return ENOMEM; pub->ua = mem_ref(ua); pub->expires = account_pubint(ua_account(ua)); tmr_init(&pub->tmr); tmr_start(&pub->tmr, 10, tmr_handler, pub); list_append(&publ, &pub->le, pub); return 0; } static void pub_ua_event_handler(struct ua *ua, enum ua_event ev, struct call *call, const char *prm, void *arg ) { (void)call; (void)prm; (void)arg; if (account_pubint(ua_account(ua)) == 0) return; if (ev == UA_EVENT_REGISTER_OK) { if (ua_presence_status(ua) == PRESENCE_UNKNOWN) { ua_presence_status_set(ua, PRESENCE_OPEN); publisher_update_status(ua); } } } int publisher_init(void) { struct le *le; int err = 0; err = uag_event_register(pub_ua_event_handler, NULL); if (err) return err; for (le = list_head(uag_list()); le; le = le->next) { struct ua *ua = le->data; struct account *acc = ua_account(ua); if (account_pubint(acc) == 0) continue; err |= publisher_alloc(ua); } if (err) return err; return 0; } void publisher_close(void) { struct le *le; uag_event_unregister(pub_ua_event_handler); for (le = list_head(&publ); le; le = le->next) { struct publisher *pub = le->data; ua_presence_status_set(pub->ua, PRESENCE_CLOSED); pub->expires = 0; publish(pub); } list_flush(&publ); } baresip-1.0.0/modules/presence/subscriber.c000066400000000000000000000165621372575704200207460ustar00rootroot00000000000000/** * @file subscriber.c Presence subscriber * * Copyright (C) 2010 Creytiv.com */ #include #include #include "presence.h" /* * Subscriber - we subscribe to the status information of N resources. * * For each entry in the address book marked with ;presence=p2p, * we send a SUBSCRIBE to that person, and expect to receive * a NOTIFY when her status changes. */ /** Constants */ enum { SHUTDOWN_DELAY = 500 /**< Delay before un-registering [ms] */ }; struct presence { struct le le; struct sipsub *sub; struct tmr tmr; enum presence_status status; unsigned failc; struct contact *contact; struct ua *ua; bool shutdown; }; static struct list presencel; static void tmr_handler(void *arg); static uint32_t wait_term(const struct sipevent_substate *substate) { uint32_t wait; switch (substate->reason) { case SIPEVENT_DEACTIVATED: case SIPEVENT_TIMEOUT: wait = 5; break; case SIPEVENT_REJECTED: case SIPEVENT_NORESOURCE: wait = 3600; break; case SIPEVENT_PROBATION: case SIPEVENT_GIVEUP: default: wait = 300; if (pl_isset(&substate->retry_after)) wait = max(wait, pl_u32(&substate->retry_after)); break; } return wait; } static uint32_t wait_fail(unsigned failc) { switch (failc) { case 1: return 30; case 2: return 300; case 3: return 3600; default: return 86400; } } static void notify_handler(struct sip *sip, const struct sip_msg *msg, void *arg) { enum presence_status status = PRESENCE_CLOSED; struct presence *pres = arg; const struct sip_hdr *type_hdr, *length_hdr; struct pl pl; if (pres->shutdown) goto done; pres->failc = 0; type_hdr = sip_msg_hdr(msg, SIP_HDR_CONTENT_TYPE); if (!type_hdr) { length_hdr = sip_msg_hdr(msg, SIP_HDR_CONTENT_LENGTH); if (0 == pl_strcmp(&length_hdr->val, "0")) { status = PRESENCE_UNKNOWN; goto done; } } if (!type_hdr || 0 != pl_strcasecmp(&type_hdr->val, "application/pidf+xml")) { if (type_hdr) warning("presence: unsupported content-type: '%r'\n", &type_hdr->val); sip_treplyf(NULL, NULL, sip, msg, false, 415, "Unsupported Media Type", "Accept: application/pidf+xml\r\n" "Content-Length: 0\r\n" "\r\n"); return; } if (!re_regex((const char *)mbuf_buf(msg->mb), mbuf_get_left(msg->mb), "[^<]+", NULL, &pl, NULL)) { if (!pl_strcasecmp(&pl, "open")) status = PRESENCE_OPEN; } if (!re_regex((const char *)mbuf_buf(msg->mb), mbuf_get_left(msg->mb), "", NULL)) { status = PRESENCE_CLOSED; } else if (!re_regex((const char *)mbuf_buf(msg->mb), mbuf_get_left(msg->mb), "", NULL)) { status = PRESENCE_BUSY; } else if (!re_regex((const char *)mbuf_buf(msg->mb), mbuf_get_left(msg->mb), "", NULL)) { status = PRESENCE_BUSY; } done: (void)sip_treply(NULL, sip, msg, 200, "OK"); contact_set_presence(pres->contact, status); if (pres->shutdown) mem_deref(pres); } static void close_handler(int err, const struct sip_msg *msg, const struct sipevent_substate *substate, void *arg) { struct presence *pres = arg; uint32_t wait; pres->sub = mem_deref(pres->sub); info("presence: subscriber closed <%s>: ", contact_uri(pres->contact)); if (substate) { info("%s", sipevent_reason_name(substate->reason)); wait = wait_term(substate); } else if (msg) { info("%u %r", msg->scode, &msg->reason); wait = wait_fail(++pres->failc); } else { info("%m", err); wait = wait_fail(++pres->failc); } info("; will retry in %u secs (failc=%u)\n", wait, pres->failc); tmr_start(&pres->tmr, wait * 1000, tmr_handler, pres); contact_set_presence(pres->contact, PRESENCE_UNKNOWN); } static void destructor(void *arg) { struct presence *pres = arg; debug("presence: subscriber destroyed\n"); list_unlink(&pres->le); tmr_cancel(&pres->tmr); mem_deref(pres->contact); mem_deref(pres->sub); mem_deref(pres->ua); } static void deref_handler(void *arg) { struct presence *pres = arg; mem_deref(pres); } static int auth_handler(char **username, char **password, const char *realm, void *arg) { return account_auth(arg, username, password, realm); } static int subscribe(struct presence *pres) { const char *routev[1]; struct ua *ua; int err; /* We use the first UA */ ua = uag_find_aor(NULL); if (!ua) { warning("presence: no UA found\n"); return ENOENT; } mem_deref(pres->ua); pres->ua = mem_ref(ua); routev[0] = ua_outbound(ua); err = sipevent_subscribe(&pres->sub, uag_sipevent_sock(), contact_uri(pres->contact), NULL, ua_aor(ua), "presence", NULL, 600, ua_cuser(ua), routev, routev[0] ? 1 : 0, auth_handler, ua_account(ua), true, NULL, notify_handler, close_handler, pres, "%H", ua_print_supported, ua); if (err) { warning("presence: sipevent_subscribe failed: %m\n", err); } return err; } static void tmr_handler(void *arg) { struct presence *pres = arg; if (subscribe(pres)) { tmr_start(&pres->tmr, wait_fail(++pres->failc) * 1000, tmr_handler, pres); } } static int presence_alloc(struct contact *contact) { struct presence *pres; pres = mem_zalloc(sizeof(*pres), destructor); if (!pres) return ENOMEM; pres->status = PRESENCE_UNKNOWN; pres->contact = mem_ref(contact); tmr_init(&pres->tmr); tmr_start(&pres->tmr, 1000, tmr_handler, pres); list_append(&presencel, &pres->le, pres); return 0; } static void contact_handler(struct contact *contact, bool removed, void *arg) { struct le *le; struct pl val; struct presence *pres = NULL; struct sip_addr *addr = contact_addr(contact); (void)arg; if (0 == msg_param_decode(&addr->params, "presence", &val) && 0 == pl_strcasecmp(&val, "p2p")) { if (!removed) { if (presence_alloc(contact) != 0) { warning("presence: presence_alloc failed\n"); return; } } else { /* Find matching presence element for contact */ for (le = list_head(&presencel); le; le = le->next) { pres = (struct presence*)le->data; if (pres->contact == contact) { break; } pres = NULL; } if (pres) { mem_deref(pres); } else { warning("presence: No contact to remove\n"); } } } } int subscriber_init(void) { struct contacts *contacts = baresip_contacts(); struct le *le; int err = 0; for (le = list_head(contact_list(contacts)); le; le = le->next) { struct contact *c = le->data; struct sip_addr *addr = contact_addr(c); struct pl val; if (0 == msg_param_decode(&addr->params, "presence", &val) && 0 == pl_strcasecmp(&val, "p2p")) { err |= presence_alloc(le->data); } } info("Subscribing to %u contacts\n", list_count(&presencel)); contact_set_update_handler(contacts, contact_handler, NULL); contacts_enable_presence(contacts, true); return err; } void subscriber_close(void) { contact_set_update_handler(baresip_contacts(), NULL, NULL); list_flush(&presencel); } void subscriber_close_all(void) { struct le *le; info("presence: subscriber: closing %u subs\n", list_count(&presencel)); contact_set_update_handler(baresip_contacts(), NULL, NULL); le = presencel.head; while (le) { struct presence *pres = le->data; le = le->next; debug("presence: shutdown: sub=%p\n", pres->sub); pres->shutdown = true; if (pres->sub) { pres->sub = mem_deref(pres->sub); tmr_start(&pres->tmr, SHUTDOWN_DELAY, deref_handler, pres); } else mem_deref(pres); } } baresip-1.0.0/modules/pulse/000077500000000000000000000000001372575704200157515ustar00rootroot00000000000000baresip-1.0.0/modules/pulse/module.mk000066400000000000000000000004371372575704200175730ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 - 2016 Creytiv.com # MOD := pulse $(MOD)_SRCS += pulse.c $(MOD)_SRCS += player.c $(MOD)_SRCS += recorder.c $(MOD)_LFLAGS += $(shell pkg-config --libs libpulse-simple) $(MOD)_CFLAGS += $(shell pkg-config --cflags libpulse-simple) include mk/mod.mk baresip-1.0.0/modules/pulse/player.c000066400000000000000000000073121372575704200174140ustar00rootroot00000000000000/** * @file pulse/player.c Pulseaudio sound driver - player * * Copyright (C) 2010 - 2016 Creytiv.com */ #include #include #include #include #include #include #include "pulse.h" struct auplay_st { const struct auplay *ap; /* inheritance */ pa_simple *s; pthread_t thread; bool run; void *sampv; size_t sampc; size_t sampsz; auplay_write_h *wh; void *arg; }; static void auplay_destructor(void *arg) { struct auplay_st *st = arg; int pa_error = 0; int pa_ret; /* Wait for termination of other thread */ if (st->run) { debug("pulse: stopping playback thread\n"); st->run = false; (void)pthread_join(st->thread, NULL); } if (st->s) { pa_ret = pa_simple_drain(st->s, &pa_error); if (pa_ret < 0) warning("pulse: pa_simple_drain error (%s)\n", pa_strerror(pa_error)); pa_simple_free(st->s); } mem_deref(st->sampv); } static void *write_thread(void *arg) { struct auplay_st *st = arg; const size_t num_bytes = st->sampc * st->sampsz; int ret, pa_error = 0; while (st->run) { st->wh(st->sampv, st->sampc, st->arg); ret = pa_simple_write(st->s, st->sampv, num_bytes, &pa_error); if (ret < 0) { warning("pulse: pa_simple_write error (%s)\n", pa_strerror(pa_error)); } } return NULL; } static int aufmt_to_pulse_format(enum aufmt fmt) { switch (fmt) { case AUFMT_S16LE: return PA_SAMPLE_S16NE; case AUFMT_FLOAT: return PA_SAMPLE_FLOAT32NE; default: return 0; } } int pulse_player_alloc(struct auplay_st **stp, const struct auplay *ap, struct auplay_prm *prm, const char *device, auplay_write_h *wh, void *arg) { struct auplay_st *st; pa_sample_spec ss; pa_buffer_attr attr; int err = 0, pa_error = 0; if (!stp || !ap || !prm || !wh) return EINVAL; debug("pulse: opening player (%u Hz, %d channels, device '%s')\n", prm->srate, prm->ch, device); st = mem_zalloc(sizeof(*st), auplay_destructor); if (!st) return ENOMEM; st->ap = ap; st->wh = wh; st->arg = arg; st->sampc = prm->srate * prm->ch * prm->ptime / 1000; st->sampsz = aufmt_sample_size(prm->fmt); st->sampv = mem_alloc(st->sampsz * st->sampc, NULL); if (!st->sampv) { err = ENOMEM; goto out; } ss.format = aufmt_to_pulse_format(prm->fmt); ss.channels = prm->ch; ss.rate = prm->srate; attr.maxlength = (uint32_t)-1; attr.tlength = (uint32_t)pa_usec_to_bytes(prm->ptime * 1000, &ss); attr.prebuf = (uint32_t)-1; attr.minreq = (uint32_t)-1; attr.fragsize = (uint32_t)-1; st->s = pa_simple_new(NULL, "Baresip", PA_STREAM_PLAYBACK, str_isset(device) ? device : NULL, "VoIP Playback", &ss, NULL, &attr, &pa_error); if (!st->s) { warning("pulse: could not connect to server (%s)\n", pa_strerror(pa_error)); err = ENODEV; goto out; } st->run = true; err = pthread_create(&st->thread, NULL, write_thread, st); if (err) { st->run = false; goto out; } debug("pulse: playback started\n"); out: if (err) mem_deref(st); else *stp = st; return err; } static void dev_list_cb(pa_context *c, const pa_sink_info *l, int eol, void *userdata) { struct list *dev_list = userdata; int err; (void)c; if (eol > 0) { return; } err = mediadev_add(dev_list, l->name); if (err) { warning("pulse player: media device (%s) can not be added\n", l->name); } } static pa_operation *get_dev_info(pa_context *pa_ctx, struct list *dev_list){ return pa_context_get_sink_info_list(pa_ctx, dev_list_cb, dev_list); } int pulse_player_init(struct auplay *ap) { if (!ap) { return EINVAL; } list_init(&ap->dev_list); return set_available_devices(&ap->dev_list, get_dev_info); } baresip-1.0.0/modules/pulse/pulse.c000066400000000000000000000047041372575704200172520ustar00rootroot00000000000000/** * @file pulse.c Pulseaudio sound driver * * Copyright (C) 2010 - 2016 Creytiv.com */ #include #include #include #include #include #include "pulse.h" /** * @defgroup pulse pulse * * Audio driver module for Pulseaudio * * This module is experimental and work-in-progress. It is using * the pulseaudio "simple" interface. */ static struct auplay *auplay; static struct ausrc *ausrc; static int module_init(void) { int err; err = auplay_register(&auplay, baresip_auplayl(), "pulse", pulse_player_alloc); err |= ausrc_register(&ausrc, baresip_ausrcl(), "pulse", pulse_recorder_alloc); if (err) return err; err = pulse_player_init(auplay); err |= pulse_recorder_init(ausrc); return err; } int set_available_devices(struct list *dev_list, pa_operation *(get_dev_info_cb)(pa_context *, struct list *)) { pa_mainloop *pa_ml = NULL; pa_mainloop_api *pa_mlapi = NULL; pa_operation *pa_op = NULL; pa_context *pa_ctx = NULL; int err = 0, pa_error = 0; /* Create a mainloop API and connection to the default server */ pa_ml = pa_mainloop_new(); if (!pa_ml){ warning("pulse: mainloop_new failed\n"); err = 1; goto out; } pa_mlapi = pa_mainloop_get_api(pa_ml); if (!pa_mlapi){ warning("pulse: pa_mainloop_get_api failed\n"); err = 1; goto out; } pa_ctx = pa_context_new(pa_mlapi, "Baresip"); if (pa_context_connect(pa_ctx, NULL, 0, NULL) < 0) { warning("pulse: pa_context_connect failed: (%s)\n", pa_strerror(pa_context_errno(pa_ctx))); err = 1; goto out; } while (pa_context_get_state(pa_ctx) != PA_CONTEXT_READY) { pa_error = pa_mainloop_iterate(pa_ml, 1, NULL); if (pa_error < 0) { warning("pulse: pa_mainloop_iterate failed\n"); err = 1; goto out; } } pa_op = get_dev_info_cb(pa_ctx, dev_list); while (pa_operation_get_state(pa_op) != PA_OPERATION_DONE) { pa_error = pa_mainloop_iterate(pa_ml, 1, NULL); if (pa_error < 0) { warning("pulse: pa_mainloop_iterate failed\n"); err = 1; goto out; } } out: if (pa_op) pa_operation_unref(pa_op); if (pa_ctx) { pa_context_disconnect(pa_ctx); pa_context_unref(pa_ctx); } if (pa_ml) pa_mainloop_free(pa_ml); return err; } static int module_close(void) { auplay = mem_deref(auplay); ausrc = mem_deref(ausrc); return 0; } EXPORT_SYM const struct mod_export DECL_EXPORTS(pulse) = { "pulse", "audio", module_init, module_close, }; baresip-1.0.0/modules/pulse/pulse.h000066400000000000000000000012631372575704200172540ustar00rootroot00000000000000/** * @file pulse.h Pulseaudio sound driver -- internal API * * Copyright (C) 2010 - 2016 Creytiv.com */ int pulse_player_alloc(struct auplay_st **stp, const struct auplay *ap, struct auplay_prm *prm, const char *device, auplay_write_h *wh, void *arg); int pulse_recorder_alloc(struct ausrc_st **stp, const struct ausrc *as, struct media_ctx **ctx, struct ausrc_prm *prm, const char *device, ausrc_read_h *rh, ausrc_error_h *errh, void *arg); int set_available_devices(struct list *dev_list, pa_operation *(get_dev_info_cb)(pa_context *, struct list *)); int pulse_player_init(struct auplay *ap); int pulse_recorder_init(struct ausrc *as); baresip-1.0.0/modules/pulse/recorder.c000066400000000000000000000114211372575704200177210ustar00rootroot00000000000000/** * @file pulse/recorder.c Pulseaudio sound driver - recorder * * Copyright (C) 2010 - 2016 Creytiv.com */ #include #include #include #include #include #include #include #include "pulse.h" struct ausrc_st { const struct ausrc *as; /* inheritance */ struct ausrc_prm prm; pa_simple *s; pthread_t thread; bool run; void *sampv; size_t sampc; size_t sampsz; uint32_t ptime; enum aufmt fmt; ausrc_read_h *rh; void *arg; }; static void ausrc_destructor(void *arg) { struct ausrc_st *st = arg; /* Wait for termination of other thread */ if (st->run) { debug("pulse: stopping record thread\n"); st->run = false; (void)pthread_join(st->thread, NULL); } if (st->s) pa_simple_free(st->s); mem_deref(st->sampv); } static void *read_thread(void *arg) { struct ausrc_st *st = arg; const size_t num_bytes = st->sampc * st->sampsz; int ret, pa_error = 0; uint64_t now, last_read, diff; unsigned dropped = 0; bool init = true; size_t sampc = 0; if (pa_simple_flush(st->s, &pa_error)) { warning("pulse: pa_simple_flush error (%s)\n", pa_strerror(pa_error)); } last_read = tmr_jiffies(); while (st->run) { struct auframe af = { .fmt = st->fmt, .sampv = st->sampv, .sampc = st->sampc, .timestamp = sampc * AUDIO_TIMEBASE / (st->prm.srate * st->prm.ch) }; ret = pa_simple_read(st->s, st->sampv, num_bytes, &pa_error); if (ret < 0) { warning("pulse: pa_simple_read error (%s)\n", pa_strerror(pa_error)); continue; } /* Some devices might send a burst of samples right after the initialization - filter them out */ if (init) { now = tmr_jiffies(); diff = (now > last_read)? now - last_read : 0; if (diff < st->ptime / 2) { last_read = now; ++dropped; continue; } else { init = false; if (dropped) debug("pulse: dropped %u frames of " "garbage at the beginning of " "the recording\n", dropped); } } sampc += st->sampc; st->rh(&af, st->arg); } return NULL; } static int aufmt_to_pulse_format(enum aufmt fmt) { switch (fmt) { case AUFMT_S16LE: return PA_SAMPLE_S16NE; case AUFMT_FLOAT: return PA_SAMPLE_FLOAT32NE; default: return 0; } } int pulse_recorder_alloc(struct ausrc_st **stp, const struct ausrc *as, struct media_ctx **ctx, struct ausrc_prm *prm, const char *device, ausrc_read_h *rh, ausrc_error_h *errh, void *arg) { struct ausrc_st *st; pa_sample_spec ss; pa_buffer_attr attr; int pa_error; int err; (void)ctx; (void)device; (void)errh; if (!stp || !as || !prm) return EINVAL; debug("pulse: opening recorder (%u Hz, %d channels, device '%s')\n", prm->srate, prm->ch, device); st = mem_zalloc(sizeof(*st), ausrc_destructor); if (!st) return ENOMEM; st->as = as; st->rh = rh; st->arg = arg; st->sampc = prm->srate * prm->ch * prm->ptime / 1000; st->sampsz = aufmt_sample_size(prm->fmt); st->ptime = prm->ptime; st->fmt = prm->fmt; st->prm = *prm; st->sampv = mem_alloc(st->sampsz * st->sampc, NULL); if (!st->sampv) { err = ENOMEM; goto out; } ss.format = aufmt_to_pulse_format(prm->fmt); ss.channels = prm->ch; ss.rate = prm->srate; attr.maxlength = (uint32_t)-1; attr.tlength = (uint32_t)-1; attr.prebuf = (uint32_t)-1; attr.minreq = (uint32_t)-1; attr.fragsize = (uint32_t)pa_usec_to_bytes(prm->ptime * 1000, &ss); st->s = pa_simple_new(NULL, "Baresip", PA_STREAM_RECORD, str_isset(device) ? device : NULL, "VoIP Record", &ss, NULL, &attr, &pa_error); if (!st->s) { warning("pulse: could not connect to server (%s)\n", pa_strerror(pa_error)); err = ENODEV; goto out; } st->run = true; err = pthread_create(&st->thread, NULL, read_thread, st); if (err) { st->run = false; goto out; } debug("pulse: recording started\n"); out: if (err) mem_deref(st); else *stp = st; return err; } static void dev_list_cb(pa_context *c, const pa_source_info *l, int eol, void *userdata) { struct list *dev_list = userdata; int err; (void)c; if (eol > 0) { return; } /* In pulseaudio every sink automatically has a monitor source This "output" device must be filtered out */ if (!strstr(l->name,"output")) { err = mediadev_add(dev_list, l->name); if (err) { warning("pulse recorder: media device (%s) " "can not be added\n",l->name); } } } static pa_operation *get_dev_info(pa_context *pa_ctx, struct list *dev_list){ return pa_context_get_source_info_list(pa_ctx, dev_list_cb, dev_list); } int pulse_recorder_init(struct ausrc *as) { if (!as) { return EINVAL; } list_init(&as->dev_list); return set_available_devices(&as->dev_list, get_dev_info); } baresip-1.0.0/modules/qtcapture/000077500000000000000000000000001372575704200166315ustar00rootroot00000000000000baresip-1.0.0/modules/qtcapture/module.mk000066400000000000000000000002741372575704200204520ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # MOD := qtcapture $(MOD)_SRCS += qtcapture.m $(MOD)_LFLAGS += -framework Cocoa -framework QTKit -framework CoreVideo include mk/mod.mk baresip-1.0.0/modules/qtcapture/qtcapture.m000066400000000000000000000165221372575704200210250ustar00rootroot00000000000000/** * @file qtcapture.m Video source using QTKit QTCapture * * Copyright (C) 2010 Creytiv.com */ #include #include #include #include static void frame_handler(struct vidsrc_st *st, const CVImageBufferRef videoFrame); static struct vidsrc *vidsrc; @interface qtcap : NSObject { QTCaptureSession *sess; QTCaptureDeviceInput *input; QTCaptureDecompressedVideoOutput *output; struct vidsrc_st *vsrc; } @end struct vidsrc_st { const struct vidsrc *vs; /* inheritance */ qtcap *cap; struct lock *lock; struct vidsz app_sz; struct vidsz sz; struct mbuf *buf; vidsrc_frame_h *frameh; void *arg; bool started; #ifdef QTCAPTURE_RUNLOOP struct tmr tmr; #endif }; @implementation qtcap - (id)init:(struct vidsrc_st *)st dev:(const char *)name { NSAutoreleasePool *pool; QTCaptureDevice *dev; BOOL success = NO; NSError *err; pool = [[NSAutoreleasePool alloc] init]; if (!pool) return nil; self = [super init]; if (!self) goto out; vsrc = st; sess = [[QTCaptureSession alloc] init]; if (!sess) goto out; if (str_isset(name)) { NSString *s = [NSString stringWithUTF8String:name]; dev = [QTCaptureDevice deviceWithUniqueID:s]; info("qtcapture: using device: %s\n", name); } else { dev = [QTCaptureDevice defaultInputDeviceWithMediaType:QTMediaTypeVideo]; } success = [dev open:&err]; if (!success) goto out; input = [[QTCaptureDeviceInput alloc] initWithDevice:dev]; success = [sess addInput:input error:&err]; if (!success) goto out; output = [[QTCaptureDecompressedVideoOutput alloc] init]; [output setDelegate:self]; [output setPixelBufferAttributes: [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithInt:st->app_sz.h], kCVPixelBufferHeightKey, [NSNumber numberWithInt:st->app_sz.w], kCVPixelBufferWidthKey, #if 0 /* This does not work reliably */ [NSNumber numberWithInt:kCVPixelFormatType_420YpCbCr8Planar], (id)kCVPixelBufferPixelFormatTypeKey, #endif nil]]; success = [sess addOutput:output error:&err]; if (!success) goto out; /* Start */ [sess startRunning]; out: if (!success && self) { [self dealloc]; self = nil; } [pool release]; return self; } - (void)stop:(id)unused { (void)unused; [sess stopRunning]; if ([[input device] isOpen]) { [[input device] close]; [sess removeInput:input]; [input release]; } if (output) { [output setDelegate:nil]; [sess removeOutput:output]; [output release]; } } - (void)dealloc { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; [self performSelectorOnMainThread:@selector(stop:) withObject:nil waitUntilDone:YES]; [sess release]; [super dealloc]; [pool release]; } - (void)captureOutput:(QTCaptureOutput *)captureOutput didOutputVideoFrame:(CVImageBufferRef)videoFrame withSampleBuffer:(QTSampleBuffer *)sampleBuffer fromConnection:(QTCaptureConnection *)connection { (void)captureOutput; (void)sampleBuffer; (void)connection; #if 0 printf("got frame: %zu x %zu - fmt=0x%08x\n", CVPixelBufferGetWidth(videoFrame), CVPixelBufferGetHeight(videoFrame), CVPixelBufferGetPixelFormatType(videoFrame)); #endif frame_handler(vsrc, videoFrame); } @end static enum vidfmt get_pixfmt(OSType type) { switch (type) { case kCVPixelFormatType_420YpCbCr8Planar: return VID_FMT_YUV420P; case kCVPixelFormatType_422YpCbCr8: return VID_FMT_UYVY422; case 0x79757673: /* yuvs */ return VID_FMT_YUYV422; case kCVPixelFormatType_32ARGB: return VID_FMT_ARGB; default: return -1; } } static inline void avpict_init_planar(struct vidframe *p, const CVImageBufferRef f) { int i; if (!p) return; for (i=0; i<3; i++) { p->data[i] = CVPixelBufferGetBaseAddressOfPlane(f, i); p->linesize[i] = (int)CVPixelBufferGetBytesPerRowOfPlane(f, i); } p->data[3] = NULL; p->linesize[3] = 0; } static inline void avpict_init_chunky(struct vidframe *p, const CVImageBufferRef f) { p->data[0] = CVPixelBufferGetBaseAddress(f); p->linesize[0] = (int)CVPixelBufferGetBytesPerRow(f); p->data[1] = p->data[2] = p->data[3] = NULL; p->linesize[1] = p->linesize[2] = p->linesize[3] = 0; } static void frame_handler(struct vidsrc_st *st, const CVImageBufferRef videoFrame) { struct vidframe src; vidsrc_frame_h *frameh; void *arg; enum vidfmt vidfmt; lock_write_get(st->lock); frameh = st->frameh; arg = st->arg; lock_rel(st->lock); if (!frameh) return; vidfmt = get_pixfmt(CVPixelBufferGetPixelFormatType(videoFrame)); if (vidfmt == (enum vidfmt)-1) { warning("qtcapture: unknown pixel format: 0x%08x\n", CVPixelBufferGetPixelFormatType(videoFrame)); return; } st->started = true; st->sz.w = (int)CVPixelBufferGetWidth(videoFrame); st->sz.h = (int)CVPixelBufferGetHeight(videoFrame); CVPixelBufferLockBaseAddress(videoFrame, 0); if (CVPixelBufferIsPlanar(videoFrame)) avpict_init_planar(&src, videoFrame); else avpict_init_chunky(&src, videoFrame); src.fmt = vidfmt; src.size = st->sz; CVPixelBufferUnlockBaseAddress(videoFrame, 0); frameh(&src, arg); } static void destructor(void *arg) { struct vidsrc_st *st = arg; #ifdef QTCAPTURE_RUNLOOP tmr_cancel(&st->tmr); #endif lock_write_get(st->lock); st->frameh = NULL; lock_rel(st->lock); [st->cap dealloc]; mem_deref(st->buf); mem_deref(st->lock); } #ifdef QTCAPTURE_RUNLOOP static void tmr_handler(void *arg) { struct vidsrc_st *st = arg; /* Check if frame_handler was called */ if (st->started) return; tmr_start(&st->tmr, 100, tmr_handler, st); /* Simulate the Run-Loop */ (void)CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, YES); } #endif static int alloc(struct vidsrc_st **stp, const struct vidsrc *vs, struct media_ctx **ctx, struct vidsrc_prm *prm, const struct vidsz *size, const char *fmt, const char *dev, vidsrc_frame_h *frameh, vidsrc_error_h *errorh, void *arg) { struct vidsrc_st *st; int err; (void)ctx; (void)prm; (void)fmt; (void)errorh; if (!stp) return EINVAL; st = mem_zalloc(sizeof(*st), destructor); if (!st) return ENOMEM; st->vs = vs; st->frameh = frameh; st->arg = arg; if (size) st->app_sz = *size; err = lock_alloc(&st->lock); if (err) goto out; st->cap = [[qtcap alloc] init:st dev:dev]; if (!st->cap) { err = ENODEV; goto out; } #ifdef QTCAPTURE_RUNLOOP tmr_start(&st->tmr, 10, tmr_handler, st); #endif out: if (err) mem_deref(st); else *stp = st; return err; } static void device_info(void) { NSAutoreleasePool *pool; NSArray *devs; pool = [[NSAutoreleasePool alloc] init]; if (!pool) return; devs = [QTCaptureDevice inputDevicesWithMediaType:QTMediaTypeVideo]; if (devs && [devs count] > 1) { QTCaptureDevice *d; debug("qtcapture: devices:\n"); for (d in devs) { NSString *name = [d localizedDisplayName]; debug(" %s: %s\n", [[d uniqueID] UTF8String], [name UTF8String]); } } [pool release]; } static int module_init(void) { device_info(); return vidsrc_register(&vidsrc, baresip_vidsrcl(), "qtcapture", alloc, NULL); } static int module_close(void) { vidsrc = mem_deref(vidsrc); return 0; } EXPORT_SYM const struct mod_export DECL_EXPORTS(qtcapture) = { "qtcapture", "vidsrc", module_init, module_close }; baresip-1.0.0/modules/rst/000077500000000000000000000000001372575704200154315ustar00rootroot00000000000000baresip-1.0.0/modules/rst/audio.c000066400000000000000000000116621372575704200167040ustar00rootroot00000000000000/** * @file rst/audio.c MP3/ICY HTTP Audio Source * * Copyright (C) 2011 Creytiv.com */ #define _DEFAULT_SOURCE 1 #define _BSD_SOURCE 1 #include #include #include #include #include #include #include #include #include "rst.h" #define MIN_PTIME 20 struct ausrc_st { const struct ausrc *as; /* pointer to base-class (inheritance) */ pthread_t thread; struct rst *rst; mpg123_handle *mp3; struct aubuf *aubuf; ausrc_read_h *rh; ausrc_error_h *errh; void *arg; bool run; uint32_t ptime; size_t sampc; size_t sampsz; enum aufmt fmt; }; static struct ausrc *ausrc; static void destructor(void *arg) { struct ausrc_st *st = arg; rst_set_audio(st->rst, NULL); mem_deref(st->rst); if (st->run) { st->run = false; pthread_join(st->thread, NULL); } if (st->mp3) { mpg123_close(st->mp3); mpg123_delete(st->mp3); } mem_deref(st->aubuf); } static void *play_thread(void *arg) { uint64_t now, ts = tmr_jiffies(); struct ausrc_st *st = arg; void *sampv; size_t num_bytes = st->sampc * st->sampsz; sampv = mem_alloc(num_bytes, NULL); if (!sampv) return NULL; while (st->run) { struct auframe af = { .fmt = st->fmt, .sampv = sampv, .sampc = st->sampc, .timestamp = ts * 1000 }; sys_msleep(4); now = tmr_jiffies(); if (ts > now) continue; #if 1 if (now > ts + 100) { debug("rst: cpu lagging behind (%u ms)\n", now - ts); } #endif aubuf_read(st->aubuf, sampv, num_bytes); st->rh(&af, st->arg); ts += st->ptime; } mem_deref(sampv); return NULL; } static inline int decode(struct ausrc_st *st) { int err, ch, encoding; struct mbuf *mb; long srate; mb = mbuf_alloc(4096); if (!mb) return ENOMEM; err = mpg123_read(st->mp3, mb->buf, mb->size, &mb->end); switch (err) { case MPG123_NEW_FORMAT: mpg123_getformat(st->mp3, &srate, &ch, &encoding); info("rst: new format: %i hz, %i ch, encoding 0x%04x\n", srate, ch, encoding); /*@fallthrough@*/ case MPG123_OK: case MPG123_NEED_MORE: if (mb->end == 0) break; aubuf_append(st->aubuf, mb); break; default: warning("rst: mpg123_read error: %s\n", mpg123_plain_strerror(err)); break; } mem_deref(mb); return err; } void rst_audio_feed(struct ausrc_st *st, const uint8_t *buf, size_t sz) { int err; if (!st) return; err = mpg123_feed(st->mp3, buf, sz); if (err) return; while (MPG123_OK == decode(st)) ; } static int aufmt_to_encoding(enum aufmt fmt) { switch (fmt) { case AUFMT_S16LE: return MPG123_ENC_SIGNED_16; case AUFMT_FLOAT: return MPG123_ENC_FLOAT_32; case AUFMT_S24_3LE: return MPG123_ENC_SIGNED_24; /* NOTE: endian */ default: return 0; } } static int alloc_handler(struct ausrc_st **stp, const struct ausrc *as, struct media_ctx **ctx, struct ausrc_prm *prm, const char *dev, ausrc_read_h *rh, ausrc_error_h *errh, void *arg) { struct ausrc_st *st; int encoding; int err; if (!stp || !as || !prm || !rh) return EINVAL; encoding = aufmt_to_encoding(prm->fmt); if (!encoding) return ENOTSUP; st = mem_zalloc(sizeof(*st), destructor); if (!st) return ENOMEM; st->as = as; st->rh = rh; st->errh = errh; st->arg = arg; st->mp3 = mpg123_new(NULL, &err); if (!st->mp3) { err = ENODEV; goto out; } err = mpg123_open_feed(st->mp3); if (err != MPG123_OK) { warning("rst: mpg123_open_feed: %s\n", mpg123_strerror(st->mp3)); err = ENODEV; goto out; } /* Set wanted output format */ mpg123_format_none(st->mp3); err = mpg123_format(st->mp3, prm->srate, prm->ch, encoding); if (err != MPG123_OK) { warning("rst: mpg123_format: %s\n", mpg123_strerror(st->mp3)); err = ENOTSUP; goto out; } mpg123_volume(st->mp3, 0.3); st->ptime = max(prm->ptime, MIN_PTIME); st->sampc = prm->srate * prm->ch * st->ptime / 1000; st->sampsz = aufmt_sample_size(prm->fmt); st->fmt = prm->fmt; info("rst: audio ptime=%u sampc=%zu aubuf=[%u:%u]\n", st->ptime, st->sampc, prm->srate * prm->ch * 2, prm->srate * prm->ch * 40); /* 1 - 20 seconds of audio */ err = aubuf_alloc(&st->aubuf, prm->srate * prm->ch * st->sampsz, prm->srate * prm->ch * st->sampsz * 20); if (err) goto out; if (ctx && *ctx && (*ctx)->id && !strcmp((*ctx)->id, "rst")) { st->rst = mem_ref(*ctx); } else { err = rst_alloc(&st->rst, dev); if (err) goto out; if (ctx) *ctx = (struct media_ctx *)st->rst; } rst_set_audio(st->rst, st); st->run = true; err = pthread_create(&st->thread, NULL, play_thread, st); if (err) { st->run = false; goto out; } out: if (err) mem_deref(st); else *stp = st; return err; } int rst_audio_init(void) { int err; err = mpg123_init(); if (err != MPG123_OK) { warning("rst: mpg123_init: %s\n", mpg123_plain_strerror(err)); return ENODEV; } return ausrc_register(&ausrc, baresip_ausrcl(), "rst", alloc_handler); } void rst_audio_close(void) { ausrc = mem_deref(ausrc); mpg123_exit(); } baresip-1.0.0/modules/rst/module.mk000066400000000000000000000004201372575704200172430ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2011 Creytiv.com # MOD := rst $(MOD)_SRCS += audio.c $(MOD)_SRCS += rst.c $(MOD)_SRCS += video.c $(MOD)_LFLAGS += $(shell pkg-config --libs cairo libmpg123) $(MOD)_CFLAGS += $(shell pkg-config --cflags cairo libmpg123) include mk/mod.mk baresip-1.0.0/modules/rst/rst.c000066400000000000000000000161351372575704200164130ustar00rootroot00000000000000/** * @file rst.c MP3/ICY HTTP AV Source * * Copyright (C) 2011 Creytiv.com */ #include #include #include #include #include "rst.h" /** * @defgroup rst rst * * Audio and video source module using mpg123 as input * * The module 'rst' is using the mpg123 to play streaming * media (MP3) and provide this as an internal audio/video source. * * Example config: \verbatim audio_source rst,http://relay.slayradio.org:8000/ video_source rst,http://relay.slayradio.org:8000/ \endverbatim */ enum { RETRY_WAIT = 10000, }; struct rst { const char *id; struct ausrc_st *ausrc_st; struct vidsrc_st *vidsrc_st; struct tmr tmr; struct dns_query *dnsq; struct tcp_conn *tc; struct mbuf *mb; char *host; char *path; char *name; char *meta; bool head_recv; size_t metaint; size_t metasz; size_t bytec; uint16_t port; }; static int rst_connect(struct rst *rst); static void destructor(void *arg) { struct rst *rst = arg; tmr_cancel(&rst->tmr); mem_deref(rst->dnsq); mem_deref(rst->tc); mem_deref(rst->mb); mem_deref(rst->host); mem_deref(rst->path); mem_deref(rst->name); mem_deref(rst->meta); } static void reconnect(void *arg) { struct rst *rst = arg; int err; rst->mb = mem_deref(rst->mb); rst->name = mem_deref(rst->name); rst->meta = mem_deref(rst->meta); rst->head_recv = false; rst->metaint = 0; rst->metasz = 0; rst->bytec = 0; err = rst_connect(rst); if (err) tmr_start(&rst->tmr, RETRY_WAIT, reconnect, rst); } static void recv_handler(struct mbuf *mb, void *arg) { struct rst *rst = arg; size_t n; if (!rst->head_recv) { struct pl hdr, name, metaint, eoh; if (rst->mb) { size_t pos; int err; pos = rst->mb->pos; rst->mb->pos = rst->mb->end; err = mbuf_write_mem(rst->mb, mbuf_buf(mb), mbuf_get_left(mb)); if (err) { warning("rst: buffer write error: %m\n", err); rst->tc = mem_deref(rst->tc); tmr_start(&rst->tmr, RETRY_WAIT, reconnect, rst); return; } rst->mb->pos = pos; } else { rst->mb = mem_ref(mb); } if (re_regex((const char *)mbuf_buf(rst->mb), mbuf_get_left(rst->mb), "[^\r\n]1\r\n\r\n", &eoh)) return; rst->head_recv = true; hdr.p = (const char *)mbuf_buf(rst->mb); hdr.l = eoh.p + 5 - hdr.p; if (!re_regex(hdr.p, hdr.l, "icy-name:[ \t]*[^\r\n]+\r\n", NULL, &name)) (void)pl_strdup(&rst->name, &name); if (!re_regex(hdr.p, hdr.l, "icy-metaint:[ \t]*[0-9]+\r\n", NULL, &metaint)) rst->metaint = pl_u32(&metaint); if (rst->metaint == 0) { info("rst: icy meta interval not available\n"); rst->tc = mem_deref(rst->tc); tmr_start(&rst->tmr, RETRY_WAIT, reconnect, rst); return; } rst_video_update(rst->vidsrc_st, rst->name, NULL); rst->mb->pos += hdr.l; info("rst: name='%s' metaint=%zu\n", rst->name, rst->metaint); if (rst->mb->pos >= rst->mb->end) return; mb = rst->mb; } while (mb->pos < mb->end) { if (rst->metasz > 0) { n = min(mbuf_get_left(mb), rst->metasz - rst->bytec); if (rst->meta) mbuf_read_mem(mb, (uint8_t *)&rst->meta[rst->bytec], n); else mb->pos += n; rst->bytec += n; #if 0 info("rst: metadata %zu bytes\n", n); #endif if (rst->bytec >= rst->metasz) { #if 0 info("rst: metadata: [%s]\n", rst->meta); #endif rst->metasz = 0; rst->bytec = 0; rst_video_update(rst->vidsrc_st, rst->name, rst->meta); } } else if (rst->bytec < rst->metaint) { n = min(mbuf_get_left(mb), rst->metaint - rst->bytec); rst_audio_feed(rst->ausrc_st, mbuf_buf(mb), n); rst->bytec += n; mb->pos += n; #if 0 info("rst: mp3data %zu bytes\n", n); #endif } else { rst->metasz = mbuf_read_u8(mb) * 16; rst->bytec = 0; rst->meta = mem_deref(rst->meta); rst->meta = mem_zalloc(rst->metasz + 1, NULL); #if 0 info("rst: metalength %zu bytes\n", rst->metasz); #endif } } } static void estab_handler(void *arg) { struct rst *rst = arg; struct mbuf *mb; int err; info("rst: connection established\n"); mb = mbuf_alloc(512); if (!mb) { err = ENOMEM; goto out; } err = mbuf_printf(mb, "GET %s HTTP/1.0\r\n" "Icy-MetaData: 1\r\n" "\r\n", rst->path); if (err) goto out; mb->pos = 0; err = tcp_send(rst->tc, mb); if (err) goto out; out: if (err) { warning("rst: error sending HTTP request: %m\n", err); } mem_deref(mb); } static void close_handler(int err, void *arg) { struct rst *rst = arg; info("rst: tcp closed: %m\n", err); rst->tc = mem_deref(rst->tc); tmr_start(&rst->tmr, RETRY_WAIT, reconnect, rst); } static void dns_handler(int err, const struct dnshdr *hdr, struct list *ansl, struct list *authl, struct list *addl, void *arg) { struct rst *rst = arg; struct dnsrr *rr; struct sa srv; (void)err; (void)hdr; (void)authl; (void)addl; rr = dns_rrlist_find(ansl, rst->host, DNS_TYPE_A, DNS_CLASS_IN, true); if (!rr) { warning("rst: unable to resolve: %s\n", rst->host); tmr_start(&rst->tmr, RETRY_WAIT, reconnect, rst); return; } sa_set_in(&srv, rr->rdata.a.addr, rst->port); err = tcp_connect(&rst->tc, &srv, estab_handler, recv_handler, close_handler, rst); if (err) { warning("rst: tcp connect error: %m\n", err); tmr_start(&rst->tmr, RETRY_WAIT, reconnect, rst); return; } } static int rst_connect(struct rst *rst) { struct sa srv; int err; if (!sa_set_str(&srv, rst->host, rst->port)) { err = tcp_connect(&rst->tc, &srv, estab_handler, recv_handler, close_handler, rst); if (err) { warning("rst: tcp connect error: %m\n", err); } } else { err = dnsc_query(&rst->dnsq, net_dnsc(baresip_network()), rst->host, DNS_TYPE_A, DNS_CLASS_IN, true, dns_handler, rst); if (err) { warning("rst: dns query error: %m\n", err); } } return err; } int rst_alloc(struct rst **rstp, const char *dev) { struct pl host, port, path; struct rst *rst; int err; if (!rstp || !dev) return EINVAL; if (re_regex(dev, strlen(dev), "http://[^:/]+[:]*[0-9]*[^]+", &host, NULL, &port, &path)) { warning("rst: bad http url: %s\n", dev); return EBADMSG; } rst = mem_zalloc(sizeof(*rst), destructor); if (!rst) return ENOMEM; rst->id = "rst"; err = pl_strdup(&rst->host, &host); if (err) goto out; err = pl_strdup(&rst->path, &path); if (err) goto out; rst->port = pl_u32(&port); rst->port = rst->port ? rst->port : 80; err = rst_connect(rst); if (err) goto out; out: if (err) mem_deref(rst); else *rstp = rst; return err; } void rst_set_audio(struct rst *rst, struct ausrc_st *st) { if (!rst) return; rst->ausrc_st = st; } void rst_set_video(struct rst *rst, struct vidsrc_st *st) { if (!rst) return; rst->vidsrc_st = st; } static int module_init(void) { int err; err = rst_audio_init(); if (err) goto out; err = rst_video_init(); if (err) goto out; out: if (err) { rst_audio_close(); rst_video_close(); } return err; } static int module_close(void) { rst_audio_close(); rst_video_close(); return 0; } EXPORT_SYM const struct mod_export DECL_EXPORTS(rst) = { "rst", "avsrc", module_init, module_close }; baresip-1.0.0/modules/rst/rst.h000066400000000000000000000011151372575704200164100ustar00rootroot00000000000000/** * @file rst.h MP3/ICY HTTP AV Source * * Copyright (C) 2011 Creytiv.com */ /* Shared AV state */ struct rst; int rst_alloc(struct rst **rstp, const char *dev); void rst_set_audio(struct rst *rst, struct ausrc_st *st); void rst_set_video(struct rst *rst, struct vidsrc_st *st); /* Audio */ void rst_audio_feed(struct ausrc_st *st, const uint8_t *buf, size_t sz); int rst_audio_init(void); void rst_audio_close(void); /* Video */ void rst_video_update(struct vidsrc_st *st, const char *name, const char *meta); int rst_video_init(void); void rst_video_close(void); baresip-1.0.0/modules/rst/video.c000066400000000000000000000114501372575704200167040ustar00rootroot00000000000000/** * @file rst/video.c MP3/ICY HTTP Video Source * * Copyright (C) 2011 Creytiv.com */ #define _DEFAULT_SOURCE 1 #define _BSD_SOURCE 1 #include #include #include #include #include #include #include "rst.h" struct vidsrc_st { const struct vidsrc *vs; /* pointer to base-class (inheritance) */ pthread_mutex_t mutex; pthread_t thread; struct vidsrc_prm prm; struct vidsz size; struct rst *rst; cairo_surface_t *surface; cairo_t *cairo; struct vidframe *frame; vidsrc_frame_h *frameh; void *arg; bool run; }; static struct vidsrc *vidsrc; static void destructor(void *arg) { struct vidsrc_st *st = arg; rst_set_video(st->rst, NULL); mem_deref(st->rst); if (st->run) { st->run = false; pthread_join(st->thread, NULL); } if (st->cairo) cairo_destroy(st->cairo); if (st->surface) cairo_surface_destroy(st->surface); mem_deref(st->frame); } static void *video_thread(void *arg) { uint64_t now, ts = tmr_jiffies(); struct vidsrc_st *st = arg; while (st->run) { uint64_t timestamp; sys_msleep(4); now = tmr_jiffies(); if (ts > now) continue; timestamp = ts * VIDEO_TIMEBASE / 1000; pthread_mutex_lock(&st->mutex); st->frameh(st->frame, timestamp, st->arg); pthread_mutex_unlock(&st->mutex); ts += 1000/st->prm.fps; } return NULL; } static void background(cairo_t *cr, unsigned width, unsigned height) { cairo_pattern_t *pat; double r, g, b; pat = cairo_pattern_create_linear(0.0, 0.0, 0.0, height); if (!pat) return; r = 0.0; g = 0.0; b = 0.8; cairo_pattern_add_color_stop_rgba(pat, 1, r, g, b, 1); cairo_pattern_add_color_stop_rgba(pat, 0, 0, 0, 0.2, 1); cairo_rectangle(cr, 0, 0, width, height); cairo_set_source(cr, pat); cairo_fill(cr); cairo_pattern_destroy(pat); } static void icy_printf(cairo_t *cr, int x, int y, double size, const char *fmt, ...) { char buf[4096] = ""; va_list ap; va_start(ap, fmt); (void)re_vsnprintf(buf, sizeof(buf), fmt, ap); va_end(ap); /* Draw text */ cairo_select_font_face(cr, "Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); cairo_set_font_size(cr, size); cairo_move_to(cr, x, y); cairo_text_path(cr, buf); cairo_set_source_rgb(cr, 1, 1, 1); cairo_fill(cr); } static size_t linelen(const struct pl *pl) { size_t len = 72, i; if (pl->l <= len) return pl->l; for (i=len; i>1; i--) { if (pl->p[i-1] == ' ') { len = i; break; } } return len; } void rst_video_update(struct vidsrc_st *st, const char *name, const char *meta) { struct vidframe frame; if (!st) return; background(st->cairo, st->size.w, st->size.h); icy_printf(st->cairo, 50, 100, 40.0, "%s", name); if (meta) { struct pl title; if (!re_regex(meta, strlen(meta), "StreamTitle='[ \t]*[^;]+;", NULL, &title)) { unsigned i; title.l--; for (i=0; title.l; i++) { const size_t len = linelen(&title); icy_printf(st->cairo, 50, 150 + 25*i, 18.0, "%b", title.p, len); title.p += len; title.l -= len; } } } vidframe_init_buf(&frame, VID_FMT_RGB32, &st->size, cairo_image_surface_get_data(st->surface)); pthread_mutex_lock(&st->mutex); vidconv(st->frame, &frame, NULL); pthread_mutex_unlock(&st->mutex); } static int alloc_handler(struct vidsrc_st **stp, const struct vidsrc *vs, struct media_ctx **ctx, struct vidsrc_prm *prm, const struct vidsz *size, const char *fmt, const char *dev, vidsrc_frame_h *frameh, vidsrc_error_h *errorh, void *arg) { struct vidsrc_st *st; int err; (void)fmt; (void)errorh; if (!stp || !vs || !prm || !size || !frameh) return EINVAL; st = mem_zalloc(sizeof(*st), destructor); if (!st) return ENOMEM; err = pthread_mutex_init(&st->mutex, NULL); if (err) goto out; st->vs = vs; st->prm = *prm; st->size = *size; st->frameh = frameh; st->arg = arg; st->surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, size->w, size->h); if (!st->surface) { err = ENOMEM; goto out; } st->cairo = cairo_create(st->surface); if (!st->cairo) { err = ENOMEM; goto out; } err = vidframe_alloc(&st->frame, VID_FMT_YUV420P, size); if (err) goto out; vidframe_fill(st->frame, 0, 0, 0); if (ctx && *ctx && (*ctx)->id && !strcmp((*ctx)->id, "rst")) { st->rst = mem_ref(*ctx); } else { err = rst_alloc(&st->rst, dev); if (err) goto out; if (ctx) *ctx = (struct media_ctx *)st->rst; } rst_set_video(st->rst, st); st->run = true; err = pthread_create(&st->thread, NULL, video_thread, st); if (err) { st->run = false; goto out; } out: if (err) mem_deref(st); else *stp = st; return err; } int rst_video_init(void) { return vidsrc_register(&vidsrc, baresip_vidsrcl(), "rst", alloc_handler, NULL); } void rst_video_close(void) { vidsrc = mem_deref(vidsrc); } baresip-1.0.0/modules/rtcpsummary/000077500000000000000000000000001372575704200172075ustar00rootroot00000000000000baresip-1.0.0/modules/rtcpsummary/module.mk000066400000000000000000000002111372575704200210170ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # MOD := rtcpsummary $(MOD)_SRCS += rtcpsummary.c $(MOD)_LFLAGS += include mk/mod.mk baresip-1.0.0/modules/rtcpsummary/rtcpsummary.c000066400000000000000000000045351372575704200217500ustar00rootroot00000000000000/** * @file rtcpsummary.c RTCP summary module * Output RTCP stats at the end of a call if there are any * * Copyright (C) 2010 - 2018 Creytiv.com */ #include #include static void print_rtcp_summary_line(const struct call *call, const struct stream *s) { const struct rtcp_stats *rtcp; rtcp = stream_rtcp_stats(s); if (rtcp && (rtcp->tx.sent || rtcp->rx.sent)) { info("\n"); /* * Add a stats line to make it easier to parse result * from script. Use a similar format used for the * XRTP message in audio.c */ info( "EX=BareSip;" /* Reporter Identifier */ "CS=%d;" /* Call Setup in ms */ "CD=%d;" /* Call Duration in sec */ "PR=%u;" /* Packets RX */ "PS=%u;" /* Packets TX */ "PL=%d,%d;" /* Packets Lost RX, TX */ "PD=%d,%d;" /* Packets Discarded, RX,TX */ "JI=%.1f,%.1f;"/* Jitter RX, TX in ms */ "DL=%.1f;" /* RTT in ms */ "IP=%J,%J;" /* Local, Remote IPs */ "\n" , call_setup_duration(call) * 1000, call_duration(call), rtcp->rx.sent, rtcp->tx.sent, rtcp->rx.lost, rtcp->tx.lost, stream_metric_get_rx_n_err(s), stream_metric_get_tx_n_err(s), 1.0 * rtcp->rx.jit/1000, 1.0 * rtcp->tx.jit/1000, 1.0 * rtcp->rtt/1000, sdp_media_laddr(stream_sdpmedia(s)), sdp_media_raddr(stream_sdpmedia(s))); } else { /* * put a line showing how * RTCP stats were NOT collected */ info("\n"); info("EX=BareSip;ERROR=No RTCP stats collected;\n"); } } static void ua_event_handler(struct ua *ua, enum ua_event ev, struct call *call, const char *prm, void *arg) { const struct stream *s; struct le *le; (void)ua; (void)prm; (void)arg; switch (ev) { case UA_EVENT_CALL_CLOSED: for (le = call_streaml(call)->head; le; le = le->next) { s = le->data; print_rtcp_summary_line(call, s); } break; default: break; } } static int module_init(void) { int err = uag_event_register(ua_event_handler, NULL); if (err) { info("Error loading rtcpsummary module: %d", err); return err; } return 0; } static int module_close(void) { debug("rtcpsummary: module closing..\n"); uag_event_unregister(ua_event_handler); return 0; } const struct mod_export DECL_EXPORTS(rtcpsummary) = { "rtcpsummary", "application", module_init, module_close }; baresip-1.0.0/modules/sdl/000077500000000000000000000000001372575704200154035ustar00rootroot00000000000000baresip-1.0.0/modules/sdl/module.mk000066400000000000000000000002001372575704200172110ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # MOD := sdl $(MOD)_SRCS += sdl.c $(MOD)_LFLAGS += -lSDL2 include mk/mod.mk baresip-1.0.0/modules/sdl/sdl.c000066400000000000000000000157701372575704200163430ustar00rootroot00000000000000/** * @file sdl/sdl.c Simple DirectMedia Layer module for SDL v2.0 * * Copyright (C) 2010 Creytiv.com */ #include #include #include #include /** * @defgroup sdl sdl * * Video display using Simple DirectMedia Layer version 2 (SDL2) */ struct vidisp_st { const struct vidisp *vd; /**< Inheritance (1st) */ SDL_Window *window; /**< SDL Window */ SDL_Renderer *renderer; /**< SDL Renderer */ SDL_Texture *texture; /**< Texture for pixels */ struct vidsz size; /**< Current size */ enum vidfmt fmt; /**< Current pixel format */ bool fullscreen; /**< Fullscreen flag */ struct tmr tmr; Uint32 flags; bool quit; }; static struct vidisp *vid; static void event_handler(void *arg); static uint32_t match_fmt(enum vidfmt fmt) { switch (fmt) { case VID_FMT_YUV420P: return SDL_PIXELFORMAT_IYUV; case VID_FMT_YUYV422: return SDL_PIXELFORMAT_YUY2; case VID_FMT_UYVY422: return SDL_PIXELFORMAT_UYVY; #if SDL_VERSION_ATLEAST(2, 0, 4) case VID_FMT_NV12: return SDL_PIXELFORMAT_NV12; case VID_FMT_NV21: return SDL_PIXELFORMAT_NV21; #endif case VID_FMT_RGB32: return SDL_PIXELFORMAT_ARGB8888; default: return SDL_PIXELFORMAT_UNKNOWN; } } static uint32_t chroma_step(enum vidfmt fmt) { switch (fmt) { case VID_FMT_YUV420P: return 2; case VID_FMT_NV12: return 1; case VID_FMT_NV21: return 1; case VID_FMT_RGB32: return 0; default: return 0; } } static void sdl_reset(struct vidisp_st *st) { if (st->texture) { /*SDL_DestroyTexture(st->texture);*/ st->texture = NULL; } if (st->renderer) { /*SDL_DestroyRenderer(st->renderer);*/ st->renderer = NULL; } if (st->window) { SDL_DestroyWindow(st->window); st->window = NULL; } } static void event_handler(void *arg) { struct vidisp_st *st = arg; SDL_Event event; tmr_start(&st->tmr, 100, event_handler, st); /* NOTE: events must be checked from main thread */ while (SDL_PollEvent(&event)) { if (event.type == SDL_KEYDOWN) { switch (event.key.keysym.sym) { case SDLK_f: /* press key 'f' to toggle fullscreen */ st->fullscreen = !st->fullscreen; info("sdl: %sable fullscreen mode\n", st->fullscreen ? "en" : "dis"); if (st->fullscreen) st->flags |= SDL_WINDOW_FULLSCREEN_DESKTOP; else st->flags &= ~SDL_WINDOW_FULLSCREEN_DESKTOP; SDL_SetWindowFullscreen(st->window, st->flags); break; case SDLK_q: ui_input_key(baresip_uis(), 'q', NULL); break; default: break; } } else if (event.type == SDL_QUIT) { st->quit = true; break; } } } static void destructor(void *arg) { struct vidisp_st *st = arg; tmr_cancel(&st->tmr); sdl_reset(st); /* needed to close the window */ SDL_PumpEvents(); } static int alloc(struct vidisp_st **stp, const struct vidisp *vd, struct vidisp_prm *prm, const char *dev, vidisp_resize_h *resizeh, void *arg) { struct vidisp_st *st; /* Not used by SDL */ (void)dev; (void)resizeh; (void)arg; if (!stp || !vd) return EINVAL; st = mem_zalloc(sizeof(*st), destructor); if (!st) return ENOMEM; st->vd = vd; st->fullscreen = prm ? prm->fullscreen : false; tmr_start(&st->tmr, 100, event_handler, st); *stp = st; return 0; } static int display(struct vidisp_st *st, const char *title, const struct vidframe *frame, uint64_t timestamp) { void *pixels; uint8_t *d; int dpitch, ret; unsigned i, h; uint32_t format; (void)timestamp; if (!st || !frame) return EINVAL; if (st->quit) return ENODEV; format = match_fmt(frame->fmt); if (format == SDL_PIXELFORMAT_UNKNOWN) { warning("sdl: pixel format not supported (%s)\n", vidfmt_name(frame->fmt)); return ENOTSUP; } if (!vidsz_cmp(&st->size, &frame->size) || frame->fmt != st->fmt) { if (st->size.w && st->size.h) { info("sdl: reset size:" " %s %u x %u ---> %s %u x %u\n", vidfmt_name(st->fmt), st->size.w, st->size.h, vidfmt_name(frame->fmt), frame->size.w, frame->size.h); } sdl_reset(st); } if (!st->window) { char capt[256]; st->flags = SDL_WINDOW_SHOWN | SDL_WINDOW_INPUT_FOCUS; st->flags |= SDL_WINDOW_RESIZABLE; if (st->fullscreen) st->flags |= SDL_WINDOW_FULLSCREEN_DESKTOP; if (title) { re_snprintf(capt, sizeof(capt), "%s - %u x %u", title, frame->size.w, frame->size.h); } else { re_snprintf(capt, sizeof(capt), "%u x %u", frame->size.w, frame->size.h); } st->window = SDL_CreateWindow(capt, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, frame->size.w, frame->size.h, st->flags); if (!st->window) { warning("sdl: unable to create sdl window: %s\n", SDL_GetError()); return ENODEV; } st->size = frame->size; st->fmt = frame->fmt; SDL_RaiseWindow(st->window); SDL_SetWindowBordered(st->window, true); SDL_ShowWindow(st->window); } if (!st->renderer) { SDL_RendererInfo rend_info; Uint32 flags = 0; flags |= SDL_RENDERER_ACCELERATED; flags |= SDL_RENDERER_PRESENTVSYNC; st->renderer = SDL_CreateRenderer(st->window, -1, flags); if (!st->renderer) { warning("sdl: unable to create renderer: %s\n", SDL_GetError()); return ENOMEM; } if (!SDL_GetRendererInfo(st->renderer, &rend_info)) { info("sdl: created renderer '%s'\n", rend_info.name); } } if (!st->texture) { st->texture = SDL_CreateTexture(st->renderer, format, SDL_TEXTUREACCESS_STREAMING, frame->size.w, frame->size.h); if (!st->texture) { warning("sdl: unable to create texture: %s\n", SDL_GetError()); return ENODEV; } } ret = SDL_LockTexture(st->texture, NULL, &pixels, &dpitch); if (ret != 0) { warning("sdl: unable to lock texture (ret=%d)\n", ret); return ENODEV; } d = pixels; for (i=0; i<3; i++) { const uint8_t *s = frame->data[i]; unsigned sz, dsz, hstep, wstep; if (!frame->data[i] || !frame->linesize[i]) break; hstep = i==0 ? 1 : 2; wstep = i==0 ? 1 : chroma_step(frame->fmt); if (wstep == 0) continue; dsz = dpitch / wstep; sz = min(frame->linesize[i], dsz); for (h = 0; h < frame->size.h; h += hstep) { memcpy(d, s, sz); s += frame->linesize[i]; d += dsz; } } SDL_UnlockTexture(st->texture); /* Blit the sprite onto the screen */ SDL_RenderCopy(st->renderer, st->texture, NULL, NULL); /* Update the screen! */ SDL_RenderPresent(st->renderer); return 0; } static void hide(struct vidisp_st *st) { if (!st || !st->window) return; SDL_HideWindow(st->window); } static int module_init(void) { int err; if (SDL_VideoInit(NULL) < 0) { warning("sdl: unable to init Video: %s\n", SDL_GetError()); return ENODEV; } err = vidisp_register(&vid, baresip_vidispl(), "sdl", alloc, NULL, display, hide); if (err) return err; return 0; } static int module_close(void) { vid = mem_deref(vid); SDL_Quit(); return 0; } EXPORT_SYM const struct mod_export DECL_EXPORTS(sdl) = { "sdl", "vidisp", module_init, module_close, }; baresip-1.0.0/modules/selfview/000077500000000000000000000000001372575704200164455ustar00rootroot00000000000000baresip-1.0.0/modules/selfview/module.mk000066400000000000000000000002031372575704200202560ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # MOD := selfview $(MOD)_SRCS += selfview.c $(MOD)_LFLAGS += include mk/mod.mk baresip-1.0.0/modules/selfview/selfview.c000066400000000000000000000127451372575704200204460ustar00rootroot00000000000000/** * @file selfview.c Selfview Video-Filter * * Copyright (C) 2010 Creytiv.com */ #include #include #include #include /** * @defgroup selfview selfview * * Show a selfview of the captured video stream * * Example config: \verbatim video_selfview pip # {window,pip} selfview_size 64x64 \endverbatim */ /* shared state */ struct selfview { struct lock *lock; /**< Protect frame */ struct vidframe *frame; /**< Copy of encoded frame */ }; struct selfview_enc { struct vidfilt_enc_st vf; /**< Inheritance */ struct selfview *selfview; /**< Ref. to shared state */ struct vidisp_st *disp; /**< Selfview display */ }; struct selfview_dec { struct vidfilt_dec_st vf; /**< Inheritance */ struct selfview *selfview; /**< Ref. to shared state */ }; static struct vidsz selfview_size = {0, 0}; static void destructor(void *arg) { struct selfview *st = arg; lock_write_get(st->lock); mem_deref(st->frame); lock_rel(st->lock); mem_deref(st->lock); } static void encode_destructor(void *arg) { struct selfview_enc *st = arg; list_unlink(&st->vf.le); mem_deref(st->selfview); mem_deref(st->disp); } static void decode_destructor(void *arg) { struct selfview_dec *st = arg; list_unlink(&st->vf.le); mem_deref(st->selfview); } static int selfview_alloc(struct selfview **selfviewp, void **ctx) { struct selfview *selfview; int err; if (!selfviewp || !ctx) return EINVAL; if (*ctx) { *selfviewp = mem_ref(*ctx); } else { selfview = mem_zalloc(sizeof(*selfview), destructor); if (!selfview) return ENOMEM; err = lock_alloc(&selfview->lock); if (err) return err; *ctx = selfview; *selfviewp = selfview; } return 0; } static int encode_update(struct vidfilt_enc_st **stp, void **ctx, const struct vidfilt *vf, struct vidfilt_prm *prm, const struct video *vid) { struct selfview_enc *st; int err; (void)prm; (void)vid; if (!stp || !ctx || !vf) return EINVAL; if (*stp) return 0; st = mem_zalloc(sizeof(*st), encode_destructor); if (!st) return ENOMEM; err = selfview_alloc(&st->selfview, ctx); if (err) mem_deref(st); else *stp = (struct vidfilt_enc_st *)st; return err; } static int decode_update(struct vidfilt_dec_st **stp, void **ctx, const struct vidfilt *vf, struct vidfilt_prm *prm, const struct video *vid) { struct selfview_dec *st; int err; (void)prm; (void)vid; if (!stp || !ctx || !vf) return EINVAL; st = mem_zalloc(sizeof(*st), decode_destructor); if (!st) return ENOMEM; err = selfview_alloc(&st->selfview, ctx); if (err) mem_deref(st); else *stp = (struct vidfilt_dec_st *)st; return err; } static int encode_win(struct vidfilt_enc_st *st, struct vidframe *frame, uint64_t *timestamp) { struct selfview_enc *enc = (struct selfview_enc *)st; int err; if (!frame) return 0; if (!enc->disp) { err = vidisp_alloc(&enc->disp, baresip_vidispl(), NULL, NULL, NULL, NULL, NULL); if (err) return err; } return vidisp_display(enc->disp, "Selfview", frame, *timestamp); } static int encode_pip(struct vidfilt_enc_st *st, struct vidframe *frame, uint64_t *timestamp) { struct selfview_enc *enc = (struct selfview_enc *)st; struct selfview *selfview = enc->selfview; int err = 0; (void)timestamp; if (!frame) return 0; lock_write_get(selfview->lock); if (!selfview->frame) { struct vidsz sz; /* Use size if configured, or else 20% of main window */ if (selfview_size.w && selfview_size.h) { sz = selfview_size; } else { sz.w = frame->size.w / 5; sz.h = frame->size.h / 5; } err = vidframe_alloc(&selfview->frame, VID_FMT_YUV420P, &sz); } if (!err) vidconv(selfview->frame, frame, NULL); lock_rel(selfview->lock); return err; } static int decode_pip(struct vidfilt_dec_st *st, struct vidframe *frame, uint64_t *timestamp) { struct selfview_dec *dec = (struct selfview_dec *)st; struct selfview *sv = dec->selfview; (void)timestamp; if (!frame) return 0; lock_read_get(sv->lock); if (sv->frame) { struct vidrect rect; rect.w = min(sv->frame->size.w, frame->size.w/2); rect.h = min(sv->frame->size.h, frame->size.h/2); if (rect.w <= (frame->size.w - 10)) rect.x = frame->size.w - rect.w - 10; else rect.x = frame->size.w/2; if (rect.h <= (frame->size.h - 10)) rect.y = frame->size.h - rect.h - 10; else rect.y = frame->size.h/2; vidconv(frame, sv->frame, &rect); vidframe_draw_rect(frame, rect.x, rect.y, rect.w, rect.h, 127, 127, 127); } lock_rel(sv->lock); return 0; } static struct vidfilt selfview_win = { .name = "selfview_window", .encupdh = encode_update, .ench = encode_win, }; static struct vidfilt selfview_pip = { .name = "selfview_pip", .encupdh = encode_update, .ench = encode_pip, .decupdh = decode_update, .dech = decode_pip }; static int module_init(void) { struct pl pl = PL("pip"); (void)conf_get(conf_cur(), "video_selfview", &pl); if (0 == pl_strcasecmp(&pl, "window")) vidfilt_register(baresip_vidfiltl(), &selfview_win); else if (0 == pl_strcasecmp(&pl, "pip")) vidfilt_register(baresip_vidfiltl(), &selfview_pip); (void)conf_get_vidsz(conf_cur(), "selfview_size", &selfview_size); return 0; } static int module_close(void) { vidfilt_unregister(&selfview_win); vidfilt_unregister(&selfview_pip); return 0; } EXPORT_SYM const struct mod_export DECL_EXPORTS(selfview) = { "selfview", "vidfilt", module_init, module_close }; baresip-1.0.0/modules/snapshot/000077500000000000000000000000001372575704200164605ustar00rootroot00000000000000baresip-1.0.0/modules/snapshot/module.mk000066400000000000000000000002221372575704200202720ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # MOD := snapshot $(MOD)_SRCS += snapshot.c png_vf.c $(MOD)_LFLAGS += -lpng include mk/mod.mk baresip-1.0.0/modules/snapshot/png_vf.c000066400000000000000000000056041372575704200201100ustar00rootroot00000000000000/** * @file png_vf.c Write vidframe to a PNG-file * * Author: Doug Blewett * Review: Alfred E. Heggestad */ #define _DEFAULT_SOURCE 1 #define _BSD_SOURCE 1 #include #include #include #include #include #include "png_vf.h" static void png_save_free(png_structp png_ptr, png_byte **png_row_pointers, int png_height); int png_save_vidframe(const struct vidframe *vf, const char *path) { png_byte **png_row_pointers = NULL; png_byte *row; const png_byte *p; png_byte red, green, blue; png_structp png_ptr = NULL; png_infop info_ptr = NULL; FILE *fp = NULL; size_t x, y; unsigned int width = vf->size.w & ~1; unsigned int height = vf->size.h & ~1; unsigned int bytes_per_pixel = 3; /* RGB format */ struct vidframe *f2 = NULL; int err = 0; if (vf->fmt != VID_FMT_RGB32) { err = vidframe_alloc(&f2, VID_FMT_RGB32, &vf->size); if (err) goto out; vidconv(f2, vf, NULL); vf = f2; } /* Initialize the write struct. */ png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) { err = ENOMEM; goto out; } /* Initialize the info struct. */ info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { err = ENOMEM; goto out; } /* Set up error handling. */ if (setjmp(png_jmpbuf(png_ptr))) { err = ENOMEM; goto out; } /* Set image attributes. */ png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); /* Initialize rows of PNG * bytes_per_row = width * bytes_per_pixel; */ png_row_pointers = png_malloc(png_ptr, height * sizeof(png_byte *)); for (y = 0; y < height; ++y) { png_row_pointers[y] = (png_byte *) png_malloc(png_ptr, width * sizeof(uint8_t) * bytes_per_pixel); } p = vf->data[0]; for (y = 0; y < height; ++y) { row = png_row_pointers[y]; for (x = 0; x < width; ++x) { red = *p++; green = *p++; blue = *p++; *row++ = blue; *row++ = green; *row++ = red; ++p; /* skip alpha */ } } /* Write the image data. */ fp = fopen(path, "wb"); if (fp == NULL) { err = errno; goto out; } png_init_io(png_ptr, fp); png_set_rows(png_ptr, info_ptr, png_row_pointers); png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); info("png: wrote %s\n", path); out: /* Finish writing. */ mem_deref(f2); png_save_free(png_ptr, png_row_pointers, height); png_destroy_write_struct(&png_ptr, &info_ptr); if (fp) fclose(fp); return 0; } static void png_save_free(png_structp png_ptr, png_byte **png_row_pointers, int png_height) { int y; /* Cleanup. */ if (png_height == 0 || png_row_pointers == NULL) return; for (y = 0; y < png_height; y++) { png_free(png_ptr, png_row_pointers[y]); } png_free(png_ptr, png_row_pointers); } baresip-1.0.0/modules/snapshot/png_vf.h000066400000000000000000000001401372575704200201030ustar00rootroot00000000000000/** * @file png_vf.h */ int png_save_vidframe(const struct vidframe *vf, const char *path); baresip-1.0.0/modules/snapshot/snapshot.c000066400000000000000000000070601372575704200204660ustar00rootroot00000000000000/** * @file snapshot.c Snapshot Video-Filter * * Copyright (C) 2010 Creytiv.com */ #include #include #include #include #include "png_vf.h" #include /** * @defgroup snapshot snapshot * * Take snapshot of the video stream and save it as PNG-files * * * Commands: * \verbatim snapshot Take video snapshot of both video streams snapshot_recv path Take snapshot of receiving video and save it to the path snapshot_send path Take snapshot of sending video and save it to the path \endverbatim */ static bool flag_enc, flag_dec; static char path_enc[100], path_dec[100]; static char *png_filename(const struct tm *tmx, const char *name, char *buf, unsigned int length); static int encode(struct vidfilt_enc_st *st, struct vidframe *frame, uint64_t *timestamp) { (void)st; (void)timestamp; if (!frame) return 0; if (flag_enc) { flag_enc = false; png_save_vidframe(frame, path_enc); } return 0; } static int decode(struct vidfilt_dec_st *st, struct vidframe *frame, uint64_t *timestamp) { (void)st; (void)timestamp; if (!frame) return 0; if (flag_dec) { flag_dec = false; png_save_vidframe(frame, path_dec); } return 0; } static int do_snapshot(struct re_printf *pf, void *arg) { time_t tnow; struct tm *tmx; (void)pf; (void)arg; if (flag_enc || flag_dec) return 0; tnow = time(NULL); tmx = localtime(&tnow); /* NOTE: not re-entrant */ png_filename(tmx, "snapshot-recv", path_dec, sizeof(path_dec)); png_filename(tmx, "snapshot-send", path_enc, sizeof(path_enc)); flag_enc = flag_dec = true; return 0; } static int do_snapshot_recv(struct re_printf *pf, void *arg) { (void)pf; const struct cmd_arg *carg = arg; if (flag_dec) return 0; /* NOTE: not re-entrant */ str_ncpy(path_dec, carg->prm, sizeof(path_dec)); flag_dec = true; return 0; } static int do_snapshot_send(struct re_printf *pf, void *arg) { (void)pf; const struct cmd_arg *carg = arg; if (flag_enc) return 0; /* NOTE: not re-entrant */ str_ncpy(path_enc, carg->prm, sizeof(path_enc)); flag_enc = true; return 0; } static struct vidfilt snapshot = { .name = "snapshot", .ench = encode, .dech = decode, }; static const struct cmd cmdv[] = { {"snapshot", 0, 0, "Take video snapshot", do_snapshot }, {"snapshot_recv", 0, CMD_PRM, "Take receiving video snapshot and save to path", do_snapshot_recv}, {"snapshot_send", 0, CMD_PRM, "Take sending video snapshot and save to path", do_snapshot_send} }; static int module_init(void) { vidfilt_register(baresip_vidfiltl(), &snapshot); return cmd_register(baresip_commands(), cmdv, ARRAY_SIZE(cmdv)); } static int module_close(void) { vidfilt_unregister(&snapshot); cmd_unregister(baresip_commands(), cmdv); return 0; } static char *png_filename(const struct tm *tmx, const char *name, char *buf, unsigned int length) { /* * -2013-03-03-15-22-56.png - 24 chars */ if (strlen(name) + 24 >= length) { buf[0] = '\0'; return buf; } sprintf(buf, (tmx->tm_mon < 9 ? "%s-%d-0%d" : "%s-%d-%d"), name, 1900 + tmx->tm_year, tmx->tm_mon + 1); sprintf(buf + strlen(buf), (tmx->tm_mday < 10 ? "-0%d" : "-%d"), tmx->tm_mday); sprintf(buf + strlen(buf), (tmx->tm_hour < 10 ? "-0%d" : "-%d"), tmx->tm_hour); sprintf(buf + strlen(buf), (tmx->tm_min < 10 ? "-0%d" : "-%d"), tmx->tm_min); sprintf(buf + strlen(buf), (tmx->tm_sec < 10 ? "-0%d.png" : "-%d.png"), tmx->tm_sec); return buf; } EXPORT_SYM const struct mod_export DECL_EXPORTS(snapshot) = { "snapshot", "vidfilt", module_init, module_close }; baresip-1.0.0/modules/sndfile/000077500000000000000000000000001372575704200162455ustar00rootroot00000000000000baresip-1.0.0/modules/sndfile/module.mk000066400000000000000000000002131372575704200200570ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # MOD := sndfile $(MOD)_SRCS += sndfile.c $(MOD)_LFLAGS += -lsndfile include mk/mod.mk baresip-1.0.0/modules/sndfile/sndfile.c000066400000000000000000000103331372575704200200350ustar00rootroot00000000000000/** * @file sndfile.c Audio dumper using libsndfile * * Copyright (C) 2010 Creytiv.com */ #include #include #include #include #include /** * @defgroup sndfile sndfile * * Audio filter that writes audio samples to WAV-file * * Example Configuration: \verbatim snd_path /tmp/ \endverbatim */ struct sndfile_enc { struct aufilt_enc_st af; /* base class */ SNDFILE *enc; enum aufmt fmt; }; struct sndfile_dec { struct aufilt_dec_st af; /* base class */ SNDFILE *dec; enum aufmt fmt; }; static char file_path[256] = "."; static int timestamp_print(struct re_printf *pf, const struct tm *tm) { if (!tm) return 0; return re_hprintf(pf, "%d-%02d-%02d-%02d-%02d-%02d", 1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); } static void enc_destructor(void *arg) { struct sndfile_enc *st = arg; if (st->enc) sf_close(st->enc); list_unlink(&st->af.le); } static void dec_destructor(void *arg) { struct sndfile_dec *st = arg; if (st->dec) sf_close(st->dec); list_unlink(&st->af.le); } static int get_format(enum aufmt fmt) { switch (fmt) { case AUFMT_S16LE: return SF_FORMAT_PCM_16; case AUFMT_FLOAT: return SF_FORMAT_FLOAT; default: return 0; } } static SNDFILE *openfile(const struct aufilt_prm *prm, bool enc) { char filename[128]; SF_INFO sfinfo; time_t tnow = time(0); struct tm *tm = localtime(&tnow); SNDFILE *sf; int format; (void)re_snprintf(filename, sizeof(filename), "%s/dump-%H-%s.wav", file_path, timestamp_print, tm, enc ? "enc" : "dec"); format = get_format(prm->fmt); if (!format) { warning("sndfile: sample format not supported (%s)\n", aufmt_name(prm->fmt)); return NULL; } sfinfo.samplerate = prm->srate; sfinfo.channels = prm->ch; sfinfo.format = SF_FORMAT_WAV | format; sf = sf_open(filename, SFM_WRITE, &sfinfo); if (!sf) { warning("sndfile: could not open: %s\n", filename); puts(sf_strerror(NULL)); return NULL; } info("sndfile: dumping %s audio to %s\n", enc ? "encode" : "decode", filename); return sf; } static int encode_update(struct aufilt_enc_st **stp, void **ctx, const struct aufilt *af, struct aufilt_prm *prm, const struct audio *au) { struct sndfile_enc *st; int err = 0; (void)ctx; (void)af; (void)au; if (!stp || !prm) return EINVAL; st = mem_zalloc(sizeof(*st), enc_destructor); if (!st) return EINVAL; st->fmt = prm->fmt; st->enc = openfile(prm, true); if (!st->enc) err = ENOMEM; if (err) mem_deref(st); else *stp = (struct aufilt_enc_st *)st; return err; } static int decode_update(struct aufilt_dec_st **stp, void **ctx, const struct aufilt *af, struct aufilt_prm *prm, const struct audio *au) { struct sndfile_dec *st; int err = 0; (void)ctx; (void)af; (void)au; if (!stp || !prm) return EINVAL; st = mem_zalloc(sizeof(*st), dec_destructor); if (!st) return EINVAL; st->fmt = prm->fmt; st->dec = openfile(prm, false); if (!st->dec) err = ENOMEM; if (err) mem_deref(st); else *stp = (struct aufilt_dec_st *)st; return err; } static int encode(struct aufilt_enc_st *st, struct auframe *af) { struct sndfile_enc *sf = (struct sndfile_enc *)st; size_t num_bytes; if (!st || !af) return EINVAL; num_bytes = af->sampc * aufmt_sample_size(sf->fmt); sf_write_raw(sf->enc, af->sampv, num_bytes); return 0; } static int decode(struct aufilt_dec_st *st, struct auframe *af) { struct sndfile_dec *sf = (struct sndfile_dec *)st; size_t num_bytes; if (!st || !af) return EINVAL; num_bytes = af->sampc * aufmt_sample_size(sf->fmt); sf_write_raw(sf->dec, af->sampv, num_bytes); return 0; } static struct aufilt sndfile = { .name = "sndfile", .encupdh = encode_update, .ench = encode, .decupdh = decode_update, .dech = decode }; static int module_init(void) { aufilt_register(baresip_aufiltl(), &sndfile); conf_get_str(conf_cur(), "snd_path", file_path, sizeof(file_path)); info("sndfile: saving files in %s\n", file_path); return 0; } static int module_close(void) { aufilt_unregister(&sndfile); return 0; } EXPORT_SYM const struct mod_export DECL_EXPORTS(sndfile) = { "sndfile", "filter", module_init, module_close }; baresip-1.0.0/modules/sndio/000077500000000000000000000000001372575704200157355ustar00rootroot00000000000000baresip-1.0.0/modules/sndio/module.mk000066400000000000000000000002051372575704200175500ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2014 Creytiv.com # MOD := sndio $(MOD)_SRCS += sndio.c $(MOD)_LFLAGS += -lsndio include mk/mod.mk baresip-1.0.0/modules/sndio/sndio.c000066400000000000000000000124121372575704200172150ustar00rootroot00000000000000/** * @file sndio.c SndIO sound driver * * Copyright (C) 2014 Creytiv.com */ #include #include #include #include #include #include #include /** * @defgroup sndio sndio * * This module implements audio driver for OpenBSD sndio */ struct ausrc_st { const struct ausrc *as; /* pointer to base-class */ struct sio_hdl *hdl; pthread_t thread; int16_t *sampv; size_t sampc; int run; ausrc_read_h *rh; void *arg; }; struct auplay_st { const struct auplay *ap; /* pointer to base-class */ struct sio_hdl *hdl; pthread_t thread; int16_t *sampv; size_t sampc; int run; auplay_write_h *wh; void *arg; }; static struct ausrc *ausrc; static struct auplay *auplay; static struct sio_par *sndio_initpar(uint32_t srate, uint8_t ch) { struct sio_par *par = NULL; if ((par = mem_zalloc(sizeof(*par), NULL)) == NULL) return NULL; sio_initpar(par); /* sndio doesn't support a-low and u-low */ par->bits = 16; par->bps = SIO_BPS(par->bits); par->sig = 1; par->le = SIO_LE_NATIVE; par->rchan = ch; par->pchan = ch; par->rate = srate; return par; } static void *read_thread(void *arg) { struct ausrc_st *st = arg; if (!sio_start(st->hdl)) { warning("sndio: could not start record\n"); goto out; } while (st->run) { struct auframe af; size_t n = sio_read(st->hdl, st->sampv, st->sampc*2); af.fmt = AUFMT_S16LE; af.sampv = st->sampv; af.sampc = n/2; st->rh(&af, st->arg); } out: return NULL; } static void *write_thread(void *arg) { struct auplay_st *st = arg; if (!sio_start(st->hdl)) { warning("sndio: could not start playback\n"); goto out; } while (st->run) { st->wh(st->sampv, st->sampc, st->arg); sio_write(st->hdl, st->sampv, st->sampc*2); } out: return NULL; } static void ausrc_destructor(void *arg) { struct ausrc_st *st = arg; if (st->run) { st->run = false; (void)pthread_join(st->thread, NULL); } if (st->hdl) sio_close(st->hdl); mem_deref(st->sampv); } static void auplay_destructor(void *arg) { struct auplay_st *st = arg; if (st->run) { st->run = false; (void)pthread_join(st->thread, NULL); } if (st->hdl) sio_close(st->hdl); mem_deref(st->sampv); } static int src_alloc(struct ausrc_st **stp, const struct ausrc *as, struct media_ctx **ctx, struct ausrc_prm *prm, const char *device, ausrc_read_h *rh, ausrc_error_h *errh, void *arg) { struct ausrc_st *st; struct sio_par *par = NULL; int err; const char *name; (void)ctx; (void)errh; if (!stp || !as || !prm) return EINVAL; if (prm->fmt != AUFMT_S16LE) { warning("sndio: source: unsupported sample format (%s)\n", aufmt_name(prm->fmt)); return ENOTSUP; } name = (str_isset(device)) ? device : SIO_DEVANY; if ((st = mem_zalloc(sizeof(*st), ausrc_destructor)) == NULL) return ENOMEM; st->as = as; st->rh = rh; st->arg = arg; st->hdl = sio_open(name, SIO_REC, 0); if (!st->hdl) { warning("sndio: could not open ausrc device '%s'\n", name); err = EINVAL; goto out; } par = sndio_initpar(prm->srate, prm->ch); if (!par) { err = ENOMEM; goto out; } if (!sio_setpar(st->hdl, par)) { err = EINVAL; goto out; } if (!sio_getpar(st->hdl, par)) { err = EINVAL; goto out; } st->sampc = par->bufsz / 2; st->sampv = mem_alloc(2 * st->sampc, NULL); if (!st->sampv) { err = ENOMEM; goto out; } st->run = true; err = pthread_create(&st->thread, NULL, read_thread, st); if (err) st->run = false; out: mem_deref(par); if (err) mem_deref(st); else *stp = st; return err; } static int play_alloc(struct auplay_st **stp, const struct auplay *ap, struct auplay_prm *prm, const char *device, auplay_write_h *wh, void *arg) { struct auplay_st *st; struct sio_par *par = NULL; int err; const char *name; if (!stp || !ap || !prm) return EINVAL; if (prm->fmt != AUFMT_S16LE) { warning("sndio: playback: unsupported sample format (%s)\n", aufmt_name(prm->fmt)); return ENOTSUP; } name = (str_isset(device)) ? device : SIO_DEVANY; if ((st = mem_zalloc(sizeof(*st), auplay_destructor)) == NULL) return ENOMEM; st->ap = ap; st->wh = wh; st->arg = arg; st->hdl = sio_open(name, SIO_PLAY, 0); if (!st->hdl) { warning("sndio: could not open auplay device '%s'\n", name); err = EINVAL; goto out; } par = sndio_initpar(prm->srate, prm->ch); if (!par) { err = ENOMEM; goto out; } if (!sio_setpar(st->hdl, par)) { err = EINVAL; goto out; } if (!sio_getpar(st->hdl, par)) { err = EINVAL; goto out; } st->sampc = prm->srate * prm->ch * prm->ptime / 1000; st->sampv = mem_alloc(2 * st->sampc, NULL); if (!st->sampv) { err = ENOMEM; goto out; } st->run = true; err = pthread_create(&st->thread, NULL, write_thread, st); if (err) st->run = false; out: mem_deref(par); if (err) mem_deref(st); else *stp = st; return err; } static int sndio_init(void) { int err = 0; err |= ausrc_register(&ausrc, baresip_ausrcl(), "sndio", src_alloc); err |= auplay_register(&auplay, baresip_auplayl(), "sndio", play_alloc); return err; } static int sndio_close(void) { ausrc = mem_deref(ausrc); auplay = mem_deref(auplay); return 0; } EXPORT_SYM const struct mod_export DECL_EXPORTS(sndio) = { "sndio", "sound", sndio_init, sndio_close }; baresip-1.0.0/modules/speex_pp/000077500000000000000000000000001372575704200164445ustar00rootroot00000000000000baresip-1.0.0/modules/speex_pp/module.mk000066400000000000000000000002201372575704200202540ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # MOD := speex_pp $(MOD)_SRCS += speex_pp.c $(MOD)_LFLAGS += "-lspeexdsp" include mk/mod.mk baresip-1.0.0/modules/speex_pp/speex_pp.c000066400000000000000000000062711372575704200204410ustar00rootroot00000000000000/** * @file speex_pp.c Speex Pre-processor * * Copyright (C) 2010 Creytiv.com */ #include #include #include #include #include #include /** * @defgroup speex_pp speex_pp * * Audio pre-processor from libspeexdsp */ struct preproc { struct aufilt_enc_st af; /* base class */ SpeexPreprocessState *state; uint32_t srate; size_t frame_size; }; /** Speex configuration */ static struct { int denoise_enabled; int agc_enabled; int vad_enabled; int dereverb_enabled; spx_int32_t agc_level; } pp_conf = { 1, 1, 1, 1, 8000 }; static void speexpp_destructor(void *arg) { struct preproc *st = arg; if (st->state) speex_preprocess_state_destroy(st->state); list_unlink(&st->af.le); } static int init_state(struct preproc *st, size_t frame_size) { st->state = speex_preprocess_state_init((int)frame_size, st->srate); if (!st->state) return ENOMEM; speex_preprocess_ctl(st->state, SPEEX_PREPROCESS_SET_DENOISE, &pp_conf.denoise_enabled); speex_preprocess_ctl(st->state, SPEEX_PREPROCESS_SET_AGC, &pp_conf.agc_enabled); #ifdef SPEEX_PREPROCESS_SET_AGC_TARGET if (pp_conf.agc_enabled) { speex_preprocess_ctl(st->state, SPEEX_PREPROCESS_SET_AGC_TARGET, &pp_conf.agc_level); } #endif speex_preprocess_ctl(st->state, SPEEX_PREPROCESS_SET_VAD, &pp_conf.vad_enabled); speex_preprocess_ctl(st->state, SPEEX_PREPROCESS_SET_DEREVERB, &pp_conf.dereverb_enabled); st->frame_size = frame_size; info("speex_pp: state inited (frame_size=%zu)\n", frame_size); return 0; } static int encode_update(struct aufilt_enc_st **stp, void **ctx, const struct aufilt *af, struct aufilt_prm *prm, const struct audio *au) { struct preproc *st; (void)ctx; (void)au; if (!stp || !af || !prm) return EINVAL; if (prm->fmt != AUFMT_S16LE) { warning("speex_pp: unsupported sample format (%s)\n", aufmt_name(prm->fmt)); return ENOTSUP; } st = mem_zalloc(sizeof(*st), speexpp_destructor); if (!st) return ENOMEM; st->srate = prm->srate; info("speex_pp: Speex preprocessor loaded: srate = %uHz\n", prm->srate); *stp = (struct aufilt_enc_st *)st; return 0; } static int encode(struct aufilt_enc_st *st, struct auframe *af) { struct preproc *pp = (struct preproc *)st; int err; if (!st || !af) return EINVAL; if (!af->sampc) return 0; if (pp->state && af->sampc != pp->frame_size) { speex_preprocess_state_destroy(pp->state); pp->state = NULL; } if (!pp->state) { err = init_state(pp, af->sampc); if (err) return err; } speex_preprocess_run(pp->state, af->sampv); return 0; } static void config_parse(struct conf *conf) { uint32_t v; if (0 == conf_get_u32(conf, "speex_agc_level", &v)) pp_conf.agc_level = v; } static struct aufilt preproc = { .name = "speex_pp", .encupdh = encode_update, .ench = encode, }; static int module_init(void) { config_parse(conf_cur()); aufilt_register(baresip_aufiltl(), &preproc); return 0; } static int module_close(void) { aufilt_unregister(&preproc); return 0; } EXPORT_SYM const struct mod_export DECL_EXPORTS(speex_pp) = { "speex_pp", "filter", module_init, module_close }; baresip-1.0.0/modules/srtp/000077500000000000000000000000001372575704200156115ustar00rootroot00000000000000baresip-1.0.0/modules/srtp/module.mk000066400000000000000000000002021372575704200174210ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # MOD := srtp $(MOD)_SRCS += srtp.c sdes.c $(MOD)_LFLAGS += include mk/mod.mk baresip-1.0.0/modules/srtp/sdes.c000066400000000000000000000020441372575704200167130ustar00rootroot00000000000000/** * @file /srtp/sdes.c SDP Security Descriptions for Media Streams (RFC 4568) * * Copyright (C) 2010 Creytiv.com */ #include #include #include "sdes.h" const char sdp_attr_crypto[] = "crypto"; int sdes_encode_crypto(struct sdp_media *m, uint32_t tag, const char *suite, const char *key, size_t key_len) { return sdp_media_set_lattr(m, true, sdp_attr_crypto, "%u %s inline:%b", tag, suite, key, key_len); } /* http://tools.ietf.org/html/rfc4568 * a=crypto: [] */ int sdes_decode_crypto(struct crypto *c, const char *val) { struct pl tag, key_prms; int err; err = re_regex(val, str_len(val), "[0-9]+ [^ ]+ [^ ]+[]*[^]*", &tag, &c->suite, &key_prms, NULL, &c->sess_prms); if (err) return err; c->tag = pl_u32(&tag); c->lifetime = c->mki = pl_null; err = re_regex(key_prms.p, key_prms.l, "[^:]+:[^|]+[|]*[^|]*[|]*[^|]*", &c->key_method, &c->key_info, NULL, &c->lifetime, NULL, &c->mki); if (err) return err; return 0; } baresip-1.0.0/modules/srtp/sdes.h000066400000000000000000000010371372575704200167210ustar00rootroot00000000000000/** * @file /srtp/sdes.h SDP Security Descriptions for Media Streams API * * Copyright (C) 2010 Creytiv.com */ struct crypto { uint32_t tag; struct pl suite; struct pl key_method; struct pl key_info; struct pl lifetime; /* optional */ struct pl mki; /* optional */ struct pl sess_prms; /* optional */ }; extern const char sdp_attr_crypto[]; int sdes_encode_crypto(struct sdp_media *m, uint32_t tag, const char *suite, const char *key, size_t key_len); int sdes_decode_crypto(struct crypto *c, const char *val); baresip-1.0.0/modules/srtp/srtp.c000066400000000000000000000245151372575704200167540ustar00rootroot00000000000000/** * @file modules/srtp/srtp.c Secure Real-time Transport Protocol (RFC 3711) * * Copyright (C) 2010 Creytiv.com */ #include #include #include "sdes.h" /** * @defgroup srtp srtp * * Secure Real-time Transport Protocol module * * This module implements media encryption using SRTP and SDES. * * SRTP can be enabled in ~/.baresip/accounts: * \verbatim ;mediaenc=srtp ;mediaenc=srtp-mand \endverbatim * */ struct menc_sess { menc_event_h *eventh; void *arg; }; struct menc_st { /* one SRTP session per media line */ const struct menc_sess *sess; uint8_t key_tx[32+12]; /* base64_decoding worst case encoded 32+12 key */ uint8_t key_rx[46]; struct srtp *srtp_tx, *srtp_rx; bool use_srtp; bool got_sdp; char *crypto_suite; void *rtpsock; void *rtcpsock; struct udp_helper *uh_rtp; /**< UDP helper for RTP encryption */ struct udp_helper *uh_rtcp; /**< UDP helper for RTCP encryption */ struct sdp_media *sdpm; const struct stream *strm; /**< pointer to parent */ }; static const char aes_cm_128_hmac_sha1_32[] = "AES_CM_128_HMAC_SHA1_32"; static const char aes_cm_128_hmac_sha1_80[] = "AES_CM_128_HMAC_SHA1_80"; static const char aes_128_gcm[] = "AEAD_AES_128_GCM"; static const char aes_256_gcm[] = "AEAD_AES_256_GCM"; static const char *preferred_suite = aes_cm_128_hmac_sha1_80; static void destructor(void *arg) { struct menc_st *st = arg; mem_deref(st->sdpm); mem_deref(st->crypto_suite); /* note: must be done before freeing socket */ mem_deref(st->uh_rtp); mem_deref(st->uh_rtcp); mem_deref(st->rtpsock); mem_deref(st->rtcpsock); mem_deref(st->srtp_tx); mem_deref(st->srtp_rx); } static bool cryptosuite_issupported(const struct pl *suite) { if (0 == pl_strcasecmp(suite, aes_cm_128_hmac_sha1_32)) return true; if (0 == pl_strcasecmp(suite, aes_cm_128_hmac_sha1_80)) return true; if (0 == pl_strcasecmp(suite, aes_128_gcm)) return true; if (0 == pl_strcasecmp(suite, aes_256_gcm)) return true; return false; } /* * See RFC 5764 figure 3: * * +----------------+ * | 127 < B < 192 -+--> forward to RTP * | | * packet --> | 19 < B < 64 -+--> forward to DTLS * | | * | B < 2 -+--> forward to STUN * +----------------+ * */ static bool is_rtp_or_rtcp(const struct mbuf *mb) { uint8_t b; if (mbuf_get_left(mb) < 1) return false; b = mbuf_buf(mb)[0]; return 127 < b && b < 192; } static bool is_rtcp_packet(const struct mbuf *mb) { uint8_t pt; if (mbuf_get_left(mb) < 2) return false; pt = mbuf_buf(mb)[1] & 0x7f; return 64 <= pt && pt <= 95; } static enum srtp_suite resolve_suite(const char *suite) { if (0 == str_casecmp(suite, aes_cm_128_hmac_sha1_32)) return SRTP_AES_CM_128_HMAC_SHA1_32; if (0 == str_casecmp(suite, aes_cm_128_hmac_sha1_80)) return SRTP_AES_CM_128_HMAC_SHA1_80; if (0 == str_casecmp(suite, aes_128_gcm)) return SRTP_AES_128_GCM; if (0 == str_casecmp(suite, aes_256_gcm)) return SRTP_AES_256_GCM; return -1; } static size_t get_master_keylen(enum srtp_suite suite) { switch (suite) { case SRTP_AES_CM_128_HMAC_SHA1_32: return 16+14; case SRTP_AES_CM_128_HMAC_SHA1_80: return 16+14; case SRTP_AES_128_GCM: return 16+12; case SRTP_AES_256_GCM: return 32+12; default: return 0; } } static int start_srtp(struct menc_st *st, const char *suite_name) { enum srtp_suite suite; size_t len; int err; suite = resolve_suite(suite_name); len = get_master_keylen(suite); /* allocate and initialize the SRTP session */ if (!st->srtp_tx) { err = srtp_alloc(&st->srtp_tx, suite, st->key_tx, len, 0); if (err) { warning("srtp: srtp_alloc TX failed (%m)\n", err); return err; } } if (!st->srtp_rx) { err = srtp_alloc(&st->srtp_rx, suite, st->key_rx, len, 0); if (err) { warning("srtp: srtp_alloc RX failed (%m)\n", err); return err; } } /* use SRTP for this stream/session */ st->use_srtp = true; return 0; } static bool send_handler(int *err, struct sa *dst, struct mbuf *mb, void *arg) { struct menc_st *st = arg; size_t len = mbuf_get_left(mb); int lerr = 0; (void)dst; if (!st->use_srtp || !is_rtp_or_rtcp(mb)) return false; if (is_rtcp_packet(mb)) { lerr = srtcp_encrypt(st->srtp_tx, mb); } else { lerr = srtp_encrypt(st->srtp_tx, mb); } if (lerr) { warning("srtp: failed to encrypt %s-packet" " with %zu bytes (%m)\n", is_rtcp_packet(mb) ? "RTCP" : "RTP", len, lerr); *err = lerr; return false; } return false; /* continue processing */ } static bool recv_handler(struct sa *src, struct mbuf *mb, void *arg) { struct menc_st *st = arg; size_t len = mbuf_get_left(mb); int err = 0; (void)src; if (!st->got_sdp) return true; /* drop the packet */ if (!st->use_srtp || !is_rtp_or_rtcp(mb)) return false; if (is_rtcp_packet(mb)) { err = srtcp_decrypt(st->srtp_rx, mb); if (err) { warning("srtp: failed to decrypt RTCP packet" " with %zu bytes (%m)\n", len, err); } } else { err = srtp_decrypt(st->srtp_rx, mb); if (err) { warning("srtp: failed to decrypt RTP packet" " with %zu bytes (%m)\n", len, err); } } return err ? true : false; } /* a=crypto: [] */ static int sdp_enc(struct menc_st *st, struct sdp_media *m, uint32_t tag, const char *suite) { char key[128] = ""; size_t len, olen; int err; len = get_master_keylen(resolve_suite(suite)); olen = sizeof(key); err = base64_encode(st->key_tx, len, key, &olen); if (err) return err; return sdes_encode_crypto(m, tag, suite, key, olen); } static int start_crypto(struct menc_st *st, const struct pl *key_info) { size_t olen, len; char buf[64] = ""; int err; len = get_master_keylen(resolve_suite(st->crypto_suite)); /* key-info is BASE64 encoded */ olen = sizeof(st->key_rx); err = base64_decode(key_info->p, key_info->l, st->key_rx, &olen); if (err) return err; if (len != olen) { warning("srtp: %s: srtp keylen is %u (should be %zu)\n", st->crypto_suite, olen, len); } err = start_srtp(st, st->crypto_suite); if (err) return err; info("srtp: %s: SRTP is Enabled (cryptosuite=%s)\n", sdp_media_name(st->sdpm), st->crypto_suite); if (st->sess->eventh) { if (re_snprintf(buf, sizeof(buf), "%s,%s", sdp_media_name(st->sdpm), st->crypto_suite)) st->sess->eventh(MENC_EVENT_SECURE, buf, (struct stream *)st->strm, st->sess->arg); else warning("srtp: failed to print secure" " event arguments\n"); } return 0; } static bool sdp_attr_handler(const char *name, const char *value, void *arg) { struct menc_st *st = arg; struct crypto c; (void)name; if (sdes_decode_crypto(&c, value)) return false; if (0 != pl_strcmp(&c.key_method, "inline")) return false; if (!cryptosuite_issupported(&c.suite)) return false; st->crypto_suite = mem_deref(st->crypto_suite); pl_strdup(&st->crypto_suite, &c.suite); if (start_crypto(st, &c.key_info)) return false; sdp_enc(st, st->sdpm, c.tag, st->crypto_suite); return true; } static int session_alloc(struct menc_sess **sessp, struct sdp_session *sdp, bool offerer, menc_event_h *eventh, menc_error_h *errorh, void *arg) { struct menc_sess *sess; (void)sdp; (void)offerer; (void)errorh; if (!sessp) return EINVAL; sess = mem_zalloc(sizeof(*sess), NULL); if (!sess) return ENOMEM; sess->eventh = eventh; sess->arg = arg; *sessp = sess; return 0; } static int media_alloc(struct menc_media **stp, struct menc_sess *sess, struct rtp_sock *rtp, struct udp_sock *rtpsock, struct udp_sock *rtcpsock, const struct sa *raddr_rtp, const struct sa *raddr_rtcp, struct sdp_media *sdpm, const struct stream *strm) { struct menc_st *st; const char *rattr = NULL; int layer = 10; /* above zero */ int err = 0; bool mux = (rtpsock == rtcpsock); (void)sess; (void)rtp; (void)raddr_rtp; (void)raddr_rtcp; if (!stp || !sdpm || !sess) return EINVAL; st = (struct menc_st *)*stp; if (!st) { st = mem_zalloc(sizeof(*st), destructor); if (!st) return ENOMEM; st->sess = sess; st->sdpm = mem_ref(sdpm); st->strm = strm; if (0 == str_cmp(sdp_media_proto(sdpm), "RTP/AVP")) { err = sdp_media_set_alt_protos(st->sdpm, 4, "RTP/AVP", "RTP/AVPF", "RTP/SAVP", "RTP/SAVPF"); if (err) goto out; } if (rtpsock) { st->rtpsock = mem_ref(rtpsock); err |= udp_register_helper(&st->uh_rtp, rtpsock, layer, send_handler, recv_handler, st); } if (rtcpsock && !mux) { st->rtcpsock = mem_ref(rtcpsock); err |= udp_register_helper(&st->uh_rtcp, rtcpsock, layer, send_handler, recv_handler, st); } if (err) goto out; /* set our preferred crypto-suite */ err |= str_dup(&st->crypto_suite, preferred_suite); if (err) goto out; rand_bytes(st->key_tx, sizeof(st->key_tx)); } /* SDP handling */ if (sdp_media_rport(sdpm)) st->got_sdp = true; if (sdp_media_rattr(st->sdpm, "crypto")) { rattr = sdp_media_rattr_apply(st->sdpm, "crypto", sdp_attr_handler, st); if (!rattr) { warning("srtp: no valid a=crypto attribute from" " remote peer\n"); } } if (!rattr) err = sdp_enc(st, sdpm, 1, st->crypto_suite); out: if (err) mem_deref(st); else *stp = (struct menc_media *)st; return err; } static struct menc menc_srtp_opt = { .id = "srtp", .sdp_proto = "RTP/AVP", .sessh = session_alloc, .mediah = media_alloc }; static struct menc menc_srtp_mand = { .id = "srtp-mand", .sdp_proto = "RTP/SAVP", .sessh = session_alloc, .mediah = media_alloc }; static struct menc menc_srtp_mandf = { .id = "srtp-mandf", .sdp_proto = "RTP/SAVPF", .sessh = session_alloc, .mediah = media_alloc }; static int mod_srtp_init(void) { struct list *mencl = baresip_mencl(); menc_register(mencl, &menc_srtp_opt); menc_register(mencl, &menc_srtp_mand); menc_register(mencl, &menc_srtp_mandf); return 0; } static int mod_srtp_close(void) { menc_unregister(&menc_srtp_mandf); menc_unregister(&menc_srtp_mand); menc_unregister(&menc_srtp_opt); return 0; } EXPORT_SYM const struct mod_export DECL_EXPORTS(srtp) = { "srtp", "menc", mod_srtp_init, mod_srtp_close }; baresip-1.0.0/modules/stdio/000077500000000000000000000000001372575704200157435ustar00rootroot00000000000000baresip-1.0.0/modules/stdio/module.mk000066400000000000000000000001751372575704200175640ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # MOD := stdio $(MOD)_SRCS += stdio.c $(MOD)_LFLAGS += include mk/mod.mk baresip-1.0.0/modules/stdio/stdio.c000066400000000000000000000055451372575704200172420ustar00rootroot00000000000000/** * @file stdio.c Standard Input/Output UI module * * Copyright (C) 2010 Creytiv.com */ #include #include #include #include #include #include /** * @defgroup stdio stdio * * User-Interface (UI) module for standard input/output * * This module sets up the terminal in raw mode, and reads characters from the * input to the UI subsystem. The module is indented for Unix-based systems. */ /** Local constants */ enum { RELEASE_VAL = 250 /**< Key release value in [ms] */ }; struct ui_st { struct tmr tmr; struct termios term; bool term_set; }; /* We only allow one instance */ static struct ui_st *ui_state; static void ui_destructor(void *arg) { struct ui_st *st = arg; fd_close(STDIN_FILENO); if (st->term_set) tcsetattr(STDIN_FILENO, TCSANOW, &st->term); tmr_cancel(&st->tmr); } static int print_handler(const char *p, size_t size, void *arg) { (void)arg; return 1 == fwrite(p, size, 1, stderr) ? 0 : ENOMEM; } static void report_key(struct ui_st *ui, char key) { static struct re_printf pf_stderr = {print_handler, NULL}; (void)ui; ui_input_key(baresip_uis(), key, &pf_stderr); } static void timeout(void *arg) { struct ui_st *st = arg; /* Emulate key-release */ report_key(st, KEYCODE_REL); } static void ui_fd_handler(int flags, void *arg) { struct ui_st *st = arg; char key; (void)flags; if (1 != read(STDIN_FILENO, &key, 1)) { return; } tmr_start(&st->tmr, RELEASE_VAL, timeout, st); report_key(st, key); } static int term_setup(struct ui_st *st) { struct termios now; if (tcgetattr(STDIN_FILENO, &st->term) < 0) return errno; now = st->term; now.c_lflag |= ISIG; now.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN); /* required on Solaris */ now.c_cc[VMIN] = 1; now.c_cc[VTIME] = 0; if (tcsetattr(STDIN_FILENO, TCSANOW, &now) < 0) return errno; st->term_set = true; return 0; } static int ui_alloc(struct ui_st **stp) { struct ui_st *st; int err; if (!stp) return EINVAL; st = mem_zalloc(sizeof(*st), ui_destructor); if (!st) return ENOMEM; tmr_init(&st->tmr); err = fd_listen(STDIN_FILENO, FD_READ, ui_fd_handler, st); if (err) goto out; err = term_setup(st); if (err) { info("stdio: could not setup terminal: %m\n", err); err = 0; } out: if (err) mem_deref(st); else *stp = st; return err; } static int output_handler(const char *str) { return print_handler(str, str_len(str), NULL); } static struct ui ui_stdio = { .name = "stdio", .outputh = output_handler }; static int module_init(void) { int err; err = ui_alloc(&ui_state); if (err) return err; ui_register(baresip_uis(), &ui_stdio); return 0; } static int module_close(void) { ui_unregister(&ui_stdio); ui_state = mem_deref(ui_state); return 0; } const struct mod_export DECL_EXPORTS(stdio) = { "stdio", "ui", module_init, module_close }; baresip-1.0.0/modules/stun/000077500000000000000000000000001372575704200156125ustar00rootroot00000000000000baresip-1.0.0/modules/stun/module.mk000066400000000000000000000001521372575704200174260ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # MOD := stun $(MOD)_SRCS += stun.c include mk/mod.mk baresip-1.0.0/modules/stun/stun.c000066400000000000000000000105021372575704200167450ustar00rootroot00000000000000/** * @file stun.c STUN Module for Media NAT-traversal * * Copyright (C) 2010 Creytiv.com */ #include #include /** * @defgroup stun stun * * Session Traversal Utilities for NAT (STUN) for media NAT traversal */ enum {LAYER = 0, INTERVAL = 30}; struct mnat_sess { struct list medial; struct sa srv; struct stun_dns *dnsq; mnat_estab_h *estabh; void *arg; int mediac; }; struct mnat_media { struct le le; struct sa addr1; struct sa addr2; struct mnat_sess *sess; struct sdp_media *sdpm; struct stun_keepalive *ska1; struct stun_keepalive *ska2; void *sock1; void *sock2; }; static void session_destructor(void *arg) { struct mnat_sess *sess = arg; list_flush(&sess->medial); mem_deref(sess->dnsq); } static void media_destructor(void *arg) { struct mnat_media *m = arg; list_unlink(&m->le); mem_deref(m->sdpm); mem_deref(m->ska1); mem_deref(m->ska2); mem_deref(m->sock1); mem_deref(m->sock2); } static void mapped_handler1(int err, const struct sa *map_addr, void *arg) { struct mnat_media *m = arg; if (!err) { sdp_media_set_laddr(m->sdpm, map_addr); m->addr1 = *map_addr; if (m->ska2 && !sa_isset(&m->addr2, SA_ALL)) return; if (--m->sess->mediac) return; } m->sess->estabh(err, 0, NULL, m->sess->arg); } static void mapped_handler2(int err, const struct sa *map_addr, void *arg) { struct mnat_media *m = arg; if (!err) { sdp_media_set_laddr_rtcp(m->sdpm, map_addr); m->addr2 = *map_addr; if (m->ska1 && !sa_isset(&m->addr1, SA_ALL)) return; if (--m->sess->mediac) return; } m->sess->estabh(err, 0, NULL, m->sess->arg); } static int media_start(struct mnat_sess *sess, struct mnat_media *m) { int err = 0; if (m->sock1) { err |= stun_keepalive_alloc(&m->ska1, IPPROTO_UDP, m->sock1, LAYER, &sess->srv, NULL, mapped_handler1, m); } if (m->sock2) { err |= stun_keepalive_alloc(&m->ska2, IPPROTO_UDP, m->sock2, LAYER, &sess->srv, NULL, mapped_handler2, m); } if (err) return err; stun_keepalive_enable(m->ska1, INTERVAL); stun_keepalive_enable(m->ska2, INTERVAL); return 0; } static void dns_handler(int err, const struct sa *srv, void *arg) { struct mnat_sess *sess = arg; struct le *le; if (err) goto out; sess->srv = *srv; for (le=sess->medial.head; le; le=le->next) { struct mnat_media *m = le->data; err = media_start(sess, m); if (err) goto out; } return; out: sess->estabh(err, 0, NULL, sess->arg); } static int session_alloc(struct mnat_sess **sessp, const struct mnat *mnat, struct dnsc *dnsc, int af, const struct stun_uri *srv, const char *user, const char *pass, struct sdp_session *ss, bool offerer, mnat_estab_h *estabh, void *arg) { struct mnat_sess *sess; int err; (void)mnat; (void)user; (void)pass; (void)ss; (void)offerer; if (!sessp || !dnsc || !srv || !ss || !estabh) return EINVAL; if (srv->scheme != STUN_SCHEME_STUN) return ENOTSUP; sess = mem_zalloc(sizeof(*sess), session_destructor); if (!sess) return ENOMEM; sess->estabh = estabh; sess->arg = arg; err = stun_server_discover(&sess->dnsq, dnsc, stun_usage_binding, stun_proto_udp, af, srv->host, srv->port, dns_handler, sess); if (err) mem_deref(sess); else *sessp = sess; return err; } static int media_alloc(struct mnat_media **mp, struct mnat_sess *sess, struct udp_sock *sock1, struct udp_sock *sock2, struct sdp_media *sdpm, mnat_connected_h *connh, void *arg) { struct mnat_media *m; int err = 0; (void)connh; (void)arg; if (!mp || !sess || !sdpm) return EINVAL; m = mem_zalloc(sizeof(*m), media_destructor); if (!m) return ENOMEM; list_append(&sess->medial, &m->le, m); m->sdpm = mem_ref(sdpm); m->sess = sess; m->sock1 = mem_ref(sock1); m->sock2 = mem_ref(sock2); if (sa_isset(&sess->srv, SA_ALL)) err = media_start(sess, m); if (err) mem_deref(m); else { *mp = m; ++sess->mediac; } return err; } static struct mnat mnat_stun = { .id = "stun", .sessh = session_alloc, .mediah = media_alloc, }; static int module_init(void) { mnat_register(baresip_mnatl(), &mnat_stun); return 0; } static int module_close(void) { mnat_unregister(&mnat_stun); return 0; } EXPORT_SYM const struct mod_export DECL_EXPORTS(stun) = { "stun", "mnat", module_init, module_close, }; baresip-1.0.0/modules/swscale/000077500000000000000000000000001372575704200162625ustar00rootroot00000000000000baresip-1.0.0/modules/swscale/module.mk000066400000000000000000000002131372575704200200740ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # MOD := swscale $(MOD)_SRCS += swscale.c $(MOD)_LFLAGS += -lswscale include mk/mod.mk baresip-1.0.0/modules/swscale/swscale.c000066400000000000000000000076301372575704200200750ustar00rootroot00000000000000/** * @file swscale.c Video filter for scaling and pixel conversion * * Copyright (C) 2010 - 2016 Creytiv.com */ #include #include #include #include struct swscale_enc { struct vidfilt_enc_st vf; /**< Inheritance */ struct SwsContext *sws; struct vidframe *frame; struct vidsz dst_size; enum vidfmt swscale_format; }; static enum AVPixelFormat vidfmt_to_avpixfmt(enum vidfmt fmt) { switch (fmt) { case VID_FMT_YUV420P: return AV_PIX_FMT_YUV420P; case VID_FMT_YUV444P: return AV_PIX_FMT_YUV444P; case VID_FMT_NV12: return AV_PIX_FMT_NV12; case VID_FMT_NV21: return AV_PIX_FMT_NV21; default: return AV_PIX_FMT_NONE; } } static void encode_destructor(void *arg) { struct swscale_enc *st = arg; list_unlink(&st->vf.le); mem_deref(st->frame); sws_freeContext(st->sws); } static int encode_update(struct vidfilt_enc_st **stp, void **ctx, const struct vidfilt *vf, struct vidfilt_prm *prm, const struct video *vid) { struct swscale_enc *st; int err = 0; (void)vid; if (!stp || !ctx || !vf || !prm) return EINVAL; if (*stp) return 0; st = mem_zalloc(sizeof(*st), encode_destructor); if (!st) return ENOMEM; st->dst_size.w = prm->width; st->dst_size.h = prm->height; st->swscale_format = prm->fmt; if (err) mem_deref(st); else *stp = (struct vidfilt_enc_st *)st; return err; } static int encode_process(struct vidfilt_enc_st *st, struct vidframe *frame, uint64_t *timestamp) { struct swscale_enc *enc = (struct swscale_enc *)st; enum AVPixelFormat avpixfmt, avpixfmt_dst; const uint8_t *srcSlice[4]; uint8_t *dst[4]; int srcStride[4], dstStride[4]; int width, height, i, h; int err = 0; (void)timestamp; if (!st) return EINVAL; if (!frame) return 0; width = frame->size.w; height = frame->size.h; avpixfmt = vidfmt_to_avpixfmt(frame->fmt); if (avpixfmt == AV_PIX_FMT_NONE) { warning("swscale: unknown pixel-format (%s)\n", vidfmt_name(frame->fmt)); return EINVAL; } avpixfmt_dst = vidfmt_to_avpixfmt(enc->swscale_format); if (avpixfmt_dst == AV_PIX_FMT_NONE) { warning("swscale: unknown pixel-format (%s)\n", vidfmt_name(enc->swscale_format)); return EINVAL; } if (!enc->sws) { struct SwsContext *sws; int flags = 0; sws = sws_getContext(width, height, avpixfmt, enc->dst_size.w, enc->dst_size.h, avpixfmt_dst, flags, NULL, NULL, NULL); if (!sws) { warning("swscale: sws_getContext error\n"); return ENOMEM; } enc->sws = sws; info("swscale: created SwsContext:" " '%s' %d x %d --> '%s' %u x %u\n", vidfmt_name(frame->fmt), width, height, vidfmt_name(enc->swscale_format), enc->dst_size.w, enc->dst_size.h); } if (!enc->frame) { err = vidframe_alloc(&enc->frame, enc->swscale_format, &enc->dst_size); if (err) { warning("swscale: vidframe_alloc error (%m)\n", err); return err; } } for (i=0; i<4; i++) { srcSlice[i] = frame->data[i]; srcStride[i] = frame->linesize[i]; dst[i] = enc->frame->data[i]; dstStride[i] = enc->frame->linesize[i]; } h = sws_scale(enc->sws, srcSlice, srcStride, 0, height, dst, dstStride); if (h <= 0) { warning("swscale: sws_scale error (%d)\n", h); return EPROTO; } /* Copy the converted frame back to the input frame */ for (i=0; i<4; i++) { frame->data[i] = enc->frame->data[i]; frame->linesize[i] = enc->frame->linesize[i]; } frame->size = enc->frame->size; frame->fmt = enc->frame->fmt; return 0; } static struct vidfilt vf_swscale = { .name = "swscale", .encupdh = encode_update, .ench = encode_process, }; static int module_init(void) { vidfilt_register(baresip_vidfiltl(), &vf_swscale); return 0; } static int module_close(void) { vidfilt_unregister(&vf_swscale); return 0; } EXPORT_SYM const struct mod_export DECL_EXPORTS(swscale) = { "swscale", "vidfilt", module_init, module_close }; baresip-1.0.0/modules/syslog/000077500000000000000000000000001372575704200161415ustar00rootroot00000000000000baresip-1.0.0/modules/syslog/module.mk000066400000000000000000000001561372575704200177610ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # MOD := syslog $(MOD)_SRCS += syslog.c include mk/mod.mk baresip-1.0.0/modules/syslog/syslog.c000066400000000000000000000021401372575704200176220ustar00rootroot00000000000000/** * @file syslog.c Syslog module * * Copyright (C) 2010 Creytiv.com */ #include #include #include /** * @defgroup syslog syslog * * This module implements a logging handler for output to syslog */ #define DEBUG_MODULE "" #define DEBUG_LEVEL 0 #include static const int lmap[] = { LOG_DEBUG, LOG_INFO, LOG_WARNING, LOG_ERR }; static void log_handler(uint32_t level, const char *msg) { syslog(lmap[MIN(level, ARRAY_SIZE(lmap)-1)], "%s", msg); } static struct log lg = { .h = log_handler, }; static void syslog_handler(int level, const char *p, size_t len, void *arg) { (void)arg; syslog(level, "%.*s", (int)len, p); } static int module_init(void) { openlog("baresip", LOG_NDELAY | LOG_PID, LOG_LOCAL0); dbg_init(DBG_INFO, DBG_NONE); dbg_handler_set(syslog_handler, NULL); log_register_handler(&lg); return 0; } static int module_close(void) { log_unregister_handler(&lg); dbg_handler_set(NULL, NULL); closelog(); return 0; } const struct mod_export DECL_EXPORTS(syslog) = { "syslog", "application", module_init, module_close }; baresip-1.0.0/modules/turn/000077500000000000000000000000001372575704200156115ustar00rootroot00000000000000baresip-1.0.0/modules/turn/module.mk000066400000000000000000000001521372575704200174250ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # MOD := turn $(MOD)_SRCS += turn.c include mk/mod.mk baresip-1.0.0/modules/turn/turn.c000066400000000000000000000124341372575704200167510ustar00rootroot00000000000000/** * @file turn.c TURN Module * * Copyright (C) 2010 Creytiv.com */ #include #include /** * @defgroup turn turn * * Traversal Using Relays around NAT (TURN) for media NAT traversal */ enum {LAYER = 0}; struct mnat_sess { struct list medial; struct sa srv; struct stun_dns *dnsq; char *user; char *pass; mnat_estab_h *estabh; void *arg; int mediac; }; struct mnat_media { struct le le; struct sa addr1; struct sa addr2; struct mnat_sess *sess; struct sdp_media *sdpm; struct turnc *turnc1; struct turnc *turnc2; void *sock1; void *sock2; }; static void session_destructor(void *arg) { struct mnat_sess *sess = arg; list_flush(&sess->medial); mem_deref(sess->dnsq); mem_deref(sess->user); mem_deref(sess->pass); } static void media_destructor(void *arg) { struct mnat_media *m = arg; list_unlink(&m->le); mem_deref(m->sdpm); mem_deref(m->turnc1); mem_deref(m->turnc2); mem_deref(m->sock1); mem_deref(m->sock2); } static void turn_handler1(int err, uint16_t scode, const char *reason, const struct sa *relay_addr, const struct sa *mapped_addr, const struct stun_msg *msg, void *arg) { struct mnat_media *m = arg; (void)mapped_addr; (void)msg; if (!err && !scode) { sdp_media_set_laddr(m->sdpm, relay_addr); m->addr1 = *relay_addr; if (m->turnc2 && !sa_isset(&m->addr2, SA_ALL)) return; if (--m->sess->mediac) return; } m->sess->estabh(err, scode, reason, m->sess->arg); } static void turn_handler2(int err, uint16_t scode, const char *reason, const struct sa *relay_addr, const struct sa *mapped_addr, const struct stun_msg *msg, void *arg) { struct mnat_media *m = arg; (void)mapped_addr; (void)msg; if (!err && !scode) { sdp_media_set_laddr_rtcp(m->sdpm, relay_addr); m->addr2 = *relay_addr; if (m->turnc1 && !sa_isset(&m->addr1, SA_ALL)) return; if (--m->sess->mediac) return; } m->sess->estabh(err, scode, reason, m->sess->arg); } static int media_start(struct mnat_sess *sess, struct mnat_media *m) { int err = 0; if (m->sock1) { err |= turnc_alloc(&m->turnc1, NULL, IPPROTO_UDP, m->sock1, LAYER, &sess->srv, sess->user, sess->pass, TURN_DEFAULT_LIFETIME, turn_handler1, m); } if (m->sock2) { err |= turnc_alloc(&m->turnc2, NULL, IPPROTO_UDP, m->sock2, LAYER, &sess->srv, sess->user, sess->pass, TURN_DEFAULT_LIFETIME, turn_handler2, m); } return err; } static void dns_handler(int err, const struct sa *srv, void *arg) { struct mnat_sess *sess = arg; struct le *le; if (err) goto out; sess->srv = *srv; for (le=sess->medial.head; le; le=le->next) { struct mnat_media *m = le->data; err = media_start(sess, m); if (err) goto out; } return; out: sess->estabh(err, 0, NULL, sess->arg); } static int session_alloc(struct mnat_sess **sessp, const struct mnat *mnat, struct dnsc *dnsc, int af, const struct stun_uri *srv, const char *user, const char *pass, struct sdp_session *ss, bool offerer, mnat_estab_h *estabh, void *arg) { struct mnat_sess *sess; int err; (void)mnat; (void)ss; (void)offerer; if (!sessp || !dnsc || !srv || !user || !pass || !ss || !estabh) return EINVAL; if (srv->scheme != STUN_SCHEME_TURN) return ENOTSUP; sess = mem_zalloc(sizeof(*sess), session_destructor); if (!sess) return ENOMEM; err = str_dup(&sess->user, user); err |= str_dup(&sess->pass, pass); if (err) goto out; sess->estabh = estabh; sess->arg = arg; err = stun_server_discover(&sess->dnsq, dnsc, stun_usage_relay, stun_proto_udp, af, srv->host, srv->port, dns_handler, sess); out: if (err) mem_deref(sess); else *sessp = sess; return err; } static int media_alloc(struct mnat_media **mp, struct mnat_sess *sess, struct udp_sock *sock1, struct udp_sock *sock2, struct sdp_media *sdpm, mnat_connected_h *connh, void *arg) { struct mnat_media *m; int err = 0; (void)connh; (void)arg; if (!mp || !sess || !sdpm) return EINVAL; m = mem_zalloc(sizeof(*m), media_destructor); if (!m) return ENOMEM; list_append(&sess->medial, &m->le, m); m->sdpm = mem_ref(sdpm); m->sess = sess; m->sock1 = mem_ref(sock1); m->sock2 = mem_ref(sock2); if (sa_isset(&sess->srv, SA_ALL)) err = media_start(sess, m); if (err) mem_deref(m); else { *mp = m; ++sess->mediac; } return err; } static int update(struct mnat_sess *sess) { struct le *le; int err = 0; if (!sess) return EINVAL; for (le=sess->medial.head; le; le=le->next) { struct mnat_media *m = le->data; struct sa raddr1, raddr2; raddr1 = *sdp_media_raddr(m->sdpm); sdp_media_raddr_rtcp(m->sdpm, &raddr2); if (m->turnc1 && sa_isset(&raddr1, SA_ALL)) err |= turnc_add_chan(m->turnc1, &raddr1, NULL, NULL); if (m->turnc2 && sa_isset(&raddr2, SA_ALL)) err |= turnc_add_chan(m->turnc2, &raddr2, NULL, NULL); } return err; } static struct mnat mnat_turn = { .id = "turn", .sessh = session_alloc, .mediah = media_alloc, .updateh = update, }; static int module_init(void) { mnat_register(baresip_mnatl(), &mnat_turn); return 0; } static int module_close(void) { mnat_unregister(&mnat_turn); return 0; } EXPORT_SYM const struct mod_export DECL_EXPORTS(turn) = { "turn", "mnat", module_init, module_close, }; baresip-1.0.0/modules/uuid/000077500000000000000000000000001372575704200155675ustar00rootroot00000000000000baresip-1.0.0/modules/uuid/module.mk000066400000000000000000000001521372575704200174030ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # MOD := uuid $(MOD)_SRCS += uuid.c include mk/mod.mk baresip-1.0.0/modules/uuid/uuid.c000066400000000000000000000033151372575704200167030ustar00rootroot00000000000000/** * @file modules/uuid/uuid.c Generate and load UUID * * Copyright (C) 2010 Creytiv.com */ #include #include #include #include #include /** * @defgroup uuid uuid * * UUID generator and loader */ enum { UUID_LEN = 36 }; static int generate_random_uuid(FILE *f) { if (re_fprintf(f, "%08x-%04x-%04x-%04x-%08x%04x", rand_u32(), rand_u16(), rand_u16(), rand_u16(), rand_u32(), rand_u16()) != UUID_LEN) return ENOMEM; return 0; } static int uuid_init(const char *file) { FILE *f = NULL; int err = 0; f = fopen(file, "r"); if (f) { err = 0; goto out; } f = fopen(file, "w"); if (!f) { err = errno; warning("uuid: fopen() %s (%m)\n", file, err); goto out; } err = generate_random_uuid(f); if (err) { warning("uuid: generate random UUID failed (%m)\n", err); goto out; } info("uuid: generated new UUID in %s\n", file); out: if (f) fclose(f); return err; } static int uuid_load(const char *file, char *uuid, size_t sz) { FILE *f = NULL; int err = 0; f = fopen(file, "r"); if (!f) return errno; if (!fgets(uuid, (int)sz, f)) err = errno; (void)fclose(f); debug("uuid: loaded UUID %s from file %s\n", uuid, file); return err; } static int module_init(void) { struct config *cfg = conf_config(); char path[256]; int err = 0; err = conf_path_get(path, sizeof(path)); if (err) return err; strncat(path, "/uuid", sizeof(path) - strlen(path) - 1); err = uuid_init(path); if (err) return err; err = uuid_load(path, cfg->sip.uuid, sizeof(cfg->sip.uuid)); if (err) return err; return 0; } EXPORT_SYM const struct mod_export DECL_EXPORTS(uuid) = { "uuid", NULL, module_init, NULL }; baresip-1.0.0/modules/v4l2/000077500000000000000000000000001372575704200154105ustar00rootroot00000000000000baresip-1.0.0/modules/v4l2/module.mk000066400000000000000000000003011372575704200172200ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # MOD := v4l2 $(MOD)_SRCS += v4l2.c ifneq ($(HAVE_LIBV4L2),) $(MOD)_LFLAGS += -lv4l2 $(MOD)_CFLAGS += -DHAVE_LIBV4L2 endif include mk/mod.mk baresip-1.0.0/modules/v4l2/v4l2.c000066400000000000000000000256571372575704200163620ustar00rootroot00000000000000/** * @file v4l2.c Video4Linux2 video-source * * Copyright (C) 2010 Creytiv.com */ #define _DEFAULT_SOURCE 1 #define _BSD_SOURCE 1 #include #include #include #include #include #include #include #include #include #undef __STRICT_ANSI__ /* needed for RHEL4 kernel 2.6.9 */ #include #include #include #include #if defined (OPENBSD) || defined (NETBSD) #include #else #include #endif #ifdef HAVE_LIBV4L2 #include #else #define v4l2_open open #define v4l2_read read #define v4l2_ioctl ioctl #define v4l2_mmap mmap #define v4l2_munmap munmap #define v4l2_close close #endif /** * @defgroup v4l2 v4l2 * * V4L2 (Video for Linux 2) video-source module */ struct buffer { void *start; size_t length; }; struct vidsrc_st { const struct vidsrc *vs; /* inheritance */ int fd; pthread_t thread; bool run; struct vidsz sz; u_int32_t pixfmt; struct buffer *buffers; unsigned int n_buffers; vidsrc_frame_h *frameh; void *arg; }; static struct vidsrc *vidsrc; static enum vidfmt match_fmt(u_int32_t fmt) { switch (fmt) { case V4L2_PIX_FMT_YUV420: return VID_FMT_YUV420P; case V4L2_PIX_FMT_YUYV: return VID_FMT_YUYV422; case V4L2_PIX_FMT_UYVY: return VID_FMT_UYVY422; case V4L2_PIX_FMT_RGB32: return VID_FMT_RGB32; case V4L2_PIX_FMT_RGB565: return VID_FMT_RGB565; case V4L2_PIX_FMT_RGB555: return VID_FMT_RGB555; case V4L2_PIX_FMT_NV12: return VID_FMT_NV12; case V4L2_PIX_FMT_NV21: return VID_FMT_NV21; default: return VID_FMT_N; } } static void print_video_input(const struct vidsrc_st *st) { struct v4l2_input input; memset(&input, 0, sizeof(input)); #ifndef OPENBSD if (-1 == v4l2_ioctl(st->fd, VIDIOC_G_INPUT, &input.index)) { warning("v4l2: VIDIOC_G_INPUT: %m\n", errno); return; } #endif if (-1 == v4l2_ioctl(st->fd, VIDIOC_ENUMINPUT, &input)) { warning("v4l2: VIDIOC_ENUMINPUT: %m\n", errno); return; } info("v4l2: Current input: \"%s\"\n", input.name); } static void print_framerate(const struct vidsrc_st *st) { struct v4l2_streamparm streamparm; struct v4l2_fract tpf; double fps; memset(&streamparm, 0, sizeof(streamparm)); streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (v4l2_ioctl(st->fd, VIDIOC_G_PARM, &streamparm) != 0) { warning("v4l2: VIDIOC_G_PARM error (%m)\n", errno); return; } tpf = streamparm.parm.capture.timeperframe; fps = (double)tpf.denominator / (double)tpf.numerator; info("v4l2: current framerate is %.2f fps\n", fps); } static int xioctl(int fd, unsigned long int request, void *arg) { int r; do { r = v4l2_ioctl(fd, request, arg); } while (-1 == r && EINTR == errno); return r; } static int init_mmap(struct vidsrc_st *st, const char *dev_name) { struct v4l2_requestbuffers req; memset(&req, 0, sizeof(req)); req.count = 4; req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; req.memory = V4L2_MEMORY_MMAP; if (-1 == xioctl(st->fd, VIDIOC_REQBUFS, &req)) { if (EINVAL == errno) { warning("v4l2: %s does not support " "memory mapping\n", dev_name); return errno; } else { return errno; } } if (req.count < 2) { warning("v4l2: Insufficient buffer memory on %s\n", dev_name); return ENOMEM; } st->buffers = mem_zalloc(req.count * sizeof(*st->buffers), NULL); if (!st->buffers) return ENOMEM; for (st->n_buffers = 0; st->n_buffersn_buffers) { struct v4l2_buffer buf; memset(&buf, 0, sizeof(buf)); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; buf.index = st->n_buffers; if (-1 == xioctl(st->fd, VIDIOC_QUERYBUF, &buf)) { warning("v4l2: VIDIOC_QUERYBUF\n"); return errno; } st->buffers[st->n_buffers].length = buf.length; st->buffers[st->n_buffers].start = v4l2_mmap(NULL /* start anywhere */, buf.length, PROT_READ | PROT_WRITE /* required */, MAP_SHARED /* recommended */, st->fd, buf.m.offset); if (MAP_FAILED == st->buffers[st->n_buffers].start) { warning("v4l2: mmap failed\n"); return ENODEV; } } return 0; } static int v4l2_init_device(struct vidsrc_st *st, const char *dev_name, int width, int height) { struct v4l2_capability cap; struct v4l2_format fmt; struct v4l2_fmtdesc fmts; unsigned int min; const char *pix; int err; if (-1 == xioctl(st->fd, VIDIOC_QUERYCAP, &cap)) { if (EINVAL == errno) { warning("v4l2: %s is no V4L2 device\n", dev_name); return ENODEV; } else { warning("v4l2: VIDIOC_QUERYCAP: %m\n", errno); return errno; } } if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) { warning("v4l2: %s is no video capture device\n", dev_name); return ENODEV; } if (!(cap.capabilities & V4L2_CAP_STREAMING)) { warning("v4l2: %s does not support streaming i/o\n", dev_name); return ENOSYS; } /* Negotiate video format */ memset(&fmts, 0, sizeof(fmts)); fmts.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; for (fmts.index=0; !v4l2_ioctl(st->fd, VIDIOC_ENUM_FMT, &fmts); fmts.index++) { if (match_fmt(fmts.pixelformat) != VID_FMT_N) { st->pixfmt = fmts.pixelformat; break; } } if (!st->pixfmt) { warning("v4l2: format negotiation failed: %m\n", errno); return errno; } /* Select video input, video standard and tune here. */ memset(&fmt, 0, sizeof(fmt)); fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; fmt.fmt.pix.width = width; fmt.fmt.pix.height = height; fmt.fmt.pix.pixelformat = st->pixfmt; fmt.fmt.pix.field = V4L2_FIELD_INTERLACED; if (-1 == xioctl(st->fd, VIDIOC_S_FMT, &fmt)) { warning("v4l2: VIDIOC_S_FMT: %m\n", errno); return errno; } /* Note VIDIOC_S_FMT may change width and height. */ /* Buggy driver paranoia. */ min = fmt.fmt.pix.width * 2; if (fmt.fmt.pix.bytesperline < min) fmt.fmt.pix.bytesperline = min; min = fmt.fmt.pix.bytesperline * fmt.fmt.pix.height; if (fmt.fmt.pix.sizeimage < min) fmt.fmt.pix.sizeimage = min; st->sz.w = fmt.fmt.pix.width; st->sz.h = fmt.fmt.pix.height; err = init_mmap(st, dev_name); if (err) return err; pix = (char *)&fmt.fmt.pix.pixelformat; if (st->pixfmt != fmt.fmt.pix.pixelformat) { warning("v4l2: %s: unexpectedly got %c%c%c%c\n", dev_name, pix[0], pix[1], pix[2], pix[3]); return ENODEV; } info("v4l2: %s: found valid V4L2 device (%u x %u) pixfmt=%c%c%c%c\n", dev_name, fmt.fmt.pix.width, fmt.fmt.pix.height, pix[0], pix[1], pix[2], pix[3]); return 0; } static void stop_capturing(struct vidsrc_st *st) { enum v4l2_buf_type type; if (st->fd < 0) return; type = V4L2_BUF_TYPE_VIDEO_CAPTURE; xioctl(st->fd, VIDIOC_STREAMOFF, &type); } static void uninit_device(struct vidsrc_st *st) { unsigned int i; for (i=0; in_buffers; ++i) { v4l2_munmap(st->buffers[i].start, st->buffers[i].length); } st->buffers = mem_deref(st->buffers); st->n_buffers = 0; } static int start_capturing(struct vidsrc_st *st) { unsigned int i; enum v4l2_buf_type type; for (i = 0; i < st->n_buffers; ++i) { struct v4l2_buffer buf; memset(&buf, 0, sizeof(buf)); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; buf.index = i; if (-1 == xioctl (st->fd, VIDIOC_QBUF, &buf)) return errno; } type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (-1 == xioctl (st->fd, VIDIOC_STREAMON, &type)) return errno; return 0; } static void call_frame_handler(struct vidsrc_st *st, uint8_t *buf, uint64_t timestamp) { struct vidframe frame; vidframe_init_buf(&frame, match_fmt(st->pixfmt), &st->sz, buf); st->frameh(&frame, timestamp, st->arg); } static int read_frame(struct vidsrc_st *st) { struct v4l2_buffer buf; struct timeval ts; uint64_t timestamp; memset(&buf, 0, sizeof(buf)); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; if (-1 == xioctl (st->fd, VIDIOC_DQBUF, &buf)) { switch (errno) { case EAGAIN: return 0; case EIO: /* Could ignore EIO, see spec. */ /* fall through */ default: warning("v4l2: VIDIOC_DQBUF: %m\n", errno); return errno; } } if (buf.index >= st->n_buffers) { warning("v4l2: index >= n_buffers\n"); } ts = buf.timestamp; timestamp = 1000000U * ts.tv_sec + ts.tv_usec; timestamp = timestamp * VIDEO_TIMEBASE / 1000000U; call_frame_handler(st, st->buffers[buf.index].start, timestamp); if (-1 == xioctl (st->fd, VIDIOC_QBUF, &buf)) { warning("v4l2: VIDIOC_QBUF\n"); return errno; } return 0; } static int set_available_devices(struct list* dev_list) { int i, fd; char name[16]; int err; for (i=0;i < 16;i++) { re_snprintf(name, sizeof(name), "/dev/video%i", i); if ((fd = open(name, O_RDONLY)) == -1) { continue; } else { close(fd); err = mediadev_add(dev_list, name); if (err) return err; } } return 0; } static int vd_open(struct vidsrc_st *st, const char *device) { st->fd = v4l2_open(device, O_RDWR); if (st->fd < 0) { warning("v4l2: open %s: %m\n", device, errno); return errno; } return 0; } static void destructor(void *arg) { struct vidsrc_st *st = arg; debug("v4l2: stopping video source..\n"); if (st->run) { st->run = false; pthread_join(st->thread, NULL); } stop_capturing(st); uninit_device(st); if (st->fd >= 0) v4l2_close(st->fd); } static void *read_thread(void *arg) { struct vidsrc_st *st = arg; int err; while (st->run) { err = read_frame(st); if (err) { warning("v4l2: read_frame: %m\n", err); } } return NULL; } static int alloc(struct vidsrc_st **stp, const struct vidsrc *vs, struct media_ctx **ctx, struct vidsrc_prm *prm, const struct vidsz *size, const char *fmt, const char *dev, vidsrc_frame_h *frameh, vidsrc_error_h *errorh, void *arg) { struct vidsrc_st *st; struct mediadev *md; int err; (void)ctx; (void)prm; (void)fmt; (void)errorh; if (!stp || !size || !frameh) return EINVAL; if (!str_isset(dev)) { md = mediadev_get_default(&vs->dev_list); if (md) { dev = md->name; } else { warning("v4l2: No available devices\n"); return ENODEV; } } st = mem_zalloc(sizeof(*st), destructor); if (!st) return ENOMEM; st->vs = vs; st->fd = -1; st->sz = *size; st->frameh = frameh; st->arg = arg; st->pixfmt = 0; err = vd_open(st, dev); if (err) goto out; err = v4l2_init_device(st, dev, size->w, size->h); if (err) goto out; print_video_input(st); print_framerate(st); err = start_capturing(st); if (err) goto out; st->run = true; err = pthread_create(&st->thread, NULL, read_thread, st); if (err) { st->run = false; goto out; } out: if (err) mem_deref(st); else *stp = st; return err; } static int v4l_init(void) { int err; err = vidsrc_register(&vidsrc, baresip_vidsrcl(), "v4l2", alloc, NULL); if (err) return err; list_init(&vidsrc->dev_list); err = set_available_devices(&vidsrc->dev_list); return err; } static int v4l_close(void) { vidsrc = mem_deref(vidsrc); return 0; } EXPORT_SYM const struct mod_export DECL_EXPORTS(v4l2) = { "v4l2", "vidsrc", v4l_init, v4l_close }; baresip-1.0.0/modules/v4l2_codec/000077500000000000000000000000001372575704200165455ustar00rootroot00000000000000baresip-1.0.0/modules/v4l2_codec/README000066400000000000000000000016141372575704200174270ustar00rootroot00000000000000README ------ This module is using V4L2 (Video for Linux 2) as a codec module for devices that supports compressed formats such as H.264 The module implements both the vidsrc API and the vidcodec API. - encoder/decoder: Encoder only - codec formats: H.264 - keyframe refresh: Not supported EXAMPLE CONFIG -------------- # Video video_source v4l2_codec,/dev/video0 video_size 640x480 # Video codec Modules (in order) module v4l2_codec.so SUPPORTED DEVICES ----------------- This webcam supports H.264 hardware acceleration: HD Pro Webcam C920 (usb-0000:00:1a.0-1.5): /dev/video0 ELP-USB100W04H-L36 ARC International - (Product ID : 05a3:9420) This device provide 2 /dev/video sub-devices. The first is a YUV and MJPEG device (/dev/video0), the second is for the H264 stream (/dev/video1). You must use the second the second (/dev/video1). baresip-1.0.0/modules/v4l2_codec/module.mk000066400000000000000000000002161372575704200203620ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 - 2015 Creytiv.com # MOD := v4l2_codec $(MOD)_SRCS += v4l2_codec.c $(MOD)_LFLAGS += include mk/mod.mk baresip-1.0.0/modules/v4l2_codec/v4l2_codec.c000066400000000000000000000263301372575704200206410ustar00rootroot00000000000000/** * @file v4l2_codec.c Video4Linux2 video-source and video-codec * * Copyright (C) 2010 - 2015 Creytiv.com */ #define _DEFAULT_SOURCE 1 #include #include #include #include #include #include #include #include #include #include #include #include #if defined (OPENBSD) || defined (NETBSD) #include #else #include #endif /** * @defgroup v4l2_codec v4l2_codec * * V4L2 (Video for Linux 2) video-codec and source hybrid module * * This module is using V4L2 (Video for Linux 2) as a codec module * for devices that supports compressed formats such as H.264. * The module implements both the vidsrc API and the vidcodec API. * */ struct vidsrc_st { const struct vidsrc *vs; /* inheritance */ uint8_t *buffer; size_t buffer_len; int fd; pthread_t thread; bool run; struct { unsigned n_key; unsigned n_delta; } stats; }; struct videnc_state { struct le le; struct videnc_param encprm; videnc_packet_h *pkth; void *arg; }; /* NOTE: global data, move to per vidsrc instance */ static struct { /* List of encoder-states (struct videnc_state) */ struct list encoderl; } v4l2; static struct vidsrc *vidsrc; static int xioctl(int fd, unsigned long int request, void *arg) { int r; do r = ioctl (fd, request, arg); while (-1 == r && EINTR == errno); return r; } static int print_caps(int fd, unsigned width, unsigned height) { struct v4l2_capability caps; struct v4l2_fmtdesc fmtdesc; struct v4l2_format fmt; bool support_h264 = false; char fourcc[5] = {0}; char c; int err; memset(&caps, 0, sizeof(caps)); memset(&fmtdesc, 0, sizeof(fmtdesc)); memset(&fmt, 0, sizeof(fmt)); if (-1 == xioctl(fd, VIDIOC_QUERYCAP, &caps)) { err = errno; warning("v4l2_codec: error Querying Capabilities (%m)\n", err); return err; } info("v4l2_codec: Driver Caps:\n" " Driver: \"%s\"\n" " Card: \"%s\"\n" " Bus: \"%s\"\n" " Version: %d.%d\n" " Capabilities: 0x%08x\n", caps.driver, caps.card, caps.bus_info, (caps.version>>16) & 0xff, (caps.version>>24) & 0xff, caps.capabilities); fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; info(" Formats:\n"); while (0 == xioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc)) { bool selected = false; strncpy(fourcc, (char *)&fmtdesc.pixelformat, 4); #ifdef V4L2_PIX_FMT_H264 if (fmtdesc.pixelformat == V4L2_PIX_FMT_H264) { support_h264 = true; selected = true; } #endif c = fmtdesc.flags & V4L2_FMT_FLAG_COMPRESSED ? 'C' : ' '; info(" %c %s: %c '%s'\n", selected ? '>' : ' ', fourcc, c, fmtdesc.description); fmtdesc.index++; } info("\n"); if (!support_h264) { warning("v4l2_codec: Doesn't support H264.\n"); return ENODEV; } fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; fmt.fmt.pix.width = width; fmt.fmt.pix.height = height; #ifdef V4L2_PIX_FMT_H264 fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_H264; #endif fmt.fmt.pix.field = V4L2_FIELD_NONE; if (-1 == xioctl(fd, VIDIOC_S_FMT, &fmt)) { err = errno; warning("v4l2_codec: Setting Pixel Format (%m)\n", err); return err; } strncpy(fourcc, (char *)&fmt.fmt.pix.pixelformat, 4); info("v4l2_codec: Selected Camera Mode:\n" " Width: %d\n" " Height: %d\n" " PixFmt: %s\n" " Field: %d\n", fmt.fmt.pix.width, fmt.fmt.pix.height, fourcc, fmt.fmt.pix.field); return 0; } static int init_mmap(struct vidsrc_st *st, int fd) { struct v4l2_requestbuffers req; struct v4l2_buffer buf; int err; memset(&req, 0, sizeof(req)); memset(&buf, 0, sizeof(buf)); req.count = 1; req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; req.memory = V4L2_MEMORY_MMAP; if (-1 == xioctl(fd, VIDIOC_REQBUFS, &req)) { err = errno; warning("v4l2_codec: Requesting Buffer (%m)\n", err); return err; } buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; buf.index = 0; if (-1 == xioctl(fd, VIDIOC_QUERYBUF, &buf)) { err = errno; warning("v4l2_codec: Querying Buffer (%m)\n", err); return err; } st->buffer = mmap(NULL, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, buf.m.offset); if (st->buffer == MAP_FAILED) { err = errno; warning("v4l2_codec: mmap failed (%m)\n", err); return err; } st->buffer_len = buf.length; return 0; } static int query_buffer(int fd) { struct v4l2_buffer buf; memset(&buf, 0, sizeof(buf)); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; buf.index = 0; if (-1 == xioctl(fd, VIDIOC_QBUF, &buf)) return errno; return 0; } static int start_streaming(int fd) { struct v4l2_buffer buf; int err; memset(&buf, 0, sizeof(buf)); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; buf.index = 0; if (-1 == xioctl(fd, VIDIOC_STREAMON, &buf.type)) { err = errno; warning("v4l2_codec: Start Capture (%m)\n", err); return err; } return 0; } static void stop_capturing(int fd) { enum v4l2_buf_type type; if (fd < 0) return; type = V4L2_BUF_TYPE_VIDEO_CAPTURE; xioctl(fd, VIDIOC_STREAMOFF, &type); } static void enc_destructor(void *arg) { struct videnc_state *st = arg; list_unlink(&st->le); } static void encoders_read(uint64_t rtp_ts, const uint8_t *buf, size_t sz) { struct le *le; int err; for (le = v4l2.encoderl.head; le; le = le->next) { struct videnc_state *st = le->data; err = h264_packetize(rtp_ts, buf, sz, st->encprm.pktsize, st->pkth, st->arg); if (err) { warning("h264_packetize error (%m)\n", err); } } } static void read_frame(struct vidsrc_st *st) { struct v4l2_buffer buf; bool keyframe = false; struct timeval ts; uint64_t rtp_ts; int err; memset(&buf, 0, sizeof(buf)); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; buf.index = 0; if (-1 == xioctl(st->fd, VIDIOC_DQBUF, &buf)) { err = errno; warning("v4l2_codec: Retrieving Frame (%m)\n", err); return; } { struct mbuf mb = {0,0,0,0}; struct h264_hdr hdr; mb.buf = st->buffer; mb.pos = 4; mb.end = buf.bytesused - 4; mb.size = buf.bytesused; err = h264_hdr_decode(&hdr, &mb); if (err) { warning("could not decode H.264 header\n"); } else { keyframe = h264_is_keyframe(hdr.type); if (keyframe) { ++st->stats.n_key; } else ++st->stats.n_delta; } } ts = buf.timestamp; rtp_ts = (90000ULL * (1000000*ts.tv_sec + ts.tv_usec)) / 1000000; #if 0 debug("v4l2_codec: %s frame captured at %ldsec, %ldusec" " (%zu bytes) rtp_ts=%llu\n", keyframe ? "KEY" : " ", buf.timestamp.tv_sec, buf.timestamp.tv_usec, (size_t)buf.bytesused, rtp_ts); #endif /* pass the frame to the encoders */ encoders_read(rtp_ts, st->buffer, buf.bytesused); err = query_buffer(st->fd); if (err) { warning("v4l2_codec: query_buffer failed (%m)\n", err); } } static void *read_thread(void *arg) { struct vidsrc_st *st = arg; while (st->run) { read_frame(st); } return NULL; } static int open_encoder(struct vidsrc_st *st, const char *device, unsigned width, unsigned height) { int err; debug("v4l2_codec: opening video-encoder device (device=%s)\n", device); st->fd = open(device, O_RDWR); if (st->fd == -1) { err = errno; warning("Opening video device (%m)\n", err); goto out; } err = print_caps(st->fd, width, height); if (err) goto out; err = init_mmap(st, st->fd); if (err) goto out; err = query_buffer(st->fd); if (err) goto out; err = start_streaming(st->fd); if (err) goto out; st->run = true; err = pthread_create(&st->thread, NULL, read_thread, st); if (err) { st->run = false; goto out; } out: return err; } static int encode_update(struct videnc_state **vesp, const struct vidcodec *vc, struct videnc_param *prm, const char *fmtp, videnc_packet_h *pkth, void *arg) { struct videnc_state *st; (void)fmtp; if (!vesp || !vc || !prm || !pkth) return EINVAL; if (*vesp) return 0; st = mem_zalloc(sizeof(*st), enc_destructor); if (!st) return ENOMEM; st->encprm = *prm; st->pkth = pkth; st->arg = arg; list_append(&v4l2.encoderl, &st->le, st); info("v4l2_codec: video encoder %s: %.2f fps, %d bit/s, pktsize=%u\n", vc->name, prm->fps, prm->bitrate, prm->pktsize); *vesp = st; return 0; } /* note: dummy function, the input is unused */ static int encode_packet(struct videnc_state *st, bool update, const struct vidframe *frame, uint64_t timestamp) { (void)st; (void)update; (void)frame; (void)timestamp; /* * NOTE: add support for KEY frame requests */ if (update) { info("v4l2_codec: peer requested a KEY frame (ignored)\n"); } return 0; } static uint32_t packetization_mode(const char *fmtp) { struct pl pl, mode; if (!fmtp) return 0; pl_set_str(&pl, fmtp); if (fmt_param_get(&pl, "packetization-mode", &mode)) return pl_u32(&mode); return 0; } static int h264_fmtp_enc(struct mbuf *mb, const struct sdp_format *fmt, bool offer, void *arg) { struct vidcodec *vc = arg; const uint8_t profile_idc = 0x42; /* baseline profile */ const uint8_t profile_iop = 0x80; static const uint8_t h264_level_idc = 0x0c; (void)offer; if (!mb || !fmt || !vc) return 0; return mbuf_printf(mb, "a=fmtp:%s" " packetization-mode=0" ";profile-level-id=%02x%02x%02x" "\r\n", fmt->id, profile_idc, profile_iop, h264_level_idc); } static bool h264_fmtp_cmp(const char *fmtp1, const char *fmtp2, void *data) { (void)data; return packetization_mode(fmtp1) == packetization_mode(fmtp2); } static void src_destructor(void *arg) { struct vidsrc_st *st = arg; if (st->run) { st->run = false; pthread_join(st->thread, NULL); } if (st->fd >=0 ) { info("v4l2_codec: encoder stats" " (keyframes:%u, deltaframes:%u)\n", st->stats.n_key, st->stats.n_delta); } stop_capturing(st->fd); if (st->buffer) munmap(st->buffer, st->buffer_len); if (st->fd >= 0) { close(st->fd); } } static int src_alloc(struct vidsrc_st **stp, const struct vidsrc *vs, struct media_ctx **ctx, struct vidsrc_prm *prm, const struct vidsz *size, const char *fmt, const char *dev, vidsrc_frame_h *frameh, vidsrc_error_h *errorh, void *arg) { struct vidsrc_st *st; int err = 0; (void)ctx; (void)prm; (void)fmt; (void)errorh; (void)arg; if (!stp || !size || !frameh) return EINVAL; if (!str_isset(dev)) dev = "/dev/video0"; debug("v4l2_codec: video-source alloc (device=%s)\n", dev); st = mem_zalloc(sizeof(*st), src_destructor); if (!st) return ENOMEM; st->vs = vs; err = open_encoder(st, dev, size->w, size->h); if (err) goto out; out: if (err) mem_deref(st); else *stp = st; return err; } static struct vidcodec h264 = { .name = "H264", .variant = "packetization-mode=0", .encupdh = encode_update, .ench = encode_packet, .fmtp_ench = h264_fmtp_enc, .fmtp_cmph = h264_fmtp_cmp, }; static int module_init(void) { info("v4l2_codec inited\n"); vidcodec_register(baresip_vidcodecl(), &h264); return vidsrc_register(&vidsrc, baresip_vidsrcl(), "v4l2_codec", src_alloc, NULL); } static int module_close(void) { vidsrc = mem_deref(vidsrc); vidcodec_unregister(&h264); return 0; } EXPORT_SYM const struct mod_export DECL_EXPORTS(v4l2_codec) = { "v4l2_codec", "vidcodec", module_init, module_close }; baresip-1.0.0/modules/vidbridge/000077500000000000000000000000001372575704200165605ustar00rootroot00000000000000baresip-1.0.0/modules/vidbridge/disp.c000066400000000000000000000032371372575704200176700ustar00rootroot00000000000000/** * @file vidbridge/disp.c Video bridge -- display * * Copyright (C) 2010 Creytiv.com */ #include #include #include #include "vidbridge.h" static void destructor(void *arg) { struct vidisp_st *st = arg; if (st->vidsrc) st->vidsrc->vidisp = NULL; list_unlink(&st->le); mem_deref(st->device); } int vidbridge_disp_alloc(struct vidisp_st **stp, const struct vidisp *vd, struct vidisp_prm *prm, const char *dev, vidisp_resize_h *resizeh, void *arg) { struct vidisp_st *st; int err = 0; (void)prm; (void)resizeh; (void)arg; if (!stp || !vd || !dev) return EINVAL; st = mem_zalloc(sizeof(*st), destructor); if (!st) return ENOMEM; st->vd = vd; err = str_dup(&st->device, dev); if (err) goto out; /* find the vidsrc with the same device-name */ st->vidsrc = vidbridge_src_find(dev); if (st->vidsrc) { st->vidsrc->vidisp = st; } hash_append(ht_disp, hash_joaat_str(dev), &st->le, st); out: if (err) mem_deref(st); else *stp = st; return err; } static bool list_apply_handler(struct le *le, void *arg) { struct vidisp_st *st = le->data; return 0 == str_cmp(st->device, arg); } int vidbridge_disp_display(struct vidisp_st *st, const char *title, const struct vidframe *frame, uint64_t timestamp) { int err = 0; (void)title; if (st->vidsrc) vidbridge_src_input(st->vidsrc, frame, timestamp); else { debug("vidbridge: display: dropping frame (%u x %u)\n", frame->size.w, frame->size.h); } return err; } struct vidisp_st *vidbridge_disp_find(const char *device) { return list_ledata(hash_lookup(ht_disp, hash_joaat_str(device), list_apply_handler, (void *)device)); } baresip-1.0.0/modules/vidbridge/module.mk000066400000000000000000000002221372575704200203720ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # MOD := vidbridge $(MOD)_SRCS += vidbridge.c src.c disp.c $(MOD)_LFLAGS += include mk/mod.mk baresip-1.0.0/modules/vidbridge/src.c000066400000000000000000000032661372575704200175220ustar00rootroot00000000000000/** * @file vidbridge/src.c Video bridge -- source * * Copyright (C) 2010 Creytiv.com */ #include #include #include #include "vidbridge.h" static void destructor(void *arg) { struct vidsrc_st *st = arg; if (st->vidisp) st->vidisp->vidsrc = NULL; list_unlink(&st->le); mem_deref(st->device); } int vidbridge_src_alloc(struct vidsrc_st **stp, const struct vidsrc *vs, struct media_ctx **ctx, struct vidsrc_prm *prm, const struct vidsz *size, const char *fmt, const char *dev, vidsrc_frame_h *frameh, vidsrc_error_h *errorh, void *arg) { struct vidsrc_st *st; int err; (void)ctx; (void)fmt; (void)errorh; if (!stp || !prm || !size || !frameh) return EINVAL; st = mem_zalloc(sizeof(*st), destructor); if (!st) return ENOMEM; st->vs = vs; st->frameh = frameh; st->arg = arg; st->fps = prm->fps; err = str_dup(&st->device, dev); if (err) goto out; /* find a vidisp device with same name */ st->vidisp = vidbridge_disp_find(dev); if (st->vidisp) { st->vidisp->vidsrc = st; } hash_append(ht_src, hash_joaat_str(dev), &st->le, st); out: if (err) mem_deref(st); else *stp = st; return err; } static bool list_apply_handler(struct le *le, void *arg) { struct vidsrc_st *st = le->data; return 0 == str_cmp(st->device, arg); } struct vidsrc_st *vidbridge_src_find(const char *device) { return list_ledata(hash_lookup(ht_src, hash_joaat_str(device), list_apply_handler, (void *)device)); } void vidbridge_src_input(struct vidsrc_st *st, const struct vidframe *frame, uint64_t timestamp) { if (!st || !frame) return; if (st->frameh) st->frameh((struct vidframe *)frame, timestamp, st->arg); } baresip-1.0.0/modules/vidbridge/vidbridge.c000066400000000000000000000025101372575704200206610ustar00rootroot00000000000000/** * @file vidbridge.c Video bridge * * Copyright (C) 2010 Creytiv.com */ #include #include #include #include "vidbridge.h" /** * @defgroup vidbridge vidbridge * * Video bridge module * * This module can be used to connect two video devices together, * so that all output to VIDISP device is bridged as the input to * a VIDSRC device. * * Sample config: * \verbatim video_display vidbridge,pseudo0 video_source vidbridge,pseudo0 \endverbatim */ static struct vidisp *vidisp; static struct vidsrc *vidsrc; struct hash *ht_src; struct hash *ht_disp; static int module_init(void) { int err; err = hash_alloc(&ht_src, 32); err |= hash_alloc(&ht_disp, 32); if (err) return err; err = vidisp_register(&vidisp, baresip_vidispl(), "vidbridge", vidbridge_disp_alloc, NULL, vidbridge_disp_display, 0); if (err) return err; err = vidsrc_register(&vidsrc, baresip_vidsrcl(), "vidbridge", vidbridge_src_alloc, NULL); if (err) return err; return err; } static int module_close(void) { vidsrc = mem_deref(vidsrc); vidisp = mem_deref(vidisp); ht_src = mem_deref(ht_src); ht_disp = mem_deref(ht_disp); return 0; } EXPORT_SYM const struct mod_export DECL_EXPORTS(vidbridge) = { "vidbridge", "video", module_init, module_close, }; baresip-1.0.0/modules/vidbridge/vidbridge.h000066400000000000000000000023261372575704200206730ustar00rootroot00000000000000/** * @file vidbridge.h Video bridge -- internal interface * * Copyright (C) 2010 Creytiv.com */ struct vidsrc_st { const struct vidsrc *vs; /* inheritance (1st) */ struct le le; struct vidisp_st *vidisp; double fps; char *device; vidsrc_frame_h *frameh; void *arg; }; struct vidisp_st { const struct vidisp *vd; /* inheritance (1st) */ struct le le; struct vidsrc_st *vidsrc; char *device; }; extern struct hash *ht_src; extern struct hash *ht_disp; int vidbridge_disp_alloc(struct vidisp_st **stp, const struct vidisp *vd, struct vidisp_prm *prm, const char *dev, vidisp_resize_h *resizeh, void *arg); int vidbridge_disp_display(struct vidisp_st *st, const char *title, const struct vidframe *frame, uint64_t timestamp); struct vidisp_st *vidbridge_disp_find(const char *device); int vidbridge_src_alloc(struct vidsrc_st **stp, const struct vidsrc *vs, struct media_ctx **ctx, struct vidsrc_prm *prm, const struct vidsz *size, const char *fmt, const char *dev, vidsrc_frame_h *frameh, vidsrc_error_h *errorh, void *arg); struct vidsrc_st *vidbridge_src_find(const char *device); void vidbridge_src_input(struct vidsrc_st *st, const struct vidframe *frame, uint64_t timestamp); baresip-1.0.0/modules/vidinfo/000077500000000000000000000000001372575704200162575ustar00rootroot00000000000000baresip-1.0.0/modules/vidinfo/draw.c000066400000000000000000000050021372575704200173550ustar00rootroot00000000000000/** * @file draw.c Video draw functions * * Copyright (C) 2010 - 2015 Creytiv.com */ #include #include #include #include "vidinfo.h" #include "xga_font_data.h" static void dim_region(struct vidframe *frame, int x0, int y0, unsigned width, unsigned height) { unsigned x, y; uint8_t *p; double grade = 0.5; p = frame->data[0] + x0 + y0 * frame->linesize[0]; /* first dim the background */ for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { p[x] = p[x] * grade; } p += frame->linesize[0]; } } static void draw_char(struct vidframe *frame, int x0, int y0, uint8_t ch) { const uint8_t *font; int x, y; font = &vidinfo_cga_font[ch * FONT_HEIGHT]; for (y = 0; y < FONT_HEIGHT; y++) { /* draw one raster-line */ for (x = 0; x < FONT_WIDTH; x++) { if (*font & 1<<(7-x)) { vidframe_draw_point(frame, x0+x, y0+y, 255, 255, 255); } } ++font; } } static void draw_text(struct vidframe *frame, struct vidpt *pos, const char *fmt, ...) { char buf[4096] = ""; va_list ap; int len, i; const unsigned x0 = pos->x; va_start(ap, fmt); len = re_vsnprintf(buf, sizeof(buf), fmt, ap); va_end(ap); for (i=0; ix = x0; pos->y += FONT_HEIGHT; continue; } draw_char(frame, pos->x, pos->y, ch); pos->x += FONT_WIDTH; } } int vidinfo_draw_box(struct vidframe *frame, uint64_t timestamp, const struct stats *stats, const struct video *vid, int x0, int y0, int width, int height) { const struct vidcodec *vc; struct stream *strm; const struct rtcp_stats *rtcp; struct vidpt pos = {x0+2, y0+2}; int64_t dur; dur = timestamp - stats->last_timestamp; dim_region(frame, x0, y0, width, height); vidframe_draw_rect(frame, x0, y0, width, height, 255, 255, 255); vidframe_draw_rect(frame, x0+1, y0+1, width, height, 0, 0, 0); draw_text(frame, &pos, "[%H]\n" "Resolution: %u x %u\n" "Framerate: %.1f\n" , fmt_gmtime, NULL, frame->size.w, frame->size.h, (double)VIDEO_TIMEBASE / (double)dur); vc = video_codec(vid, false); if (vc) { draw_text(frame, &pos, "Decoder: %s\n", vc->name); } strm = video_strm(vid); rtcp = stream_rtcp_stats(strm); if (rtcp && rtcp->rx.sent) { double loss; loss = 100.0 * (double)rtcp->rx.lost / (double)rtcp->rx.sent; draw_text(frame, &pos, "Jitter: %.1f ms\n" "Packetloss: %.2f %%\n" , (double)rtcp->rx.jit * .001, loss); } return 0; } baresip-1.0.0/modules/vidinfo/module.mk000066400000000000000000000002451372575704200200760ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # MOD := vidinfo $(MOD)_SRCS += draw.c $(MOD)_SRCS += vidinfo.c $(MOD)_SRCS += xga_font_data.c include mk/mod.mk baresip-1.0.0/modules/vidinfo/vidinfo.c000066400000000000000000000050771372575704200200720ustar00rootroot00000000000000/** * @file vidinfo.c Video-info filter * * Copyright (C) 2010 - 2015 Creytiv.com */ #include #include #include #include "vidinfo.h" #include "xga_font_data.h" /** * @defgroup vidinfo vidinfo * * Display video-info overlay on the encode/decode streams * * Displays info like framerate and packet timing, this is mainly * for development and debugging. */ #define MAX_CHARS_WIDTH 32 #define MAX_CHARS_HEIGHT 10 #define MAX_PIXELS_WIDTH (MAX_CHARS_WIDTH * FONT_WIDTH) #define MAX_PIXELS_HEIGHT (MAX_CHARS_HEIGHT * FONT_HEIGHT) enum layout { LAYOUT_TOP, LAYOUT_BOTTOM, }; struct vidinfo_dec { struct vidfilt_dec_st vf; /* base member (inheritance) */ struct stats stats; const struct video *vid; }; static enum layout box_layout = LAYOUT_TOP; static void decode_destructor(void *arg) { struct vidinfo_dec *st = arg; list_unlink(&st->vf.le); } static int decode_update(struct vidfilt_dec_st **stp, void **ctx, const struct vidfilt *vf, struct vidfilt_prm *prm, const struct video *vid) { struct vidinfo_dec *st; (void)prm; (void)vid; if (!stp || !ctx || !vf) return EINVAL; if (*stp) return 0; st = mem_zalloc(sizeof(*st), decode_destructor); if (!st) return ENOMEM; st->vid = vid; *stp = (struct vidfilt_dec_st *)st; return 0; } static int decode(struct vidfilt_dec_st *_st, struct vidframe *frame, uint64_t *timestamp) { struct vidinfo_dec *st = (struct vidinfo_dec *)(void *)_st; if (!st) return EINVAL; if (frame && timestamp) { unsigned x0, y0; if (frame->fmt != VID_FMT_YUV420P) return ENOTSUP; switch (box_layout) { case LAYOUT_TOP: x0 = 4; y0 = 4; break; case LAYOUT_BOTTOM: x0 = 4; y0 = frame->size.h - MAX_PIXELS_HEIGHT; break; default: return EINVAL; } vidinfo_draw_box(frame, *timestamp, &st->stats, st->vid, x0, y0, MAX_PIXELS_WIDTH, MAX_PIXELS_HEIGHT); st->stats.last_timestamp = *timestamp; } return 0; } static struct vidfilt vidinfo = { .name = "vidinfo", .decupdh = decode_update, .dech = decode, }; static int module_init(void) { struct pl pl; if (0 == conf_get(conf_cur(), "vidinfo_layout", &pl)) { if (0 == pl_strcasecmp(&pl, "top")) { box_layout = LAYOUT_TOP; } else if (0 == pl_strcasecmp(&pl, "bottom")) { box_layout = LAYOUT_BOTTOM; } } vidfilt_register(baresip_vidfiltl(), &vidinfo); return 0; } static int module_close(void) { vidfilt_unregister(&vidinfo); return 0; } EXPORT_SYM const struct mod_export DECL_EXPORTS(vidinfo) = { "vidinfo", "vidfilt", module_init, module_close }; baresip-1.0.0/modules/vidinfo/vidinfo.h000066400000000000000000000004651372575704200200730ustar00rootroot00000000000000/** * @file vidinfo.h Video-info filter * * Copyright (C) 2010 - 2015 Creytiv.com */ struct stats { uint64_t last_timestamp; }; int vidinfo_draw_box(struct vidframe *frame, uint64_t timestamp, const struct stats *stats, const struct video *vid, int x0, int y0, int width, int height); baresip-1.0.0/modules/vidinfo/xga_font_data.c000066400000000000000000000310301372575704200212160ustar00rootroot00000000000000/** * @file xga_font_data.c CGA Font * * Copyright (C) 2010 - 2015 Creytiv.com */ #include #include "xga_font_data.h" /* * 8x8 font CGA font * * Credits: FFmpeg project (libavutil/xga_font_data.c) */ const uint8_t vidinfo_cga_font[256 * FONT_HEIGHT] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0xbd, 0x99, 0x81, 0x7e, 0x7e, 0xff, 0xdb, 0xff, 0xc3, 0xe7, 0xff, 0x7e, 0x6c, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x38, 0x7c, 0x38, 0xfe, 0xfe, 0x7c, 0x38, 0x7c, 0x10, 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x7c, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00, 0xff, 0xc3, 0x99, 0xbd, 0xbd, 0x99, 0xc3, 0xff, 0x0f, 0x07, 0x0f, 0x7d, 0xcc, 0xcc, 0xcc, 0x78, 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x70, 0xf0, 0xe0, 0x7f, 0x63, 0x7f, 0x63, 0x63, 0x67, 0xe6, 0xc0, 0x99, 0x5a, 0x3c, 0xe7, 0xe7, 0x3c, 0x5a, 0x99, 0x80, 0xe0, 0xf8, 0xfe, 0xf8, 0xe0, 0x80, 0x00, 0x02, 0x0e, 0x3e, 0xfe, 0x3e, 0x0e, 0x02, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x00, 0x7f, 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x00, 0x3e, 0x63, 0x38, 0x6c, 0x6c, 0x38, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x7e, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x7e, 0x3c, 0x18, 0xff, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x78, 0x78, 0x30, 0x30, 0x00, 0x30, 0x00, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x6c, 0xfe, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, 0x30, 0x7c, 0xc0, 0x78, 0x0c, 0xf8, 0x30, 0x00, 0x00, 0xc6, 0xcc, 0x18, 0x30, 0x66, 0xc6, 0x00, 0x38, 0x6c, 0x38, 0x76, 0xdc, 0xcc, 0x76, 0x00, 0x60, 0x60, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x60, 0x60, 0x30, 0x18, 0x00, 0x60, 0x30, 0x18, 0x18, 0x18, 0x30, 0x60, 0x00, 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, 0x7c, 0xc6, 0xce, 0xde, 0xf6, 0xe6, 0x7c, 0x00, 0x30, 0x70, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x00, 0x78, 0xcc, 0x0c, 0x38, 0x60, 0xcc, 0xfc, 0x00, 0x78, 0xcc, 0x0c, 0x38, 0x0c, 0xcc, 0x78, 0x00, 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, 0x0c, 0x1e, 0x00, 0xfc, 0xc0, 0xf8, 0x0c, 0x0c, 0xcc, 0x78, 0x00, 0x38, 0x60, 0xc0, 0xf8, 0xcc, 0xcc, 0x78, 0x00, 0xfc, 0xcc, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0xcc, 0xcc, 0x78, 0x00, 0x78, 0xcc, 0xcc, 0x7c, 0x0c, 0x18, 0x70, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x60, 0x18, 0x30, 0x60, 0xc0, 0x60, 0x30, 0x18, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x60, 0x30, 0x18, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x78, 0xcc, 0x0c, 0x18, 0x30, 0x00, 0x30, 0x00, 0x7c, 0xc6, 0xde, 0xde, 0xde, 0xc0, 0x78, 0x00, 0x30, 0x78, 0xcc, 0xcc, 0xfc, 0xcc, 0xcc, 0x00, 0xfc, 0x66, 0x66, 0x7c, 0x66, 0x66, 0xfc, 0x00, 0x3c, 0x66, 0xc0, 0xc0, 0xc0, 0x66, 0x3c, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0xfe, 0x62, 0x68, 0x78, 0x68, 0x62, 0xfe, 0x00, 0xfe, 0x62, 0x68, 0x78, 0x68, 0x60, 0xf0, 0x00, 0x3c, 0x66, 0xc0, 0xc0, 0xce, 0x66, 0x3e, 0x00, 0xcc, 0xcc, 0xcc, 0xfc, 0xcc, 0xcc, 0xcc, 0x00, 0x78, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78, 0x00, 0xe6, 0x66, 0x6c, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0x00, 0xc6, 0xe6, 0xf6, 0xde, 0xce, 0xc6, 0xc6, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0xfc, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xdc, 0x78, 0x1c, 0x00, 0xfc, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0xe6, 0x00, 0x78, 0xcc, 0xe0, 0x70, 0x1c, 0xcc, 0x78, 0x00, 0xfc, 0xb4, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xfc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x00, 0xc6, 0xc6, 0xc6, 0xd6, 0xfe, 0xee, 0xc6, 0x00, 0xc6, 0xc6, 0x6c, 0x38, 0x38, 0x6c, 0xc6, 0x00, 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x30, 0x78, 0x00, 0xfe, 0xc6, 0x8c, 0x18, 0x32, 0x66, 0xfe, 0x00, 0x78, 0x60, 0x60, 0x60, 0x60, 0x60, 0x78, 0x00, 0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x02, 0x00, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x76, 0x00, 0xe0, 0x60, 0x60, 0x7c, 0x66, 0x66, 0xdc, 0x00, 0x00, 0x00, 0x78, 0xcc, 0xc0, 0xcc, 0x78, 0x00, 0x1c, 0x0c, 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00, 0x38, 0x6c, 0x60, 0xf0, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8, 0xe0, 0x60, 0x6c, 0x76, 0x66, 0x66, 0xe6, 0x00, 0x30, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, 0x0c, 0x00, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78, 0xe0, 0x60, 0x66, 0x6c, 0x78, 0x6c, 0xe6, 0x00, 0x70, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00, 0x00, 0x00, 0xcc, 0xfe, 0xfe, 0xd6, 0xc6, 0x00, 0x00, 0x00, 0xf8, 0xcc, 0xcc, 0xcc, 0xcc, 0x00, 0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x7c, 0x60, 0xf0, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0x7c, 0x0c, 0x1e, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x7c, 0xc0, 0x78, 0x0c, 0xf8, 0x00, 0x10, 0x30, 0x7c, 0x30, 0x30, 0x34, 0x18, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x00, 0x00, 0x00, 0xc6, 0xd6, 0xfe, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0xc6, 0x6c, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8, 0x00, 0x00, 0xfc, 0x98, 0x30, 0x64, 0xfc, 0x00, 0x1c, 0x30, 0x30, 0xe0, 0x30, 0x30, 0x1c, 0x00, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00, 0xe0, 0x30, 0x30, 0x1c, 0x30, 0x30, 0xe0, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0x00, 0x78, 0xcc, 0xc0, 0xcc, 0x78, 0x18, 0x0c, 0x78, 0x00, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00, 0x1c, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00, 0x7e, 0xc3, 0x3c, 0x06, 0x3e, 0x66, 0x3f, 0x00, 0xcc, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00, 0xe0, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00, 0x30, 0x30, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00, 0x00, 0x00, 0x78, 0xc0, 0xc0, 0x78, 0x0c, 0x38, 0x7e, 0xc3, 0x3c, 0x66, 0x7e, 0x60, 0x3c, 0x00, 0xcc, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00, 0xe0, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00, 0xcc, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, 0x7c, 0xc6, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x00, 0xe0, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, 0xc6, 0x38, 0x6c, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, 0x30, 0x30, 0x00, 0x78, 0xcc, 0xfc, 0xcc, 0x00, 0x1c, 0x00, 0xfc, 0x60, 0x78, 0x60, 0xfc, 0x00, 0x00, 0x00, 0x7f, 0x0c, 0x7f, 0xcc, 0x7f, 0x00, 0x3e, 0x6c, 0xcc, 0xfe, 0xcc, 0xcc, 0xce, 0x00, 0x78, 0xcc, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0xcc, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0xe0, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00, 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00, 0x00, 0xe0, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00, 0x00, 0xcc, 0x00, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8, 0xc3, 0x18, 0x3c, 0x66, 0x66, 0x3c, 0x18, 0x00, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x18, 0x18, 0x7e, 0xc0, 0xc0, 0x7e, 0x18, 0x18, 0x38, 0x6c, 0x64, 0xf0, 0x60, 0xe6, 0xfc, 0x00, 0xcc, 0xcc, 0x78, 0xfc, 0x30, 0xfc, 0x30, 0x30, 0xf8, 0xcc, 0xcc, 0xfa, 0xc6, 0xcf, 0xc6, 0xc7, 0x0e, 0x1b, 0x18, 0x3c, 0x18, 0x18, 0xd8, 0x70, 0x1c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00, 0x38, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, 0x00, 0x1c, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x1c, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00, 0x00, 0xf8, 0x00, 0xf8, 0xcc, 0xcc, 0xcc, 0x00, 0xfc, 0x00, 0xcc, 0xec, 0xfc, 0xdc, 0xcc, 0x00, 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00, 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x7c, 0x00, 0x00, 0x30, 0x00, 0x30, 0x60, 0xc0, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x0c, 0x0c, 0x00, 0x00, 0xc3, 0xc6, 0xcc, 0xde, 0x33, 0x66, 0xcc, 0x0f, 0xc3, 0xc6, 0xcc, 0xdb, 0x37, 0x6f, 0xcf, 0x03, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x33, 0x66, 0xcc, 0x66, 0x33, 0x00, 0x00, 0x00, 0xcc, 0x66, 0x33, 0x66, 0xcc, 0x00, 0x00, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0xdb, 0x77, 0xdb, 0xee, 0xdb, 0x77, 0xdb, 0xee, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36, 0x00, 0x00, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x36, 0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0xfe, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00, 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x36, 0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f, 0x00, 0x00, 0x00, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36, 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0xc8, 0xdc, 0x76, 0x00, 0x00, 0x78, 0xcc, 0xf8, 0xcc, 0xf8, 0xc0, 0xc0, 0x00, 0xfc, 0xcc, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0xfc, 0xcc, 0x60, 0x30, 0x60, 0xcc, 0xfc, 0x00, 0x00, 0x00, 0x7e, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0xc0, 0x00, 0x76, 0xdc, 0x18, 0x18, 0x18, 0x18, 0x00, 0xfc, 0x30, 0x78, 0xcc, 0xcc, 0x78, 0x30, 0xfc, 0x38, 0x6c, 0xc6, 0xfe, 0xc6, 0x6c, 0x38, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x6c, 0xee, 0x00, 0x1c, 0x30, 0x18, 0x7c, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x7e, 0xdb, 0xdb, 0x7e, 0x00, 0x00, 0x06, 0x0c, 0x7e, 0xdb, 0xdb, 0x7e, 0x60, 0xc0, 0x38, 0x60, 0xc0, 0xf8, 0xc0, 0x60, 0x38, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x00, 0x00, 0xfc, 0x00, 0xfc, 0x00, 0xfc, 0x00, 0x00, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x00, 0xfc, 0x00, 0x60, 0x30, 0x18, 0x30, 0x60, 0x00, 0xfc, 0x00, 0x18, 0x30, 0x60, 0x30, 0x18, 0x00, 0xfc, 0x00, 0x0e, 0x1b, 0x1b, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0x70, 0x30, 0x30, 0x00, 0xfc, 0x00, 0x30, 0x30, 0x00, 0x00, 0x76, 0xdc, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x0f, 0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x3c, 0x1c, 0x78, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x70, 0x18, 0x30, 0x60, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; baresip-1.0.0/modules/vidinfo/xga_font_data.h000066400000000000000000000003171372575704200212270ustar00rootroot00000000000000/** * @file xga_font_data.c CGA Font -- interface * * Copyright (C) 2010 - 2015 Creytiv.com */ enum { FONT_WIDTH = 8, FONT_HEIGHT = 8, }; extern const uint8_t vidinfo_cga_font[256 * FONT_HEIGHT]; baresip-1.0.0/modules/vidloop/000077500000000000000000000000001372575704200162755ustar00rootroot00000000000000baresip-1.0.0/modules/vidloop/module.mk000066400000000000000000000001601372575704200201100ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # MOD := vidloop $(MOD)_SRCS += vidloop.c include mk/mod.mk baresip-1.0.0/modules/vidloop/vidloop.c000066400000000000000000000410151372575704200201160ustar00rootroot00000000000000/** * @file vidloop.c Video loop * * Copyright (C) 2010 Creytiv.com */ #define _DEFAULT_SOURCE 1 #define _BSD_SOURCE 1 #include #include #include #include #include /** * @defgroup vidloop vidloop * * A video-loop module for testing * * Simple test module that loops back the video frames from a * video-source to a video-display, optionally via a video codec. * * Example usage without codec: \verbatim baresip -e/vidloop \endverbatim * * Example usage with codec: \verbatim baresip -e"/vidloop h264" \endverbatim */ /** Video Statistics */ struct vstat { uint64_t tsamp; uint32_t frames; size_t bytes; uint32_t bitrate; double efps; size_t n_keyframe; }; struct timestamp_state { uint64_t base; /* lowest timestamp */ uint64_t last; /* most recent timestamp */ bool is_set; }; /** Video loop */ struct video_loop { const struct vidcodec *vc_enc; const struct vidcodec *vc_dec; struct config_video cfg; struct videnc_state *enc; struct viddec_state *dec; struct vidisp_st *vidisp; struct vidsrc_st *vsrc; struct vidsrc_prm srcprm; struct list filtencl; struct list filtdecl; struct vstat stat; struct tmr tmr_bw; struct tmr tmr_display; struct tmr tmr_update_src; struct vidsz src_size; struct vidsz disp_size; enum vidfmt src_fmt; enum vidfmt disp_fmt; struct vidframe *frame; uint64_t frame_timestamp; struct lock *frame_mutex; bool new_frame; uint64_t ts_start; /* usec */ uint64_t ts_last; /* usec */ uint16_t seq; bool need_conv; bool started; int err; struct { uint64_t src_frames; uint64_t enc_bytes; uint64_t enc_packets; uint64_t disp_frames; } stats; struct timestamp_state ts_src; struct timestamp_state ts_rtp; }; static struct video_loop *gvl; static void timestamp_state_update(struct timestamp_state *st, uint64_t ts) { if (st->is_set) { if (ts < st->base) { warning("vidloop: timestamp wrapped -- reset base" " (base=%llu, current=%llu)\n", st->base, ts); st->base = ts; } } else { st->base = ts; st->is_set = true; } st->last = ts; } static double timestamp_state_duration(const struct timestamp_state *ts, uint32_t clock_rate) { uint64_t dur; if (ts->is_set) dur = ts->last - ts->base; else dur = 0; return (double)dur / (double)clock_rate; } static void display_handler(void *arg) { struct video_loop *vl = arg; int err; tmr_start(&vl->tmr_display, 10, display_handler, vl); lock_write_get(vl->frame_mutex); if (!vl->new_frame) goto out; /* display frame */ err = vidisp_display(vl->vidisp, "Video Loop", vl->frame, vl->frame_timestamp); vl->new_frame = false; if (err == ENODEV) { info("vidloop: video-display was closed\n"); vl->vidisp = mem_deref(vl->vidisp); vl->err = err; } ++vl->stats.disp_frames; out: lock_rel(vl->frame_mutex); } static int display(struct video_loop *vl, struct vidframe *frame, uint64_t timestamp) { struct vidframe *frame_filt = NULL; struct le *le; int err = 0; if (!vidframe_isvalid(frame)) return 0; /* Process video frame through all Video Filters */ for (le = vl->filtdecl.head; le; le = le->next) { struct vidfilt_dec_st *st = le->data; /* Some video decoders keeps the displayed video frame * in memory and we should not write to that frame. */ if (!frame_filt) { err = vidframe_alloc(&frame_filt, frame->fmt, &frame->size); if (err) return err; vidframe_copy(frame_filt, frame); frame = frame_filt; } if (st->vf->dech) err |= st->vf->dech(st, frame, ×tamp); } if (err) { warning("vidloop: error in decode video-filter (%m)\n", err); } /* save the displayed frame info */ vl->disp_size = frame->size; vl->disp_fmt = frame->fmt; lock_write_get(vl->frame_mutex); if (vl->frame && ! vidsz_cmp(&vl->frame->size, &frame->size)) { info("vidloop: resolution changed: %u x %u\n", frame->size.w, frame->size.h); vl->frame = mem_deref(vl->frame); } if (!vl->frame) { err = vidframe_alloc(&vl->frame, frame->fmt, &frame->size); if (err) goto out; } vidframe_copy(vl->frame, frame); vl->frame_timestamp = timestamp; vl->new_frame = true; out: lock_rel(vl->frame_mutex); mem_deref(frame_filt); return err; } static int packet_handler(bool marker, uint64_t rtp_ts, const uint8_t *hdr, size_t hdr_len, const uint8_t *pld, size_t pld_len, void *arg) { struct video_loop *vl = arg; struct vidframe frame; struct mbuf *mb; uint64_t timestamp; bool keyframe; int err = 0; ++vl->stats.enc_packets; vl->stats.enc_bytes += (hdr_len + pld_len); timestamp_state_update(&vl->ts_rtp, rtp_ts); mb = mbuf_alloc(hdr_len + pld_len); if (!mb) return ENOMEM; if (hdr_len) mbuf_write_mem(mb, hdr, hdr_len); mbuf_write_mem(mb, pld, pld_len); mb->pos = 0; vl->stat.bytes += mbuf_get_left(mb); /* decode */ frame.data[0] = NULL; if (vl->vc_dec && vl->dec) { err = vl->vc_dec->dech(vl->dec, &frame, &keyframe, marker, vl->seq++, mb); if (err) { warning("vidloop: codec decode: %m\n", err); goto out; } if (keyframe) ++vl->stat.n_keyframe; } /* convert the RTP timestamp to VIDEO_TIMEBASE timestamp */ timestamp = video_calc_timebase_timestamp(rtp_ts); if (vidframe_isvalid(&frame)) { display(vl, &frame, timestamp); } out: mem_deref(mb); return 0; } static void vidsrc_frame_handler(struct vidframe *frame, uint64_t timestamp, void *arg) { struct video_loop *vl = arg; struct vidframe *f2 = NULL; struct le *le; const uint64_t now = tmr_jiffies_usec(); int err = 0; /* save the timing info */ if (!gvl->ts_start) gvl->ts_start = now; gvl->ts_last = now; /* save the video frame info */ vl->src_size = frame->size; vl->src_fmt = frame->fmt; ++vl->stats.src_frames; timestamp_state_update(&vl->ts_src, timestamp); ++vl->stat.frames; if (frame->fmt != (enum vidfmt)vl->cfg.enc_fmt) { if (!vl->need_conv) { info("vidloop: NOTE: pixel-format conversion" " needed: %s --> %s\n", vidfmt_name(frame->fmt), vidfmt_name(vl->cfg.enc_fmt)); vl->need_conv = true; } if (vidframe_alloc(&f2, vl->cfg.enc_fmt, &frame->size)) return; vidconv(f2, frame, 0); frame = f2; } /* Process video frame through all Video Filters */ for (le = vl->filtencl.head; le; le = le->next) { struct vidfilt_enc_st *st = le->data; if (st->vf->ench) err |= st->vf->ench(st, frame, ×tamp); } if (vl->vc_enc && vl->enc) { err = vl->vc_enc->ench(vl->enc, false, frame, timestamp); if (err) { warning("vidloop: encoder error (%m)\n", err); goto out; } } else { vl->stat.bytes += vidframe_size(frame->fmt, &frame->size); (void)display(vl, frame, timestamp); } out: mem_deref(f2); } static int print_stats(struct re_printf *pf, const struct video_loop *vl) { const struct config_video *cfg = &vl->cfg; double src_dur, real_dur = .0; int err = 0; src_dur = timestamp_state_duration(&vl->ts_src, VIDEO_TIMEBASE); if (vl->ts_start) real_dur = (vl->ts_last - vl->ts_start) * .000001; err |= re_hprintf(pf, "~~~~~ Videoloop summary: ~~~~~\n"); /* Source */ if (vl->vsrc) { struct vidsrc *vs = vidsrc_get(vl->vsrc); double avg_fps = .0; if (vl->stats.src_frames >= 2) avg_fps = (vl->stats.src_frames-1) / src_dur; err |= re_hprintf(pf, "* Source\n" " module %s\n" " resolution %u x %u (actual %u x %u)\n" " pixformat %s\n" " frames %llu\n" " framerate %.2f fps (avg %.2f fps)\n" " duration %.3f sec (real %.3f sec)\n" "\n" , vs->name, cfg->width, cfg->height, vl->src_size.w, vl->src_size.h, vidfmt_name(vl->src_fmt), vl->stats.src_frames, vl->srcprm.fps, avg_fps, src_dur, real_dur); } /* Video conversion */ if (vl->need_conv) { err |= re_hprintf(pf, "* Vidconv\n" " pixformat %s\n" "\n" , vidfmt_name(cfg->enc_fmt)); } /* Filters */ if (!list_isempty(baresip_vidfiltl())) { struct le *le; err |= re_hprintf(pf, "* Filters (%u):", list_count(baresip_vidfiltl())); for (le = list_head(baresip_vidfiltl()); le; le = le->next) { struct vidfilt *vf = le->data; err |= re_hprintf(pf, " %s", vf->name); } err |= re_hprintf(pf, "\n\n"); } /* Encoder */ if (vl->vc_enc) { double avg_bitrate; double avg_pktrate; double dur; dur = timestamp_state_duration(&vl->ts_rtp, 90000); avg_bitrate = 8.0 * (double)vl->stats.enc_bytes / dur; avg_pktrate = (double)vl->stats.enc_packets / dur; err |= re_hprintf(pf, "* Encoder\n" " module %s\n" " bitrate %u bit/s (avg %.1f bit/s)\n" " packets %llu (avg %.1f pkt/s)\n" " duration %.3f sec\n" "\n" , vl->vc_enc->name, cfg->bitrate, avg_bitrate, vl->stats.enc_packets, avg_pktrate, dur); } /* Decoder */ if (vl->vc_dec) { err |= re_hprintf(pf, "* Decoder\n" " module %s\n" " key-frames %zu\n" "\n" , vl->vc_dec->name, vl->stat.n_keyframe); } /* Display */ if (vl->vidisp) { struct vidisp *vd = vidisp_get(vl->vidisp); err |= re_hprintf(pf, "* Display\n" " module %s\n" " resolution %u x %u\n" " pixformat %s\n" " frames %llu\n" "\n" , vd->name, vl->disp_size.w, vl->disp_size.h, vidfmt_name(vl->disp_fmt), vl->stats.disp_frames); } return err; } static void vidloop_destructor(void *arg) { struct video_loop *vl = arg; if (vl->started) re_printf("%H\n", print_stats, vl); tmr_cancel(&vl->tmr_bw); mem_deref(vl->vsrc); mem_deref(vl->enc); mem_deref(vl->dec); tmr_cancel(&vl->tmr_update_src); lock_write_get(vl->frame_mutex); mem_deref(vl->vidisp); mem_deref(vl->frame); tmr_cancel(&vl->tmr_display); lock_rel(vl->frame_mutex); list_flush(&vl->filtencl); list_flush(&vl->filtdecl); mem_deref(vl->frame_mutex); } static int enable_codec(struct video_loop *vl, const char *name) { struct list *vidcodecl = baresip_vidcodecl(); struct videnc_param prm; int err; prm.fps = vl->cfg.fps; prm.pktsize = 1480; prm.bitrate = vl->cfg.bitrate; prm.max_fs = -1; /* Use the first video codec */ vl->vc_enc = vidcodec_find_encoder(vidcodecl, name); if (!vl->vc_enc) { warning("vidloop: could not find encoder (%s)\n", name); return ENOENT; } info("vidloop: enabled encoder %s (%.2f fps, %u bit/s)\n", vl->vc_enc->name, prm.fps, prm.bitrate); vl->vc_dec = vidcodec_find_decoder(vidcodecl, name); if (!vl->vc_dec) { warning("vidloop: could not find decoder (%s)\n", name); return ENOENT; } info("vidloop: enabled decoder %s\n", vl->vc_dec->name); err = vl->vc_enc->encupdh(&vl->enc, vl->vc_enc, &prm, NULL, packet_handler, vl); if (err) { warning("vidloop: update encoder failed: %m\n", err); return err; } if (vl->vc_dec->decupdh) { err = vl->vc_dec->decupdh(&vl->dec, vl->vc_dec, NULL); if (err) { warning("vidloop: update decoder failed: %m\n", err); return err; } } return 0; } static void print_status(struct video_loop *vl) { re_printf("\rstatus:" " %.3f sec [%s] [%s] fmt=%s " " EFPS=%.1f %u kbit/s", timestamp_state_duration(&vl->ts_src, VIDEO_TIMEBASE), vl->vc_enc ? vl->vc_enc->name : "", vl->vc_dec ? vl->vc_dec->name : "", vidfmt_name(vl->cfg.enc_fmt), vl->stat.efps, vl->stat.bitrate); if (vl->enc || vl->dec) re_printf(" key-frames=%zu", vl->stat.n_keyframe); re_printf(" \r"); fflush(stdout); } static void calc_bitrate(struct video_loop *vl) { const uint64_t now = tmr_jiffies(); if (now > vl->stat.tsamp) { const uint32_t dur = (uint32_t)(now - vl->stat.tsamp); vl->stat.efps = 1000.0f * vl->stat.frames / dur; vl->stat.bitrate = (uint32_t) (8 * vl->stat.bytes / dur); } vl->stat.frames = 0; vl->stat.bytes = 0; vl->stat.tsamp = now; } static void timeout_bw(void *arg) { struct video_loop *vl = arg; if (vl->err) { info("error in video-loop -- closing (%m)\n", vl->err); gvl = mem_deref(gvl); return; } tmr_start(&vl->tmr_bw, 100, timeout_bw, vl); calc_bitrate(vl); print_status(vl); } static int vsrc_reopen(struct video_loop *vl, const struct vidsz *sz) { int err; info("vidloop: %s,%s: open video source: %u x %u at %.2f fps\n", vl->cfg.src_mod, vl->cfg.src_dev, sz->w, sz->h, vl->cfg.fps); vl->srcprm.fps = vl->cfg.fps; vl->srcprm.fmt = vl->cfg.enc_fmt; vl->vsrc = mem_deref(vl->vsrc); err = vidsrc_alloc(&vl->vsrc, baresip_vidsrcl(), vl->cfg.src_mod, NULL, &vl->srcprm, sz, NULL, vl->cfg.src_dev, vidsrc_frame_handler, NULL, vl); if (err) { warning("vidloop: vidsrc '%s' failed: %m\n", vl->cfg.src_dev, err); } return err; } static void update_vidsrc(void *arg) { struct video_loop *vl = arg; struct vidsz size; struct config *cfg = conf_config(); int err; tmr_start(&vl->tmr_update_src, 100, update_vidsrc, vl); if (!strcmp(vl->cfg.src_mod, cfg->video.src_mod) && !strcmp(vl->cfg.src_dev, cfg->video.src_dev)) return; str_ncpy(vl->cfg.src_mod, cfg->video.src_mod, sizeof(vl->cfg.src_mod)); str_ncpy(vl->cfg.src_dev, cfg->video.src_dev, sizeof(vl->cfg.src_dev)); size.w = cfg->video.width; size.h = cfg->video.height; err = vsrc_reopen(gvl, &size); if (err) gvl = mem_deref(gvl); } static int video_loop_alloc(struct video_loop **vlp) { struct video_loop *vl; struct config *cfg; struct le *le; int err = 0; cfg = conf_config(); if (!cfg) return EINVAL; vl = mem_zalloc(sizeof(*vl), vidloop_destructor); if (!vl) return ENOMEM; vl->cfg = cfg->video; tmr_init(&vl->tmr_bw); tmr_init(&vl->tmr_display); tmr_init(&vl->tmr_update_src); vl->src_fmt = -1; vl->disp_fmt = -1; err = lock_alloc(&vl->frame_mutex); if (err) goto out; vl->new_frame = false; vl->frame = NULL; /* Video filters */ for (le = list_head(baresip_vidfiltl()); le; le = le->next) { struct vidfilt *vf = le->data; struct vidfilt_prm prm; void *ctx = NULL; prm.width = vl->cfg.width; prm.height = vl->cfg.height; prm.fmt = vl->cfg.enc_fmt; prm.fps = vl->cfg.fps; info("vidloop: added video-filter `%s'\n", vf->name); err |= vidfilt_enc_append(&vl->filtencl, &ctx, vf, &prm, 0); err |= vidfilt_dec_append(&vl->filtdecl, &ctx, vf, &prm, 0); if (err) { warning("vidloop: vidfilt error: %m\n", err); } } info("vidloop: open video display (%s.%s)\n", vl->cfg.disp_mod, vl->cfg.disp_dev); err = vidisp_alloc(&vl->vidisp, baresip_vidispl(), vl->cfg.disp_mod, NULL, vl->cfg.disp_dev, NULL, vl); if (err) { warning("vidloop: video display failed: %m\n", err); goto out; } tmr_start(&vl->tmr_bw, 1000, timeout_bw, vl); /* NOTE: usually (e.g. SDL2), video frame must be rendered from main thread */ tmr_start(&vl->tmr_display, 10, display_handler, vl); tmr_start(&vl->tmr_update_src, 10, update_vidsrc, vl); out: if (err) mem_deref(vl); else *vlp = vl; return err; } /** * Start the video loop (for testing) */ static int vidloop_start(struct re_printf *pf, void *arg) { const struct cmd_arg *carg = arg; struct vidsz size; struct config *cfg = conf_config(); const char *codec_name = carg->prm; int err = 0; size.w = cfg->video.width; size.h = cfg->video.height; if (gvl) { return re_hprintf(pf, "video-loop already running.\n"); } (void)re_hprintf(pf, "Enable video-loop on %s,%s: %u x %u\n", cfg->video.src_mod, cfg->video.src_dev, size.w, size.h); err = video_loop_alloc(&gvl); if (err) { warning("vidloop: alloc: %m\n", err); return err; } if (str_isset(codec_name)) { err = enable_codec(gvl, codec_name); if (err) { gvl = mem_deref(gvl); return err; } (void)re_hprintf(pf, "%sabled codec: %s\n", gvl->vc_enc ? "En" : "Dis", gvl->vc_enc ? gvl->vc_enc->name : ""); } /* Start video source, after codecs are created */ err = vsrc_reopen(gvl, &size); if (err) { gvl = mem_deref(gvl); return err; } gvl->started = true; return err; } static int vidloop_stop(struct re_printf *pf, void *arg) { (void)arg; if (gvl) (void)re_hprintf(pf, "Disable video-loop\n"); gvl = mem_deref(gvl); return 0; } static const struct cmd cmdv[] = { {"vidloop", 0, CMD_PRM, "Start video-loop ", vidloop_start}, {"vidloop_stop",0, 0, "Stop video-loop", vidloop_stop }, }; static int module_init(void) { return cmd_register(baresip_commands(), cmdv, ARRAY_SIZE(cmdv)); } static int module_close(void) { gvl = mem_deref(gvl); cmd_unregister(baresip_commands(), cmdv); return 0; } EXPORT_SYM const struct mod_export DECL_EXPORTS(vidloop) = { "vidloop", "application", module_init, module_close, }; baresip-1.0.0/modules/vp8/000077500000000000000000000000001372575704200153365ustar00rootroot00000000000000baresip-1.0.0/modules/vp8/decode.c000066400000000000000000000107661372575704200167370ustar00rootroot00000000000000/** * @file vp8/decode.c VP8 Decode * * Copyright (C) 2010 Creytiv.com */ #include #include #include #include #include #include #include "vp8.h" enum { DECODE_MAXSZ = 524288, }; struct hdr { unsigned x:1; unsigned noref:1; unsigned start:1; unsigned partid:4; /* extension fields */ unsigned i:1; unsigned l:1; unsigned t:1; unsigned k:1; uint16_t picid; uint8_t tl0picidx; unsigned tid:2; unsigned y:1; unsigned keyidx:5; }; struct viddec_state { vpx_codec_ctx_t ctx; struct mbuf *mb; bool ctxup; bool started; uint16_t seq; }; static void destructor(void *arg) { struct viddec_state *vds = arg; if (vds->ctxup) vpx_codec_destroy(&vds->ctx); mem_deref(vds->mb); } int vp8_decode_update(struct viddec_state **vdsp, const struct vidcodec *vc, const char *fmtp) { struct viddec_state *vds; vpx_codec_err_t res; int err = 0; (void)vc; (void)fmtp; if (!vdsp) return EINVAL; vds = *vdsp; if (vds) return 0; vds = mem_zalloc(sizeof(*vds), destructor); if (!vds) return ENOMEM; vds->mb = mbuf_alloc(1024); if (!vds->mb) { err = ENOMEM; goto out; } res = vpx_codec_dec_init(&vds->ctx, &vpx_codec_vp8_dx_algo, NULL, 0); if (res) { err = ENOMEM; goto out; } vds->ctxup = true; out: if (err) mem_deref(vds); else *vdsp = vds; return err; } static inline int hdr_decode(struct hdr *hdr, struct mbuf *mb) { uint8_t v; memset(hdr, 0, sizeof(*hdr)); if (mbuf_get_left(mb) < 1) return EBADMSG; v = mbuf_read_u8(mb); hdr->x = v>>7 & 0x1; hdr->noref = v>>5 & 0x1; hdr->start = v>>4 & 0x1; hdr->partid = v & 0x07; if (hdr->x) { if (mbuf_get_left(mb) < 1) return EBADMSG; v = mbuf_read_u8(mb); hdr->i = v>>7 & 0x1; hdr->l = v>>6 & 0x1; hdr->t = v>>5 & 0x1; hdr->k = v>>4 & 0x1; } if (hdr->i) { if (mbuf_get_left(mb) < 1) return EBADMSG; v = mbuf_read_u8(mb); if (v>>7 & 0x1) { if (mbuf_get_left(mb) < 1) return EBADMSG; hdr->picid = (v & 0x7f)<<8; hdr->picid += mbuf_read_u8(mb); } else { hdr->picid = v & 0x7f; } } if (hdr->l) { if (mbuf_get_left(mb) < 1) return EBADMSG; hdr->tl0picidx = mbuf_read_u8(mb); } if (hdr->t || hdr->k) { if (mbuf_get_left(mb) < 1) return EBADMSG; v = mbuf_read_u8(mb); hdr->tid = v>>6 & 0x3; hdr->y = v>>5 & 0x1; hdr->keyidx = v & 0x1f; } return 0; } static inline bool is_keyframe(struct mbuf *mb) { if (mbuf_get_left(mb) < 1) return false; if (mb->buf[mb->pos] & 0x01) return false; return true; } static inline int16_t seq_diff(uint16_t x, uint16_t y) { return (int16_t)(y - x); } int vp8_decode(struct viddec_state *vds, struct vidframe *frame, bool *intra, bool marker, uint16_t seq, struct mbuf *mb) { vpx_codec_iter_t iter = NULL; vpx_codec_err_t res; vpx_image_t *img; struct hdr hdr; int err, i; if (!vds || !frame || !intra || !mb) return EINVAL; *intra = false; err = hdr_decode(&hdr, mb); if (err) return err; #if 0 debug("vp8: header: x=%u noref=%u start=%u partid=%u " "i=%u l=%u t=%u k=%u " "picid=%u tl0picidx=%u tid=%u y=%u keyidx=%u\n", hdr.x, hdr.noref, hdr.start, hdr.partid, hdr.i, hdr.l, hdr.t, hdr.k, hdr.picid, hdr.tl0picidx, hdr.tid, hdr.y, hdr.keyidx); #endif if (hdr.start && hdr.partid == 0) { if (is_keyframe(mb)) *intra = true; mbuf_rewind(vds->mb); vds->started = true; } else { if (!vds->started) return 0; if (seq_diff(vds->seq, seq) != 1) { mbuf_rewind(vds->mb); vds->started = false; return 0; } } vds->seq = seq; err = mbuf_write_mem(vds->mb, mbuf_buf(mb), mbuf_get_left(mb)); if (err) goto out; if (!marker) { if (vds->mb->end > DECODE_MAXSZ) { warning("vp8: decode buffer size exceeded\n"); err = ENOMEM; goto out; } return 0; } res = vpx_codec_decode(&vds->ctx, vds->mb->buf, (unsigned int)vds->mb->end, NULL, 1); if (res) { debug("vp8: decode error: %s\n", vpx_codec_err_to_string(res)); err = EPROTO; goto out; } img = vpx_codec_get_frame(&vds->ctx, &iter); if (!img) { debug("vp8: no picture\n"); goto out; } if (img->fmt != VPX_IMG_FMT_I420) { warning("vp8: bad pixel format (%i)\n", img->fmt); goto out; } for (i=0; i<4; i++) { frame->data[i] = img->planes[i]; frame->linesize[i] = img->stride[i]; } frame->size.w = img->d_w; frame->size.h = img->d_h; frame->fmt = VID_FMT_YUV420P; out: mbuf_rewind(vds->mb); vds->started = false; return err; } baresip-1.0.0/modules/vp8/encode.c000066400000000000000000000126151372575704200167440ustar00rootroot00000000000000/** * @file vp8/encode.c VP8 Encode * * Copyright (C) 2010 Creytiv.com */ #include #include #include #include #include #include #include "vp8.h" enum { HDR_SIZE = 4, }; struct videnc_state { vpx_codec_ctx_t ctx; struct vidsz size; unsigned fps; unsigned bitrate; unsigned pktsize; bool ctxup; uint16_t picid; videnc_packet_h *pkth; void *arg; }; static void destructor(void *arg) { struct videnc_state *ves = arg; if (ves->ctxup) vpx_codec_destroy(&ves->ctx); } int vp8_encode_update(struct videnc_state **vesp, const struct vidcodec *vc, struct videnc_param *prm, const char *fmtp, videnc_packet_h *pkth, void *arg) { const struct vp8_vidcodec *vp8 = (struct vp8_vidcodec *)vc; struct videnc_state *ves; uint32_t max_fs; (void)vp8; if (!vesp || !vc || !prm || prm->pktsize < (HDR_SIZE + 1)) return EINVAL; ves = *vesp; if (!ves) { ves = mem_zalloc(sizeof(*ves), destructor); if (!ves) return ENOMEM; ves->picid = rand_u16(); *vesp = ves; } else { if (ves->ctxup && (ves->bitrate != prm->bitrate || ves->fps != prm->fps)) { vpx_codec_destroy(&ves->ctx); ves->ctxup = false; } } ves->bitrate = prm->bitrate; ves->pktsize = prm->pktsize; ves->fps = prm->fps; ves->pkth = pkth; ves->arg = arg; max_fs = vp8_max_fs(fmtp); if (max_fs > 0) prm->max_fs = max_fs * 256; return 0; } static int open_encoder(struct videnc_state *ves, const struct vidsz *size) { vpx_codec_enc_cfg_t cfg; vpx_codec_err_t res; vpx_codec_flags_t flags = 0; res = vpx_codec_enc_config_default(&vpx_codec_vp8_cx_algo, &cfg, 0); if (res) return EPROTO; cfg.g_profile = 2; cfg.g_w = size->w; cfg.g_h = size->h; cfg.g_timebase.num = 1; cfg.g_timebase.den = ves->fps; #ifdef VPX_ERROR_RESILIENT_DEFAULT cfg.g_error_resilient = VPX_ERROR_RESILIENT_DEFAULT; #endif cfg.g_pass = VPX_RC_ONE_PASS; cfg.g_lag_in_frames = 0; cfg.rc_end_usage = VPX_VBR; cfg.rc_target_bitrate = ves->bitrate; cfg.kf_mode = VPX_KF_AUTO; if (ves->ctxup) { debug("vp8: re-opening encoder\n"); vpx_codec_destroy(&ves->ctx); ves->ctxup = false; } #ifdef VPX_CODEC_USE_OUTPUT_PARTITION flags |= VPX_CODEC_USE_OUTPUT_PARTITION; #endif res = vpx_codec_enc_init(&ves->ctx, &vpx_codec_vp8_cx_algo, &cfg, flags); if (res) { warning("vp8: enc init: %s\n", vpx_codec_err_to_string(res)); return EPROTO; } ves->ctxup = true; res = vpx_codec_control(&ves->ctx, VP8E_SET_CPUUSED, 16); if (res) { warning("vp8: codec ctrl: %s\n", vpx_codec_err_to_string(res)); } res = vpx_codec_control(&ves->ctx, VP8E_SET_NOISE_SENSITIVITY, 0); if (res) { warning("vp8: codec ctrl: %s\n", vpx_codec_err_to_string(res)); } return 0; } static inline void hdr_encode(uint8_t hdr[HDR_SIZE], bool noref, bool start, uint8_t partid, uint16_t picid) { hdr[0] = 1<<7 | noref<<5 | start<<4 | (partid & 0x7); hdr[1] = 1<<7; hdr[2] = 1<<7 | (picid>>8 & 0x7f); hdr[3] = picid & 0xff; } static inline int packetize(bool marker, const uint8_t *buf, size_t len, size_t maxlen, bool noref, uint8_t partid, uint16_t picid, uint64_t rtp_ts, videnc_packet_h *pkth, void *arg) { uint8_t hdr[HDR_SIZE]; bool start = true; int err = 0; maxlen -= sizeof(hdr); while (len > maxlen) { hdr_encode(hdr, noref, start, partid, picid); err |= pkth(false, rtp_ts, hdr, sizeof(hdr), buf, maxlen, arg); buf += maxlen; len -= maxlen; start = false; } hdr_encode(hdr, noref, start, partid, picid); err |= pkth(marker, rtp_ts, hdr, sizeof(hdr), buf, len, arg); return err; } int vp8_encode(struct videnc_state *ves, bool update, const struct vidframe *frame, uint64_t timestamp) { vpx_enc_frame_flags_t flags = 0; vpx_codec_iter_t iter = NULL; vpx_codec_err_t res; vpx_image_t img; int err, i; if (!ves || !frame || frame->fmt != VID_FMT_YUV420P) return EINVAL; if (!ves->ctxup || !vidsz_cmp(&ves->size, &frame->size)) { err = open_encoder(ves, &frame->size); if (err) return err; ves->size = frame->size; } if (update) { /* debug("vp8: picture update\n"); */ flags |= VPX_EFLAG_FORCE_KF; } memset(&img, 0, sizeof(img)); img.fmt = VPX_IMG_FMT_I420; img.w = img.d_w = frame->size.w; img.h = img.d_h = frame->size.h; for (i=0; i<4; i++) { img.stride[i] = frame->linesize[i]; img.planes[i] = frame->data[i]; } res = vpx_codec_encode(&ves->ctx, &img, timestamp, 1, flags, VPX_DL_REALTIME); if (res) { warning("vp8: enc error: %s\n", vpx_codec_err_to_string(res)); return ENOMEM; } ++ves->picid; for (;;) { bool keyframe = false, marker = true; const vpx_codec_cx_pkt_t *pkt; uint8_t partid = 0; uint64_t ts; pkt = vpx_codec_get_cx_data(&ves->ctx, &iter); if (!pkt) break; if (pkt->kind != VPX_CODEC_CX_FRAME_PKT) continue; if (pkt->data.frame.flags & VPX_FRAME_IS_KEY) keyframe = true; #ifdef VPX_FRAME_IS_FRAGMENT if (pkt->data.frame.flags & VPX_FRAME_IS_FRAGMENT) marker = false; if (pkt->data.frame.partition_id >= 0) partid = pkt->data.frame.partition_id; #endif /* * convert PTS to RTP Timestamp */ ts = video_calc_rtp_timestamp_fix(pkt->data.frame.pts); err = packetize(marker, pkt->data.frame.buf, pkt->data.frame.sz, ves->pktsize, !keyframe, partid, ves->picid, ts, ves->pkth, ves->arg); if (err) return err; } return 0; } baresip-1.0.0/modules/vp8/module.mk000066400000000000000000000003041372575704200171510ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # MOD := vp8 $(MOD)_SRCS += decode.c $(MOD)_SRCS += encode.c $(MOD)_SRCS += vp8.c $(MOD)_SRCS += sdp.c $(MOD)_LFLAGS += -lvpx include mk/mod.mk baresip-1.0.0/modules/vp8/sdp.c000066400000000000000000000011561372575704200162730ustar00rootroot00000000000000/** * @file vp8/sdp.c VP8 SDP Functions * * Copyright (C) 2010 Creytiv.com */ #include #include #include "vp8.h" uint32_t vp8_max_fs(const char *fmtp) { struct pl pl, max_fs; if (!fmtp) return 0; pl_set_str(&pl, fmtp); if (fmt_param_get(&pl, "max-fs", &max_fs)) return pl_u32(&max_fs); return 0; } int vp8_fmtp_enc(struct mbuf *mb, const struct sdp_format *fmt, bool offer, void *arg) { const struct vp8_vidcodec *vp8 = arg; (void)offer; if (!mb || !fmt || !vp8 || !vp8->max_fs) return 0; return mbuf_printf(mb, "a=fmtp:%s max-fs=%u\r\n", fmt->id, vp8->max_fs); } baresip-1.0.0/modules/vp8/vp8.c000066400000000000000000000017041372575704200162210ustar00rootroot00000000000000/** * @file vp8.c VP8 Video Codec * * Copyright (C) 2010 Creytiv.com */ #include #include #include #include "vp8.h" /** * @defgroup vp8 vp8 * * The VP8 video codec * * This module implements the VP8 video codec that is compatible * with the WebRTC standard. * * References: * * http://www.webmproject.org/ * * https://tools.ietf.org/html/rfc7741 */ static struct vp8_vidcodec vp8 = { .vc = { .name = "VP8", .encupdh = vp8_encode_update, .ench = vp8_encode, .decupdh = vp8_decode_update, .dech = vp8_decode, .fmtp_ench = vp8_fmtp_enc, }, .max_fs = 3600, }; static int module_init(void) { vidcodec_register(baresip_vidcodecl(), (struct vidcodec *)&vp8); return 0; } static int module_close(void) { vidcodec_unregister((struct vidcodec *)&vp8); return 0; } EXPORT_SYM const struct mod_export DECL_EXPORTS(vp8) = { "vp8", "codec", module_init, module_close }; baresip-1.0.0/modules/vp8/vp8.h000066400000000000000000000015101372575704200162210ustar00rootroot00000000000000/** * @file vp8.h Private VP8 Interface * * Copyright (C) 2010 Creytiv.com */ struct vp8_vidcodec { struct vidcodec vc; uint32_t max_fs; }; /* Encode */ int vp8_encode_update(struct videnc_state **vesp, const struct vidcodec *vc, struct videnc_param *prm, const char *fmtp, videnc_packet_h *pkth, void *arg); int vp8_encode(struct videnc_state *ves, bool update, const struct vidframe *frame, uint64_t timestamp); /* Decode */ int vp8_decode_update(struct viddec_state **vdsp, const struct vidcodec *vc, const char *fmtp); int vp8_decode(struct viddec_state *vds, struct vidframe *frame, bool *intra, bool marker, uint16_t seq, struct mbuf *mb); /* SDP */ uint32_t vp8_max_fs(const char *fmtp); int vp8_fmtp_enc(struct mbuf *mb, const struct sdp_format *fmt, bool offer, void *arg); baresip-1.0.0/modules/vp9/000077500000000000000000000000001372575704200153375ustar00rootroot00000000000000baresip-1.0.0/modules/vp9/decode.c000066400000000000000000000136111372575704200167300ustar00rootroot00000000000000/** * @file vp9/decode.c VP9 Decode * * Copyright (C) 2010 - 2016 Creytiv.com */ #include #include #include #include #include #include #include "vp9.h" enum { DECODE_MAXSZ = 524288, }; struct hdr { /* header: */ unsigned i:1; /* I: Picture ID (PID) present */ unsigned p:1; /* P: Inter-picture predicted layer frame */ unsigned l:1; /* L: Layer indices present */ unsigned f:1; /* F: Flexible mode */ unsigned b:1; /* B: Start of a layer frame */ unsigned e:1; /* E: End of a layer frame */ unsigned v:1; /* V: Scalability structure (SS) data present */ /* extension fields */ uint16_t picid; }; /* Scalability Structure (SS) */ struct ss { unsigned n_s:3; unsigned y:1; unsigned g:1; }; struct viddec_state { vpx_codec_ctx_t ctx; struct mbuf *mb; bool ctxup; bool started; uint16_t seq; unsigned n_frames; size_t n_bytes; }; static void destructor(void *arg) { struct viddec_state *vds = arg; if (vds->ctxup) { debug("vp9: decoder stats: frames=%u, bytes=%zu\n", vds->n_frames, vds->n_bytes); vpx_codec_destroy(&vds->ctx); } mem_deref(vds->mb); } int vp9_decode_update(struct viddec_state **vdsp, const struct vidcodec *vc, const char *fmtp) { struct viddec_state *vds; vpx_codec_err_t res; int err = 0; (void)vc; (void)fmtp; if (!vdsp) return EINVAL; vds = *vdsp; if (vds) return 0; vds = mem_zalloc(sizeof(*vds), destructor); if (!vds) return ENOMEM; vds->mb = mbuf_alloc(1024); if (!vds->mb) { err = ENOMEM; goto out; } res = vpx_codec_dec_init(&vds->ctx, &vpx_codec_vp9_dx_algo, NULL, 0); if (res) { err = ENOMEM; goto out; } vds->ctxup = true; out: if (err) mem_deref(vds); else *vdsp = vds; return err; } static int ss_decode(struct ss *ss, struct mbuf *mb) { uint8_t v; if (mbuf_get_left(mb) < 1) return EBADMSG; v = mbuf_read_u8(mb); ss->n_s = (v >> 5) & 0x7; ss->y = (v >> 4) & 0x1; ss->g = (v >> 3) & 0x1; info("vp9: decode: ss n_s=%u y=%u g=%u\n", ss->n_s, ss->y, ss->g); if (ss->n_s != 0) return ENOTSUP; if (ss->y) { uint16_t width, height; if (mbuf_get_left(mb) < 4) return EBADMSG; width = ntohs(mbuf_read_u16(mb)); height = ntohs(mbuf_read_u16(mb)); (void)width; (void)height; } if (ss->g) { uint8_t n_g, i, tidur, p_diff; if (mbuf_get_left(mb) < 1) return EBADMSG; n_g = mbuf_read_u8(mb); for (i=0; ii = v>>7 & 0x1; hdr->p = v>>6 & 0x1; hdr->l = v>>5 & 0x1; hdr->f = v>>4 & 0x1; hdr->b = v>>3 & 0x1; hdr->e = v>>2 & 0x1; hdr->v = v>>1 & 0x1; if (hdr->l) { warning("vp9: decode: L-bit not supported\n"); return EPROTO; } if (hdr->f) { warning("vp9: decode: F-bit not supported\n"); return EPROTO; } if (hdr->i) { if (mbuf_get_left(mb) < 1) return EBADMSG; v = mbuf_read_u8(mb); if (v>>7 & 0x1) { if (mbuf_get_left(mb) < 1) return EBADMSG; hdr->picid = (v & 0x7f)<<8; hdr->picid += mbuf_read_u8(mb); } else { hdr->picid = v & 0x7f; } } if (hdr->p) { uint8_t p_diff; if (mbuf_get_left(mb) < 1) return EBADMSG; p_diff = mbuf_read_u8(mb); (void)p_diff; } if (hdr->v) { struct ss ss; err = ss_decode(&ss, mb); if (err) return err; (void)ss; } return 0; } static inline bool is_keyframe(const struct mbuf *mb) { vpx_codec_stream_info_t si; vpx_codec_err_t ret; memset(&si, 0, sizeof(si)); si.sz = sizeof(si); ret = vpx_codec_peek_stream_info(&vpx_codec_vp9_dx_algo, mbuf_buf(mb), (unsigned int)mbuf_get_left(mb), &si); if (ret != VPX_CODEC_OK) return false; return si.is_kf; } static inline int16_t seq_diff(uint16_t x, uint16_t y) { return (int16_t)(y - x); } int vp9_decode(struct viddec_state *vds, struct vidframe *frame, bool *intra, bool marker, uint16_t seq, struct mbuf *mb) { vpx_codec_iter_t iter = NULL; vpx_codec_err_t res; vpx_image_t *img; struct hdr hdr; int err, i; if (!vds || !frame || !intra || !mb) return EINVAL; *intra = false; vds->n_bytes += mbuf_get_left(mb); err = hdr_decode(&hdr, mb); if (err) return err; #if 0 debug("vp9: [%c] header: i=%u start=%u end=%u picid=%u \n", marker ? 'M' : ' ', hdr.i, hdr.b, hdr.e, hdr.picid); #endif if (hdr.b) { if (is_keyframe(mb)) *intra = true; mbuf_rewind(vds->mb); vds->started = true; } else { if (!vds->started) return 0; if (seq_diff(vds->seq, seq) != 1) { mbuf_rewind(vds->mb); vds->started = false; return 0; } } vds->seq = seq; err = mbuf_write_mem(vds->mb, mbuf_buf(mb), mbuf_get_left(mb)); if (err) goto out; if (!marker) { if (vds->mb->end > DECODE_MAXSZ) { warning("vp9: decode buffer size exceeded\n"); err = ENOMEM; goto out; } return 0; } res = vpx_codec_decode(&vds->ctx, vds->mb->buf, (unsigned int)vds->mb->end, NULL, 1); if (res) { debug("vp9: decode error: %s\n", vpx_codec_err_to_string(res)); err = EPROTO; goto out; } img = vpx_codec_get_frame(&vds->ctx, &iter); if (!img) { debug("vp9: no picture\n"); goto out; } if (img->fmt != VPX_IMG_FMT_I420) { warning("vp9: bad pixel format (%i)\n", img->fmt); goto out; } for (i=0; i<4; i++) { frame->data[i] = img->planes[i]; frame->linesize[i] = img->stride[i]; } frame->size.w = img->d_w; frame->size.h = img->d_h; frame->fmt = VID_FMT_YUV420P; ++vds->n_frames; out: mbuf_rewind(vds->mb); vds->started = false; return err; } baresip-1.0.0/modules/vp9/encode.c000066400000000000000000000140651372575704200167460ustar00rootroot00000000000000/** * @file vp9/encode.c VP9 Encode * * Copyright (C) 2010 - 2016 Creytiv.com */ #include #include #include #include #include #include #include "vp9.h" enum { HDR_SIZE = 3, }; struct videnc_state { vpx_codec_ctx_t ctx; struct vidsz size; unsigned fps; unsigned bitrate; unsigned pktsize; bool ctxup; uint16_t picid; videnc_packet_h *pkth; void *arg; unsigned n_frames; unsigned n_key_frames; size_t n_bytes; }; static void destructor(void *arg) { struct videnc_state *ves = arg; if (ves->ctxup) { debug("vp9: encoder stats:" " frames=%u, key_frames=%u, bytes=%zu\n", ves->n_frames, ves->n_key_frames, ves->n_bytes); vpx_codec_destroy(&ves->ctx); } } int vp9_encode_update(struct videnc_state **vesp, const struct vidcodec *vc, struct videnc_param *prm, const char *fmtp, videnc_packet_h *pkth, void *arg) { const struct vp9_vidcodec *vp9 = (struct vp9_vidcodec *)vc; struct videnc_state *ves; uint32_t max_fs; (void)vp9; if (!vesp || !vc || !prm || prm->pktsize < (HDR_SIZE + 1)) return EINVAL; ves = *vesp; if (!ves) { ves = mem_zalloc(sizeof(*ves), destructor); if (!ves) return ENOMEM; ves->picid = rand_u16(); *vesp = ves; } else { if (ves->ctxup && (ves->bitrate != prm->bitrate || ves->fps != prm->fps)) { vpx_codec_destroy(&ves->ctx); ves->ctxup = false; } } ves->bitrate = prm->bitrate; ves->pktsize = prm->pktsize; ves->fps = prm->fps; ves->pkth = pkth; ves->arg = arg; max_fs = vp9_max_fs(fmtp); if (max_fs > 0) prm->max_fs = max_fs * 256; return 0; } static int open_encoder(struct videnc_state *ves, const struct vidsz *size) { vpx_codec_enc_cfg_t cfg; vpx_codec_err_t res; res = vpx_codec_enc_config_default(&vpx_codec_vp9_cx_algo, &cfg, 0); if (res) return EPROTO; /* Profile 0 = 8 bit yuv420p Profile 1 = 8 bit yuv422/440/444p Profile 2 = 10/12 bit yuv420p Profile 3 = 10/12 bit yuv422/440/444p */ cfg.g_profile = 0; cfg.g_w = size->w; cfg.g_h = size->h; cfg.g_timebase.num = 1; cfg.g_timebase.den = ves->fps; cfg.rc_target_bitrate = ves->bitrate / 1000; cfg.g_error_resilient = VPX_ERROR_RESILIENT_DEFAULT; cfg.g_pass = VPX_RC_ONE_PASS; cfg.g_lag_in_frames = 0; cfg.rc_end_usage = VPX_VBR; cfg.kf_mode = VPX_KF_AUTO; if (ves->ctxup) { debug("vp9: re-opening encoder\n"); vpx_codec_destroy(&ves->ctx); ves->ctxup = false; } res = vpx_codec_enc_init(&ves->ctx, &vpx_codec_vp9_cx_algo, &cfg, 0); if (res) { warning("vp9: enc init: %s\n", vpx_codec_err_to_string(res)); return EPROTO; } ves->ctxup = true; res = vpx_codec_control(&ves->ctx, VP8E_SET_CPUUSED, 8); if (res) { warning("vp9: codec ctrl: %s\n", vpx_codec_err_to_string(res)); } #ifdef VP9E_SET_NOISE_SENSITIVITY res = vpx_codec_control(&ves->ctx, VP9E_SET_NOISE_SENSITIVITY, 0); if (res) { warning("vp9: codec ctrl: %s\n", vpx_codec_err_to_string(res)); } #endif info("vp9: encoder opened, picture size %u x %u\n", size->w, size->h); return 0; } static inline void hdr_encode(uint8_t hdr[HDR_SIZE], bool start, bool end, uint16_t picid) { hdr[0] = 1<<7 | start<<3 | end<<2; hdr[1] = 1<<7 | (picid>>8 & 0x7f); hdr[2] = picid & 0xff; } static int send_packet(struct videnc_state *ves, bool marker, const uint8_t *hdr, size_t hdr_len, const uint8_t *pld, size_t pld_len, uint64_t rtp_ts) { ves->n_bytes += (hdr_len + pld_len); return ves->pkth(marker, rtp_ts, hdr, hdr_len, pld, pld_len, ves->arg); } static inline int packetize(struct videnc_state *ves, bool marker, const uint8_t *buf, size_t len, size_t maxlen, uint16_t picid, uint64_t rtp_ts) { uint8_t hdr[HDR_SIZE]; bool start = true; int err = 0; maxlen -= sizeof(hdr); while (len > maxlen) { hdr_encode(hdr, start, false, picid); err |= send_packet(ves, false, hdr, sizeof(hdr), buf, maxlen, rtp_ts); buf += maxlen; len -= maxlen; start = false; } hdr_encode(hdr, start, true, picid); err |= send_packet(ves, marker, hdr, sizeof(hdr), buf, len, rtp_ts); return err; } int vp9_encode(struct videnc_state *ves, bool update, const struct vidframe *frame, uint64_t timestamp) { vpx_enc_frame_flags_t flags = 0; vpx_codec_iter_t iter = NULL; vpx_codec_err_t res; vpx_image_t *img = NULL; vpx_img_fmt_t img_fmt; int err, i; if (!ves || !frame) return EINVAL; switch (frame->fmt) { case VID_FMT_YUV420P: img_fmt = VPX_IMG_FMT_I420; break; default: warning("vp9: pixel format not supported (%s)\n", vidfmt_name(frame->fmt)); return EINVAL; } if (!ves->ctxup || !vidsz_cmp(&ves->size, &frame->size)) { err = open_encoder(ves, &frame->size); if (err) return err; ves->size = frame->size; } ++ves->n_frames; if (update) { /* debug("vp9: picture update\n"); */ flags |= VPX_EFLAG_FORCE_KF; } img = vpx_img_wrap(NULL, img_fmt, frame->size.w, frame->size.h, 16, NULL); if (!img) { warning("vp9: encoder: could not allocate image\n"); err = ENOMEM; goto out; } for (i=0; i<4; i++) { img->stride[i] = frame->linesize[i]; img->planes[i] = frame->data[i]; } res = vpx_codec_encode(&ves->ctx, img, timestamp, 1, flags, VPX_DL_REALTIME); if (res) { warning("vp9: enc error: %s\n", vpx_codec_err_to_string(res)); err = ENOMEM; goto out; } ++ves->picid; for (;;) { bool marker = true; const vpx_codec_cx_pkt_t *pkt; uint64_t ts; pkt = vpx_codec_get_cx_data(&ves->ctx, &iter); if (!pkt) break; if (pkt->kind != VPX_CODEC_CX_FRAME_PKT) { continue; } if (pkt->data.frame.flags & VPX_FRAME_IS_KEY) { ++ves->n_key_frames; } if (pkt->data.frame.flags & VPX_FRAME_IS_FRAGMENT) marker = false; ts = video_calc_rtp_timestamp_fix(pkt->data.frame.pts); err = packetize(ves, marker, pkt->data.frame.buf, pkt->data.frame.sz, ves->pktsize, ves->picid, ts); if (err) return err; } out: if (img) vpx_img_free(img); return err; } baresip-1.0.0/modules/vp9/module.mk000066400000000000000000000003041372575704200171520ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # MOD := vp9 $(MOD)_SRCS += decode.c $(MOD)_SRCS += encode.c $(MOD)_SRCS += vp9.c $(MOD)_SRCS += sdp.c $(MOD)_LFLAGS += -lvpx include mk/mod.mk baresip-1.0.0/modules/vp9/sdp.c000066400000000000000000000011651372575704200162740ustar00rootroot00000000000000/** * @file vp9/sdp.c VP9 SDP Functions * * Copyright (C) 2010 - 2016 Creytiv.com */ #include #include #include "vp9.h" uint32_t vp9_max_fs(const char *fmtp) { struct pl pl, max_fs; if (!fmtp) return 0; pl_set_str(&pl, fmtp); if (fmt_param_get(&pl, "max-fs", &max_fs)) return pl_u32(&max_fs); return 0; } int vp9_fmtp_enc(struct mbuf *mb, const struct sdp_format *fmt, bool offer, void *arg) { const struct vp9_vidcodec *vp9 = arg; (void)offer; if (!mb || !fmt || !vp9 || !vp9->max_fs) return 0; return mbuf_printf(mb, "a=fmtp:%s max-fs=%u\r\n", fmt->id, vp9->max_fs); } baresip-1.0.0/modules/vp9/vp9.c000066400000000000000000000020051372575704200162160ustar00rootroot00000000000000/** * @file vp9.c VP9 video codec * * Copyright (C) 2010 - 2016 Creytiv.com */ #include #include #include #include #include "vp9.h" /** * @defgroup vp9 vp9 * * The VP9 video codec * * This module implements the VP9 video codec that is compatible * with the WebRTC standard. * * Libvpx version 1.3.0 or later is required. * * * References: * * http://www.webmproject.org/ * * draft-ietf-payload-vp9-07 */ static struct vp9_vidcodec vp9 = { .vc = { .name = "VP9", .encupdh = vp9_encode_update, .ench = vp9_encode, .decupdh = vp9_decode_update, .dech = vp9_decode, .fmtp_ench = vp9_fmtp_enc, }, .max_fs = 3600 }; static int module_init(void) { vidcodec_register(baresip_vidcodecl(), (struct vidcodec *)&vp9); return 0; } static int module_close(void) { vidcodec_unregister((struct vidcodec *)&vp9); return 0; } EXPORT_SYM const struct mod_export DECL_EXPORTS(vp9) = { "vp9", "codec", module_init, module_close }; baresip-1.0.0/modules/vp9/vp9.h000066400000000000000000000015171372575704200162320ustar00rootroot00000000000000/** * @file vp9.h Private VP9 Interface * * Copyright (C) 2010 - 2016 Creytiv.com */ struct vp9_vidcodec { struct vidcodec vc; uint32_t max_fs; }; /* Encode */ int vp9_encode_update(struct videnc_state **vesp, const struct vidcodec *vc, struct videnc_param *prm, const char *fmtp, videnc_packet_h *pkth, void *arg); int vp9_encode(struct videnc_state *ves, bool update, const struct vidframe *frame, uint64_t timestamp); /* Decode */ int vp9_decode_update(struct viddec_state **vdsp, const struct vidcodec *vc, const char *fmtp); int vp9_decode(struct viddec_state *vds, struct vidframe *frame, bool *intra, bool marker, uint16_t seq, struct mbuf *mb); /* SDP */ uint32_t vp9_max_fs(const char *fmtp); int vp9_fmtp_enc(struct mbuf *mb, const struct sdp_format *fmt, bool offer, void *arg); baresip-1.0.0/modules/vumeter/000077500000000000000000000000001372575704200163105ustar00rootroot00000000000000baresip-1.0.0/modules/vumeter/module.mk000066400000000000000000000002011372575704200201170ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # MOD := vumeter $(MOD)_SRCS += vumeter.c $(MOD)_LFLAGS += include mk/mod.mk baresip-1.0.0/modules/vumeter/vumeter.c000066400000000000000000000102651372575704200201470ustar00rootroot00000000000000/** * @file vumeter.c VU-meter * * Copyright (C) 2010 Creytiv.com */ #include #include #include #include #include /** * @defgroup vumeter vumeter * * Simple ASCII VU-meter for the audio-signal. * * The Volume unit (VU) meter module takes the audio-signal as input * and prints a simple ASCII-art bar for the recording and playback levels. * It is using the aufilt API to get the audio samples. */ struct vumeter_enc { struct aufilt_enc_st af; /* inheritance */ struct tmr tmr; const struct audio *au; double avg_rec; volatile bool started; enum aufmt fmt; }; struct vumeter_dec { struct aufilt_dec_st af; /* inheritance */ struct tmr tmr; const struct audio *au; double avg_play; volatile bool started; enum aufmt fmt; }; static bool vumeter_stderr; static void send_event(const struct audio *au, enum ua_event ev, double value) { audio_level_put(au, ev == UA_EVENT_VU_TX, value); } static void enc_destructor(void *arg) { struct vumeter_enc *st = arg; list_unlink(&st->af.le); tmr_cancel(&st->tmr); } static void dec_destructor(void *arg) { struct vumeter_dec *st = arg; list_unlink(&st->af.le); tmr_cancel(&st->tmr); } static int audio_print_vu(struct re_printf *pf, double *level) { char buf[16]; size_t res; double x; x = (*level + -AULEVEL_MIN) / -AULEVEL_MIN; res = min((size_t)(sizeof(buf) * x), sizeof(buf)-1); memset(buf, '=', res); buf[res] = '\0'; return re_hprintf(pf, "[%-16s]", buf); } static void print_vumeter(int pos, int color, double value) { /* move cursor to a fixed position */ re_fprintf(stderr, "\x1b[%dG", pos); /* print VU-meter in Nice colors */ re_fprintf(stderr, " \x1b[%dm%H\x1b[;m\r", color, audio_print_vu, &value); } static void enc_tmr_handler(void *arg) { struct vumeter_enc *st = arg; tmr_start(&st->tmr, 500, enc_tmr_handler, st); if (st->started) { if (vumeter_stderr) print_vumeter(60, 31, st->avg_rec); send_event(st->au, UA_EVENT_VU_TX, st->avg_rec); } } static void dec_tmr_handler(void *arg) { struct vumeter_dec *st = arg; tmr_start(&st->tmr, 500, dec_tmr_handler, st); if (st->started) { if (vumeter_stderr) print_vumeter(80, 32, st->avg_play); send_event(st->au, UA_EVENT_VU_RX, st->avg_play); } } static int encode_update(struct aufilt_enc_st **stp, void **ctx, const struct aufilt *af, struct aufilt_prm *prm, const struct audio *au) { struct vumeter_enc *st; (void)ctx; (void)prm; if (!stp || !af || !prm) return EINVAL; if (*stp) return 0; st = mem_zalloc(sizeof(*st), enc_destructor); if (!st) return ENOMEM; st->au = au; st->fmt = prm->fmt; tmr_start(&st->tmr, 100, enc_tmr_handler, st); *stp = (struct aufilt_enc_st *)st; return 0; } static int decode_update(struct aufilt_dec_st **stp, void **ctx, const struct aufilt *af, struct aufilt_prm *prm, const struct audio *au) { struct vumeter_dec *st; (void)ctx; (void)prm; if (!stp || !af || !prm) return EINVAL; if (*stp) return 0; st = mem_zalloc(sizeof(*st), dec_destructor); if (!st) return ENOMEM; st->au = au; st->fmt = prm->fmt; tmr_start(&st->tmr, 100, dec_tmr_handler, st); *stp = (struct aufilt_dec_st *)st; return 0; } static int encode(struct aufilt_enc_st *st, struct auframe *af) { struct vumeter_enc *vu = (void *)st; if (!st || !af) return EINVAL; vu->avg_rec = aulevel_calc_dbov(vu->fmt, af->sampv, af->sampc); vu->started = true; return 0; } static int decode(struct aufilt_dec_st *st, struct auframe *af) { struct vumeter_dec *vu = (void *)st; if (!st || !af) return EINVAL; vu->avg_play = aulevel_calc_dbov(vu->fmt, af->sampv, af->sampc); vu->started = true; return 0; } static struct aufilt vumeter = { .name = "vumeter", .encupdh = encode_update, .ench = encode, .decupdh = decode_update, .dech = decode }; static int module_init(void) { struct conf *conf = conf_cur(); conf_get_bool(conf, "vumeter_stderr", &vumeter_stderr); aufilt_register(baresip_aufiltl(), &vumeter); return 0; } static int module_close(void) { aufilt_unregister(&vumeter); return 0; } EXPORT_SYM const struct mod_export DECL_EXPORTS(vumeter) = { "vumeter", "filter", module_init, module_close }; baresip-1.0.0/modules/webrtc_aec/000077500000000000000000000000001372575704200167175ustar00rootroot00000000000000baresip-1.0.0/modules/webrtc_aec/aec.cpp000066400000000000000000000067301372575704200201610ustar00rootroot00000000000000/** * @file aec.cpp WebRTC Acoustic Echo Cancellation (AEC) * * Copyright (C) 2010 Creytiv.com */ #include #include #include #ifdef HAVE_PTHREAD #include #endif #include "modules/audio_processing/aec/echo_cancellation.h" #include "aec.h" /** * @defgroup webrtc_aec webrtc_aec * * Acoustic Echo Cancellation (AEC) using WebRTC SDK. * * Configuration options: * \verbatim webrtc_aec_extended_filter {yes,no} # Enable extended_filter \endverbatim * * This code is experimental. * * Reference: * * https://webrtc.org/native-code/ */ using namespace webrtc; static void aec_destructor(void *arg) { struct aec *st = (struct aec *)arg; if (st->inst) WebRtcAec_Free(st->inst); } int webrtc_aec_alloc(struct aec **stp, void **ctx, struct aufilt_prm *prm) { struct conf *conf = conf_cur(); bool extended_filter = false; struct aec *aec; int err = 0; int r; if (!stp || !ctx || !prm) return EINVAL; if (prm->ch > MAX_CHANNELS) { warning("webrtc_aec: unsupported channels (%u > %u)\n", prm->ch, MAX_CHANNELS); return ENOTSUP; } if (*ctx) { aec = (struct aec *)*ctx; if (prm->srate != aec->srate) { warning("webrtc_aec: srate mismatch\n"); return ENOTSUP; } *stp = (struct aec *)mem_ref(*ctx); return 0; } aec = (struct aec *)mem_zalloc(sizeof(*aec), aec_destructor); if (!aec) return ENOMEM; aec->srate = prm->srate; pthread_mutex_init(&aec->mutex, NULL); if (prm->srate > 8000) aec->subframe_len = 160; else aec->subframe_len = 80; if (prm->srate > 16000) aec->num_bands = prm->srate / 16000; else aec->num_bands = 1; info("webrtc_aec: creating shared state:" " [%u Hz, %u channels, subframe %u samples, num_bands %d]\n", prm->srate, prm->ch, aec->subframe_len, aec->num_bands); aec->inst = WebRtcAec_Create(); if (!aec->inst) { err = ENODEV; goto out; } r = WebRtcAec_Init(aec->inst, prm->srate, prm->srate); if (r != 0) { err = ENODEV; goto out; } WebRtcAec_enable_delay_agnostic(WebRtcAec_aec_core(aec->inst), 1); conf_get_bool(conf, "webrtc_aec_extended_filter", &extended_filter); if (extended_filter) { info("webrtc_aec: enabling extended_filter\n"); WebRtcAec_enable_extended_filter(WebRtcAec_aec_core(aec->inst), 1); } aec->config.nlpMode = kAecNlpModerate; aec->config.skewMode = kAecFalse; aec->config.metricsMode = kAecFalse; aec->config.delay_logging = kAecFalse; /* Sets local configuration modes. */ r = WebRtcAec_set_config(aec->inst, aec->config); if (r != 0) { err = ENODEV; goto out; } out: if (err) mem_deref(aec); else { *stp = aec; *ctx = aec; } return err; } void webrtc_aec_debug(const struct aec *aec) { int median, std; float frac_delay; if (!aec) return; if (WebRtcAec_GetDelayMetrics(aec->inst, &median, &std, &frac_delay) == 0) { info("webrtc_aec: delay metrics: median=%d, std=%d, " "fraction of poor delays=%f\n", median, std, frac_delay); } } static struct aufilt webrtc_aec = { .name = "webrtc_aec", .encupdh = webrtc_aec_encode_update, .ench = webrtc_aec_encode, .decupdh = webrtc_aec_decode_update, .dech = webrtc_aec_decode }; static int module_init(void) { aufilt_register(baresip_aufiltl(), &webrtc_aec); return 0; } static int module_close(void) { aufilt_unregister(&webrtc_aec); return 0; } extern "C" const struct mod_export DECL_EXPORTS(webrtc_aec) = { "webrtc_aec", "aufilt", module_init, module_close }; baresip-1.0.0/modules/webrtc_aec/aec.h000066400000000000000000000017731372575704200176300ustar00rootroot00000000000000/** * @file aec.h WebRTC Acoustic Echo Cancellation (AEC) -- internal API * * Copyright (C) 2010 Creytiv.com */ #include #include "modules/audio_processing/aec/echo_cancellation.h" #define MAX_CHANNELS 1 using namespace webrtc; struct aec { AecConfig config; void *inst; pthread_mutex_t mutex; uint32_t srate; uint32_t subframe_len; int num_bands; }; /* Encoder */ int webrtc_aec_encode_update(struct aufilt_enc_st **stp, void **ctx, const struct aufilt *af, struct aufilt_prm *prm, const struct audio *au); int webrtc_aec_encode(struct aufilt_enc_st *st, struct auframe *af); /* Decoder */ int webrtc_aec_decode_update(struct aufilt_dec_st **stp, void **ctx, const struct aufilt *af, struct aufilt_prm *prm, const struct audio *au); int webrtc_aec_decode(struct aufilt_dec_st *st, struct auframe *af); /* Common */ int webrtc_aec_alloc(struct aec **stp, void **ctx, struct aufilt_prm *prm); void webrtc_aec_debug(const struct aec *aec); baresip-1.0.0/modules/webrtc_aec/decode.cpp000066400000000000000000000045541372575704200206560ustar00rootroot00000000000000/** * @file decode.cpp WebRTC Acoustic Echo Cancellation (AEC) -- Decode * * Copyright (C) 2010 Creytiv.com */ #include #include #include #ifdef HAVE_PTHREAD #include #endif #include "aec.h" struct aec_dec { struct aufilt_dec_st af; /* inheritance */ struct aec *aec; enum aufmt fmt; }; static void dec_destructor(void *arg) { struct aec_dec *st = (struct aec_dec *)arg; list_unlink(&st->af.le); mem_deref(st->aec); } int webrtc_aec_decode_update(struct aufilt_dec_st **stp, void **ctx, const struct aufilt *af, struct aufilt_prm *prm, const struct audio *au) { struct aec_dec *st; int err; if (!stp || !af || !prm) return EINVAL; switch (prm->fmt) { case AUFMT_S16LE: case AUFMT_FLOAT: break; default: warning("webrtc_aec: dec: unsupported sample format (%s)\n", aufmt_name((enum aufmt)prm->fmt)); return ENOTSUP; } if (*stp) return 0; st = (struct aec_dec *)mem_zalloc(sizeof(*st), dec_destructor); if (!st) return ENOMEM; st->fmt = (enum aufmt)prm->fmt; err = webrtc_aec_alloc(&st->aec, ctx, prm); if (err) goto out; out: if (err) mem_deref(st); else *stp = (struct aufilt_dec_st *)st; return err; } static int decode_float(struct aec_dec *dec, const float *sampv, size_t sampc) { struct aec *aec = dec->aec; const float *farend = (const float *)sampv; size_t i; int r; int err = 0; pthread_mutex_lock(&aec->mutex); for (i = 0; i < sampc; i += aec->subframe_len) { r = WebRtcAec_BufferFarend(aec->inst, farend + i, aec->subframe_len); if (r != 0) { warning("webrtc_aec: decode: WebRtcAec_BufferFarend" " error (%d)\n", r); err = EPROTO; goto out; } } out: pthread_mutex_unlock(&aec->mutex); return err; } int webrtc_aec_decode(struct aufilt_dec_st *st, struct auframe *af) { struct aec_dec *dec = (struct aec_dec *)st; float *flt; int err = 0; if (!st || !af) return EINVAL; /* convert samples to float if needed */ switch (dec->fmt) { case AUFMT_S16LE: flt = (float *)mem_alloc(af->sampc * sizeof(float), NULL); if (!flt) return ENOMEM; auconv_from_s16(AUFMT_FLOAT, flt, (int16_t *)af->sampv, af->sampc); err = decode_float(dec, flt, af->sampc); mem_deref(flt); break; case AUFMT_FLOAT: err = decode_float(dec, (float *)af->sampv, af->sampc); break; default: return ENOTSUP; } return err; } baresip-1.0.0/modules/webrtc_aec/encode.cpp000066400000000000000000000053531372575704200206660ustar00rootroot00000000000000/** * @file encode.cpp WebRTC Acoustic Echo Cancellation (AEC) -- Encode * * Copyright (C) 2010 Creytiv.com */ #include #include #include #include #ifdef HAVE_PTHREAD #include #endif #include "aec.h" #define SOUND_CARD_BUF 20 struct aec_enc { struct aufilt_enc_st af; /* inheritance */ struct aec *aec; float buf[160]; enum aufmt fmt; }; static void enc_destructor(void *arg) { struct aec_enc *st = (struct aec_enc *)arg; list_unlink(&st->af.le); mem_deref(st->aec); } int webrtc_aec_encode_update(struct aufilt_enc_st **stp, void **ctx, const struct aufilt *af, struct aufilt_prm *prm, const struct audio *au) { struct aec_enc *st; int err; if (!stp || !af || !prm) return EINVAL; switch (prm->fmt) { case AUFMT_S16LE: case AUFMT_FLOAT: break; default: warning("webrtc_aec: enc: unsupported sample format (%s)\n", aufmt_name((enum aufmt)prm->fmt)); return ENOTSUP; } if (*stp) return 0; st = (struct aec_enc *)mem_zalloc(sizeof(*st), enc_destructor); if (!st) return ENOMEM; st->fmt = (enum aufmt)prm->fmt; err = webrtc_aec_alloc(&st->aec, ctx, prm); if (err) goto out; out: if (err) mem_deref(st); else *stp = (struct aufilt_enc_st *)st; return err; } static int encode_float(struct aec_enc *enc, float *sampv, size_t sampc) { struct aec *aec = enc->aec; const float *nearend = (const float *)sampv; const float *in; float *out; float *rec = (float *)sampv; size_t i; int r; int err = 0; pthread_mutex_lock(&aec->mutex); for (i = 0; i < sampc; i += aec->subframe_len) { in = &nearend[i]; out = enc->buf; r = WebRtcAec_Process(aec->inst, &in, aec->num_bands, &out, aec->subframe_len, SOUND_CARD_BUF, 0); if (r != 0) { warning("webrtc_aec: encode:" " WebRtcAec_Process error (%d)\n", r); err = EPROTO; goto out; } memcpy(&rec[i], out, aec->subframe_len * sizeof(float)); } out: pthread_mutex_unlock(&aec->mutex); return err; } int webrtc_aec_encode(struct aufilt_enc_st *st, struct auframe *af) { struct aec_enc *enc = (struct aec_enc *)st; float *flt; int err = 0; if (!st || !af) return EINVAL; switch (enc->fmt) { case AUFMT_S16LE: /* convert from S16 to FLOAT */ flt = (float *)mem_alloc(af->sampc * sizeof(float), NULL); if (!flt) return ENOMEM; auconv_from_s16(AUFMT_FLOAT, flt, (int16_t *)af->sampv, af->sampc); /* process */ err = encode_float(enc, flt, af->sampc); /* convert from FLOAT to S16 */ auconv_to_s16((int16_t *)af->sampv, AUFMT_FLOAT, flt, af->sampc); mem_deref(flt); break; case AUFMT_FLOAT: err = encode_float(enc, (float *)af->sampv, af->sampc); break; default: return ENOTSUP; } return err; } baresip-1.0.0/modules/webrtc_aec/module.mk000066400000000000000000000004701372575704200205360ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # WEBRTC_PATH := ../webrtc_sdk MOD := webrtc_aec $(MOD)_SRCS += aec.cpp $(MOD)_SRCS += encode.cpp $(MOD)_SRCS += decode.cpp CPPFLAGS += -isystem $(WEBRTC_PATH)/include LIBS += \ -L$(WEBRTC_PATH)/lib/Debug \ -lwebrtc_full \ -lstdc++ include mk/mod.mk baresip-1.0.0/modules/wincons/000077500000000000000000000000001372575704200163015ustar00rootroot00000000000000baresip-1.0.0/modules/wincons/module.mk000066400000000000000000000002011372575704200201100ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # MOD := wincons $(MOD)_SRCS += wincons.c $(MOD)_LFLAGS += include mk/mod.mk baresip-1.0.0/modules/wincons/wincons.c000066400000000000000000000064371372575704200201370ustar00rootroot00000000000000/** * @file wincons.c Windows console input * * Copyright (C) 2010 Creytiv.com */ #include #include #include /** * @defgroup wincons wincons * * User-Interface (UI) module for Windows Console */ /** Local constants */ enum { RELEASE_VAL = 250 /**< Key release value in [ms] */ }; struct ui_st { struct tmr tmr; struct mqueue *mq; HANDLE hThread; bool run; HANDLE hstdin; DWORD mode; }; static struct ui_st *wincons; static void destructor(void *arg) { struct ui_st *st = arg; /* Restore the console to its previous state */ if (st->mode) SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), st->mode); st->run = false; WaitForSingleObject(st->hThread, 5000); CloseHandle(st->hThread); tmr_cancel(&st->tmr); mem_deref(st->mq); } static int print_handler(const char *p, size_t size, void *arg) { (void)arg; return 1 == fwrite(p, size, 1, stderr) ? 0 : ENOMEM; } static void report_key(struct ui_st *ui, char key) { static struct re_printf pf_stderr = {print_handler, NULL}; (void)ui; ui_input_key(baresip_uis(), key, &pf_stderr); } static void timeout(void *arg) { struct ui_st *st = arg; /* Emulate key-release */ report_key(st, KEYCODE_REL); } static DWORD WINAPI input_thread(LPVOID arg) { struct ui_st *st = arg; /* Switch to raw mode */ SetConsoleMode(st->hstdin, 0); while (st->run) { INPUT_RECORD buf[4]; DWORD i, count = 0; ReadConsoleInput(st->hstdin, buf, ARRAY_SIZE(buf), &count); for (i=0; irun = false; /* * The keys are read from a thread so we have * to send them to the RE main event loop via * a message queue */ if (ch) mqueue_push(st->mq, ch, NULL); } } } return 0; } static void mqueue_handler(int id, void *data, void *arg) { struct ui_st *st = arg; (void)data; tmr_start(&st->tmr, RELEASE_VAL, timeout, st); report_key(st, id); } static int ui_alloc(struct ui_st **stp) { struct ui_st *st; DWORD threadID; int err = 0; if (!stp) return EINVAL; st = mem_zalloc(sizeof(*st), destructor); if (!st) return ENOMEM; tmr_init(&st->tmr); err = mqueue_alloc(&st->mq, mqueue_handler, st); if (err) goto out; st->hstdin = GetStdHandle(STD_INPUT_HANDLE); /* save the current console mode */ GetConsoleMode(st->hstdin, &st->mode); st->run = true; st->hThread = CreateThread(NULL, 0, input_thread, st, 0, &threadID); if (!st->hThread) { st->run = false; err = ENOMEM; goto out; } out: if (err) mem_deref(st); else *stp = st; return err; } static int output_handler(const char *str) { return print_handler(str, str_len(str), NULL); } static struct ui ui_wincons = { .name = "wincons", .outputh = output_handler }; static int module_init(void) { int err; err = ui_alloc(&wincons); if (err) return err; ui_register(baresip_uis(), &ui_wincons); return 0; } static int module_close(void) { ui_unregister(&ui_wincons); wincons = mem_deref(wincons); return 0; } const struct mod_export DECL_EXPORTS(wincons) = { "wincons", "ui", module_init, module_close }; baresip-1.0.0/modules/winwave/000077500000000000000000000000001372575704200163015ustar00rootroot00000000000000baresip-1.0.0/modules/winwave/module.mk000066400000000000000000000002261372575704200201170ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # MOD := winwave $(MOD)_SRCS += winwave.c src.c play.c $(MOD)_LFLAGS += -lwinmm include mk/mod.mk baresip-1.0.0/modules/winwave/play.c000066400000000000000000000117621372575704200174210ustar00rootroot00000000000000/** * @file winwave/play.c Windows sound driver -- playback * * Copyright (C) 2010 Creytiv.com */ #include #include #include #include #include #include #include "winwave.h" #define WRITE_BUFFERS 4 #define INC_WPOS(a) ((a) = (((a) + 1) % WRITE_BUFFERS)) struct auplay_st { const struct auplay *ap; /* inheritance */ struct dspbuf bufs[WRITE_BUFFERS]; int pos; HWAVEOUT waveout; volatile bool rdy; size_t inuse; size_t sampsz; auplay_write_h *wh; void *arg; }; static void auplay_destructor(void *arg) { struct auplay_st *st = arg; int i; st->wh = NULL; /* Mark the device for closing, and wait for all the * buffers to be returned by the driver */ st->rdy = false; while (st->inuse > 0) Sleep(50); waveOutReset(st->waveout); for (i = 0; i < WRITE_BUFFERS; i++) { waveOutUnprepareHeader(st->waveout, &st->bufs[i].wh, sizeof(WAVEHDR)); mem_deref(st->bufs[i].mb); } waveOutClose(st->waveout); } static int dsp_write(struct auplay_st *st) { MMRESULT res; WAVEHDR *wh; struct mbuf *mb; if (!st->rdy) return EINVAL; wh = &st->bufs[st->pos].wh; if (wh->dwFlags & WHDR_PREPARED) { return EINVAL; } mb = st->bufs[st->pos].mb; wh->lpData = (LPSTR)mb->buf; if (st->wh) { st->wh((void *)mb->buf, mb->size/st->sampsz, st->arg); } wh->dwBufferLength = mb->size; wh->dwFlags = 0; waveOutPrepareHeader(st->waveout, wh, sizeof(*wh)); INC_WPOS(st->pos); res = waveOutWrite(st->waveout, wh, sizeof(*wh)); if (res != MMSYSERR_NOERROR) warning("winwave: dsp_write: waveOutWrite: failed: %08x\n", res); else st->inuse++; return 0; } static void CALLBACK waveOutCallback(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2) { struct auplay_st *st = (struct auplay_st *)dwInstance; WAVEHDR *wh = (WAVEHDR *)dwParam1; (void)hwo; (void)dwParam2; switch (uMsg) { case WOM_OPEN: st->rdy = true; break; case WOM_DONE: /*LOCK();*/ waveOutUnprepareHeader(st->waveout, wh, sizeof(*wh)); /*UNLOCK();*/ st->inuse--; dsp_write(st); break; case WOM_CLOSE: st->rdy = false; break; default: break; } } static int write_stream_open(struct auplay_st *st, const struct auplay_prm *prm, unsigned int dev) { WAVEFORMATEX wfmt; MMRESULT res; uint32_t sampc; unsigned format; int i; st->sampsz = aufmt_sample_size(prm->fmt); format = winwave_get_format(prm->fmt); if (format == WAVE_FORMAT_UNKNOWN) { warning("winwave: playback: unsupported sample format (%s)\n", aufmt_name(prm->fmt)); return ENOTSUP; } /* Open an audio I/O stream. */ st->waveout = NULL; st->pos = 0; st->rdy = false; sampc = prm->srate * prm->ch * prm->ptime / 1000; for (i = 0; i < WRITE_BUFFERS; i++) { memset(&st->bufs[i].wh, 0, sizeof(WAVEHDR)); st->bufs[i].mb = mbuf_alloc(st->sampsz * sampc); if (!st->bufs[i].mb) return ENOMEM; } wfmt.wFormatTag = format; wfmt.nChannels = prm->ch; wfmt.nSamplesPerSec = prm->srate; wfmt.wBitsPerSample = (WORD)(st->sampsz * 8); wfmt.nBlockAlign = prm->ch * st->sampsz; wfmt.nAvgBytesPerSec = wfmt.nSamplesPerSec * wfmt.nBlockAlign; wfmt.cbSize = 0; res = waveOutOpen(&st->waveout, dev, &wfmt, (DWORD_PTR) waveOutCallback, (DWORD_PTR) st, CALLBACK_FUNCTION | WAVE_FORMAT_DIRECT); if (res != MMSYSERR_NOERROR) { warning("winwave: waveOutOpen: failed %d\n", res); return EINVAL; } return 0; } static int winwave_get_dev_name(unsigned int i, char name[32]) { WAVEOUTCAPS wic; int err = 0; if (waveOutGetDevCaps(i, &wic, sizeof(WAVEOUTCAPS)) == MMSYSERR_NOERROR) { str_ncpy(name, wic.szPname, 32); } else { err = ENODEV; } return err; } static unsigned int winwave_get_num_devs(void) { return waveOutGetNumDevs(); } static int find_dev(const char *name, unsigned int *dev) { return winwave_enum_devices(name, NULL, dev, winwave_get_num_devs, winwave_get_dev_name); } int winwave_play_alloc(struct auplay_st **stp, const struct auplay *ap, struct auplay_prm *prm, const char *device, auplay_write_h *wh, void *arg) { struct auplay_st *st; int i, err; unsigned int dev; if (!stp || !ap || !prm) return EINVAL; err = find_dev(device, &dev); if (err) return err; st = mem_zalloc(sizeof(*st), auplay_destructor); if (!st) return ENOMEM; st->ap = ap; st->wh = wh; st->arg = arg; err = write_stream_open(st, prm, dev); if (err) goto out; /* The write runs at 100ms intervals * prepare enough buffers to suite its needs */ for (i = 0; i < WRITE_BUFFERS; i++) dsp_write(st); out: if (err) mem_deref(st); else *stp = st; return err; } static int set_available_devices(struct list *dev_list) { return winwave_enum_devices(NULL, dev_list, NULL, winwave_get_num_devs, winwave_get_dev_name); } int winwave_player_init(struct auplay *ap) { if (!ap) return EINVAL; list_init(&ap->dev_list); return set_available_devices(&ap->dev_list); } baresip-1.0.0/modules/winwave/src.c000066400000000000000000000117751372575704200172470ustar00rootroot00000000000000/** * @file winwave/src.c Windows sound driver -- source * * Copyright (C) 2010 Creytiv.com */ #include #include #include #include #include #include #include "winwave.h" #define READ_BUFFERS 4 #define INC_RPOS(a) ((a) = (((a) + 1) % READ_BUFFERS)) struct ausrc_st { const struct ausrc *as; /* inheritance */ struct dspbuf bufs[READ_BUFFERS]; int pos; HWAVEIN wavein; volatile bool rdy; size_t inuse; size_t sampsz; enum aufmt fmt; ausrc_read_h *rh; void *arg; }; static void ausrc_destructor(void *arg) { struct ausrc_st *st = arg; int i; st->rh = NULL; waveInStop(st->wavein); waveInReset(st->wavein); for (i = 0; i < READ_BUFFERS; i++) { waveInUnprepareHeader(st->wavein, &st->bufs[i].wh, sizeof(WAVEHDR)); mem_deref(st->bufs[i].mb); } waveInClose(st->wavein); } static int add_wave_in(struct ausrc_st *st) { struct dspbuf *db = &st->bufs[st->pos]; WAVEHDR *wh = &db->wh; MMRESULT res; wh->lpData = (LPSTR)db->mb->buf; wh->dwBufferLength = db->mb->size; wh->dwBytesRecorded = 0; wh->dwFlags = 0; waveInPrepareHeader(st->wavein, wh, sizeof(*wh)); res = waveInAddBuffer(st->wavein, wh, sizeof(*wh)); if (res != MMSYSERR_NOERROR) { warning("winwave: add_wave_in: waveInAddBuffer fail: %08x\n", res); return ENOMEM; } INC_RPOS(st->pos); st->inuse++; return 0; } static void CALLBACK waveInCallback(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2) { struct ausrc_st *st = (struct ausrc_st *)dwInstance; WAVEHDR *wh = (WAVEHDR *)dwParam1; struct auframe af; (void)hwo; (void)dwParam2; if (!st->rh) return; switch (uMsg) { case WIM_CLOSE: st->rdy = false; break; case WIM_OPEN: st->rdy = true; break; case WIM_DATA: if (st->inuse < (READ_BUFFERS-1)) add_wave_in(st); af.fmt = st->fmt; af.sampv = (void *)wh->lpData; af.sampc = wh->dwBytesRecorded/st->sampsz; af.timestamp = tmr_jiffies_usec(); st->rh(&af, st->arg); waveInUnprepareHeader(st->wavein, wh, sizeof(*wh)); st->inuse--; break; default: break; } } static int read_stream_open(struct ausrc_st *st, const struct ausrc_prm *prm, unsigned int dev) { WAVEFORMATEX wfmt; MMRESULT res; uint32_t sampc; unsigned format; int i, err = 0; st->sampsz = aufmt_sample_size(prm->fmt); format = winwave_get_format(prm->fmt); if (format == WAVE_FORMAT_UNKNOWN) { warning("winwave: source: unsupported sample format (%s)\n", aufmt_name(prm->fmt)); return ENOTSUP; } /* Open an audio INPUT stream. */ st->wavein = NULL; st->pos = 0; st->rdy = false; st->fmt = prm->fmt; sampc = prm->srate * prm->ch * prm->ptime / 1000; for (i = 0; i < READ_BUFFERS; i++) { memset(&st->bufs[i].wh, 0, sizeof(WAVEHDR)); st->bufs[i].mb = mbuf_alloc(st->sampsz * sampc); if (!st->bufs[i].mb) return ENOMEM; } wfmt.wFormatTag = format; wfmt.nChannels = prm->ch; wfmt.nSamplesPerSec = prm->srate; wfmt.wBitsPerSample = (WORD)(st->sampsz * 8); wfmt.nBlockAlign = prm->ch * st->sampsz; wfmt.nAvgBytesPerSec = wfmt.nSamplesPerSec * wfmt.nBlockAlign; wfmt.cbSize = 0; res = waveInOpen(&st->wavein, dev, &wfmt, (DWORD_PTR) waveInCallback, (DWORD_PTR) st, CALLBACK_FUNCTION | WAVE_FORMAT_DIRECT); if (res != MMSYSERR_NOERROR) { warning("winwave: waveInOpen: failed res=%d\n", res); return EINVAL; } /* Prepare enough IN buffers to suite at least 50ms of data */ for (i = 0; i < READ_BUFFERS; i++) err |= add_wave_in(st); waveInStart(st->wavein); return err; } static int winwave_get_dev_name(unsigned int i, char name[32]) { WAVEINCAPS wic; int err = 0; if (waveInGetDevCaps(i, &wic, sizeof(WAVEINCAPS)) == MMSYSERR_NOERROR) { str_ncpy(name, wic.szPname, 32); } else { err = ENODEV; } return err; } static unsigned int winwave_get_num_devs(void) { return waveInGetNumDevs(); } static int find_dev(const char *name, unsigned int *dev) { return winwave_enum_devices(name, NULL, dev, winwave_get_num_devs, winwave_get_dev_name); } int winwave_src_alloc(struct ausrc_st **stp, const struct ausrc *as, struct media_ctx **ctx, struct ausrc_prm *prm, const char *device, ausrc_read_h *rh, ausrc_error_h *errh, void *arg) { struct ausrc_st *st; int err; unsigned int dev; (void)ctx; (void)errh; if (!stp || !as || !prm) return EINVAL; err = find_dev(device, &dev); if (err) return err; st = mem_zalloc(sizeof(*st), ausrc_destructor); if (!st) return ENOMEM; st->as = as; st->rh = rh; st->arg = arg; err |= read_stream_open(st, prm, dev); if (err) mem_deref(st); else *stp = st; return err; } static int set_available_devices(struct list *dev_list) { return winwave_enum_devices(NULL, dev_list, NULL, winwave_get_num_devs, winwave_get_dev_name); } int winwave_src_init(struct ausrc *as) { if (!as) return EINVAL; list_init(&as->dev_list); return set_available_devices(&as->dev_list); } baresip-1.0.0/modules/winwave/winwave.c000066400000000000000000000041471372575704200201330ustar00rootroot00000000000000/** * @file winwave.c Windows sound driver * * Copyright (C) 2010 Creytiv.com */ #include #include #include #include #include #include #include "winwave.h" /** * @defgroup winwave winwave * * Windows audio driver module * */ static struct ausrc *ausrc; static struct auplay *auplay; int winwave_enum_devices(const char *name, struct list *dev_list, unsigned int *dev, unsigned int (winwave_get_num_devs)(void), int (winwave_get_dev_name)(unsigned int, char*)) { /* The szPname member of the WAVEINCAPS/WAVEOUTCAPS structures is limited to MAXPNAMELEN characters, which is defined as 32 */ char dev_name[32]; int err = 0; unsigned int i, nDevices = winwave_get_num_devs(); if (!dev_list && !dev) return EINVAL; if (dev) { *dev = WAVE_MAPPER; if (!str_isset(name)) { return 0; } } for (i=0; i #include #include #include #include #include #include #include /* * DO_REDIRECT has this program handle all of the window manager operations * and displays a borderless window. That window does not take keyboard * focus - which means the keyboard input to baresip continues. Clicking * on the window allows one to drag the window around. * Blewett */ #define DO_REDIRECT 1 /** * @defgroup x11 x11 * * X11 video-display module */ struct vidisp_st { const struct vidisp *vd; /**< Inheritance (1st) */ struct vidsz size; /**< Current size */ Display *disp; Window win; GC gc; XImage *image; XShmSegmentInfo shm; bool xshmat; bool internal; enum vidfmt pixfmt; Atom XwinDeleted; int button_is_down; Time last_time; }; static struct vidisp *vid; /**< X11 Video-display */ static struct { int shm_error; int (*errorh) (Display *, XErrorEvent *); } x11; /* NOTE: Global handler */ static int error_handler(Display *d, XErrorEvent *e) { if (e->error_code == BadAccess) x11.shm_error = 1; else if (x11.errorh) return x11.errorh(d, e); return 0; } static void close_window(struct vidisp_st *st) { if (st->gc && st->disp) { XFreeGC(st->disp, st->gc); st->gc = NULL; } if (st->xshmat && st->disp) { XShmDetach(st->disp, &st->shm); } if (st->shm.shmaddr != (char *)-1) { shmdt(st->shm.shmaddr); st->shm.shmaddr = (char *)-1; } if (st->shm.shmid >= 0) shmctl(st->shm.shmid, IPC_RMID, NULL); if (st->disp) { if (st->internal && st->win) { XDestroyWindow(st->disp, st->win); st->win = 0; } XCloseDisplay(st->disp); st->disp = NULL; } } static void destructor(void *arg) { struct vidisp_st *st = arg; if (st->image) { st->image->data = NULL; XDestroyImage(st->image); } close_window(st); } static int create_window(struct vidisp_st *st, const struct vidsz *sz) { #ifdef DO_REDIRECT XSetWindowAttributes attr; #endif st->win = XCreateSimpleWindow(st->disp, DefaultRootWindow(st->disp), 0, 0, sz->w, sz->h, 1, 0, 0); if (!st->win) { warning("x11: failed to create X window\n"); return ENOMEM; } #ifdef DO_REDIRECT /* * set override rediect to avoid the "kill window" button * we need to set masks to allow for mouse tracking, etc. * to control the window - making us the window manager */ attr.override_redirect = true; attr.event_mask = SubstructureRedirectMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | Button1MotionMask; XChangeWindowAttributes(st->disp, st->win, CWOverrideRedirect | CWEventMask , &attr); #endif XClearWindow(st->disp, st->win); XMapRaised(st->disp, st->win); /* * setup to catch window deletion */ st->XwinDeleted = XInternAtom(st->disp, "WM_DELETE_WINDOW", True); XSetWMProtocols(st->disp, st->win, &st->XwinDeleted, 1); return 0; } static int x11_reset(struct vidisp_st *st, const struct vidsz *sz) { XWindowAttributes attrs; XGCValues gcv; size_t bufsz, pixsz; int err = 0; bool try_shm; if (!XGetWindowAttributes(st->disp, st->win, &attrs)) { warning("x11: cant't get window attributes\n"); return EINVAL; } switch (attrs.depth) { case 24: st->pixfmt = VID_FMT_RGB32; pixsz = 4; break; default: warning("x11: colordepth not supported: %d\n", attrs.depth); return ENOSYS; } bufsz = sz->w * sz->h * pixsz; if (st->image) { XDestroyImage(st->image); st->image = NULL; } if (st->xshmat) XShmDetach(st->disp, &st->shm); if (st->shm.shmaddr != (char *)-1) shmdt(st->shm.shmaddr); if (st->shm.shmid >= 0) shmctl(st->shm.shmid, IPC_RMID, NULL); st->shm.shmid = shmget(IPC_PRIVATE, bufsz, IPC_CREAT | 0777); if (st->shm.shmid < 0) { warning("x11: failed to allocate shared memory\n"); return ENOMEM; } st->shm.shmaddr = shmat(st->shm.shmid, NULL, 0); if (st->shm.shmaddr == (char *)-1) { warning("x11: failed to attach to shared memory\n"); return ENOMEM; } st->shm.readOnly = true; x11.shm_error = 0; x11.errorh = XSetErrorHandler(error_handler); try_shm = XShmQueryExtension(st->disp); if (try_shm) { if (!XShmAttach(st->disp, &st->shm)) { warning("x11: failed to attach X to shared memory\n"); return ENOMEM; } } else { info("x11: no shm extension\n"); x11.shm_error = 1; } XSync(st->disp, False); XSetErrorHandler(x11.errorh); if (x11.shm_error) info("x11: shared memory disabled\n"); else { info("x11: shared memory enabled\n"); st->xshmat = true; } gcv.graphics_exposures = false; st->gc = XCreateGC(st->disp, st->win, GCGraphicsExposures, &gcv); if (!st->gc) { warning("x11: failed to create graphics context\n"); return ENOMEM; } if (st->xshmat) { st->image = XShmCreateImage(st->disp, attrs.visual, attrs.depth, ZPixmap, st->shm.shmaddr, &st->shm, sz->w, sz->h); } else { st->image = XCreateImage(st->disp, attrs.visual, attrs.depth, ZPixmap, 0, st->shm.shmaddr, sz->w, sz->h, 32, 0); } if (!st->image) { warning("x11: Failed to create X image\n"); return ENOMEM; } XResizeWindow(st->disp, st->win, sz->w, sz->h); st->size = *sz; return err; } static int alloc(struct vidisp_st **stp, const struct vidisp *vd, struct vidisp_prm *prm, const char *dev, vidisp_resize_h *resizeh, void *arg) { struct vidisp_st *st; int err = 0; (void)prm; (void)dev; (void)resizeh; (void)arg; st = mem_zalloc(sizeof(*st), destructor); if (!st) return ENOMEM; st->vd = vd; st->shm.shmaddr = (char *)-1; st->disp = XOpenDisplay(NULL); if (!st->disp) { warning("x11: could not open X display\n"); err = ENODEV; goto out; } st->internal = true; out: if (err) mem_deref(st); else *stp = st; return err; } static int display(struct vidisp_st *st, const char *title, const struct vidframe *frame, uint64_t timestamp) { struct vidframe frame_rgb; int err = 0; (void)timestamp; if (!st->disp) return ENODEV; /* * check for window delete - without blocking * the switch handles both the override redirect window * and the "standard" window manager managed window. */ while (XPending(st->disp)) { XEvent e; XNextEvent(st->disp, &e); switch (e.type) { case ClientMessage: if ((Atom) e.xclient.data.l[0] == st->XwinDeleted) { info("x11: window deleted\n"); /* * we have to bail as all of the display * pointers are bad. */ close_window(st); return ENODEV; } break; case ButtonPress: st->button_is_down = 1; break; case ButtonRelease: st->button_is_down = 0; break; case MotionNotify: if (st->button_is_down == 0) break; if ((e.xmotion.time - st->last_time) < 32) break; XMoveWindow(st->disp, st->win, e.xmotion.x_root - 16, e.xmotion.y_root - 16); st->last_time = e.xmotion.time; break; default: break; } } if (!vidsz_cmp(&st->size, &frame->size)) { char capt[256]; if (st->size.w && st->size.h) { info("x11: reset: %u x %u ---> %u x %u\n", st->size.w, st->size.h, frame->size.w, frame->size.h); } if (st->internal && !st->win) err = create_window(st, &frame->size); err |= x11_reset(st, &frame->size); if (err) return err; if (title) { re_snprintf(capt, sizeof(capt), "%s - %u x %u", title, frame->size.w, frame->size.h); } else { re_snprintf(capt, sizeof(capt), "%u x %u", frame->size.w, frame->size.h); } XStoreName(st->disp, st->win, capt); } /* Convert from YUV420P to RGB */ vidframe_init_buf(&frame_rgb, st->pixfmt, &frame->size, (uint8_t *)st->shm.shmaddr); vidconv(&frame_rgb, frame, 0); /* draw */ if (st->xshmat) XShmPutImage(st->disp, st->win, st->gc, st->image, 0, 0, 0, 0, st->size.w, st->size.h, false); else XPutImage(st->disp, st->win, st->gc, st->image, 0, 0, 0, 0, st->size.w, st->size.h); XSync(st->disp, false); return err; } static void hide(struct vidisp_st *st) { if (!st) return; if (st->win) XLowerWindow(st->disp, st->win); } static int module_init(void) { return vidisp_register(&vid, baresip_vidispl(), "x11", alloc, NULL, display, hide); } static int module_close(void) { vid = mem_deref(vid); return 0; } EXPORT_SYM const struct mod_export DECL_EXPORTS(x11) = { "x11", "vidisp", module_init, module_close, }; baresip-1.0.0/modules/x11grab/000077500000000000000000000000001372575704200160665ustar00rootroot00000000000000baresip-1.0.0/modules/x11grab/module.mk000066400000000000000000000002641372575704200177060ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # MOD := x11grab $(MOD)_SRCS += x11grab.c $(MOD)_LFLAGS += -lX11 -lXext $(MOD)_CFLAGS += -Wno-variadic-macros include mk/mod.mk baresip-1.0.0/modules/x11grab/x11grab.c000066400000000000000000000071021372575704200174770ustar00rootroot00000000000000/** * @file x11grab.c X11 grabbing video-source * * Copyright (C) 2010 Creytiv.com */ #define _DEFAULT_SOURCE 1 #define _BSD_SOURCE 1 #include #ifndef SOLARIS #define _XOPEN_SOURCE 1 #endif #include #include #include #include #include #include /** * @defgroup x11grab x11grab * * X11 window-grabbing video-source module * */ struct vidsrc_st { const struct vidsrc *vs; /* inheritance */ Display *disp; XImage *image; pthread_t thread; bool run; int fps; struct vidsz size; enum vidfmt pixfmt; vidsrc_frame_h *frameh; void *arg; }; static struct vidsrc *vidsrc; static int x11grab_open(struct vidsrc_st *st, const struct vidsz *sz, const char *dev) { int x = 0, y = 0; st->disp = XOpenDisplay(dev); if (!st->disp) { warning("x11grab: error opening display '%s'\n", dev); return ENODEV; } st->image = XGetImage(st->disp, RootWindow(st->disp, DefaultScreen(st->disp)), x, y, sz->w, sz->h, AllPlanes, ZPixmap); if (!st->image) { warning("x11grab: error creating Ximage\n"); return ENODEV; } switch (st->image->bits_per_pixel) { case 32: st->pixfmt = VID_FMT_RGB32; break; default: warning("x11grab: not supported: bpp=%d\n", st->image->bits_per_pixel); return ENOSYS; } return 0; } static inline uint8_t *x11grab_read(struct vidsrc_st *st) { const int x = 0, y = 0; XImage *im; im = XGetSubImage(st->disp, RootWindow(st->disp, DefaultScreen(st->disp)), x, y, st->size.w, st->size.h, AllPlanes, ZPixmap, st->image, 0, 0); if (!im) return NULL; return (uint8_t *)st->image->data; } static void call_frame_handler(struct vidsrc_st *st, uint8_t *buf, uint64_t timestamp) { struct vidframe frame; vidframe_init_buf(&frame, st->pixfmt, &st->size, buf); st->frameh(&frame, timestamp, st->arg); } static void *read_thread(void *arg) { struct vidsrc_st *st = arg; uint64_t ts = tmr_jiffies(); uint8_t *buf; while (st->run) { uint64_t timestamp; if (tmr_jiffies() < ts) { sys_msleep(4); continue; } buf = x11grab_read(st); if (!buf) continue; timestamp = ts * VIDEO_TIMEBASE / 1000; ts += (1000/st->fps); call_frame_handler(st, buf, timestamp); } return NULL; } static void destructor(void *arg) { struct vidsrc_st *st = arg; if (st->run) { st->run = false; pthread_join(st->thread, NULL); } if (st->image) XDestroyImage(st->image); if (st->disp) XCloseDisplay(st->disp); } static int alloc(struct vidsrc_st **stp, const struct vidsrc *vs, struct media_ctx **ctx, struct vidsrc_prm *prm, const struct vidsz *size, const char *fmt, const char *dev, vidsrc_frame_h *frameh, vidsrc_error_h *errorh, void *arg) { struct vidsrc_st *st; int err; (void)ctx; (void)fmt; (void)errorh; if (!stp || !prm || !size || !frameh) return EINVAL; st = mem_zalloc(sizeof(*st), destructor); if (!st) return ENOMEM; st->vs = vs; st->size = *size; st->fps = prm->fps; st->frameh = frameh; st->arg = arg; err = x11grab_open(st, size, dev); if (err) goto out; st->run = true; err = pthread_create(&st->thread, NULL, read_thread, st); if (err) { st->run = false; goto out; } out: if (err) mem_deref(st); else *stp = st; return err; } static int x11grab_init(void) { return vidsrc_register(&vidsrc, baresip_vidsrcl(), "x11grab", alloc, NULL); } static int x11grab_close(void) { vidsrc = mem_deref(vidsrc); return 0; } EXPORT_SYM const struct mod_export DECL_EXPORTS(x11grab) = { "x11grab", "vidsrc", x11grab_init, x11grab_close }; baresip-1.0.0/modules/zrtp/000077500000000000000000000000001372575704200156205ustar00rootroot00000000000000baresip-1.0.0/modules/zrtp/module.mk000066400000000000000000000010521372575704200174340ustar00rootroot00000000000000# # module.mk # # Copyright (C) 2010 Creytiv.com # # # To build zrtp libraries and include files, run the following commands: # # git clone git@github.com:juha-h/libzrtp.git # cd libzrtp # ./bootstrap.sh # ./configure CFLAGS="-O0 -g3 -W -Wall -DBUILD_WITH_CFUNC \ # -DBUILD_DEFAULT_CACHE -DBUILD_DEFAULT_TIMER" # make # sudo make install # MOD := zrtp $(MOD)_SRCS += zrtp.c $(MOD)_LFLAGS += -lzrtp -lbn $(MOD)_CFLAGS += -isystem /usr/local/include/libzrtp $(MOD)_CFLAGS += -Wno-strict-prototypes include mk/mod.mk baresip-1.0.0/modules/zrtp/zrtp.c000066400000000000000000000366741372575704200170030ustar00rootroot00000000000000/** * @file zrtp.c ZRTP: Media Path Key Agreement for Unicast Secure RTP * * Copyright (C) 2010 Creytiv.com */ #include #include #include #include /** * @defgroup zrtp zrtp * * ZRTP: Media Path Key Agreement for Unicast Secure RTP * * Experimental support for ZRTP * * See http://tools.ietf.org/html/rfc6189 * * Briefly tested with Twinkle 1.4.2 and Jitsi 2.2.4603.9615 * * This module is using ZRTP implementation in Freeswitch * https://github.com/juha-h/libzrtp * * Thanks: * * Ingo Feinerer * * Configuration options: * \verbatim zrtp_hash {yes,no} # Enable SDP zrtp-hash (recommended) \endverbatim * */ enum { PRESZ = 36 /* Preamble size for TURN/STUN header */ }; struct menc_sess { zrtp_session_t *zrtp_session; menc_event_h *eventh; menc_error_h *errorh; void *arg; struct tmr abort_timer; int err; }; struct menc_media { struct menc_sess *sess; struct udp_helper *uh_rtp; struct udp_helper *uh_rtcp; struct sa raddr; void *rtpsock; void *rtcpsock; zrtp_stream_t *zrtp_stream; const struct stream *strm; /**< pointer to parent */ }; static zrtp_global_t *zrtp_global; static zrtp_config_t zrtp_config; static zrtp_zid_t zid; /* RFC 6189, section 8.1. */ static bool use_sig_hash = true; enum pkt_type { PKT_TYPE_UNKNOWN = 0, PKT_TYPE_RTP = 1, PKT_TYPE_RTCP = 2, PKT_TYPE_ZRTP = 4 }; static enum pkt_type get_packet_type(const struct mbuf *mb) { uint8_t b, pt; uint32_t magic; if (mbuf_get_left(mb) < 8) return PKT_TYPE_UNKNOWN; b = mbuf_buf(mb)[0]; if (127 < b && b < 192) { pt = mbuf_buf(mb)[1] & 0x7f; if (72 <= pt && pt <= 76) return PKT_TYPE_RTCP; else return PKT_TYPE_RTP; } else { memcpy(&magic, &mbuf_buf(mb)[4], 4); magic = ntohl(magic); if (magic == ZRTP_PACKETS_MAGIC) return PKT_TYPE_ZRTP; } return PKT_TYPE_UNKNOWN; } static void session_destructor(void *arg) { struct menc_sess *st = arg; tmr_cancel(&st->abort_timer); if (st->zrtp_session) zrtp_session_down(st->zrtp_session); } static void media_destructor(void *arg) { struct menc_media *st = arg; mem_deref(st->uh_rtp); mem_deref(st->uh_rtcp); mem_deref(st->rtpsock); mem_deref(st->rtcpsock); if (st->zrtp_stream) zrtp_stream_stop(st->zrtp_stream); } static void abort_timer_h(void *arg) { struct menc_sess *sess = arg; if (sess->errorh) { sess->errorh(sess->err, sess->arg); sess->errorh = NULL; } } static void abort_call(struct menc_sess *sess) { if (!sess->err) { sess->err = EPIPE; tmr_start(&sess->abort_timer, 0, abort_timer_h, sess); } } static bool drop_packets(const struct menc_media *st) { return (st)? st->sess->err != 0 : true; } static bool udp_helper_send(int *err, struct sa *dst, struct mbuf *mb, void *arg) { struct menc_media *st = arg; unsigned int length; zrtp_status_t s; const char *proto_name = "rtp"; enum pkt_type ptype = get_packet_type(mb); if (drop_packets(st)) return true; length = (unsigned int)mbuf_get_left(mb); /* only RTP/RTCP packets should be processed */ if (ptype == PKT_TYPE_RTCP) { proto_name = "rtcp"; s = zrtp_process_rtcp(st->zrtp_stream, (char *)mbuf_buf(mb), &length); } else if (ptype == PKT_TYPE_RTP) { s = zrtp_process_rtp(st->zrtp_stream, (char *)mbuf_buf(mb), &length); } else return false; if (s != zrtp_status_ok) { if (s == zrtp_status_drop) return true; warning("zrtp: send(port=%d): zrtp_process_%s failed" " (status = %d '%s')\n", sa_port(dst), proto_name, s, zrtp_log_status2str(s)); return false; } /* make sure target buffer is large enough */ if (length > mbuf_get_space(mb)) { warning("zrtp: zrtp_process_%s: length > space (%u > %u)\n", proto_name, length, mbuf_get_space(mb)); *err = ENOMEM; } mb->end = mb->pos + length; return false; } static bool udp_helper_recv(struct sa *src, struct mbuf *mb, void *arg) { struct menc_media *st = arg; unsigned int length; zrtp_status_t s; const char *proto_name = "srtp"; enum pkt_type ptype = get_packet_type(mb); if (drop_packets(st)) return true; length = (unsigned int)mbuf_get_left(mb); if (ptype == PKT_TYPE_RTCP) { proto_name = "srtcp"; s = zrtp_process_srtcp(st->zrtp_stream, (char *)mbuf_buf(mb), &length); } else if (ptype == PKT_TYPE_RTP || ptype == PKT_TYPE_ZRTP) { s = zrtp_process_srtp(st->zrtp_stream, (char *)mbuf_buf(mb), &length); } else return false; if (s != zrtp_status_ok) { if (s == zrtp_status_drop) return true; warning("zrtp: recv(port=%d): zrtp_process_%s: %d '%s'\n", sa_port(src), proto_name, s, zrtp_log_status2str(s)); return false; } mb->end = mb->pos + length; return false; } static int sig_hash_encode(struct zrtp_stream_t *stream, struct sdp_media *m) { char buf[ZRTP_SIGN_ZRTP_HASH_LENGTH + 1]; zrtp_status_t s; int err = 0; s = zrtp_signaling_hash_get(stream, buf, sizeof(buf)); if (s != zrtp_status_ok) { warning("zrtp: zrtp_signaling_hash_get: status = %d\n", s); return EINVAL; } err = sdp_media_set_lattr(m, true, "zrtp-hash", "%s %s", ZRTP_PROTOCOL_VERSION, buf); if (err) { warning("zrtp: sdp_media_set_lattr: %d\n", err); } return err; } static void sig_hash_decode(struct zrtp_stream_t *stream, const struct sdp_media *m) { const char *attr_val; struct pl major, minor, hash; uint32_t version; int err; zrtp_status_t s; attr_val = sdp_media_rattr(m, "zrtp-hash"); if (!attr_val) return; err = re_regex(attr_val, strlen(attr_val), "[0-9]+.[0-9]2 [0-9a-f]+", &major, &minor, &hash); if (err || hash.l < ZRTP_SIGN_ZRTP_HASH_LENGTH) { warning("zrtp: malformed zrtp-hash attribute, ignoring...\n"); return; } version = pl_u32(&major) * 100 + pl_u32(&minor); /* more version checks? */ if (version < 110) { warning("zrtp: zrtp-hash: version (%d) is too low, " "ignoring...", version); } s = zrtp_signaling_hash_set(stream, hash.p, (uint32_t)hash.l); if (s != zrtp_status_ok) warning("zrtp: zrtp_signaling_hash_set: status = %d\n", s); } static int session_alloc(struct menc_sess **sessp, struct sdp_session *sdp, bool offerer, menc_event_h *eventh, menc_error_h *errorh, void *arg) { struct menc_sess *st; zrtp_status_t s; int err = 0; (void)offerer; if (!sessp || !sdp) return EINVAL; st = mem_zalloc(sizeof(*st), session_destructor); if (!st) return ENOMEM; st->eventh = eventh; st->errorh = errorh; st->arg = arg; st->err = 0; tmr_init(&st->abort_timer); s = zrtp_session_init(zrtp_global, NULL, zid, ZRTP_SIGNALING_ROLE_UNKNOWN, &st->zrtp_session); if (s != zrtp_status_ok) { warning("zrtp: zrtp_session_init failed (status = %d)\n", s); err = EPROTO; goto out; } out: if (err) mem_deref(st); else *sessp = st; return err; } static int media_alloc(struct menc_media **stp, struct menc_sess *sess, struct rtp_sock *rtp, struct udp_sock *rtpsock, struct udp_sock *rtcpsock, const struct sa *raddr_rtp, const struct sa *raddr_rtcp, struct sdp_media *sdpm, const struct stream *strm) { struct menc_media *st; zrtp_status_t s; int layer = 10; /* above zero */ int err = 0; (void)raddr_rtp; (void)raddr_rtcp; if (!stp || !sess) return EINVAL; st = *stp; if (st) goto start; st = mem_zalloc(sizeof(*st), media_destructor); if (!st) return ENOMEM; st->sess = sess; st->strm = strm; if (rtpsock) { st->rtpsock = mem_ref(rtpsock); err |= udp_register_helper(&st->uh_rtp, rtpsock, layer, udp_helper_send, udp_helper_recv, st); } if (rtcpsock && (rtcpsock != rtpsock)) { st->rtcpsock = mem_ref(rtcpsock); err |= udp_register_helper(&st->uh_rtcp, rtcpsock, layer, udp_helper_send, udp_helper_recv, st); } if (err) goto out; s = zrtp_stream_attach(sess->zrtp_session, &st->zrtp_stream); if (s != zrtp_status_ok) { warning("zrtp: zrtp_stream_attach failed (status=%d)\n", s); err = EPROTO; goto out; } zrtp_stream_set_userdata(st->zrtp_stream, st); if (use_sig_hash) { err = sig_hash_encode(st->zrtp_stream, sdpm); if (err) goto out; } out: if (err) { mem_deref(st); return err; } else *stp = st; start: if (sa_isset(sdp_media_raddr(sdpm), SA_ALL)) { st->raddr = *sdp_media_raddr(sdpm); if (use_sig_hash) sig_hash_decode(st->zrtp_stream, sdpm); s = zrtp_stream_start(st->zrtp_stream, rtp_sess_ssrc(rtp)); if (s != zrtp_status_ok) { warning("zrtp: zrtp_stream_start: status = %d\n", s); } } return err; } static int on_send_packet(const zrtp_stream_t *stream, char *rtp_packet, unsigned int rtp_packet_length) { struct menc_media *st = zrtp_stream_get_userdata(stream); struct mbuf *mb; int err; if (drop_packets(st)) return zrtp_status_ok; if (!sa_isset(&st->raddr, SA_ALL)) return zrtp_status_ok; mb = mbuf_alloc(PRESZ + rtp_packet_length); if (!mb) return zrtp_status_alloc_fail; mb->pos = PRESZ; (void)mbuf_write_mem(mb, (void *)rtp_packet, rtp_packet_length); mb->pos = PRESZ; err = udp_send_helper(st->rtpsock, &st->raddr, mb, st->uh_rtp); if (err) { warning("zrtp: udp_send %u bytes (%m)\n", rtp_packet_length, err); } mem_deref(mb); return zrtp_status_ok; } static void on_zrtp_secure(zrtp_stream_t *stream) { const struct menc_media *st = zrtp_stream_get_userdata(stream); const struct menc_sess *sess = st->sess; zrtp_session_info_t sess_info; char buf[128] = ""; zrtp_session_get(sess->zrtp_session, &sess_info); if (!sess_info.sas_is_verified && sess_info.sas_is_ready) { info("zrtp: verify SAS <%s> <%s> for remote peer %w" " (type /zrtp_verify %w to verify)\n", sess_info.sas1.buffer, sess_info.sas2.buffer, sess_info.peer_zid.buffer, (size_t)sess_info.peer_zid.length, sess_info.peer_zid.buffer, (size_t)sess_info.peer_zid.length); if (sess->eventh) { if (re_snprintf(buf, sizeof(buf), "%s,%s,%w", sess_info.sas1.buffer, sess_info.sas2.buffer, sess_info.peer_zid.buffer, (size_t)sess_info.peer_zid.length)) (sess->eventh)(MENC_EVENT_VERIFY_REQUEST, buf, (struct stream *)st->strm, sess->arg); else warning("zrtp: failed to print verify " " arguments\n"); } } else if (sess_info.sas_is_verified) { info("zrtp: secure session with verified remote peer %w\n", sess_info.peer_zid.buffer, (size_t)sess_info.peer_zid.length); if (sess->eventh) { if (re_snprintf(buf, sizeof(buf), "%w", sess_info.peer_zid.buffer, (size_t)sess_info.peer_zid.length)) (sess->eventh)(MENC_EVENT_PEER_VERIFIED, buf, (struct stream *)st->strm, sess->arg); else warning("zrtp: failed to print verified " " argument\n"); } } } static void on_zrtp_security_event(zrtp_stream_t *stream, zrtp_security_event_t event) { debug("zrtp: got security_event '%u'\n", event); if (event == ZRTP_EVENT_WRONG_SIGNALING_HASH) { const struct menc_media *st = zrtp_stream_get_userdata(stream); warning("zrtp: Attack detected!!! Signaling hash from the " "zrtp-hash SDP attribute doesn't match the hash of " "the Hello message. Aborting the call.\n"); /* As this was called from zrtp_process_xxx(), we need a safe shutdown. */ abort_call(st->sess); } } static struct menc menc_zrtp = { .id = "zrtp", .sdp_proto = "RTP/AVP", .sessh = session_alloc, .mediah = media_alloc }; static int cmd_sas(int verify, struct re_printf *pf, void *arg) { const struct cmd_arg *carg = arg; (void)pf; if (str_isset(carg->prm)) { char rzid[ZRTP_STRING16] = ""; zrtp_status_t s; zrtp_string16_t local_zid = ZSTR_INIT_EMPTY(local_zid); zrtp_string16_t remote_zid = ZSTR_INIT_EMPTY(remote_zid); zrtp_zstrncpyc(ZSTR_GV(local_zid), (const char*)zid, sizeof(zrtp_zid_t)); if (str_len(carg->prm) != 24) { warning("zrtp: invalid remote ZID (%s)\n", carg->prm); return EINVAL; } (void) str2hex(carg->prm, (int) str_len(carg->prm), rzid, sizeof(rzid)); zrtp_zstrncpyc(ZSTR_GV(remote_zid), (const char*)rzid, sizeof(zrtp_zid_t)); s = zrtp_verified_set(zrtp_global, &local_zid, &remote_zid, verify); if (s == zrtp_status_ok) if (verify) info("zrtp: SAS for peer %s verified\n", carg->prm); else info("zrtp: SAS for peer %s unverified\n", carg->prm); else { warning("zrtp: zrtp_verified_set" " failed (status = %d)\n", s); return EINVAL; } } return 0; } static int verify_sas(struct re_printf *pf, void *arg) { return cmd_sas(true, pf, arg); } static int unverify_sas(struct re_printf *pf, void *arg) { return cmd_sas(false, pf, arg); } static void zrtp_log(int level, char *data, int len, int offset) { (void)offset; if (level == 1) { warning("%b\n", data, len); } else if (level == 2) { info("%b\n", data, len); } else { debug("%b\n", data, len); } } static const struct cmd cmdv[] = { {"zrtp_verify", 0, CMD_PRM, "Verify ZRTP SAS ", verify_sas }, {"zrtp_unverify", 0, CMD_PRM, "Unverify ZRTP SAS ", unverify_sas }, }; static int module_init(void) { zrtp_status_t s; char config_path[256] = ""; char zrtp_zid_path[256] = ""; FILE *f; int ret, err; (void)conf_get_bool(conf_cur(), "zrtp_hash", &use_sig_hash); zrtp_log_set_log_engine(zrtp_log); zrtp_config_defaults(&zrtp_config); str_ncpy(zrtp_config.client_id, "baresip/zrtp", sizeof(zrtp_config.client_id)); zrtp_config.lic_mode = ZRTP_LICENSE_MODE_UNLIMITED; zrtp_config.cb.misc_cb.on_send_packet = on_send_packet; zrtp_config.cb.event_cb.on_zrtp_secure = on_zrtp_secure; zrtp_config.cb.event_cb.on_zrtp_security_event = on_zrtp_security_event; err = conf_path_get(config_path, sizeof(config_path)); if (err) { warning("zrtp: could not get config path: %m\n", err); return err; } ret = re_snprintf(zrtp_config.def_cache_path.buffer, zrtp_config.def_cache_path.max_length, "%s/zrtp_cache.dat", config_path); if (ret < 0) { warning("zrtp: could not write cache path\n"); return ENOMEM; } zrtp_config.def_cache_path.length = ret; if (re_snprintf(zrtp_zid_path, sizeof(zrtp_zid_path), "%s/zrtp_zid", config_path) < 0) return ENOMEM; if ((f = fopen(zrtp_zid_path, "rb")) != NULL) { if (fread(zid, sizeof(zid), 1, f) != 1) { if (feof(f) || ferror(f)) { warning("zrtp: invalid zrtp_zid file\n"); } } } else if ((f = fopen(zrtp_zid_path, "wb")) != NULL) { rand_bytes(zid, sizeof(zid)); if (fwrite(zid, sizeof(zid), 1, f) != 1) { warning("zrtp: zrtp_zid file write failed\n"); } info("zrtp: generated new persistent ZID (%s)\n", zrtp_zid_path); } else { err = errno; warning("zrtp: fopen() %s (%m)\n", zrtp_zid_path, err); } if (f) (void) fclose(f); s = zrtp_init(&zrtp_config, &zrtp_global); if (zrtp_status_ok != s) { warning("zrtp: zrtp_init() failed (status = %d)\n", s); return ENOSYS; } menc_register(baresip_mencl(), &menc_zrtp); debug("zrtp: cache_file: %s\n", zrtp_config.def_cache_path.buffer); debug(" zid_file: %s\n", zrtp_zid_path); debug(" zid: %w\n", zid, sizeof(zid)); return cmd_register(baresip_commands(), cmdv, ARRAY_SIZE(cmdv)); } static int module_close(void) { cmd_unregister(baresip_commands(), cmdv); menc_unregister(&menc_zrtp); if (zrtp_global) { zrtp_down(zrtp_global); zrtp_global = NULL; } return 0; } EXPORT_SYM const struct mod_export DECL_EXPORTS(zrtp) = { "zrtp", "menc", module_init, module_close }; baresip-1.0.0/share/000077500000000000000000000000001372575704200142535ustar00rootroot00000000000000baresip-1.0.0/share/busy.wav000066400000000000000000001755001372575704200157640ustar00rootroot00000000000000RIFF8ûWAVEfmt @@factûdataû~~~}|}|||{|{{{yyxxxxvxxxwvwxwwwwvwwvvvvvvwwvvuuuuttuuusstutsrqqrrrqpqqrqqrrrqopqstststtuuttuvyyxzz{z{|~ú÷øøöööóïîïòòññïîíííìííììíìììíîíîíìëêììííïðîîîîììîñïíìëìëëëëéçæææãàßßÞÝÝÝÝÜÜÛÚÛÚÙØ××××ר×ÖÖ××ØØØ××ÙÙØØØ××ÖÕÖÖÖÖÖ×רÙÚÚÙÚÚÙØ×ÖÖÙÛÛÚÙØÙØÙÚØÖÖÕÕÔÓÒÒÑÑÐÏÏÏÐÏÏÑÑÐÏÎÎÎÎÎÎÎÍÎÍÎÏÏÏÎÎÎÎÎÎÏÏÏÐÐÏÏÐÑÓÕÕÔÓÓÓÓÕØØ×ר×ÖÖÔÓÓÕרÖÖÕÒÑÏÏÑÑÓÔÓÑÐÒÔÕÖÔÓÔÑÐÑÒÒÒÑÒÒÒÒÔÕÔÕÓÑÒÑÐÑÕØØØÛÜÛáãÝÛÜÝÜÚ×ÖÕÕÜâïôíÞÚÚØÙØÔÓÓÔÕÖ×ÓÌËÌÉÉÈÈÉÉËÉÊÊÊÊÉÊËÍÏÕÚÛÝâðùvn`__ckh}}ûíìúñßÜÚØÖÔ××ÑÑÏÏÑÓ×ÛÞàëìîíò|qjmfb_]^^c__eda\`baf`\WWYWTVXXWWUURONOOPQQRRQRSVZZ]]]]Z[XZ]ZY[\ZZWSSSSTWXYZ]a^_dnzúîðõìçÞÛÚÛÜØÙÛÝÜÞÜÛÜÞäæåèíìêèì|wùîëñþwzyoono}úxoheijjhb^^bhijihisz{odcgy|okddnznillkgn}oe^_djkeimjmwùú|snmq}}vmic_\VPPQONMLKIGGHHGDEEDCCBBABBDDDDDDEECCEGGEDEFCCAAA@@??@BCCA@A@@AAA@@?>>>?@@@??>>>>>??>>?@@@ABCDCAA@BEGHFDDEDEFGFEDFGFDDCDGJIFDFFFGGHHHIIIHFDCEEEDCBCDCDCA@?ABCBBAABAAAABBDECCCDDEHIIIJJKKJJJLONNRUSQRSVRPSTUXWWYYZ[_]^`dqztjhzîõòèåëéáÝÞÞßçæàÞÞÝàæäãåçæëôöîâçïîëæççáÝÙØÚÛÛÜÙ×ÖÙØÒÑÓÐÏÐÎÎÍÌÌÍÏÏÎÎÎÎÌËÌÍÌÍÏÎÌÊÉËÍÎÎÎÍÌËÌÎÎÍÌÍËÊÉÉÉÈÉÈÉÊÊÇÆÈÉÈÇÇÆÇÇÆÇÈÉÈÇÉËËÉÈÇÈÉÊÌËÊÊÊÌÍÌËÊÊÊÊÉËÍÌËÊÊÉÇÇÇÈÊËËËËËËÊËËËÉÊÌÎÐÎÎÎÏÕÙØØÖØÛÛáæï}ýûøñûvqkefijuþÿ{yúøüö~t|}}øîíîíêëøúðîùrww}ø}zøðò÷ûýûüùüûürw~}vyý|omsquzuþú~ûzvzóêèíñîíéâÞÝÛÙ×ÖÖÕÔÐÏÑÐÎÍÎÏÎÌËÌÎÏÎÍÎÏÏÑÒÑÏÍÍÎÒÔÖØÙÛÛÚØØ×Ø×ÔÕØÙÚÜÜÛØÙÜÞÞÛÚÛÞâßÙÙÜÜÛÜÜÚ×ÔÓÐÏÎÏÏÐÎÍÍÌÌÍÍÎÎÌËËËÍÏÏÏÎÎÏÓÔÔըרÛÛÛÙØÙÛÜÜÚÚÙ×ÔÓÒÕÚÙØÖÖ×ÖÕÓÐÐÑÓÖØÖÒÔÕרØ×ÕÕÕÒÏÎÏÐÐÒÔÓÑÑÒÑÒÒÑÏÐÑÔ××ÚÜÝßâàÜÛÙÙÙÚÞÝÜÚÚÞÞÞÙ××ÚÞÞâææèæëðçáãàâåéõððóôùüõæãçëíäßâßâéíèæéãäæêèåããêò{zzüíéêûwroznnqkg_][Y[^^\[[]^^_\\]Z[]^]^`a__c`]\_^ZYZY\YVUWXVTSVVTROOQTXWUVVWVVUTQOSRPQPQQRRRRRTSRRVTPNNQSSSVVTSRTTTSSQOSSRUTTTSPNMNRTTSRQQSWZXVXYXVUVUSSTTSSSUTTUTUSUWVUTTXZWUTUXWX[YY\_ba]YY[_`_b\WVXYY\_a\ZZ\]\]fnkf^`ded_^`dcgfd]ZZ]\ZZYXYZ[_]XUUVUXZ\\\_^ZVWZZ\[XWRPRSURTTUTRTSVWURTSOQUWWTSSONMOUWTPOOSTSQPOOQTRPQQRTUTQQQPPNMLMKHGGHFEFGGHJIGHJLLLLKLLNNQTTTSTUVYYXY[]]]\_bb___^es~qhpôóòëäêôóïïïëééï÷ò÷÷~sxûôïïüòçÞÝäßßëøïàÞÝÝÛÖÓר×ÕÒÔØÔÒÔÕÙ×ÕØÚÙ×ÕÓØÙÙ×Õ×ÙØÛÝÚ×ÔÒÐÒÔÖÕÑÕÚÚÖÒÒÔÒÓÓÕÓÓØØ×ÚÜÙÙÚÝßâãâãßÞÝÝÛÜÞÝßáÞÚÛÜÞÞÝàãÞÜÛÙÛÝÛÚ×ÙÚØÚÜÞßßÜ×ÕÓÑÑÕÔÖÕÕÙÔÒÒÏÒÖ×ÕÕÐÎÑØäâåãßÞäéçèæéëîðïìñö}omvøëæçéïñ÷óïçéôî÷zøïëì{tqpwûñïìõüùùõîçßßäåèëìî~|{uxóäÞÛÚÚÝêúys}ó}{ïëï{wúñûðâáãäæðy|eONWcãÏÈÄÅÈÒ÷RHB?CNüÎþ¾ÂÍñQB<;=BNhàØÛâó`WX\oûïnVE=7;@.0ï½®©©ª¹S-!(T¯–•™¢È,4½£›˜š ±ü6)##'-4>ZæÓËǸ­ª¨¨¬»T- 7¶“Ž” Ù% 2°šŽ” Ë*"9¿§žœž£ª°½É×bI9.+('*<Á©œ•’”›­CU¢“ŒŽ–§=B¬œ•”—«Ö6)$"%)/9FbÛ¼®§ žž ¬Ø0*ž’™², "ÓŸ”ŽŽ’œ±: '?Ä­§¤¤§«±¹ÃéA/'*H°ž—’’—£ï$ +´šŒŒÀ)-Á£š––š¡°è8-*'(+.4;J×¹ª œšœ£¶A">¨–ŽŒ’ h 9­™Ž—£Ë/ &5l¼®ª©©§¦¨ª®ºk5%,Û¥˜‘™¬; [¢”ŒŽ—©G $F² ›šœ ©¸ãLA82.++,.9s¶¤›—–š¡¾/%Ëž’Œš´, $’“—Ÿ¶C(!)3BñÉÀ·¯ª§¦¨­¾?&2¹ž“” é! )¼œ‘Ž• Í(*]´¨¢¢¦­·Ê]F;1*% !*F¸¡™——¯< /®˜Ž•¥J 2·Ÿ˜–˜«Ð7(" "&+09CYÒ»®¦¢¡£®Û/ F¨˜Ž‘›°- :«™’•µ6.T½°­­±·ºÇÞ`=.%-⩜–•™¦i# J¤–”¡á" <·¤žž£¯Ñ:*#  "$'*/Eͯ¥ ¢ª¾5 %ÌŸ–—§B $礘•—­K&"/GßËÃÀ¾¹»¿Èp:&2¾ —“–±0 ,µ›’‘š­;-Öª Ÿ ¦¯ÅT:0,*(%##%*:Õ® ›™œ¥Ç,F¦–Žš³- I©š”“—ž®Y,!#*6JßÁ¹±¬§¤¡¢¨³c/ 3¸ž’Ž›·+ *ºœ‘‘œ³50Ѭ ž¢¨®¸¿ÊïE7.)+/>À¦š“”ž».K¤“Œ‰ŠŽ™³.#O©™’‘–¬ÌE3//4@YâÆº¯©¡œ™˜™ž«Ù,,Þ‘ŒŠ‹Ç&'ÄŒ‹Œ’¶8$&5ܯ¤žœžŸ¡¥©¬´ÍG1)%%/_°”Ž—©I+¹›‹Š”¥O".☔“–›¤±ÏTC::<<@IV϶¨ž™––š¢½25®™‹‹Ž™´.0·œ’Ž”°F'&2T³¬¨¨¨¦¥§©­¾F-!(P¬š‘Ž”ŸÏ$9ª—ŽŒ“ Ë)6¿¦›œŸ¨µÎaF81.+()*/Cꘖ˜ž¯=J¥•ŽŒŽ–¨?Dªš”’•œ«Þ0#"'1AgÏÁ¸¯ª¦¢£§³g.*Ë¡•Ž‘šµ, !ë¡”Ž’¸1'G»ª£¢¤©¯ºÌîY?2)# "+Eº£™•”˜£Õ& (¼œ‘’žÍ%(Ö¦›—˜œ§Â?,%"#%(,3;Ghۨ¡ŸŸ¨¾:!2³œ‘Ž–¥C .´œ“’šªW&,K¿²®­®°¶¹¼Êc;+!+\¬œ•“•³0 >§–™¬9=µ¡›šœ¡­ÌE4.+)*+++/;g¹©Ÿ››ž¨Ü+%ÏŸ“Ž›º* $Û£—’‘–Ÿ·<$);ÿÄ·®¬¬ª©¨«²Æ?)!7µ•” ê$ *¹œ‘ŽŽ“ Î(+ú®¢žž¢«¸ÏR<71+)%%&)6ñ¯ ™–˜­@8«˜ŒŽ•¤L3³–”–›©Ô3& %.;Jtʾ³«¦£¢¦°Ø3%c§—Ž™­6 J¥•Ž™«? 'A¼©£ ¢¥«±ºÈèO<.&!"*>º¢˜”“•Ÿ¿-(¿œŒŒš³.*Í¤š••™Ÿ¯è9,()*,3=JbÓ¸«¤žœœ ¯Z)5²›‘žÏ$ .³›’Ž• Â/"0Z¼®ª¨¨¨©¬¯µ¿c8)-橚’‘˜¦J <§–ŽŒŽ•¦M 8º¢›š›Ÿ«ÁK5/-+)**+.9VÁ«Ÿ›™›¥½4#ó£”ŽŽ—¬5 !]¥˜‘•œ®I( )6Yɹ±¯®«©©«°¾J+.Ä –“Ç' &őޑœ¸/,z­ Ÿ¦®»ÓXB:0-*'),6Ü® ™•–›¨m%/¯™“¡í! -¼Ÿ—”–›§Æ8'  &,5=OÖŹ®©¤£¦®Ò4 ?¬š‘Ž˜«9 6­™‘‘š¬@ 0貨¦¦©®¹¿ÐU>3*"!.ݪ—•— Ç+ A¦–Ž‘œ¸+ =² ›š§»J-$! #()-6CrÁ­¤ŸŸ¦¸F$%Ø •Ž”ŸÙ! "ä¡–‘—¢É-&7}¼´³±°±µ¼ÂÝ@.##:»Ÿ—’“™§K -µšŽ•¤Z!.ʨ›¡¬ÁT:/++)(('+3>Ñ®¢›šœ£»4>ª—Ž—ª; =¬š“‘”›ª{-!'3MϾ·±®«¨§ª®º[. *Ö¤˜’›·, s¡”ŽŽ‘›²5'Jµ¤žžŸ¤«¸ÊyI>6.*'&,8þ®Ÿ˜”“˜¢Å+.´šŒŒœ¾),À ˜“”™¢¸E,#!$'-8C^Ï¿´¬¥ Ÿ ¨ºI' ?¬™“ í" 9«˜•¢Ò*#7Ì­¥¡¡¥©­³»ÇôB2*"%1Ò¨›“‘“š­:L£”ŒŽ–¨A E­˜–˜žªÄB/+*)+.17Ckɱ¦Ÿ››ž¨Ì/(ÈŸ“š². %ËŸ“Ž’œ®F'"/]»¬¦¤£¤¥¥§©®½\8'!,a¬›‘ŽŽ’œ¸,1®˜Ž‹Œœ¹.1¦œ™š¥±ÊN;4/,++*+1?Ö® š˜˜ž°E 8¬˜ŽŒ“£N 1³œ”‘”›©Þ."+9OÝû¶±­ª«°¿J+!C­›“‘“œº+ 8¬™‘”·0/Ù®§¤¦¬¹Ìd@6/+&" (5ͪž˜—›¦Ú' #ÜŸ’›¹+'Ö£˜““˜Ÿ¯j2'$&).9LøË¼±¨¢žž¢®ï- @¬™ŒŒœ¼) 2®™Ž“žº2$8ί¥  ¢¤©­°ºÇk9+$&1Ý¨š’‘˜§X?¨–ŽŒŽ•¥I4º¢›™› ­Ï;,'$$&(*-29Qį¥Ÿž¡¬ç*?ª˜Ž‘›¶+ <¬›”“—Ÿ½3,@Ú¿»¹¹¸¶º¿ÎS3%,⩚“’—£Û$ f ””ŸÊ'$J²£žŸ¨¸ßD4/-+)'')-7}²£›˜˜­[%4²™Œ’ŸÚ" /µ”‘“™¤À7%&/?|ǹ³®«§¥¥§®Ë;'&Oª™Ž–§C ?§——§S##9À¨ žŸ¤«´¿ÝVD6-)$"%+<¿§œ–”—ž¶0"ò¡“Œ™®2#^¨›••˜Ÿ¯^/&"!$+07A\ØÁ´ª¤¡¡§·K(*ÇŸ•Ž“žÆ& %ÊŸ••ŸÁ/+L»¬§¥§ª­±µ½ÑZ8*#!+N¯ž–‘’˜¥ø$ 1®˜ŽŒ“ á$6¸¡š—˜œ¦·zQÕ¸¨ž›˜š ±E%$n¢”‹”¤OR¦—Ž˜¦Ú- *;×¹®ª©«©§¨ª¯¼l3$ 4¿¡•Ž‘›°1 $מ’Œ™®7(\®Ÿ››£­¼ïE;4/-,*+1<篢›—–š§Ô*,»›ŒÀ' *ß–’“˜¢¼:&"+7R׿¹µ­¨¥¤§®Æ>&!<¯›‘Ž•£S 2®™–¥b$.ß®¥¡¡¥«´ÄöQ?3+&" '4Ú«—”—žµ3 G¦•ŽŽ—«:E¬œ–”—ž¬Ô7)%$&*/8DQÞ¾³©¡žŸ£­Û.(ÍŸ”Ž›¸+ "ä¡•”·4)C都¨ª­°¶¼ÇW8* (AµŸ–“’–£ß$ *º›’žË%+̦œ™™¦¸g8-**++,15:VÀ«¡œš› ±B":«—Ž”£L 4®›““š¨ï+".Hͺ²¯­«««­²¿W/"+÷§˜‘’š®6 O£”Ž˜¬<#A´£œ›ž¤­¿îL<3/-*''+2K¸¥œ——š¢¾- /¶’•¢Ï--J¹¨Ÿž¢¤§¸L0'""%+:è¹®««®¶ÎUH=416:@L\ÙȽ¹º¾ÏmK>:77>OþÑÆ¿¼½ÈØxOE=ª˜Œ”¤L <«™‘˜§å+%6ò¹®ª©ª©ª¬®´ÀU3' .Ì¥˜‘š®6 U£”Ž˜«;"E±¡œ›¡­ÆY=3/.,*)*/9_·¦œ˜˜›¥Ê-(ÊŒš´+ 'Í¡–‘‘–ž³D(#+;[Í»¶±­ª¦¥¨­¿?)8·“Ž• ×# -³šŽ”ŸÍ(/Ù­¤ŸŸ£ª´ÀéQG8-)$#$(4뮞˜•–­@6«–ŽŒŽ•¦B8³ž—•—«Û5' #(,6DNqǶ¬¤ŸŸ£®Ø1%ö¢–™°. X£•Ž’œ±8%=Å®§¥§«®µ»ÃÙJ5+"&:¾£™“’– Ì( &‘‘¿))ߨœ˜˜œ¥¸\5+('(+-.5>hDZ¤ž›£¯H#0±š”¡r 0±›’—£É.#1TÀ¯«ª««ª«¬¯¾`8(+r©š‘˜ª? E¦•ŽŒŽ—¨F!=¶¢œš› ª¹ðC:2.-,*+.:\º§˜—™¡¼2%П’ŒŽ™¯2 #n¥˜’’–ž²H)!)7OÞĹ²®ª¨¦§«½A)/¾Ÿ”“žÈ& '¾’ŽŽ“žÂ+*W³¦¡ ¤ª´ÆíWD7.(# %.N³Ÿ˜•–œ«F /±™Ž”£Q /»Ÿ˜•—œ¨É:)#!"&-6?Ijɺ­¥Ÿž¢«Ä6 K§—˜«8 <ª˜’›®< 0]»¬©ª®±¸ÁÍëC0(!.㨛•“— Æ' _¡”Ž‘œ¼*!I®Ÿš™¥¸X4*%$%&(),1;_»ª¢žž¥¸?!(ÍŸ“Ž•¢q  &É –‘’˜¤Ë.);è¼±¯¯­­®®´Ã^5$$A¯“‘˜¨I 6¬˜Ž–¥Y"5¿¥›œŸ©¸×L;51.+)+,1M¼¨—–˜žµ<"o¡“‹•¦>"Y¥˜‘“›¨Ï3% !%,;\ɺ°¬ª¥¡Ÿ ¤­Ø3"4¹’š¯2 '½œš¯7,q¯£ž ¤«´ÁÔkE7.)$$*3t­ž–’’—¡Ì(1¯˜Ž‹Œœ¿(0ºŸ—“”™¢¶N.'%%(.7?MäÁµ«¤žŸ¦¸C$"H¨–ŽŒ“¢h @¨—–£Û*'9ΰ§£¤¥§«®µ¼ÉG/'#2Ë¥™’“›±4 \¡“ŒŽ˜¬9"K­ž˜˜šŸ¬ÇE1++++,./6Cñ¸§ž››žªà)%ÙŸ“ŽŽ‘Ã& !u¤—’’˜£Ã0$1OÓ¿·´´±¯±·ÀU0#1»Ÿ–‘’˜¨D %“—¨M'Q²¥ ¡§°ÉK7.*&$" %-L¼§›œ¤Ç- .±šŽ™®0 -½ ˜–™ µC''..&'6¿¡—ŽŽ•¤_""ßž‹Š‹‘ŸÛ%'_©›–”•𢮯W?:65<>@RÚºªž™•”—ž®D"-º›‹ŠŒ”¦?*½’Ž˜¦Ó0#'4WÀ°ª¦¥£¢¡¡¤¨³î6%&D­š‘š±/0¯˜Ž‹‹™¯7 6¾¥œ™™›Ÿ©³ÁÞM=:3-,,3K¾¨œ•“”™¥ë&?§•‹ŒÑ#<­›“’˜¢»@*#"$*5Içû±¬¨£ŸŸ¡©¿;$&|£–Ž–¨> G¤•Ž—©K"$;¿«£ ¢¥«´¾ÐzH6-&  ';¿¥™”“•ž», "Ïž’Œš².%c¨›––™ ±u4*''(,/8>J⿯¦Ÿœ ¯e*0µ›Œ‘œÅ& ,µ›’Ž”žº4 .Q»­§¥¨¨ª­¯µÃf7) +_¬œ“‘—§Y! :©–ŽŒ“¡û";¶ š—˜§¶å?4//...07Aå·¨˜˜š¡µ;"\£”ŒŽ–¨< N¦—‘“›«Y*'7TÈ·³¯­ª¨©ª®¼N- .¿Ÿ•’›¸* "Òž“‘œ¸.&I³¤Ÿž¡©´ÊY;50+'#!#%-I»¥›˜˜œªR" )½œ“ŸÞ! )Å¡™•—›¨Ë5$")3>Näν¯ª§¥§®Î2 7µ›‘—ª> /°š‘˜©I".~¶ª¥¦ª®¶¾ÔcE3+$#/ܪœ–”•ž¸2 F¥•Ž˜­2 ?¯Ÿ™—š °í5)%#$(+-2;JÕ·ª¡žž ®l*)Æž“Ž›º) #Ò •”ž¸5)>Í´­«««­¯±¶ÄO5(&;ºŸ–’’˜¥b ,¶›Ž” Ü$-Í¨š›ž¨¹u=2.*)*)*,2CÍ­¢œ™š¡³=:¬—ŽŽ–©= 8®›““›©ê,&3MÓ¼³¯­ª§¦¨¬¶g. )Ú¤˜Ž‘š°/ S¤•ŽŽš°5%A¹¦žžŸ¥®»ÔXA6.+'$%'.N¹¤›–•™£Ì)&Ä‘Œœ¿' %㥙••™£»?) #)/Qê˼®§¡Ÿ ¦´R+3´‘Ž‘Ç& )»œ’ŽŽ”ž¼.-]¶©¥¤¥©®´ºÈeC4)""-n­”‘’˜¦Z! 7ª–Ž‹“ è"9´ž—•—œ¦¹O3+)*+-.3:Fສ¡›¥¾4 T¤•ŽŒŽ–©7 M§—’š«U('9ß·­«©©©©ª­´ÇN/# 4 –“œ¸, #Ê‘Œš²/'[­žšš¤¯ÈK93.-+**,1=ܯ¢›——›¨ë(0°™ŒŒÄ% .¹”‘’˜£¾:%$.?ðù³¯¬§¥¤§¯É:'$F«™‘Ž•£R :ª—Ž–¥d$ 6韞Ÿ£©³ÆÝS?7/*$#%+<ƨ›–•—±3O£”ŒŽ˜¬7  H«›•”˜ž®v1& $(.9Hhг¨£ Ÿ¥²e,+Ÿ“ŽŽ‘›») $Ο””¶2(B½¬§¥¦©®µ¼ÃÛI4) (D²Ÿ–’’—¥^" ,²š’ŸÔ#-Ƥ›˜™§»M1+(&(*,.2646;EX߯»´²¶½Ï[D<88=JtÓ¼Æ×oOE?AGSéÐÇÄÇÉËÌÏÜ{YMIEENzÑÉÅÁÅÍÛpWOMVoùäØÒÒØÛäë{r~øéèåírkjgm~~ôàÜãõrntsjlmvüüôó{lkecklk|úþv|qbdei|êÝÜÞáúvoghxëÛרÖÛêôù~ñìàØÔÒ×ãìëôtqyïãØÕÚÚåóùomko}|îâÝÜÜÞáÜßáäèîyýýýüðíçßÛÕÙÝßêuf][`enúåÖÏÏÒ×Ýì|a_]]ahéÜÙÜâåìvfb[X[YY]dnr{äÛÛÚÞçþe]ZVUV\zäÛ×ÒÔÜçweZQPU[böÞØÖÙÛßê÷zvtqowüíæâßåæð{phfegenjbgdfmz÷ÿzûyqnu}xmhjvõvkmv}úóô÷øôëåìñüøú}÷þòðçÝâçéåçó}xnghcbj}ìëïðõûuhjptuqþìììéèäàâÝâïûvtx|mm~züóïúsùôûö~mnsuöæßàâÜÜßáèæï~~ýodkxö÷~øötorgaecbcgp|öìéí{ookhbdipqmspn{÷~qf_bjjjghtõæßÛÛÞßãáãêðùùîæëùþìçææëõ}~~oeeinkøáàãçëú|}|üvs{zöûwúñòïîîîòïêêééäÞÜÝÝÚÙØÙÙÚÜáßÞßÞÛÓÏÒÒÐÑÕØÙØÜÜÚÜÚÚÝÛÚÜãääææçãëø{u|ûþòìütokmmglsu{}}þ}øôíßßëóïæßÝÚÙÙÙÛÞàÜÚÙ×Ö××ÕÑÑÒÏÏÔÚÞÝØ×ÙÙÚÖÙÚ×ÓÔÜßßâåêñþzro{mip}vnnonga`hjlnnno÷ïøûnk{urphkov~õíôz{ýymllljkzôêåäêðû{~nkllolhlsx}zng^]a_^_c_doh_^^``ejja]_ba`d^_a_krpqsvþ|ý÷ú}öèéèìëâÝÝæòõòïññéçéïæâêêëéíõïëöù÷üü|÷éìôòø{wopsrxwqlhny|ö|noxxpv}voz÷|puwynjmos|tmsklrrngb^^_cglokihb^_c_\XVXXZ\ZWWVXZVUUUVVY_beg^]^cgfbbeeigc^[]^^_^ZXYZYZ\YZ\\XVXUSSTURPPORQPONNOPONLMNPOPOMNMNNNQQOMLMLKLNNNMMNLJKNNLKHHIHJMLLMNNMKKLLLJLMKLMNOMLKKLLJJLMLLMKHHJNY^XPMLOTX[]]][[[[gvtjb`bfwíçÝÕÑÓØ×Ù××ÜÜÙÖÖÙÜÝÛÙÜÝàâæììïíí÷úûzþö÷ñ÷mfd__a[VWXXUSTVQMMKLOONKHIIHILNNMNRTUSPPRRTWYZ\]agjjec`___bfgebcbdhjjcbcd^_ghonlg`ddbee_[[[]^^`_`hppszþþnuøþ|õäßÞØÓÓÔÒÔר×ÖÔÓÖÔÒÑÏÏÐÒÐÑÔÔÒÔÓÓÑÐÐÎÎÏÏÓÔÓÔÔÐÓ×ÒÒÓÔØÚØÖÖרØÛÜÜØÓÐÑÕØÚÜÚ×ÕÓÑÔÖÕÔÑÓÒÎÍÎÍÌÍÍÍÌÉÉÉÉÇÇÇÆÅÆÇÅÅÃÂÄÆÇÅÃÅÆÅÆÈÆÆÅÅÆÄÃÄÄÅÃÂÂÃÂÀÀÁÂÂÄÅÄÃÅÇÆÆÆÅÃÃÆÇÈÇÆÆÈÉÉÈÈÈÇÇÉÊÉÉËËËËËËÈÉËÌÌËÊÌÎÎÐÏÏÑÑÔÕ×ÚÛ×ÖÚÛÚÚÞãÝÜÜÝÞàæëêâåéèêîêèíýwøñüúïìëðõ÷ý{|ziaaeecdafolr}upksòëåâßÜÙ×ÓÎÌÌÎÎÌËÊÉÉÊÉÇÆÅÅÆÆÄÃÄÅÅÅÅÃÁÁÀÀÁ¿¿¿¾¾¾¾¾¾¾¿¿¿¿¿¿¾¾ÀÁÁÁÀÂÃÄÄÄÄÃÁÁÃÂÁÁÄÄÃÃÄÅÃÆÇÇÆÆÈÊÊÉËÌÌÎÏÏÎÏÑÑÎÎÐÏÏÒÒÒÐÒÔÔÔÓÕÓÒÕÖÖ×ÙÜÞÝßÞÝÜáíñïöüïìíûngeaakwk_YUTRQMLMNNJHHEEGHGGFFGEDDBBCDDCDB?@ABCCBA????>??>>>??ABABBBBEEGJIFGIJKKIHHGGHJJHHEDEEEEEFGFFHGGHJJJIHJJLMNOMNOONNNMNNNPRRVYZ[ZZ[ZZ]\XZ`bfjmkghf^\\Z\fmldaa]]]_a_ZX[[Y[\ZZZZYY\\XXXUUSUUWYYYVSRSPORRTSQNMOOSSQPOPOOSVVVSORQQROOQQONLKLOTSRNLLOPPNMNMKJJJKLMMLLLMNLMNLLLKMNNNONNNLORONNOOSUSRTWXVVVWWVWVVVX[^_]\[XVWVSTUVWY[WTVVUTTUUSSPQUVUTSNLMOQOOOOPPRPOUUQQONOOSY[^^[]^^a`_ahn}þyyýõôïòôôùòîôîôùõøù~zúïíîîíóüsic_^][[Z]]\][ZXWVYWWXX]_cfec`]]]^^cikhglno{ývvmhjnmlltóúütry}ÿùõ|wlxþsuwxzobfkhhagk`^^ahe^[\^_\agilknifjjbckmtmlie_]_cisú{ÿý|÷îêííðõòîïîäãáÞÞÜÛÞàãâÞÜÚÙÜÞÝÝÜÛÜàæêéàÚרÖÓÏÒÖ××ÙÛÙÕÖÚÙÝßÛÙØØØÛÞÝÜÝÜÛÛØÔÒÏÐÑÐÐÎÎÐÐÓÚØÑÎÍÍÍÌÐÑÏÏÑÒÏÎÏÔÓÒÕÖÐÍÎÑÏÍÎÏÏÍÍÎÏÎÏÏÏÎÌÊÉÊËÊÊÌËÉÈÈÈÇÇÉÌËÈÇÆÇÇÇÉËËÉÉÈÈÊÉÉËÌÌËÊÉÉËÌÎÍÌÌÌÌÎÎÎÏÏÏÐÓÓÏÏÓ×ÚÚØÕÕÒÑÒÑÍÌÌÌÌËÊÉÉÈÈÈÇÆÆÆÅÇÉÉÆÄÃÄÆÇÈÈÇÈÈÊÊÈÈÉËÊÊËËÌËÊËËÌÎÎÌËÌÏÓÖÕÙÛÝÞÞàÝÝßáâÞÝÞÜÜÜÙÛàߨըÙÕÓÖÛÜÝÞÝÛ×ÖÖØÖÑÎÏÎÏÓÒÓÒÑÐÒÐÏÎÍÑÒÔÒÒÖÖÛáßßááåíï÷ûøvmhfhm|ýûöïòü÷ùyyýwüó}~}ööøïïóznszùïïðöîíæäêìêîîêèåìëíëâßë~vmmsz~xgb__cb_\\^_^\[YXWZ_a\[]][[[[[\\^b]\^flie`_^[]bb__geo|pllmjb]^_beidfg^\[[^\\]]^\YX[]]_`[ZWY\\]XVUVVUY\]]eb[WWXWZZXWUXYZ_d\YZXWYWUSUUTUVWZ]__YTTRQQRWZXUUWTRQQSPPQQPONOQOOOONNNORVUURPNPQRWY]b^]afgfifbefcddfmyonvngdfnwkid]]bea`aaih_ZX[][WUTRQQPTTRQNMNMLJHJMOSUSSOQVXYSOPTWWY]^gtû|omnuïçùjs|íÝÝÛàêîîáÞãèéìîíëçæìíðïøû|oowøûm``dfhcbb___`jh_a_^^aa_agihoqlosvqpuyüx}õòýþìîìêïíëèÞÚÜßãìêèëëñôôòîêóùîèèñüyolln}}ojgceklor{|ssmnùéäâçîðóûíåäßßÜÙØ×ÓÐÑÏÍÍÌÊÊËÌÍËÊÊËÌÍÍÍËËËÌÍÎÏÓ×ÖØÙרÚÚÛÙÚÞÛÚ×ÔØØÚÝÛØ×ÔÔ×ÖÓÓÖÚÛÚØ×ÙÛÙØÙÖÚÙ×ÛÞßÞßßåææëííîñ~{{olnkjhbb^ZVVY[Z[\]]XWY[]^^df_]^``_ZWWYWTUVZ^_d_[[TQVZXUUX[X\ba_[XXUVXZ^ZZ\\[\[Y[Z\[XY\`ghid_ded`a_]]ahkkfahtqmloolkyüôötq~òîíêßâëíïö÷þzõéèìêï}}ýtuÿuiitz}ïæãêópmptuozrqmkkmnosnha^\aegighosw{qnia_giachioýÿtmopmmrvox|{÷ðü~~yþïçíý~{zxvqnlhjjkhaehmzofimwýzsujdipy}ýó÷uqúñõñêàèñù}ù÷ïíèçèçìéßàæëóúõêèëîîíõ}}õ÷zmqwlis~xy|}}íçîóíæëêêìæåäèçãÞÜÛÚÜÛÛÜÝÛÜßÜרÚÛ×ÑÏÑÓÕÖÖÕÖÔÏÎÎÏÒÓÒÏÐÓÔÓÓ×ÙÙ×ÙÚÖÔØÙÛÜÝâæãÞáëêìëèèççáâãäë}hit}wptllx~óëâæóýöñðõþúóòïìëççâèïòvjlvrvñèèîìêïõunxzwunmlmruzyvmieca^_^_`^]_eeki`dmwrq~ôïäÜÝÞÞÞáàÞßâçåæâããàêçââÝãíøùñïèèëõúñôïïysxýøüyûëø{sgda]akrunwtrsvojkjroúì÷ù|ynilnrlgceb`dagb]WPPORVYXUUTROORQOMMOPOOOOPRRROPSTTRQRSVTSUZYXZWVUWWXZXUSURQTWYVXYXWUSTXXURTWWXYWY[ZUPOORTVVVUSSRRQOQQNOQSSSVYZYWVVUTTW[cilvsjikjifhhhimu{tuzy~øûvosùòïïðûüóïï÷îðñììñöïéåíìïùýöêããéèêëåãåéêæèêæèêææåèìêî÷üöëãáâáéìåçëëëçââèæáâåçèâÞèëçäæéáßèæàãßãæâàåéîåäçäçêïìêëîîìíëããÞÜÞßâãæÞÜÚÙÜÜÙÕÓÑÒÔÔÓÖÖÕÓÐÏÒÓÓÓÑÑÒÒÑÕØÔÎÌÏãvßÏÌÇÇÈËÕçs`_ðÖÊÄÂÁÇÚeUXVWů­­³ÈI.%"&/i¬ž™—™£Â/:¯›’—¥÷&#?² ›™šŸ«¾Q82/.259å¼°¬«©¦§ª¯¼e0"(l§™Ž—©= <§–ŽŒŽ•¤R 3¿¥œœŸª¸ÛG6/+(&##(-?Á©ž™—š£Ã* M£”Ž™±- =­œ–•˜ µH)#*2>Sã·­¨¦¦«¿?%'Ó¢•Ž“žË" !é ””ŸÅ+%=Å®¨§©­´Âß[D7,%&:¼£™•–š«C (¾œŽ•¤O )Ѧœ˜™ž«Ï7)# !%'*/5§œ–”–›¬D !c¡’Œ‹“£V"W§™’“š¥¿<*%%'-;Oåɼ²«¦Ÿž¡ªÂ8 ,ÅŸ“ŽŒŽ˜¬3 %Èž’™«D",_²¥ Ÿ £¨®³»Ía?/(! %-K°ž–‘‘•ŸÊ)*·šŒŒœ¾),Ä£š––š¢²m5+)**/69F^ϸª œššž­f*G©–Ž‹Œ‘žÏ" 7«™Ž—¤Ô,#2]¼®ª©©©ª­°µÄL2'.ا˜‘‘™ª< V¡“ŒŽ–¨E"F°Ÿš™› ¬¾d=4.--+,-/:i·¦™˜›¦È.%ÍŸ’Œš¶* $ᢗ‘‘•ž³B' +=óö°®¬¨¦¦§­¿D* :µ’Ž“ž×$ +·›Ž“žÁ+.Þ¬  §±ÂèL>6-(%"#(2ü®Ÿ™–—œ­> 2¯™Ž–¦C .¹ž—•—¬Ý2$ $,6>NÚö­§¡¢¥®à1"N¨—Žš°/ =¨—’›°7 4뵪¨©­´»ÃãN>/&"1ש›•”˜£Ï'  tŸ“Ž‘À' #R¬™™§¼G.'#"#&(*.8G㹩 ¤¶@!+¾’ŽŽ“¡j )½ž•‘˜¥Ò,*?Ï·¯®­­®®¯»ËO0$%@®œ•’™©; 1­˜—¨B1Ƨžœ£­ÀU91-+)''(*1JÁªžš˜š£¼2 b¢“ŒŽ—­0 R§˜‘‘•œ­P*(2Jѽ·°¬ª§¦¨¬½G,0¾ž“ŽŽ‘›¹* '½œ‘‘›µ2+o®¡Ÿ¥­¸ÇíN?5-(&%)4û­ž—““˜¤Ø'2®˜ŽŒŒžÏ$1¸ž–’”™¢¹E,&$%(.;Jkɼ°¨¡žžŸ§¼A%$S§—ŽŒŽ•¤O G¦–Ž—¥o'&=Æ­¦¢¡¥©¬±¸ÃÞL3(! '9¿¤™’“œ²5  þ ’ŒŽ˜®3%_«——š ­Í?.)()+.05>Oʯ¦ž››žªá*,»œ‘Œ›¼( )¾“•ž¸9"!-LŲ«ªªªªª«®·Ö>)%?±œ”–¤e  .±™ŒŽ” ä#0¦››ž§´ÏL;4/.+*+.5N¾¨™–—ž°BJ¥”Œ•¦CEªš’”›ªæ. !'3JÚº³°«¦¥¦©´~/,Ê¢•Ž™®3 !Öž’š®:(H¸¥ŸŸ¡¥­ºÈkC9/)$! #+@»¤›–•š¦ö& (¿œ‘Ê% )È£™••š¥¼>)" %+/7BQÙ¿´©¢¡¢©À9!2´›‘Ž–¦G -µ›’‘˜¦^%-X¼­¨©«­³º¿ÔY>.#,_«œ–“”œµ1 :ª–Ž™­59µ ›™›¢®Ï=/)))(+,/4>ò·¨ œ›Ÿ©Ï,%ÏŸ“š·* !ö£–•ž¶8!'9ü¾²®­¬««­±µÌ;*"8¹ž””žÈ$ +¸šŒ’žÅ(+嫟œœŸ¨·ÕJ7/-+(&&)+4Þ®¡š˜™Ÿ²?3®˜ŽŒŽ•¢N 4±œ”‘”š¨Ñ3$%.?sź·®©¥£¤¨¯Ò5"'x¥–Ž˜¬8 R¤”Ž˜ªC %B¸§ Ÿ ¤ª±¿×oJ7-'""%,Cº¢™“’–ž»-&ÆœŒŒ™²-)Σ™”“˜Ÿ®ç5)&')-5>UÞÇ´ª¤žœ¡°[)7²š’žÇ$ .³›‘ŽŽ”ŸÀ.!0e·ª¦¥§©«¯¶¼ÌR6)  +Oª›”‘˜¨H 9©–ŽŒŽ”¤N9µ ™—™ž©¾M6-+*),.04=l»©Ÿ›š¥Á/ W¤•Ž™¯/ B¨˜’•²>$$1Sʸ±±®¬­®¯¹ï:(+Ú¤—’‘–ŸÊ# ã¡”Ž”¡Ú% ;¼¨¡ ¥¯ÈO:0+&$" !$+?¿©ž››Ÿµ; (¾œ’Ž–¦A %ᥚ—˜ž¯P)!*3;EnÕ·°¯¶ÇE)0¸ž•‘“œ±/ .°š‘’›¯8-f´¨¥§¬²¿óN@4,&!-[®ž˜—™¢Å) G¥•Žš´. E¬œ—–™Ÿ°s3(##&*/7AWÚ¾¯¥ŸœŸ­é,/¼›º( )¼œ’ŽŽ“µ7 !/o·ª¤¢¢¤¥§«¯·ÏM3&! %3ب™‘ŽŽ“ž¿)<§•ŠŒ¿*:´Ÿ˜•–›¢¯ÎF:4/2/08;JÒ´¥œ˜–˜«Q$&ÒŸ‘ŒŠ‹‘ŸÜ"%Ü ”Ž• ¾8&&2MƲª¦¦¥¢¢¢£¦°Ï=(#8¹ž“Ž—©<(¼›‹‹•¦N"/˨œ™˜šž¦®»ÒlH=8/-/5?Ϋž—““–ŸÀ,.µ™Ž‹‹š¶*/·”•ž¯].$"%*2Cõȼ³®¨¡ŸŸŸ¥µQ*#J©˜Œ“ŸÕ" 6ª—ŽŒŽ”ŸÉ+"6È«¡žž ¥«°¹ÆáF6,%#$*=¿¤˜‘‘˜§U "âž‘ŒŠŒ“¢W$\¨š”’•›¦¿D/*)+-3;JdØ»®¥žœ›ž©Ç1,À’ŒŽ—«3)¾‘˜ªV(#/e¶©£ ¡£¤¦ª¬³ÊO2& +N¯œ“”žÁ( ,µšŒŒ‘¾*.Ç¥›˜™¤°ÏH91..-/02;^¿«Ÿš˜˜ž¬Q#:ª—Œ“ Y 0³œ”‘“š©ú+!,>oź¶²®«¬­¯¾L.!&U©™‘™¯2 H¥•Ž™­; 9¿§ žŸ¨°ÀkA92,)%!"#*>ɪ˜˜›¥×( t ”Ž‘œ¼' "Z¨š••™£»B) '.9Ikﵫ¦¤¦«¾?%-¿ž“ŽŽ” ú  &¾’Ž•¡Ï(*K»«¦¥§¬³»ÉôM9-%,Q°ž—”•›®< 1®˜Ž–§@ 0¼¡™—™ž«Ò8*%##&*-397:@Qåɽºº»ÂÑrOEAAFO_æÒËÆÆÆÉÏÚzVLIILZtÞÍÆÅÊÑÜó_\\_søåÛÜßáêêìöüûùøù~ÿtigccjn|vyyjeda\Z]eccefggbchhdinolfbdc]_mrq|òë÷~labhvzüyùêñrf\[_bixñì÷x{s_YVPNPY_jhba_]WSQOOPTWXZ\YW^c_]YWUOMIGHMRV\\]__^VLHFCCGMV\mñø~ob[RMNRWVXco|úûsuuje]SOPSXY^hvôâÞâìs_VOMOQ]væÙÐÏÕÜìþeWPPV_oôáÚÚÝÝÞèygjicfmsûîîèìêåëó÷~y|qigikcbknvyuopmjgiqwskkowüû~se\[[X]`_eb^\ZWVUSRU\]ZYWUVQMLLKJKLMNMPROLMLMMNRQOLMOOMRXTOQYXUSSOOSQPQSXZ]\WWWXUTSUXUW[][\eh_XWYWUY]_bgnklllojfikhkliggpùîéìö|nnwnlimþý÷õ}}ìæíïøwnn~ýõôíêéÝÜÞãâçëëñùyvòèæáÝÙÖ×ÛÝßåçæåàÞØÖÙ×ÙÝßáæð÷÷êäíðïèæçàßåèçéêíïñîåâæðûøêèëåì}njf^^^_cgjb_bbcgccaZZ]\[^ehbaa_b_\][^gdjj_^`cdb`]_cdhd_cd_``dgdb`^^][]`b^][^cee_^^diopjgfihhglutrw}x~îúoorsjccefsñðûýðîíëãààãâßàÙÕÒÐÐÑÑÏÎÎÏÎËÉÉÈÉÊÉÊËÊÈÆÄÄÆÇÈÇÇÆÈÈÈÉÈÈÉËËÌÊËÏÏÏÐÐÔØÕÒÖØØÛØÚÜßÝÕÑÐÑÕ×ÓÓÕÓÒÕ×ÕÕÔ×ÔÒÒÎÍÍÎÏÏÏÎÍÌËÍÎÎÎÍËËËÌÌÍÏÏÏÑÐÐÒÔÖ×ÛßßÜÛâêðü÷íëñïð~rnrqppicid]^^]_^\_]^]_dbf`_begheaghabim{yplpÿôñxvý~úù~úðîòõ÷õñìêîòîïúüôòñðóò~}siijf_^[ZXY[_dfc^_][XXZ\Y[a__`cfnmmtqhccceo}pw|tnýõúìèæêïëåèâÚÛàâäéîêåìëççäæëõsr~þ{úysyy{ujda`jmjlkioynjjjknrosunoùõïäãäåèäÝÛÚÚÛââßàßèçáÞÞáêéäèåäçäèööïëééëäãàâéëëäàÝÝÝÛÝÝÜáçéäÞãëèâÝÜÛÙÚØÖØØÙÛÚÛØÕÑÑÔ×ÖÓÒÏÑÓÔ××ÕÕØÙØÙÙרÙÙÛÜÛÙÚÝâããÛÕÔÖÛÞÜÙ×ÓÓØÙÜÜÙÚØÓÑÒÓÕÖÕÓÔ×ÔÒÒÓÕÖ×ÔÓÑÏÓÕÖ×ÕÓÐÑÔÕ×ÖÕ×ÙÜÞÜÚÛâåçèéêéðöùyrmf_afhla``^]\ZWXTTPOTSRPPSSOMLMNMMOOOPQRSTV]^]^[XX[]_ajmsüxzøù~shmvlgkiit}xsjc^^binflt}{þû~üxþyrg^gqøøwmlwxxvq|ýnls}wnw~vuþrppo|~z}þytoligjnoqolhfiovoicebeieafmlnwðýnjebaa[Y]`bad^Z[XZXSONONONONNMKKMMKKKKLLLKHIKLMMKKKLMNRRPPORVYUSROSTQNMNLMMNLJJJIFHJHHHGFGHGGGIIIHIIHGHKJJJJKJHHHIKJHIKMMNOSTQQROMSXYWVYXVWZYVUQQSPORVX[[]_^_`a^^^b_alüìîõý}s~ðùÿstîçâèðóôòóëåæûs÷çæîîíûrqsnihhddkdZWX]^_`]\[[]`a_YUUUUUX]ebd^Y\\YXYY_][\_cgj`]]^_^]ejjlooghgbeoma^bediefkb^_^_`^^__`dbehknnmhjnmgfmlkfcms~îæäèåääåßÚÞÞ×Ô×ÖÑÎÎÎÐÐÏÎÏÏÎÌÌÍÌÌÌÎÏÍÌËÊËÎÑÒÖÔÔÔÑÏÏÒÓÕ×ÖÔÖÚÚÚÜÚÖÒÒÒÐÕÔÐÍÏÑÏÏÎÍËÊËÎÎËÉÊËËÌÍÎÏÎÍÊÈÉÈÉÈÉÉÇÈÉÆÆÈÈÉÉËËÉÈÊÌÌÌÌÏÏÍÎÐÙÙØÙÙÖÒÕÕÕÖÙÜÜÚÖ×ÙÚÙÖÖÚÙÙÖÔÔ×ÚÛÙØØÙÙ×ÓÏÐÎÎÏÏÐÑÒÏÎÍÍÎÍËÊÌÏÏÎÎÐÐÖÞßÞÜÞáâçì÷~ñð|wxoswzúÿ~xnls~pnrv~ru|}÷óûþîìóöíÞØÚÝÞßãàÝÜÛÙØ×Õ×ÖÕÖÖÖÙÚ×ÚÜÛÙÚÛÞÛ×ÚâãáäâßàçàÞâèåÝÛÜÞÝÞàæçãääáãçðòêåãßÜÞååßÜßßÛÚÛÜÛÚÚÙÒÐÑÑÓÓÓÒÓÓÔÕÑÑ×ÛÙÖÕÖÖÕÔÔÕÙÞÝÙØÚÚÖ××ÕØÛÜÚÚÞÞàßÞÝÛÜÝÜÝÞÜÝÞÞÞÜÞæèÞÙÚÚÛÞÞßàáÝÜÞÝèïêäÞâááßßáäåàÞÝÞÞàãçæßßåèèëéîòìëìôwrõôzumllmrozzswzvnokbZY]^_aea]]ZYVTQONNRUWXYZ\\YVV\^]\\[Z[_b__\ZYVZ]YY[_a__f`ZZ[[[ZZ]]]b`_`a^[ZY]`a_ZWWZYZ_a`^\\\\^^]\YXWWYZ[]\YUSWVQQRSQNOQPOONLMMNOOOOMMNNNOONMMOQQOMLKNQSRSQONRURTWUUX[ZY\_bjd^__dcdghkowüõxpøôòõöìîèìêçáßâáìèçßàèæßÞàæñó÷õííôìíõÿþòîïéì~ñôñôòëéíðõxôíó÷öðñöúüusøðõsmopqnxxtrojiotsfbfda^]^aabiillheeioogjkijlrichionh`_chnlhb__afjkjigacejt÷ô{suqkmvýnimrsmlgbaa^bgkmgged_hmhkfcdhloszøùðûs{}}ynoùïîåààáééëúpousrs~ùôù}znovnkkfehjoxy}x}÷oroowpojmwõïîñó÷wnomjyôîöuvuqxúïü{qlpxôîïûýúïêéíùý÷ëëòêëïéååëúùïêææäáÞãâÞàäëëéâáßÞåìñèßãëëëóyúöümeffrzsiebbfhomelwoikvuozùþrpöêìèßÚÜßßßÜÚÚØÕÖØÖÔÔØÙÚÚÛààÞÞÝÙÛÞáàÞââßàäæçììííìæäïëïý{nttomf_^^bhie`fquqsqpüúzpmqxôëëñ÷ý~øü~ûúzmo{sghoþyqwnnqøïîxq|wõ}oqz{sqtmdb][ZVXVTVX^cccac_Z[[X]egfbeiknnuuzyomuymmnpùïûupvøú~{qoxöîíîñÿkhjuzmrû÷ôõ|÷ý{ö÷ðëçæåáßßàÞÝáßßÝÙØÖÙÛÜÜÖÓÔÔÔÖØÙÙÛÜÞÚÖ×Ö×ÕÙÛÙÚÚÝàßáçàÝÙØÖÙÞßàâáéæßßÞßÝÜÜÞÝÛÜÜßáæìïßÛÝÝÞÛÙØØÝÞÞÝÝÛÚÙÔÔÓÑÒÔÖÚßÝÝÝÞßäèãìëàßíüïðþtoqvzypnþðûwlgd_^^Y[[XZWWURUZXSUWWXVUVXYXVVZ\^][\]\\]aghb_d`\ZXURSSTVXZ[\]\[\befjc]]ft{ÿ|qhbcfjgcgia]_edbb_^ZXZ]abhd_]\\ag`^^`^\[Z]\]ehfghdimnqkegrøõûõ÷xnot~zkhgc`aa`^[[\[\ZVSPQRRTTTSRTRRSSQQROQONNPURPTWROQUYXUTTSW[XYY[\[XVY\^^aa``\[]cjnhijektvoqnnqllkmyskgda_dbagjd^]`gb^^a^Z]eeb_bchorpoöí÷ýûxmijlporwu÷óïêê}spqph`_hnnrù÷ôôü{zxrskgjwzjis~íéëîíåàâåçèäÝØÕÖÝÝÙÖÔÓÕÙÚÛÝÜØ×ÙÜÛÛÞàæìéãáßãìöîäâäåæîéááâéíéíïéæäåãàÞÜßàÞÞÝÛÝÜÜÝÛÙÕÔרØÛÛØÚÛÖÕÖÖÕÕÓÔÓÔ×ÚÛÕÖÙÚØÕÕ×ÛÙר×ÜÝÝÛØÚÛÞááßãæçô{úðóüûîëïø|nejrûóvonmotqng`clwöôòîíçåãçî{twû÷ïãàÞåèêëèêéëñúùîîèåçáâèéìéâãÞÙ×ÓÏÎÏÒÓÖÖÔÓÓÑÑÑÏÑÏÎÏÎÍÏÑÓÙ×ÓÑÒÓÓÒÑÔÓÒÕÓÔÙÛ×ÔÒÔÔÓÚÜÚÛÜÞÜÛרÙÚÛØØÖÖרÔÒÑÎÎÏÏÏÏÎÍÌËÏÒÐÎÌËËËÌÍËËËÊÉÉËÍÏÏÐÒÑÏÎÎÏÒÖÕÔÕÖרÚÜÛ×ÚÛØÛÚÝÞÝàßáçóéàãåêâåæêêêñíêåñòëèáááßÞÞÝÛÚÙרÙÙ×ÕÔÕÖÕÕÖÙØÛÞÞÚÚÞÞÝÝàÞáæãÝ×ÚÝÜÜàèéáßáãïüòíééêònf^_ffeb`\^bb_\]^ec``bevòðõõò|yyïæìïìâßàÝÛÛÞÞÞÜÛÝÜÛÚÛÜÜÝâèéìî÷ùïúqoqorqjb^`a`_\VRSTWVVSRUZYRTUSQRUXY\bcd_bjfbbggjjltûìèæëíõ}íæëôüþtmoxþvmlhgc]Z[Z\[Y[[]YVVVQNQTUUPOMNUTQOPNMLNQTQQPPRRRQSVZ[YXZ][UYkb][RNJILQ`ôÙ×å_I=503;NÓ¹°±«°]0#%>¹¤š—›¥Ê-)Í£˜”–œ«X($6踬©¬°µºÃÒÓýK:,%! #,K¶ ™••š§`# 1®˜ŒŽ”¤O1¸ž—•—«Ñ6'##%+/8EOîĶ«£žŸ©Ç4$ê¢”ŽŽ˜®/ Y£•Ž’›¯; %8Öµ«¨ª¬­¯´»ÎL4($9¼¡—’‘•ŸÌ% '¼œŒŒ›º+(䨛——š¢±â:-)&$&)+.7LÇ®¤›£·;-´šŽ”¢O +¸œ“‘—£Ï.,JÆ´¬¨¨¨§¨¬±¾T1"'[¨™’˜¬; 9©–ŽŽ—©@2¿§žœž¢«½l?5/,)'%%)/H¼¦œ—–˜ ½.#ן’ŒŽ˜­2 "_¥˜’‘–®Q+ !)1?ìÊ¿³­©¥££¨¶N+/¼“Ž‘œ½& '¾œ‘Ž’º.,s°¤Ÿž ¦«³¾ÊhB7-&"#'3Ý«œ•‘‘—¥ê$5¬—Ž‹Œ‘žÒ"3µž—“•š¤¹M0*((,2;Nñ͹®¦žœš›¡´K&%ú¢“‹”¢L O¥•Ž—¦ê)&<̰¨¤¥§¨«®±½ÞE0%$7Á¢—’›±0 !ÙŸ‘ŒŒ™¯2%U¬™˜›£¯Ñ>/+)())+,1Dàµ¦ššž¬o',¹œÉ% )¾ž”‘– ½5" +=ê¿¶°®­«ª¬¯¹ì2#8¯œ“—¥L /®˜Ž•¤]"2É©žœ ©¸ÚL<3.+)&&).=ƨœ˜–˜ž³4E¥•ŽŒŽ—¬4 ?¬›”“–®]-! &/>`Ó¶®¨¤¢¢¦³[.+ËŸ“Žš´, !ØŸ“ŽŽ’œ¶1&A½ª¤£¥©¯ºÌåR;0)" )F¶¡˜”“˜¥ß% )»šŒŒ‘žÈ$ +Ç¤š–—›¥»C-'$#&*-4:Iå¿®¦ŸŸ§¾ ;¨•ŽŒŽ•¦I:·¡š™šŸª½Q81,***)*-5K¼©Ÿ›™œ¦Ê, ]¤•Žš¶+ J©™“’–Ÿ¸;$%1KßĹ³¯¬¬ª«³Ì;&-ÅŸ•”ŸÐ" #Ëž’ŽŽ“ŸÍ'&Jµ¦ Ÿ¤¬¹ÛM<2-*%!!%-M¶¢š—˜¬> /°™Œ“¢Z .¹ž—”–›©Î4&#*1=Qùʹ¯§££¤®Ü2 Kª˜—©7 >¨—Ž™ªH !7Я§£¤©¯µ¾Ï_A6*!$2Ñ¦š•“–Ÿ¿* w “Œš¶, "Oªœ——›¢³n3)&%%(,/6=Vɱ¦Ÿœ¡¯V'+ºœ‘‘È# (¿“•Ÿ½2,Gı¬ª©©««¬²¼â:))R«š’–£o  ;©–‹’ŸÔ&8¸¢›˜™¥±ØG:2/.--.0;h¼¨œ—–˜ž¯>"v¡“Œ‹”¤D"i¤–‘™§Ï3$%,<å½±¬«¨¤£¡¢¨²ï1"/ÀŸ“Žš²/ $É‘Œ™®7*j®¡œœ¡©³ÁÜR@6.*&&*7Û®ž—““˜£Ì(-³™ŒŒÊ% ,¾Ÿ–’“˜¢º?*" "&-7EpÊ¿µª£ŸžŸ§»B'!I¨—Œ“¡_ 8ª—–£â(!4Я§££¥©®·¾ÑY>-$"/Ս𓑕›¯3 L¢“ŒŽ—«: G­œ—–™Ÿ­Î<,('(),05;NÖµ§Ÿœž«ì+&Ο“Ž›»' "ꢖ–Ÿº4&6y¿µ¯®®¯¯¯µÀ]5&!6ºž––¤_ '¼›‘Ž”¡p#*÷¬Ÿœ¡ª»^<2-*('&&(-;á°¡š˜šž³9;©—ŽŒ”¦D 8®›”‘“š©ç.&0?hø²¯¬§¥¦ª³ç/ )ç¥—Ž™®5 ]¡“Ž™­;$?¹§ŸžŸ¦¬¶ËgI;/*&""%,C¼¤™•”˜¢È* $É‘ŒŒœ¼) &䥙”•™¢¶H,$ !%*/;Gdμ®§¡Ÿ ¨½?$1´œ‘ŽŽ”¢^ *ºœ’—¥ý',Rº¬§¦©­¯¶ÃÒo@/% ,{«›”’“™«= ;¨–ŽŒŽ•¦E9´ž˜—™ž©¿D0,**+-15;Rѵ¥šš›£¾2%ÔŸ’ŒŽ—«5 "í¢•’›­K&(;庮¬«ªªª«­²ÈC,!8»ž”“Á' '¾œŒœº,+ß©ššž¥¯Å_?5/+*)(*.:â® š——­P#3­—ŽŒŒ‘žÖ! 4±œ“‘˜¢À9&'1Bí¶¯­©¥¢¢¥®Î8#(Y§–ŽŽ–¨> G¥•ŽŒŽ—¨F "8À©¡Ÿ ¦¬µÅïM>4,&! "*<¾¥›”’–ž¹/ "Ñž‘ŒŒŽ™´- #]¨š•”˜Ÿ°R.$ $)-8BQÛ¾°©¡Ÿ ¥±R'.¸‘‘Ç$ (¿œ‘Ž”ŸÁ--Tº¬¦£¥©¬¯µ¼ÏN5) !+]¬œ”‘‘—¥O 5­—ŽŒ”¡q 3º¢š—™§ºZ8-+++-/39FÜ·¨žš˜š ¸:  P¥”ŒŽ–¨9 E©˜‘’š«S(&6eÁ²­¬«ª¨©«¯ÀM.!3À •Ž‘›´. "ߟ’›µ.#G²£œž¦²ËN9/-*'%$&+1N·¤›—˜«T# *¹›Œ’žÓ" )ÅŸ–’“™¤À9$!*6IãÆº³­¨¥¥§¯Ï8#7¯š‘Ž–§> 0­™—§O"/Û­£Ÿ ¥«±¿áP@6+&"'7˨œ–“—ž´1 ?¦•Ž˜®1 :±ž—–™ °\.$"&*/8CZ笥ŸŸ¥²g*&ØŸ”Ž‘œ¼' "Ý •”žº2&=̳«ª«¬¯´¹ÀáJ1%%;µž—’’˜¤n# ,´šŒ‘žÊ'/½¢š—˜œ¥µî<1-,,,-05?lÀ¬ ›™šŸ°B"?©—ŽŒ“¢[ >ª™Ž—£Ç1!'6x½²¬ª©¥¥¥¦©³Þ7%/Ì¢•˜«< pŸ“ŒŽ˜¬;$F²¡œ›¢¬½çG;5/,(&&*1Iº¤›—–š¦Ó* $Õž‘‘À$ "^¨›––›¦Æ5"%,6FzÏÄ·­ªªª²Û3 ,¾ž”—¥N (¿“˜¨M!%>Á­ªª­¸ÃøE<4+%&<»¢š˜™ ¿, ,´›‘Žš¯3 -Á£›™›¢³X.$!%)-3>^ȱ¨£¡¦²^)C¨—Ž‘›¹) ?©—”³9$8Ô´«¨¨ª¬­°µ¼Þ>,!%<³ž•“¼+ +·š‹Œšµ-,Φ›—˜›¡®ËF6/.--//2©–‹‹œÂ&=ª—Ž“²D) #+=Õ·¬¦¥¤¡ŸŸŸ£ªºM-! 2¿ ”Œ“ ô""Ýž‹ŠŒ‘žÌ),滛–˜œ¡ª³Ä~YE93./5?×­Ÿ—’‘“›®D+»›Ž‹ŠŒ”¥?*Àž•’š§Ç8)%&*3FãÁ¸±ª¤Ÿœœ ¬Ì3  <®šŒŒšµ+ -²™‘œ·1.㯥ŸŸ¡¥«°ºÆßL9-&#$(5Ö©›”–£×%<¨•‹Œ‘ŸÓ$6´ž–“”˜ ´K,! ):â¶©£¢¤©²ËJ6-+,0;Vκ°®¬­°¸ÄèN@<;>Jþȹ¯­®°·ÁÕcMHJRrÑÁºµ³´·¾ÈÙôiYZ]iíÔÊÄ¿ÀÁÇÏähUMMSbúÚÏÍËÍÐØén_^gmouz~{{þ}us}óãßçëøqim}éåâÜàäçæïùîýqooo{xhg_]_\Z^^UVXWRPRRTYdok`XSQRQNOSY_dih]WTQORVY]lïçëøme^\__dkxwnqqlecijfb^\WTVZ\aejuòëýl_[RLLOVcyíãèów_WPNNMOU^môæå~hh]VSSTVXXY]amùðìëëõtk]VTY\gîèÜÕÒÓØÞïq`XW[fuûìÞÕØé{i_XPOOR[bjýñùzngcb`^\\\]hla_ahjnmdekkda_^[Y]`dowrlbdjec_]ad^]_[_b[WXZXVVY\]ad`]Y[^^^^cdcegjlsife\]adgoqpmlkgha`^^^^^Z[aijqþoilmkc_^ZZ\^cjwûôëèåîuqmlotùîêéìããìèìðìåéøëãÞÜÜÛßßÛÜÛÙÙÝêêáßßßßÝÜÛÚÛäî}ôëýöötu|zzwpyxvýoolgidjmnou}õçåôywytnqrxþéÞÜÜßáäæéîútþíëêåßÞßÞÛÝåðëéúxzþ|ry÷õ÷üøupnhddm{÷yzïïèãäèöñø|þuzíäáéïæÞÞàãççåååäçéêéèâàÞÝßÜÚÛÚ×ÝãßãããêàØÖÚÚÙÛÝâßÜÜÞÜÚÙÙÚÛÞáàÞÝÜàçäßÝßÞÛÝãçãáßÝàáçèâàáãßâææäæçßÞÞàæåäæåáäëïéíéâäáßáçáÜÜåêåíùöòîõ|}}ýûðíîôvtynbbcfola\ZUW[ZZ\[ZWOOQSTTPORTTTPNQNNMMMNOONPQNLJJJJJJJIKKKLKKLKKJHIKJLLKJKKIHHKMJGIKLKKJGGFFEFGIIGFEEEEEEDEEEGFFFFFDBBDCDDCDGHEDEFFFIJGFHJHHKKLJJJIGGGHJLNMLLLKIKKIIIIIIIIJJJJKLKKJLKLNLLNNMOTUWQOOPRVZ\_\XTSXZ]_\YZ\_adihbca[[VTW[][YUSUYXVZYVWTUYZURVYYXUWXVWYUSWVVZZ[ZY\^^_da_aejkljfmyùyrllumkooksonk_][]ced_acgmmjcjhbijkmgglhlkjroos{ôðüjhjmsxú{ujb_bfcgknhc_^abegc^^bimmc]\]bbhp~øûúv{ýymhpov~oklgekjfhlmlv÷òïï÷tq|üïîõöüýûzyy{ûõìöøïöúøíìëèìåáæéìçâÝÙÙÛÙÙÛÚÚÜÝáßÜÜßÝÙÛÖÖÖÑÑÐÐÏÐÑÑÏÑÕÒÐÐÍÌÍÍÎÏÑÑÑÕר×ÕÖÙÖÕÚÝÞÝÜßàÞÚÔÖÚÛØÙÛÙÕÓ×ÛÚÙ×ÔÕ××ÖÖÙ×ÖÖÕרÚÚÕÔÓÏÏÏÑÓÕÙØÔÑÑÔÓÐÎÎÎÐÐÒÖÒÏÑÔÕÔÏÏÏÑÏÍÏÔ×ÔÓÕ×ÙØÛÛÛÞÛÙÝßããåçãäææèçßÝßããäèâÝÞáãÜØÙÚÙ×ÙÜÚÕÒÔÖØÙÙÚÚÜÚרØÜÜÜÜÛØ×ÚÝßÝÝßÝÞäàßßâäçêæãåæìóîïèââáåèíèäèêçåäâæãßÝÞßßëóëèèûv÷ñúoijlhb`bkqrvttrwwoneb`]^agr|nhn{rkddb]_ckjfdegba_[YXY^acca^^_^_^YUSUXVTXXTWYZ[[\YUUWY]_b`__]^`ac_YXZ\_bhjkjiec_]_^^bjjfgfilomfhfaccebefca_caahg^____\[^b`a^[Z[[XY[YVWYZ\Z[]WVUSRV\YWW\\XSTWVX\^^ZWWWYZYXXY[Y]ZY\]behia[[[YWRQSRPQRONLLKKLMMKNORQMMLMNPNLMMOOQPOPOOSSQPNONNNOQRSSWWRSVVVW[\^adeac`_\YYYZXVVVWYXWXWZ\YVXXVVXVPOOOOOOONMMNNOONLJKKLLMNNNOQQUWTTSRTSSTX\`ec_[Y\ajifmzpddknr}ôú~usroqÿïìêëäæîéßÝÞâäßÞÝÞßÞÛÝÛÚÚÜÝÝÛØÓÒÔÕ×ÖÔÓÕÖØÚØÕÓÔÖØØÖÔÒÑÐÕ××ÖØÙÖÙÚÚØ×ÚÝÛÚ×ÓÒÑÓ×ÖØÜÞââéëãåæßÞßáÝÚÚÛÝÝÜÜÜÜÚÛØÓÓÒÑÒÑÏÑÒÑÒÑÔÖÕÓÐÐÏÍÍÎÏÐÒÓÕÒÑÔÕ×ÚÕÓÐÎÐÔÔÖØ×ÖÖÜßßÜÜàÜÙÚרØÔÖÚÛÙÔÔ×ÖÚÜØ×××ÖÔÖÕÔ×ÙÜÞÚÛÚÛàáàââÝÙÚÛäíîðííôíçèçêëæâäãëõóto{õëèéêãßæêêììïîëëíëäàßßèíëèçâãéçéäáßÜÚÙÚÛÞàÝÚÜÞÚÖÔÚÝÚÛÝàßÝãäàâäçãáÝàìïðí÷üíâÜÛÜÝßÞßááâÝÚÚÚÚÜßÞØÕÖ×רÙÛÚÕÖÚØÕÕØØÙÛÙÙר×ÖØÖÚÝÜÝäæçðüumw{îìÿ}}ýzzñâãïîò}øììíéãâààáè÷òìåáêúúðêææååãèìííçßßÝÝÝÙÝæìèÝÜßåìïëçæêíêìñøððýþ÷óóïïzlqöïõöyuûîëìïö}ulr{x}ü÷vssxvoea_[_edc`^a_^[XY[XWXV[YXZ[Y[]XZZ[XUZ\^_\\[XYWWVXZXWUVYZZVSRTWWVTSQTZ^[SQQUXWTQQUTUZ\YXWUTSQRUXYXXSTUTTSSQPPLMOMKJKKLMNMKKLMNPTUQQSRSPPTURPPQQPT[^^WQTTVVTRPORTSSSUTTSPPOPOOKKLNMLLLLJIILLKIIKLMMKLMMJKKJIIJKKKMNMMMQQPNQWUVWWTTX]ce`]Z^b_^_jolkb`fjnhd``cdejsroj_^cfbaeaabeadgjkekmbdf^bfii`^^bdkunhjifabflxozzosopurnninutüïìúyyÿû}x{þöñéãÜÚÛÚÝÜÜÚ××ÚÙÖÓÒÐÐÒÐÒÖÖÖ×ÕÔÕÖÙÙÖÕÒÑÏÏÓÓÕÕÓÒÕÓÏÏÑÒÐÐÓÐÎÎÏÒÑÏÐÓÑÏÎÏÎÏÏÑÏÎÌÌÏÕÚ×ÓÏÎÎÏÑÑÓ×ÛÚØÚØÕÖÛâáÛ×ÔÔÔÕØØ×ÓÐÑÒÑÐÕÖÕÓÒÑÏÑÕÕÖ××Ù×ÓÒÓÖØÔÏÏÐÒÖ×ÖÓÒÖ×ÛÛ×××ÛÜÜÝÛÙßááèéêãßÞÝÛÛÚØÙÜÜØÕÓÖÙÚ×ÕÓÑÓÒÔØØÕ×ÚÚ×ÓÑÕÙØÓÓÒÏÏÑÔÓÒÑÓÓÒÏÏÑÑÐÏÏÑÒÑÐÕ××ÛàêèæéæßÜÝãéïýw~{{íçëøûòôñïôöõëèééîïîèãåæäáàÝÚÚÜÛÙÚÛÚÚÚÖÔÕÔÑÒÔÕÔÖØÚÞßäñíâáãæàáæââãçíî÷îçåßáâææãäïôëçáßßáäæåäëéìêêæáæéìåëìéèæï}|÷þvvûôú|tmoowûwnjgjnknsoninxqzvvnhggc]_bdggfjb^`____^`a`imkg``^ZWVZZY]^^^[]fcZZ\WWXZ^_hjb`gme_\ZX\cimk}õ|oqr|~üïûðëéçâÞÝßèàäæáÞÞäãäæèèçìóø}pomggmnkmxyieged`abcfijlngkrurlnþëêìüzïæãêìæâåìïêëöîæåêìêëëôíéîìëèéèìïï}yüúïïýïêøvponlorlife_^e_^egjc^`gjomfehpv{}|ýpmsyîëïôïëëïîìïîëãâàâßÞÞÝÜßãáçéäáäèìüxxþ÷~ojgiea__b`ceiegkedfjknjlmgkxõîðï÷úûýïðìíùüÿv}öþôôöîîíõzùññììùrxtyëízkm}úüøùe]ceflmkd^fia\ZTUVSVWWXY\^[WPORVWSTTSTZ]_a_cfhil`]gnnmrrjgrkbadc]\^d^]`__\WVVUVSORRRSUSONNONNMMMLLLLLNNNNNNMLMOPU[YX[[]\aeac_^_`ecbdksontlehede`\]^\_geaa]\ZWVWTSSPQSTVVWXTPOONOTVZ]YY\eskb^_cknjo}ððõùýqotknqw{}óíí÷wtpxnkokjiihhdehhghijkhc^_eklutu}wuqyîâßÞâæäàâæææáÛ×ÙÙØÛÚÙÛÚÜÝÜÛÖÕÙÚÙÜÞáßßßääàåèéêèåèéâäêíûswüõôìííçåßååÝÚÜßßâááåãÝÙÛßÞãçãáåêæêëêìèçäàéðó~øôîëééåâçìôýþïüyôõü}þzýíìòûôúþòðíéçéïwnyyjemqmoieknv}|srighjnwz{yx÷ú÷ðîïêãäïyozúõø~scbfkhehnjjrownho~þtkkjlvzuqvvnkjjuûôû|tokjv~|rqþ|sqtø÷úüvpkpx|vsxy~}ûûùúôæåìëçâÛÚÛ×ÔÙÚ×××ÔÒÒÔÔÒÒÔÖÑÐÖÙØÖØÚ×ÔÓÐÐÐÑØ×ÔÕÕ×ØÚØÖÔ×ÜÚÜÛÜÝÞààßàâÛÚØÕÔÒÒÐÏÏÒÑÑÑÏÏÓÕÕÔÑÏÎÏÔÚÙ×ÙÚÚÖÕÕÕÓÑÒÓÒÑÑÏÑÓÒÑÓÔÓÑÍÏÕÕÙÛÛÙØÜäèî÷ïêîèäààåçæßÝÛ×ÎÎÖÚínn_ZnÝË¿º¸ºÂîD6--2@Ѳ§¢¡§²Ó6"*w­—–˜Ÿ¶9 2䛘™ž¬Ê=,'(,4A_ßÖÎËÁ¸¯¨¤¤§±é0 1¼ž”ŽŽ“žÌ$ +µšŽ”¡×',þ¯¥Ÿ ¥­»ËiE:4.($!"&.]¯Ÿ™––±< 8«–ŽŽ–¨; 9¯—•˜ž­ë1%  $*29CdÍ·¬¥  ¦³_*$ý£–Ž›¸+ R¥–’œ²6#6Õ²©¦¦©®´½Ëa<.&$7ºŸ˜”“—¥g" %Çœ‘žË$ %ò©œ—˜œ¤´X1($$$'+.5>j½¬£›¤¸:6®™”£S /±š‘—£Ï,"/QÁ°©§¨§¨©«°¼d5&-Ö¤—Ž—¨> L¤”ŒŽ–¨E!>µ¢œšœ ªºè?62.+))*,4W»§œ˜—š£À.$ÜŸ’ŒŽ™±/ #ý¤—‘‘•¯N+ "*6OÔ¿·°¬¨¥¤§¬ºK*0¹“ŽŽ“ŸË$ (½œŽ“žÁ++j°¥ŸŸ£©¯¼ÐbI;/)%""&2}­–’”™¨T"8«—Ž‹’ r!3µž—”–œ§Å9)$""&-3;J}ô«¤žŸªÇ5#Z¤•ŽŒŽ–©: O¤•Ž˜©L%'?­¦£¥¦©®±·Ãu>-#%7Á¡—’“», $Æ‘ŒŒš².'÷©œ˜—š¡¯Ñ<.,**,.29>b¾­¡œ™šžªý'.´šŒ‘Ç# +¹œ“– ¾2  -FͶ®¬¬ª©©©­¶æ8('Qªš‘Ž–¦M 5«—ŽŒŽ•¥Q 2Á§ž›œ ª¼rD7/,*)'(*/G¾ª˜—˜Ÿ·5a¡“Œ–¬7 N¨™’‘”œ¬^-" )5IßǺ¯¬¨¥£¥ªµ\,,¾ž”Ž‘œ¶* $Ç‘‘œ¶0*Sµ¥ŸŸ¢¦­»ËàP<1*$ !%-O²Ÿ—““™¦ú$ .³™ŒŒ’žÐ# -¼Ÿ˜”•š¥¼A+$!"',09Heк­¥Ÿž¨¾: @ª—Ž•¥C :ª˜Ž˜¨V&!1hº¬¨ª¬®±·¾ÊV9,!,r©š”‘“·/ O£”™®2>±Ÿš™œ¥²Ú:,('&'(*,/¨•ŒŽ•¥? ;­›”‘”›ª×3$!(0BlÏ»²­§£¡¡¥¯}0 +Ï •Ž˜­0  ÛŸ“Ž™­:&Eº§ŸŸŸ¤«´½ÈöJ8-& !&.O²ž–’‘–ž¿**·™‹‹›º*,¡˜””™ ²l3)&&(-4=Nêȶ«¡œœœ¡±U( @«—ŽŒŒÉ# 7«˜Ž”ŸÂ.#4Ú´ª¥¤¦¨ª­±¸ËL4%.쩚’‘š¬? F¤”‹•§B!A°Ÿ™—™žª¿O6.,*+,,/4?긨žš™œ¥Ã.%ÑŸ“ŒŽ˜¯. "좖”°F')8y¾³®­¬©©©ª¯ÄB) 6·ž“Ž”žË# (»›’žÇ)*o­ Ÿ¨µÌW=5/,(%$&*6ᯠ™•—¬I 3­—ŽŒ“¡R 3³œ”‘“š§Ê6%!'.;QÛÆ¼³ª¥¢¡¥­Ø1!$Q¦–˜«7 B¦•Ž˜«?":Ĭ£ ¢¦¬³»ÈúL6,'!(?¿¤˜“‘–ž», !Ýž‘Œ›¹* !Rªœ——›¤·O-$!!%*.3=V̶©¡žŸ¦·D$-¹œ‘’žÎ! )¼œ“–¡Ë,*DƲ«ªª«¯±µ¿×H.#&C¯œ”‘’™«B 3¬—ŽŒ•£[ 5º¢›˜šž¨¼Y8/,))*),/7Q¾ªžš™œ¤»1S£”ŒŽ—«5 N¦—’š«f+)8iÁµ®­«¨§§¨¬¾I-.ÁŸ”Ž‘œº* "Ìž‘‘œ·.'O°£žŸ¦¯¿æG;4-*&#$'0\²¡™–—š©O# -²šŒ’Ÿå  + —””š¥À;'$,8Gl̽±«¦ Ÿ£¨½;$"Kª—ŽŽ”¥P :¨—–¥\%!4Ï®¥¢¢¤©°¸¿ÙT<.&%6Ê¥™”’“›±2  柑Œ‹Ž–©:$b§š•”—ªÈ?/*')-/4>Mì¾®¤ž››žªØ.-½‘Œ›·* (À’ŽŽ“´8! -KÁ®¨¨§¨ªª®µ¼Ú;) $C¯”–£à! -²˜Œ“ ò"-ɦœš›ž¨¸÷?3,++)(+-4KŪžš˜™Ÿµ? >¨–ŽŒ”¤C :­š’”›ª|+$/CÙ¿¹²®«©§¨¬¹P-)Ú£–Žš¯/ 💙®9&F·¤žŸ¥¬»ßL=6.)&$"%-K¸¥›––š¥ã& 'Á‘Æ% 'Ô£™••™¢¼?) $*3ARÞÆ¸­¨£Ÿ ¨»@%8¯š“ ô /°™Ž•£è'/í´§¢¢¥ª¯·¿Î\?1' #1Ú©š”‘“š«> F¥•‹•¦?@®—•—©ÁC/*')+-29CaƱ¦žœšœ¨Ç2'Ο’ŒŽ˜¯- "ë¡•Ž“œ²=")>Ò·­ª¨©ª«­°ºÛ<) #7¹Ÿ••ŸÏ$ '¼œ’žÈ(*⪞››Ÿ¨¶æ?4.+))()+.>ذ¡›˜šž®G 1­˜Œ’¡R 2³œ“‘“š§Ó. $-?ùĸ²®ª§§¦¨²á5"'l¥—–¨; O£”ŒŽ—¨K!$?º¦žŸ¤«µÉaJ;/,'$"$,E¼¥š•”˜Ÿ¾, #Ïž‘ŒŒ™², #t¦™””˜Ÿ²M-# $)0;HxÌ»­§¢žŸ§¶F'2¶œ‘žÖ" )½œ‘ŽŽ• Ë**S¹¬¦¤¦«¯·¾È{>/'*T¯•’“™©D 2«—ŽŒ”¤I1¼¡™—™ž«Ê=,'%$%),.4>ú»«¡›œ¦Â3!Y¥”ŒŽ—ª4 K¦—’›¬G$$2]¾³¯¬¬­­®³»Ý:).Æ¢—“œº) $ÇŒŒš´/*í«™™›¡­ÃV>5/-,++-1;×­ š—˜ªT#-³šŒŒ’žÎ" -¹”‘’˜¤Ã4"#->cʵ®ª¦£¥¨­Æ9&%V©˜Ž•¥N <©–ŽŽ•£}%!7¾¨ŸžŸ¢¨²ÃÞXC7.(#!$+:Ŧ›•“–œ´4jŸ‘Œ‹Ž–«5  M©š”“—ž­ð2& !#'.9GaÔ¿±©£ŸŸ¦±W),ÄŸ“Žœ½( %È‘ŽŽ“œµ2*Lº«¦¤¤§¬°¶¾åF3) (F²ž–’’˜¥`  ,³™Œ’žØ"/½¡™•—œ¥·^6,**)*-08D麪Ÿœš›¢º:>©–ŽŽ•§; 9¬š’“›ª\'"1Sij®¬¬«ª¬®´ÆH.#/Í£—Ž‘š¯2  áž’Œ™¯6$K±¡œœž¥²ÊM8/,*'$$&)0G»¦™˜ªò% %Ä‘‘œÄ& 'Ì¡—’’—Ÿ¸='"*7KÝÁ»µ­©¦¦¨®Ì7$7³œ’Ž•¤P -²šŽŽ•¢ß&/Ô¬¢žŸ¢©²½Ò`F8.)$""(6Ø«œ–“•œ¯8 A¦•ŽŒŽ–©; <®œ–”—«Ò6(#"$).6>Yﱨ¡žž¡«Ï.(ÈŸ”ŽŒ™¯. "äŸ”Ž’›¯: '=í§¦§¨­°´»ÉU9+!%:ºŸ–‘‘–ŸÏ$ '»œŒŒœ¾(*Õ§œ˜˜œ¤¸\6,)'&(),.6P̯¤›œ¡´>!3­™”£S 1°›’—¤Î.%3TÁ±¬ª©§¦¨ª­ºn5%,ä¦˜Ž™¬: J¤•ŽŒŽ—©A#@´¢œšœ ª¸ÔO>51/+)),4R¸¥›––™¡¼.$ËŸ‘ŒŒ™±- $餗’‘–ž±O+ "+8LæÁ¸²«¦£¢£§´O+9±œ‘œ¿' ,µš’½-&g­£œ›œŸªºi5(##%+9ë¹­¨¦§¬ºÓZ>2//4=Mòʺ²¯°¶¾ÏT>9759Fnɼ¸¶¹¾ÌñRD?>AJ[îÑÆ¿ÀÄÇÌØiQMKJMUkáÔÌÅÂÅËÞkXOKLViéÚ×Ö×âûumlnkmld_bljchþ÷ùóïìîìóÿnníìéãàÝåïøôó{ysüîñob`YY^ehgggc[WTSSTVWY^jwngYPOLMPX`hjd][XQMNT]cffdicZWUVZZZ^dd`^a_\hÿsfeif``_\Z^iksíáßìpdZTTWZ[aøáÝÙ×ÛîrfZXYZYbxìäßÝÞâë÷wlg^_\[cfo|æÛÖØÚÝëq[VSU[eñÜÔÐÒרçj`\USX_mìÜÛÖÖÜæíugfgmtùïëæßÞßàâæëêòvq|}ussxzôîîöy{rl`ZWY^_fjfabeb][WUWSPSSQMMMLJHGGHHGFEGFDCCB?@BBA???ADB?>>>>??>>?>???>>?@BA@@>>>?>===<>>>?>==<<;;:99;;;<<;:98888766778987888766554456799::9:::;;;<;:<=<<=>====<;<=<<<;==>??@?>>==<===>>?AABCDCCA?>>@CFGHIJJIGGHJKJHJKMOPSTWYZWRNNQUTTUVVUX[\\\]^Z^_b^[eieelþòííïøsüñïêæßÛÙÚÛÜÝÛÙØØÚ×ÐÏÓÔÔÑÏÒÔÒÒÑÎÍÌÍÍÎÍÍÍÍÎÎÍÎÎÌËÌËÊËÊÉÈÆÈÈÊÌËËÊÉÊÊÈÉÉÈÈÉÈÈÈÈÇÅÆÇÆÄÁÁÂÀ¿¿¾¾¾¾¿¿¾½½½½½½¾¾¾¾¾¾À¿¾½¼¼¼¼¼½¼½½¼»ººº»»»»»»¼¼½½¼ºº¼¼½½¼½¼»¼¼¼»»ºº»»¼»»ºº»»»º¹ººººº¹¸¹¹ººº»»¹¹¹ºº¹¹¹ºº»¹¹¹¹¹¹º¹¹º»½¾¾½¼½½½½¾¾¾¾¿ÀÀÀÀÀ¿¿ÀÀ¿¾¿¾¾¾¿ÀÀÀÀÁÁ¿¿¿¾¾¿¿¿ÀÀÁÀ¿¿¿¾½½¾¿¿¿ÀÀÂÃÁÀÀÂÂÀ¿¿¿¿ÀÀÁÁÁÂÃÄÂÃÄÃÂÂÅÄÄÃÃÅÅÅÆÄÅÇÈÇÇÇÇÆÅÅÆÅÆÇÆÅÅÄÃÄÄÂÀÀÀÀÁÁÂÂÂÃÃÂÃÃÃÆÉÊÈÇÆÇÈÉÍÎÍÍÍÐÓÓÒÕÖÕ××ÜÚÙÜáêéæäáäîïïúqm{óøzokl{íéëëçêëååææëæëîêìéæßåéëëæëïïëêì|rzytrùôòçãåïõðñùvÿunlhlmu~wkhhhhjnjheda_hpóââêóïéàßäÜÛØ×××Ù×ÖÒÑÑÔÖØÜÚ×ÖØÝßÝÛØÖ××ÙÛÛÙÛßÞåìõùüzûüöïéêôõîæãääìïíäàáßÜßêåçåÞÝßäèâÞááßæêèíëíîíëçêëëççéæçãàèïóéèîéæëúúøþÿüòôöóú~þ÷ôüzúïìãæèçîù÷êï~t|þøòýrrxptromnlmvñïôíëìôóöyøèääñü~ÿùìê~ojc^cilgfdacfa^\]dc[XXWZ`eecbb_[Z[WVVSRUXYUTYZZYYYURTVX[\YWX\XUXYZZYWVV\`_a^[YY[]^_`[WTUWXUSTPOPNLJIJJJKLKKLMNLKKLJKLLOTZXWX]_eioôèßÚÖ×ÔÐÍÊÉÇÈÈÇÄÀ¿¾½½¾¾¿¾¾¾¿¿¿¾¾¿ÁÁÂÃÄÅÈÉÉÊÍÏÍÍÎÏÐÒÔÕÖ×ÛÝÝÜÝÛÛÞäéæçäßãéïóîèêæãçâßÛÜÞÛÙÙÝáååÞßßÞÜØÙÛÚרÛÜÚÛÛÝÝÞçåêõ÷wjjrmha`\WWTPNMLLKKKIHGGHIIIHHGFFEDDFHIFDCCCDEDCA@????????>>>>=<<<<;;;;;<==<===<:;;;;<<<<;<;;>?A@?>>>ACCBCDFGHIKLKKLMNQTWY\^^^_adfqyosw~úïëäãéìîíñöúy~ýurrqü~||q|ø}nmnwumlsùý}|prùôûùìëù|øúüûöïöùùúôêëîìéäãæçàÞÜÛÚÛßÞáæéðïîñòñõzrjc_]bca]\]]]]a^]_[[]^a]Z[\[ZZZ^a_]_cgefiiluxnwssxqnýñù÷øyrifmfhmnb^ehjgiecbab`b_^\XZWVWYYUVWVSQSVVUSTXZZXY[\^`hkmqkiinùóòö÷ÿz}÷ø{wp~ó÷úîìïùøòúþwnlonnja^_bhd^]\]]\[]]\\^abaeiefecdfgoy}wnr}zvwtonûøøysúüxmr~ü}qvxuvoqtmeinmriee_`^^_daaf_]]^__cfb^[Z\\`ccgb^[]_][VVVTTX]domb^]\]_egfirooyûøtpmnngkgbeilkgb`\YYVWWWTSUWZWXXXWWWVVVUVUUXXXUTUUVWWY\^_bgdgkkfirnnlszooqlknjmqlidfmnnpjgjfahkrvigmnhkqtvkdb__^_^]^^_`gkmvryxlouîâãåÞÝßßßÝÝÜÚßàÝÚÙÚÛÜÝàßàÝßáßßÞÞßããåääæéïíêøvwsjbfji`]\\]ak{~lfhmro}çâåçèëíìâÜÜàâãèèèâÞâçééßÜÙØÛÜÝäëôíæäîüóìâááàêý~}xprle^[_]\_gjfceb^\^_[]^\_b^[]_`dhg^]_ddgjjjhhehdcfmzpdfllorzûsggbbbffa__d^]`a`___``^\]]]^^a_\XWWY^\[Z^]VSX[ZWUUQOU\\Z\[XVXZ]a_``b_^bllkk_]^_dgijfgkle^bid]`b^`bc]Y^^]]^]Z]__]_^\XXYWVUVVUSVYWUUUTUZXSUZ[WW]_^]]_^bdfgfonloihiijmýýoiivûþ}þðì÷õïóû|üîèëíîïêëòþðñ}öôö}t|þ|þþwwy|þpnopymlyzv}ztûø}po}xrü÷òíéåèìïèãäææâàßâäáççããÞÞßÚÛßáàÞÜÝÜÜÛÙÚÞßäïïëêëéäâáççãßßãéîïø{ôìëëìîöø~þúùóòú{|úéèçèêçôzü}xþøëàÞßáæíëææìïîëäãåèéîîéîõzsvùïíêõyxúòööûqjikmiinpijr}þüùxxzùz{õöùíèïõîááÞÝâäàâëëääéæßßÝÙÚÙר×ÖÕÑÏÏÏÎÍÎÏÏÎÌÌÍÎÏÑÔ×ÖÒÏÒÐÐÒÔ×ÚÖÔÓÒÔÖØØÙ×ÖÐÎÏÏÏÖØÕÑÍÎÑÏÕÛÚÙ×ÔÒÒÑÑÑÒÒÏÍÌËËËËÌÍËËÊÇÇÈÉËÌÌÍÍÎÎÌÏÐÒÔÓÓÑÑÒÔ×ÙÙÔÑÏÏÎÐÕ×ÚÚØ×ÖÔÖ××ÓÑÓÓÒÐÑÔ×ÚÛ×ÒÏÐÑÓ×ÚØÔÒÑÕÙÛÚÙÚÚÚØØÙÙÛÞãçéßßâàãäìñü}|y}òïý~yzx}øûugehfijjkcaagkmnsoinlkjjloxwz~øüjc`eq{onuotu{øüw~sqyzø÷û|ø|mfem}vke_aegddda_]_fiif_]dkijjlmlkgeilklmkkm|ùvoxogbagnttontmd_]]^\\^chiiaa^Z[XWWTTTUV[_bb]YUWXXYY]]]`acgbcghijfaglwýztz|}úýþý}ùñóüqlouolifgh`dlhbafd`^^_^fkib_afin~ù|o~ðó}|÷ý}ÿ~øñùùôìåâàåìñôññõòøûõóïëî}pvj_``^^cijmg\[Y\[[cfc\[^iorqjijeeijmmlljjhelropþõö{mjlv{ý}nnno}ôïøùóíìýsmhq~pfbhfbbkmkssvkm{}tpoe_djgjjid_b__dkmmolnxtxyyþ{xvunswonvþöüyvnqklmmürcaiqvûüûjenqöözyýø÷ztuoghhcd`fia^_fqtþ~þyoogebfdfkkmjntvýofhgmikpgagidghmss|}mggksvýúxqjgnnkifachjheimg]Z[]dhijeb_`a]]^dfb^]\[]][ZWTTRQQTTQTVRONOQRPQUURRSTVVVXZ]YUX]_`ee]Z[[\\aggd`]WWXZ_^]ZTSUVUXVSOOPPTWVSSSQONNNNQQTUUTSSQPQVTSUSVX[^ghkljicjr{þ}vqo}òìíöúôñôëîîõý~þwrsnwmjmolljmmgihkmtttohgeb_ennmrpnrþ÷ôõýøø|yïèåçëäâáÞÝÝÜÛÛÜÛ×××ÖÖÙÞßÙÕרØ×××ÔÖØÖÓ×ÚÛÜÚÛÚÜÝáèêîíïïìðøöôïêíôïïïóùêåéëéæéìéßàæäæêëîöy{òùüöõû}~~ìæêëèååâÞáæáäãßÝâçßÜÙÞáßßÞÞäèáâéçäÞÝàäçäßÚÚÚÚßáÛרÖÔÕÖØØÖÔÓÓÕÔÐÓÕÔÓÔÓÐÎÍÏÐÏÎÎÌËÌÍÏÑÏÐÐÌÍÌËÎÎÎÎÏÏÎÍÍÍÌÍÎÏÎÌËÍÎÎÑÓÓÔÕÑÎÐÓÑÐÏÔ×ÓÓÔÖ××ÛÙ××ÔÓÓר×ÖÖ×Ú×רÙÜÝÛÚÞåêéçäàßßàãááÝÛÛÜÜÚÛÞßÞÞßÞÝàßÝÜÜÝÛÝßäéçäáãèìèâàßÜ×ÕÕ×ÖÖ×ÛÜÑÎÎÑÒÏÏÑÑÏÐÑÔ×ÖÙÛÙÖÑÏÒ×ÚÙÚÛÚÜÛÙÚÜÛÛÙרÛÛÛÛÞâÜÛÛÙÚÛÝâáÝäæàààççâÞÚÚÞÞÚÚéÞÁ¿õjôUVX}ɾ¸´µ¿íL9/-1B×µª¤¢©¼Q1&" !-^µ§ ž£­È>+" (2NÁ³­­´½ÔO>:CWM?90,*,3Qº¦›¤»3%ߢ•Ž’¸+ 'Ò¢˜””™£¿6$"*5K߯¾¼¶¯¬ª«²Ê=(0»ž”–¤]  ,²šŽ”¢þ$1Ë«Ÿž¢«´ÆjG<5-($"$):Ì«—•—¯7H¤•ŽŒ–ª; :®œ•”–œ«ß0$!&,5EèÆ¹­§£¡ ¥´\,)ÊŸ”Žš¶+ !áŸ“ŽŽ‘›´2#:Á¬¤¡£§¬µÁÞN;-% !+M°ž–’’—¤û% +¶™ŽŒŒœ¿&)Ë£™•–š£¹I.&#"$)+.:Fï¼­£žž¥½9 7­˜Ž”¡S 3®šŽ—¤Î-"0U½®ª©ªªª¬®µËK/",i©š“’›¯3 ?¨–Ž™®6:¸¢œš£®ÃO90,+)))),7Q¿©™™œ§Ð*"î¢”Žœ½'  R§™““—¡¼7#&0GòÉ»·²¬©©ª®É<'2¹“ŽŽ“žÐ# )¹›“žÁ*,k®¢žž¢©±¿åH<3+(#!#'3뮟˜”–›«I9«–‹“¢^;®œ”’”š¦À=+$#%*2>Uáǹ¯¨¢Ÿž¢«É4"ü£–Ž˜«5 W¢”Ž™«E"'C¾«£¡¡¥ª­³»Èv>.& (>¹ —’‘”ž¿+ $ÇœŒŒš¹+'ä§›—–š¢³z6*'&&+-/9FüÀ®£››Ÿ¯K'4²šŒ“ŸÜ! ,¸“–¢Å/!.M󬪪ª«¬­±½d5')W¬š‘—¦D ;©–ŽŒŽ•¦L6»£œš›Ÿ«»ìD71.,+*,/7Rº¦˜–™ ¶8"‹–«6 "l¥—‘“›¬Y, )7QÔ¼²¯­¨¤£¤ª¸\-.¿“ŽŽ›¹) '¿œ‘›·/)]¯£žž §®¼ÏY?6.)$!!'0_¯Ÿ˜””š¨[" 1¯˜Ž‹Œ’ŸÜ#2¶ž–’”š£¼?+$"#(.7BW×Á¶¬¤Ÿž ªÅ8E©˜Ž—©> ;¨—Ž˜©M$$9Ö²§¤¥§«®´¼Í`=.&#2Ê¥™“‘”ž». e “Œ™±/"O¬—–š ®Ó;-*)')-.5>Tͱ¤žššž«l*.¸›ŒŒœ»( )»“•Ÿº6! -Jȵ­«ªªªª«¯»Þ:)&D¯›“•¡r 2­—ŽŒ“ Þ#/Ƨ›œŸª¼îB5.+)(((*/?Ì«ž™—™Ÿµ9E¥•Œ•§> A«™’“›«ó. '0DôǼ¸¯ª§¥¦ª¸V,)Ö£•Žš¶, !ߟ“›±6'Gµ¥Ÿž¡¥¬·ÉfH<0*% %,F¶¡™•”™¦â' (½œŒÊ% )È¢˜”•š£¹E+%!!',0$*AÔº®­¬«ª©ª­¶Ï?*!:·ž””ŸÌ# *¸šŒ’žË'+Úªž›œž¥±ÉS=5/-*((+/;άž˜–—¯C8¬–ŽŒ“¢O 6¯›”‘”š¨Ú0"$,<]Ͻ¸°©¦¤£¨³â2 (𥖎˜¬5 V£”Ž™¬=#<¿ª¡Ÿ ¦­¶ÈüU@0*$!)=¼¥š•”—¡Å) $Ì‘Œ›¸,&ܥ𕕙 ²^1'##',1;I[м¯¥Ÿž¤³M'0³›’žÕ! +·›’Ž•¢Î+-O½­¨¨©ª­²¸¼ÒJ2&+W«›”’š©> 7ª–ŽŒŽ•§E8¸¡š˜šžªÁL4,))**+/5=sºªŸš™›¤¿3#w¢“ŒŽ˜¬2 V¥–“œ­J'(7hÀ´®­«©¨©«²ÆJ,1¿Ÿ•“») &Á‘¼,'Z®¡œœŸ§²Ë^>4/,*&&(,7ì® ™–—›«Y#.±˜Œ’žã .·•’“™¥Å7%%-:PÔ¾¹²©¥¢¡¤¬È9$$K©˜–§A >¨——¨R#!6È«£Ÿ ¥ª²¿ÏrF7-& "*=¾£™”’•¶0"Øž‘Œ‹Ž—¬6$ù§š•”—ž­à7*%%',08DTÚ½¯§Ÿœ¢®ï,.¸œŒŒ›»( *¼œ‘ŽŽ“¸4.U»¬§§§©­®±»ÆY5()J¯•‘’˜¥O /¯™Œ“¡ê"1¾£›™š§»`9-+++*+/3:h½¬Ÿš˜š¡¸:K¦–ŽŒŽ•¦; B©™‘“›¬Z)&1K͸°¯­ª©©ª®ÀM- ,Ï£–Ž’œ·-  ä “›´/$B¶¥žŸ§³ÈZA7/,)'%%*0N³¢š—–š¦×(+º›ŒŒœ¿' *Ÿ–’“˜¢º>(#+5Hh׿·®§£¡¤«½=$;¬™Ž“¡~ 7«—ŽŽ”¡Ó)!4έ¢ŸŸ£¨­¶Çã[<.& %3Õ¨›•’”œ±6 B¥”ŒŽ–©;D¬œ–”—ªÅ?.)'(,09CT×»­¦ž››ž©Ê/)Àž’Œ™°- $ÏŸ”Ž’œ´8 (=Í´«©«ª¬¯²¸Åo:(%>¶ž•–¡Ø$ *¶›Œ’žË&)ß©ž››ž©¼U6-)'&'((*.<Ù±£›š› ´:8¬˜ŽŒ”¢N 7¬™’‘˜¦Ï/ &0I˸±®¬ª¨¨¨«·e/!(a¦˜Ž™®1 L¢”Ž™­8"=»§Ÿž¥­¼ãL<2.*%"#',Cº¥›––™£Î) %ÊžŒŒ›¹* $祘““˜¢¹C*!'/+%%&'*-2;C캫¢žŸ«Ð-!S¥•Ž™¯- N¦—”œ°>#%6æ¹®ªª««­¯³¼ß?, "5¼ –”ž½( &¿œŒŒœ»+)몙š¤±ÜB5.,++**,3DÚ±¡›˜™«T#4¯™ŽŒŒ‘žÑ" .¶œ“‘—¡¿3!#.DÖ½´¯­«§¦¨©³ò5#%Iª˜Ž—¨> ;§–ŽŒŽ—¨L 7¿§Ÿž£«¶ÌUC;1,($#$*=§œ–•—Ÿ¼/ f ’ŒŽ—®. "[§™“’–­ø1&! $+4BgϾµ­¥Ÿžž¢¯þ-0·œ‘›») )ºœ‘Ž’œ¸3,[³§¢ £§¬±¹ÃáF3*#".o­”’˜¤k" 1ª—ŽŒŒ’Ÿà!3¹ ˜–—›¦»N/)&')-039Iݼ«¡›œ¦¾7G§–ŽŒŽ•¦= G¦—Ž™¨k)&6÷¸­ª©¨©«¬¯·ÌD-"/Æ¢—“œ·, ÞŸ’Œ™±1%O¯Ÿššœ¢®ÆN;5.,,++,/<Ò¯¢š–—›¥Ô(,·›ŒŒœÂ& )Þ”‘— »9%",>kÈ»²®¬¨¥¥¨®Ê=("Cª™Ž“ ó! 8©–ŽŒ“ Ô' 9¾§žœŸ§¯½âVD6.+'%&+=Ĩœ–“–œ¯9J£“Œ–¨: Hª›”“–«è2% "&.9E]Ô¼±ª£ŸŸ¤¯j,'ס”Ž›º) j¡•“¸1%=Ç®¨¦¦©®µ¼ÉxE4( 'B¶Ÿ–‘‘–¡Ü% *¶šŒŒÆ&,Ç£™–—›¤¶g6+()*+/6;J黪¡œš›¡²H$@«—ŽŒ“ Y 9«™Ž—¥Ö,#1WÀ±¬¬««««­µÉG."*o¨™‘’š¯3 M¤•Œ˜«:!=¶£œ›¤¯ÈK7/-+(&'')/AÀªžš™¨Ü& "Þ “‘œ¼& !e¤˜““˜ º<$'3<>Ì««©§«®½V8)$+>̱«ª¬³¿T82-'&(,3D{˽·¹ÄáG7.*+.4>TäÎÉÎßbOJ@<;;==>AJZúÚÔáxYJECCEGGLTPLJHKMOUYTOKD@?>>?DJMQZWQONJHHIJMW[Y\^^][[bzýlhhhhedjõæçèâßæïoklsóíæåæåèûpl_[Z]rïíôüq_ZVWWX`lïêþmfj`^ceqñìôðìêîöîàÙÖÖÕÕÚÜßãàÝØÕÐÍÌÊÉËÏÒÙåèëïêÜÑÍÊËÎÓØÛåëíü÷íîæÜØÓÑÑÖ××ÝßæåàèîïëÝÑÍÉÆÄÄÉÎÏÖàâãÚÓÌÈÄÀ¿ÁÅÈÎÔÕØÝÝÚÓÏÍÉÉÌÍÎÎÏÏÏÏÏÓÖÖÕÔÔÓÐÎÎÎÎÎÓÙÝãììéëëâÜÕÐÓÑÐÒÑÕÚÞÛ××ÔÐÎÎÎÎÍÌËËÍÏÏÐÎÍÌÍÎÏÑÏÑÔ×ÖÔÐÑÒÒÒÏÒÙÛØÚßâåááãßáßßßàêóñëíçêðùüòèåâÞßßæíÿloþ|øçäãááÞÛÚÜâéîùwwòçäÝÝÛØÚ×ÖØÚÝÞÛÞæèéèßÞàÝáïþ|}|nko|tqvrzûòõíìöûúùz~ëâßÛÙÚÙØØÞãßÛØÙÜÚÕÖÜÚ×××ÖÒÐÒÐÏÎÎÐÒÒÓÑÎÎÏÏÏÑÕÝåÞÝÜÞßÝÞÜÚÛÚÚßë}ýìäàÜÝææèÞרÙÙÜÜÝÛÚäæÞÝÛÕÕÕÓÑÑÒÒÒÐÔÖÑÐÔÒÍÍÎÎÎÎÎÏÐÐÑÑÓÓÕÖÕÔÏÒÒÓ××ÚÙØØ×ØÜÜÚÛÙÕÛÜÚÛÜÜÜÙ×ÛÚÝçðîììßÜÛÝÜÛÙÙØÕÔÑÑÑÐÒÓÒÓØÙ×ÚÙØØÜáèíìñîôtoplqyyzk_^bcea]\[[[XWWTOOQQNLKKKKMLKKMOQPRTROOOMNPUVSX[Z]ade_\\]]XY]ada`ecbc___]ZXUW[__XVYVSROONKKJJLMLJLMLMMMKHIKNONPQSSQSTWWWXYWY^cacb\Z]___]^_]^b^[YXXYVQPOMOONNNMMMMNNNNMLKNOONOQOOPOQONQTROQWX[]^\Z^finnjhhinriehlnr{|sosþþmmonn~ûù}jovø÷þööþoohab_bcdf_]^\Z\\^`cg`bfffdcejjllimsuùùoigküüöîôïöóõöüû|qûôó{yôïõþøîv_^dece``a]\ZZ\]YVWSTSRX[^^[WUXWY\^]]_]^]]bcflnfjp{ñ~ýøóðïåáâäàÝÞßßäéáßæïïãáäèíõüñîóïíñ÷ùíæàáççêêäààåäÝÜÚÛ×ÙÝÝÝÞçääåãéðéßÜÛáçáÞÛÙÜÜÛÛ×ÓÑÒ××ÚÙ××ÔÖÙ×ÙÝÛØ××ØÙØÕÖÙÙÙØ×ÙÚÙØÖÒÐÏÍÍÐÔÔÔÖÖÓÓÏÎÔ×Ù×ØÚØÛàæàààßÝÝÝÝãæäâßèèëõø÷ñíïøèääëòòzpxîçëõx~õõøqÿïééíçìûqýõðî÷ó÷øûqpmqleg_^^]]^\VWWYZUSQNOMKKKJIIIIGEEDDBABCC@???@???>>===>>>??>>>>>======<<<=>>>>>>>>===??>==>>>>>=====>>>?>>>>>>>>>=>===<==;;:;;;:999::;<<:99:;;:;;:::;;;;<=<=;<<===>===>>>>>>>>>>>???@@??>>???>=>=====>===<=<=>???>>=<=>???>>>??ABCBBDCEGGIILNOPRVX[[YYY]aafgl}øý|xytlmrôçãåèàßßßßÞêðíåßãèëéëêæääÞßãçïîëßÖÑÒÒÖ×ÖÕÏÎÎÎÍÌËÈÈÉÇÅÃÂÃÄÃÄÅÄÃÂÂÂÃÃÃÄÃÀ¿ÀÀÁÁÀ¿¿¿¿¾¾¾¾¿¿¾¾¾¾¾¿¿¿¿¿À¿¿¿¿À¿¿ÂÃÂÁ¿¿¿ÁÃÄÃÀ¿¿¿¿¾½¾¿¿¾½¼»»¼¾¾½½¼¼¼¼¼½¼½½½¼»¼¼¼»¼¾½¼½½½¾¾¾¿¿¿¾¾¿ÁÀÀÀ¿ÀÀ¿¿ÁÁÂÁÂÃÂÁÃÅÅÂÁÁÀÂÅÇÅÂÀÀÁÀÄÈÇÅÆÆÄÂÁÄÅÆÆÅÄÄÅÆÇÇÈÈÇÇÉÊÌÌÎÎÌËÌÌÍÎÎÎÎÎÏÏÑÑÐÑÑÒÐÏÎÍÏÎÌÍÍÍÌÏÔÑÏÎÍËÊÊÊÉÆÅÆÅÅÅÅÆÄÁÁÂÁÀÁÃÂÂÄÄÂÂÃÄÃÂÄÅÃÃÄÆÈÆÆÇÈÊÊÈÇÈÊÌÍÍÍÌÊËÍÍÎÍËÌÍÎÏÐÐÐÑÑÑÎÌËÊÊÈÇÇÇÇÅÃÃÄÃÂÃÄÃÁ¿¿¿ÁÁÁÂÁÁÁÁÁÀ¿ÁÂÃÂÃÃÂÂÄÄÅÅÅÇÇÇÈÈÈÊÊËÍÌÌÍÍÏÑÏÏÐÏÍËÈÆÇÊËËËÌÌÊÇÉÉÇÆÆÆÆÆÅÅÇÉÈÆÆÆÆÄÄÄÄÅÄÇÇÅÄÅÇÈÈÇÆÆÄÆÇÇÈÊÌÌÍÎÎÎÏÑÑÖÛÙÙÝÚÞéæãÞÛÙÚרÙרØÛÛ×ÔÔÔÓÓÔÔÓÒÑÎÍÍÏÓÑÑÐÑÏÎÍÏÒÏÏÐÏÏÏÏÒÓÕØÚÜÝàèõýpkgadb_]_^YUUZXTRQPPR[_^_`fc`_biklhoþvwôîþ{úøöyýðìðøïïïïïú{|{rjfipmlmd_^[alhb]_ggc_bfba`^aie^^bb_^^_eeekuzvòââæçåäáÝÚÚÜÚÙØØÚÖÔÕÕØÙÖØÚßáßàãåäåàßãíù{~yopklkihdacfd`]ZXWXZY[\WSX\]aiollllrmpþxzüüz|xsýøïîýùëíèææèòú~öñöüz~{qojoxwzxqkd_^[[[YVSTXUQSRRSSQPNNPNLIJMNMNPOQPNOONMMNTWVVUX]figebb_amtmmwzryóúwoigcda_`\XWYYUUTQONNNLMNNNNMLKKLMKIHHMMLKJKJKKMOOMMPRRSVTUWXVRQRUZ][WY[\[^gkkfbgrkiswzonü|uzsuz~r{pceiiejpoheb^^aa__\ZZ\]abgk]Z_kid_[\^^dgjnnlea`_]]\[^eeeea_^`egc^^`]^]YZXZ__[ZVSSXgg]_dgdbgfegkjehmonnptrihghpùóüzmmede_dknlkkp~ñëéýlgdbenkb_][\]]_cbgg`ca^akw{wsonyúûóóüòôõìéêìíïíêèêñïæááÛÞääéåâãßÜàääêëãáßßèýuuzwmjonlg__ceei`_^\]\Y]_boia^`agdhnnyy~zzôéæáäåååàÞÝÛÙÜÝÜÛÛâìéêæàãêçéô÷üîéñòþs{~þuwogbdjddb\\___a_]\]`^^_^_^[ZZZ[Z[\[\^__dd^]_bYUZ_dihb^\blecghmheghdff_gj`XX]a^\]ZXWXXXUTSPOONNOQQOPNLMOONNNNJJKJIGGFFGHIJKJJKKJHIJKJJIJHFFHIGGHHHJKLKKLLKKJJLNRSQONMLNRUXUSTWZZXZYSTYZXXYY[XW[[\\^ZTQOPRTQOPSSQSQNNNNNNQOLMLNRSQPPRRQQPQSWXVX\\]]]_dbab_bhooozûìæèáäëìïèåéçääçèãÞÞèðíéëêéñëâåçêèæåäááêêèçåáßééãÝÛÜÙÝßÝÜÚÛÚØ×ÕÕÕÕÖ×ÙØÔÒÏÎÏÔÕÒÏÎÏÐÕÖÒÐÒÔÖØÙÝààÝÙÞßÛÞãâæéíðîëæõûîæààßåìèçëâßâìéçîîïîøuwýyouunqÿíéïõ~}{suxw}xjròòûüÿyý~{ûùôwr|~uzøõçêïîôîçåçòùòùû~xx}zkcfi`^ab_gjaenrwyûýlonjovt|÷÷|o|îí}|üsliyïïèéöysslffqqmnnlkd__ccXRQQRTX[XTXZX[^`_ZVX]\\dkpsompofbchpyvkfadmmrskhmqsnquoog^`gcdfjmgb_]][Y[]][ZY[Z[]_^]\[[[XWX\a][W[^__]\Z`hmlhdgimüømoxnntwrunpputojbgfd`][[YZ]YY\\^hnnf_cb^^^a`]]chfh^^dghhicbfinmikmnkkonfcknnoslopoibcgfdealvw{îåäåääâßàÞâåãÞÚ×ÙÜÛÙÓÔÙÛÚÜÛÙÙÚÛÕÖÖ×ÙÖÖÜÞÝßßÝÜÙØÕÕÛÚØÚÙÚßàßÝÝÚØÙØ×ÓÐÑÓÑÏÏÏÓÖÕÕÒÏÐÓÕÔÒÐÒÎÍÍÐÒÏÏÏÎÎÍÍÎÍÍÍÍÎÏÎÏÏÏÎÏÎÎÏÎÍÍÍÍÍÎÍÎÎÎÑÏÎÏÍÌÍÑÑÐÐÑ×ÖÔÖÖÓÖÙÚÛÚÜÝÝáð|}øòðíëøtvtrnonjiklor}ü~ûü}w~{þïêëêñýù~xuý~~ux}yõþvqgaehfikj`_hhjmmhehoyqqmnxüøù|nrupikuonmioþþ}rqoonmmekwsnhbcabknljfjmmjimquzþýù|khkvý÷ôòòþý}ûõöôyoijv|z}ùòûnlmr|÷ù|kdeaedec^]_^]__emnnuyomröìï}wøùðëùvv~øøóïðòüýþø÷ysmnzøóõô÷xwý~~÷îîóøññöìëóþ~nfifhgjk^^beca^XXUSTRUVTUUWWVVSRPNMMLMOOOOOLKJLLLLKLKJJKKLMOMLLKKKMPPOONNOSRRRUUPSXXVUWVQOOOPTUX]^ZVWY[]```fa_]\_emkhiifbdhb`_^]\`dfli`]bgipx}r|ö÷÷xúýjVê¼À_bR>?2/,,./026C×´¥š™¨Ö),¸›ŒŒÅ% +»”– ½7""-BãÀ´¯®­©¨ª­·ì2#"?­›’—©A /®™Ž–¥P .Ϫžœ¡©¶ÖH93,(%#$'.F½¨œ––˜ž¼. R£“ŒŽ—«3 >«š“‘”œ«k,$-=oɼ±¬©¤¢£©ºH)-Þ“Ž›¸* #É‘›²3(L·§ Ÿ ¥«´¼ÌeC5+$#-W¯•’‘–¢Ð& ,²™Ž‹Œ‘Ç$+Ç¢˜••š¤¸S/(&%(,/7?Oθ«¡œœ£º?#B©˜ŽŒ”¡P 9«˜Ž˜§m("0a¹­¨§ª«­¯´»ÏI.$!.Ú¥™‘’™­6 oŸ‘Œ‹–¨A%W«œ˜—™ž¨»b>40/.-/28Jа¢›——š£½1*»œŒ‹Ž˜¯. (Åž”“œ®M)$/I˶®«©§¥£¤§«¼M-#>­š‘Ž’Ç% /®™ŽŒ’žÃ*/Ϫž›œŸ¦®¾íM@7/,('',>Å©—”•›«B@¦•‹“¢N<¬š“‘”š¨Ì5& "'/;Nßǹ®ª¥¡Ÿ¤®Ö/&é¢•Ž˜®2 i¡”Ž™­;%A¼«¤ ¡¦ª°ºÇèJ6*#(@¸ —’’–ŸÇ) '½›ŒŒ›º)(Ù¥š––š£¶X1)%$&+.2;GtۦŸ£·E$1²›“ f .´›’—¤Ô+-HŲ­««¬­®²»ÍI.$)O­œ”“š­8 ;ª—ŽŽ—«<5»¤œš¢­ÊD3-*((('),3M¾ªžšš¦È, `¢”Ž™³+ L¨™’’–Ÿ·;#$/?wÇ»·³®­­°¹Ø8&-Ê¡•• ç! #П“ŽŽ”ŸÉ('L´¥ŸŸ¤ª¶Ê^=7/*&" !%.R´¢š–˜œ­? -³šŒ”£N .¼Ÿ—”•›¨Ê7&$+5?YÑÆ¶«¦ Ÿ¤¬Ì1 "O§–Ž–¨; D¦•Ž˜¨N#"9Ä­¥¡£¦ª°¸¿ÞJ8,$%8䘓’•º. "ÕžŒŒŽ˜®/%o§›–•™Ÿ­Û9-)()*/49Jï¿­£››ž¬ù)/¶›ŒŒœ¿& *¹œ‘ŽŽ“¸6 !/T¼­¨§¦¥§¨«¯¸á:+!,eª™Ž•¢û  <§•‹Œ’ŸÙ&:¶¡š—™¥²ÓK<5/..-.2<[·¥œ—•˜ž°: \¡’‹•§; L§˜‘“›ªû,'2Oμ´°­©§§¨­¼K++Æ •Ž‘›·* !Õž‘›·/'Lµ¤žž §®¾èL>5-(#"!%.L¸¢™”•š§h% *ºšŒŒ‘žÎ$ *Ç¡˜”•š¥Á<(  $)0;LåǸ­¦¡Ÿ¢ª¿9"A¬™Ž•¥C 3­˜Ž—¦b& 1ݰ¨¤¤§«°·¾ÎZ<-%"/ܩ𔒔œ±1 M£”ŒŽ˜­5 C®ž˜—™Ÿ­Ó<-)(&)-/4=Ṉ¦ž››žªã+'Åž“Œ›»' $Ó ••ž¹7 )>϶®«««ªª¬¯ºæ;)$=²œ”–¡þ  ,²™Œ’ŸÕ%,Õ©ž››Ÿ©¹j<1,+*&$&(.:Ù­ ›˜™Ÿ³89ª—ŽŒ•¦B ;­š’“š©á. %/DqȺ³¯«§¦¨¬¸]-(馗ޑš®1 O¢”Ž™­;%?¸¥žŸ¤«´ÂÛY@5-'##'/M· ˜““—ŸÄ*'¿›ŒŒ›¸+ )Ë¢˜“”˜ ³O-$!#&+3>OÞ÷«£Ÿž¤±N';®šŒ‘žÕ" /°™Ž”ŸÅ,.û²©¤£¤§«²¸ÀÝK3( "0Ñ¨š’’˜¨E H£”‹”¤M=°ž˜–˜ªÃL3+**+,.3:JÒ³§ž›šœ¦Ç2$ÛŸ’ŒŽ—­0 #î¢•Ž“œ¯E%&7ữ««¬««¬®µÑ=+ 8½Ÿ•”ŸÊ& &œ‘’¿))í¬Ÿ››ž¥²ÏK82-*)''(-:ë¯¡š—™®E 1®˜Œ“¡b 1µœ”‘“š§Ó2##-­šŽ–¥D 4¬˜—¦W"0Ó®¤¡¡¥«·ÃÕR?4+&  &7Ï©›•“•´4 V¢“‹Ž—¬3  G«œ–”˜ž­Þ6(##$)/5>Tßñ¨ ¡®ù,*ÈŸ’Žœ») $ÒŸ“ŽŽ“¶5)@Ä®¨¨§©¬¯²»ÏU8)&?³ž•‘‘—¥k! )ºš”¡ó +ϧœ™šž¨º[8-*))+,,0;PíŸ›š› ³><ª—ŽŒ”¥D 6®š’’šª`)"-AÔº±¯¬ªªª«¯½R. ,Ó£–Ž™®5 ýŸ‘ŒŽ—ª<%I¯¡œ›£¬¼åD94.+(%'*1Z¶¤š––š£É*'ÁœŒŒš¸) )ÄŸ•‘‘–Ÿ²M+!$,:O×¾¹²«¦£¢£ª½@%7´›‘ŽŽ” k ,´›•¢Þ'-ú°§£¢¤ª°»ÇñH9-'! %/q«œ–“•œ¯8 :ª–ŽŽ–©= 7³ž˜–˜ž¬Ø6)" #',07ATÖ¹ª¡žž¡¬Ú.%|£”Ž™¯/ k¢•Ž’œ²:!%9Ѷ¬©©«­°³·ÇX9*"6¹Ÿ–‘•ŸÍ' )»›ŒŒœ¼*+Ô§œ˜˜œ¤³Ù>0,*++*+.3D̯¢›š›Ÿ¯E 2¯™Œ”¢d .¶œ“’™¦Ù-"-BÒ»³¯®ª¨©ª¬·l3$)^©˜Ž˜ª? ?§•ŽŽ—©G9¼¦žœž£­ÂïH91,)&#$',A½¦œ—•™¢¿- #ÙŸ‘ŒŒŽ™°, #ú¥™““—Ÿ²L,!!(3AUÒ¸®©¤¡£ªºJ'/º’ŽŽ’žÍ# )¸œŽ’½..诤ŸŸ¡¦«²¾Ðl@4+"#.X¬–’“™©K 7ª–Ž‹Œ’¡n!6´ž—”–œ¦½F0*'(+/6>Ií¾²¨Ÿœ›¤»:$l¤”ŽŒŽ—ª: G¦–Ž‘™«I&';⪦§¦§©«®²ÇK0&'=³”ŽŽ™®3*ºšŽ‹‹—¬9-È¤š––™ž©ºì?7543227Do¼¨˜””˜¡¿/=©•ŠŠŽ™´,9­™ŽŽ“´>'%/FÙ½³¯®­«©ª¯½Y/ 4¸ž–‘’›²0 (¾’’›°3 &L·ª¦§­¹ÜA4-)%!",O´£›™¦Í( 9ª˜Ž›·+ 5³ž—–™ ´H)$+4C^ß󪥢¢§µP*+ÈŸ“Ž›»( #ÍŸ“ŽŽ’¼.(B¾«¥£¥ª®µ¿Î~B1)!,M±ž–’’—¥í$ .°˜Ž‹ŒË%2·ž—“•™¢µj7,))*/7¼µ¦›™¦·C'"2ݯ¦ŸžŸ¥³Æî?-)*,3EÞ¾°ª«­´É\<2258?WÛÈÂÄÄÉÐÚ÷[H?=<>DNr×ÍÎÒÑØûOC?<;<@L_ç×Ô×ûSJFFHJJLKHCBIU_qòyeYNE?=<>BGJPX\^WQKGDEGGJMLIIIJLKLQVURNHGJIMTUXZY[YRTVQRVY[ezúsk^ZZTQV_mîæéîûo_XY`oôíãßò{vkd[[^ctmdb`\]_\\chdlj_XXVPQSZcýìíïór`ZRPOPX]füñïî}f\ZUOOTVUUX[XVW[]^\URMHFDDCCFJVba\ZRIA><<=>CILNUTOKHDA?>>@BDFFGGJMLHHIIGEDDCCDEILKJJJHFFEAABDEFILNONNNLJHGGDCFIIJLMNMMNOOPSPNOOMONNOOQTVVWSSVVSNMLLLMMKMNNMLMMMLLKLMMOOOOOPRU[]XXTPQPPUYZ]\[\Y\]^b`]ZZXY[]hu~òéçãéóëâßÞâéèàÞÛÙÕÓØÝàÜÜÛÝÝÜÝÝÞÞÜßÞÚ××ÛÞàãáÜÙÖÔÓÔØÖÏÎÏÐÓÓÐÑÒÑÓÑÎÌÊÊÊÈÅÄÄÆÆÉÍÌËËÉÆÅÅÄÂÂÅÈÉÉÊÈÇÈÉÈÈÇÆÅÄÆÇÉÉÉÈÉËÉÊÇÆÅÂÄÃÄÆÃÂÂÄÆÅÅÄÃÂÀ¿¿¿¿¾À¿¿¿¿ÁÀÂÄÃÀ¿¿ÀÁÂÁÂÄÅÅÆÈÊÊÈÉÈÈÈÇÈÉÊÊÉÈÉÈÉËÍÍÍËÊÊÊÊÉÊËÌÍÍËËÉÊÎÑÐÍÊÈÉÊÉËÌËÊÈÈÉÊÊÊËÌÍÍÍÌËËÍÎÌÍÌÌÏÒÑÍÏÓÏÏÒÒÐÏÑÕÕÕÖ×ÖÖÖÕÓÔ××ÕÓÑÒÑÔÖÔÓÓÑÏÏÑÏÍÍÍÍÎÍËËÌÏÕÓÐÏÎÐÔÖØÖÓ×××Ö×ÜÚÛßÞÞÝÛÚÚÜßæëåâæèåäçáè}lhuúxûþlt{yþ÷îòzøêâÝØÙÜÜßÞÞÝÝäçåâßãèêèåê÷÷ñöùzzûõ~kjjnsn|öúüý~~zvrlssebca`]^eb]\dd]^bfgiwyh`bceionhgefdgry}þodemln|ôúrojkoomllottof`fonige^^_]\\\[Z[Z[[]^]\\ZXURTTPOMLMNNOOORSSROOPOMLLLLLKMNOOLLPNNMKJIJJJIGFHIIHFFHHJJHGFHJHKLIGJKKLJGFHKLKKKJIHKLKKJKKLKKJKLKMNNNMOPOMMMJKNQQORSOPOMLKIHILNMLOOONMNNOPSPNONOOQTTQOOOQROOQTSPOPSRSRUSSVUPQTSVUSRPQOOQVUPPNMMNRSTRPOOONNPPMMNMNOPRPTZYWUQOOTZZTQQUXZdmea]ZZ[Z\__iomdgj`cgfdda`]_bea`fehe_\_dgkd\[[]bjqoijppuýø|ïíóøþñîêíìçàÜßæëëìêêíîïúùííö|}{uxzýóùz~|ywllljsöóøxkwúñï~ýöìííçåãæëêìðìêçæåÞÝßßÝÛÛßåáÞÝÛÖØÙ×ÙÖ×ÙÝÞÛØÙÚ×ÔÓÕÔÒÑÑÕÙÚÙÖÓÐÎÏÓÕÐÎÏÐÏÏÎÒÐÎÌÊÊÊÊÊÊÉÈÇÈÈÈÈËÌÉÉÈÈÊËËËËÌÍÎÎÐÔÕÔÐÏÎÐÑÐÎÍÎÎÐÒ×ÜØÕÕÕÑÐÔÕÓÒÓÒÔÓÑÒÒÔÒÏÎÎÎÍÎÏÒÐÑרÔÐÎÏÎÎÍÍÎÎÑÑÏÒÔÕ×ÙØØÙÛÜÙÚÞãìîð÷ïêêô{|twmhgaa\]aa^^fkgejicbfmz{óîîìó÷ôííêéçæäáâçåßàãàßæâÝÛØÛÜÜáâßßâæéíòú~{|vj`^af`]\Z[[\`ba^_da`bijeedacm}ïóõïíïþùõóýüðïìíêêêéåçêèççëëåáèêãßæìêêïòûqt}øwkorxqlx~~~ojebaajrnls~ynkkjgggb]\Z\blg]]]XYbkh_aegdckwxyóïû|qs~wyuoklgjtmqolhdfhggjkllceljjhkolotwvokicet{yvwýîíóóïîíîñîììíêìïèçëèêòôðô~p{ïöûïìï}nlkoyvidhmuwtsrjqzplcfgiieaee_foporle``bejvôìæßÝÞàèæåçâÞßÞßçäÝÛÚÜßãìïïú÷êî}jchq|øzd]^b_^]`ehgc][_fkgjklmgfiomm{}{qnuqo}ïîëíïìíêêçëîóýïîëæççèî÷unnlo~tmmkg`_^bdba]]]bimtsooouyxyüý|}øïëèçÝÜÝßàßàßßÜÜÛÚØ×ÙÙ×ÔÚßÝÜÞÝÛØÚÛÛÝÝßÞÜßßæîñôxptq|úþoiecfcffffaekdaholgkmntúñóöïîùûíéçéïçâåìùöòíêî÷yzswýþ|ng__``_[YZZZY\_]VUVWTNNOPRTUTRPNNMNOOTWWZ\^]_`agjlkjeiknvyòéðíëòûýugjikqvtsqux{|uomoqyýöútsýÿxwsponqqryxqlmrkjnkhce_^houokijdkulidddfb__ZY\^^\]]\_c___]]__`]YWY]][[TOOQUUSTVPPUUUQOONLMMMORQNMLLKKLJHFFECDDDBA@ABA@??BB?>>>?>>>=>><;<;:;;;::98889886665666666667777876555444444445666555556666777667765566656654677765556678888999:999:;<<;=>==>>>>>??ADGIHGILOPQTSUYZ\\`myýõöîîñìêéáØØÙÙÔÑÔÓÐÔÔÏÎÌÎÒÐÏÍËËËÉËÎÏÎÎÏÏÌÈÈÈÈÇÅÄÂÀÁÄÆÅÁ¿¾¾¾¾¾¾½½¾¾½¾½¼¼¼¼½½½¼¼½¼»»ººº¹¹¹¹¹¹¹¹¹¸¸¸¸¸¹¸¸·¶¶¶·¸¸·······¸·¶¶·¸¸···¶¸¸¸¹¸·¶·¸··¸¸¸¸¸¸¸¸¸¸¸¹¹¸¸¸¹º¹¹¹¹¹¹¹º»º»»ººº»»¼¼¼»º»ººº»»ºº¹º¹¹º»ºº¹·¸¸¸ºººº¹¹¹¹¹¸·¸¸¹¸··¸¹ººº¹¹¸¸¸·¸¹¹º»»»¼»¼¼»½½½¾¾¾¾¾¿¿¿¿¾¾¾¾¿¿¿ÀÀ¾¿¿ÁÄÄÃÅÆÆÄÄÆÆÅÄÄÃÁÂÄÇÈÉÇÈÇÅÃÄÆÉÉÈÈÈÈÉÊËÊÊËÌÎÏÎÍÏÓÕÓÒÕÖÖÖØÙרÖÓÔÙÜÝßâìðìéèááâãäâëæáãåèåææëéêðíîïëëüz{{wtpmhj~øzrmdab`][^eeecilhjnicecehmqibjkb_behhfh_\^][^ffaa_\[]`^__\XXZ\ZYZWTRQPSX[]^^[[]fs|roollpmÿìéÞßéçìòæßâçïýýüîéë÷þ~xüüòùxsrqkhgmllpvrlije]]][]___]^^]_a``chiaanpjvý}~ýñïðïïïìíïîòëèîèßÞÝåéèëñúø||znouÿ÷}khd][XWSOORRRRSRSVWPMNMMMNNNOOPPVVWZZWY\]\\clýóïêçæåëìíóîçäßÞàäçêòìæâæìøzúíéô|öøùîòþwspöæâæïûýÿzþùñûvÿóúüÿùïíæèîòéãáÛÙÖ×Ú×ÕÔÓÏÎÎÌÌÍÎÕ×ÔÓÏÑÒÖ××ÕÕ×ÕÓÕ×ר֨ÚÙÕÕÖØØØØÙÜÝÞÞáâàäêèäàÞÜÜÞßÝÜÝÝÙÙÙÚÛÙØÕÔÓÒÒÐÐÓÔר×ÝßÝßÞÝßÞàáÞÝÚÛãçèéæããÞÜÝÝßãâßÛÝààààéæÞÛ××ÝâêïèäáàæïîïéßÛÜßæëæêïùöñøþ÷ðýyutnoþôìéïûþposs÷êëøöñùzýæâåâããææãßÜÜÝßÞÚרØ×ÔÓØÚØ××ÙÜàèçßÞßßÝàèìõzjilrýüöú÷ö~uvý{whdyôêäèêóüïøvùý|ðíéãâäæêèèéêìëëìôïïýòèéône_\ZYZWSQUTUVVXVUPORVUUYWWYZXSQPRRQRPPRPORTTRQRRSTRPOSUUXYXUSVZ[YURSTRTSTWVVY\ZXURRPSUTUUVUTSUUTVTSSRSTQQUVWVSPNNOQQRSQPOQSPNPPOONMMMOSSTUUROPPORONORSSSTURRUWXVVTVYY]__\WXXYYZWQQV[WVYZUQPNLJKKKJIJLJIIIHGIJHHIFEFIJKKKKLNNNNMLMNONLORPRQPNMMNOOOONMNNOOOONLLLLMMLLLMNNPSSQNLLNMMKLLLLLMMKJKJKKLNMMNOOONNNNPROOMOSVYWVXYWVTVXVWXZ[[\agjlggdcfgfedb_\Z\]c`_a]YUWX\^^^[XUZZY\\YVUWUWYYZ[^b^XXXUVZZYZ\^__cb\YVWX\_\[]]\^f`XUVTRUV\\\]XZ[[^_^^^[]^[ZY]d^^_^`ehla[\[[]befeggea_egaac_`__cdjnkfihgd^_a_djimu}ÿýóèé÷}{ëì~ïèéëçßßäâàßßÞàèêéßÛÙ×ÖÖØÙÙØÖØÛÜÜ×ר×ÖÔÔÖÙÙØÔÑÑÔÒÑÔÒÏÌËÉÉÊÉÉÉÉÉÈÈÉÈÇÇÇÇÇÆÅÅÇÇÇÇÈÈÇÆÃÂÂÃÂÂÂÂÃÃÄÂÃÆÈÇÅÄÆÆÅÈÊÉÊËÍÎÌÌËËÌÎÏÏÐÎÎÍÍÍÌÍËËËÕØ¼°Ç\Ýf\äܼ¸¶©¨µÓO9.)-GÅ­¡œ›¡±t0$ '7Ú­¡Ÿ ¦¯ÃY@=:¬š‘Ž˜ª@<¬š’“›¬E$%:ε­ªª®±¶½¿Çò@/% .ਗ਼“‘”ž¼+ 䟒œ½* $V­žšš¦ºQ3*&%&&&(+/8l¶©Ÿ›œ¢³? +¸›“Ÿì *½ž”‘—¢Ã1);𿳮­¬ªª¬°ÀL. $E­š’™«; 3¬—ŽŒŽ–¦M 4¾¥œššž¨´ÓB5/*('&(,6Q¹¦˜–™¡¾/ Z¢’ŒŽ—­1 G©™‘”œ¬T*$.?gɹ°­¨¤£¥¬½H),Ÿ”ŽŽ’œ¾' #Êž’ŽŽ’ž¾,'Dº¨¢¡¥ª±¼Ð\G9.'!"-I³Ÿ˜““™¦e# -²™ŽŒ‘žÖ" .¼Ÿ˜”–œ§¿?+$"#&,0:DO׺®¥Ÿž ¨¾5<¬˜Ž—¨? 6¬˜Ž˜©Q%!3ì·«§§¨ª®³·¿}?.#"1Ì¥˜’“œ³0 e¡“Œ™®4#J­ž™˜š ­ÊE3-,,+,/15BÛ°¤™™§Ô**¼œŒŒ›»( &Æž”•ž¹7"!+>Ø»¯­­«ª©ª­¶Ï;'";°œ“•¢o /¯˜ŽŒ“ŸÕ'0çž›œŸ§³Ì[D7/-*'%'.>˪˜–—²7?§•ŽŒŽ–¨; >¬›”‘”œ«å/" '/>`Ⱦ¸¬©¦¢¢¥°n/*Í “Ž™®0  ן’™­;(J¶¦ŸžŸ¤ª²½ÌèL7,&! $-H´Ÿ—’’– Á* *¸šŽ‹‹›¸*+¡˜””™¡´X2)%%)-1)!8´œ’ŽŽ“žÌ# +¶šŒ’Ã)+謠Ÿ¨µÍO?7.*)&#&*3è­Ÿ˜•–›ªK:ª•‹Œ’Ÿa8¯›”‘“™¥Æ7&!'/=TßǺ¯©¦¡ £¬Ö3 $\¦–Ž—«6 L¤•Ž™ªE!$<«£ ¡§¬°ºÈÜN6,& (A¾¤˜’’–ž¼+ #Í‘ŒŒš¸+ %y¨š•–™ ±i3($$&*.7AKæ¼­¢›› ¯_(2³šŒ’Í" ,µ›‘Ž•ŸÅ..T½®©¨©«¬®µ»ËN2%)T¬œ“‘™§I 5«–ŽŒ•¤M7º¢›™šŸª¾Z8/,+*)*,-6PÁªŸššœ¥¾/K¤•ŽŒ˜¬2 I§˜‘‘”œ­L(&2Mλ³¯­«©ª«®ÂB+,È¡–“¿' !О’‘œº,'M²£žžŸ§°Ä]C80-)$#%'0i³ ™––š¨h$.´™ŽŒŒ‘žÒ! -»ž–’”™¥¿:&$+3AnÎÀµ¬¥ Ÿ¢«É8"!G©—ŽŽ”¥G =¨–Ž–¥p%!5̬¤ ¡¤ª°·ÃÝO8-&&6ʦ™“’”œ´3 oŸ’Œ‹Ž—«8$\¨š””—«Ç@.*(*.16F_Ùº¬¢ššžªÖ,-¼œŒŒš·) )¾’ŽŽ“µ9!-Q¾®¨¦§§©ª«°ºÚ;* )M­œ“Ž•ŸÓ# 0­—ŽŒŒ’žÏ%0¿¤›˜™¦µÜD6/--,+-06L½©ž™˜™Ÿ°<E¦”‹”£G A©˜‘’™§Ö/ &1Lм²¯¬¨¦¦§ª·[/ *Т•Žš±.  øŸ’Œ™®7&I´£œŸ¥­ºÏVE:/+&$%(/Xµ£™••™¤Õ' &Á‘Ä$ &Ö£˜””™£¼A)#)/:Gi̼¯§¢ ¢©Á:$3¶›‘ŽŽ”£N +´›‘Ž—§W#*M¸«§¦¨­´¼ÉîI6+".j­œ•“•œ³3 ;§–ŽŽ—«7 8µŸ™—š¡¯ç6*$#$&(+.5?b¼«¢ ­i*#ø£”Žš³)  k¢–”³:!(<Ü·­¬««¬®¯²¾ñ;)"7»ž”•ŸÈ$ (º›Œ‘Ã(+Ö©š›ž¦µÙF6/-+**),1=ά ›˜™ž­G 5­—ŽŒ“¢R 0´œ”“š¨Ù.#,=}ɼ´¯¬©§§«´è1 %X¦˜Ž˜«7 H¥•Ž˜ª@!:½¨ŸŸ¤«¶ËcJ=3+&$$&,?º¢™””–Ÿ¾-%ÊŒŒŽ™´, %Þ¤˜““—ž®X.%!"%*5CVãÅ´«¤ŸžŸ¢°N*7°šœ¾& -²™Ž’ž¾./ܰ¦¡ ¡¦©­´ºÍR9*##1Ù©š“—¦W :¦•‹Œ’¡c ;°ž—•—œ¦»N2,*)*.37©˜‘™¨m)%5^À´®«ª«««®´ÇK.!.Õ¤–Ž‘š¯1 "ÔŸ’ŒŽ˜¬9'R®Ÿ›š› ­½êF81.,*))-9ø¯ š––™¤Í*-·›‹‹š¹) ,¼ž•–ž³K+! '/@êø±­§£ Ÿ¡¨¸O*!Bª˜Œ‘žä" 7«–ŽŒ’žÂ* 4Æ©ŸŸ¦­µÂßU=1+%$$*=Æ§š“‘“š«@Y¢“ŒŠ”¥CHªš”“•œªÌ;*%#%+18?^;¯¦ ž ¬Ú.'Í ”Ž™³- #ÔŸ“ŽŽ‘›°; (B¿­¨¤¥©­°·¿ÔN4($7¾ —’’—¤p" &Á’žÑ# 'ë©ššžª½O0)&%%%'*-3B×°¥ž›œ¤º:/´›Ž–¦> +º•‘“›ªW'*>俵±±¯¯¯°¹ÖC-$Iªš“’›±/ =¨–Ž™®66¾§Ÿž¥®ÅS;1-*'$#$'.C¿¨˜˜›¤Ê*#Íž’ŒŒ™³, %Û¢—’‘–ž¯N* #+9TÕ¾¸²«§¢ ¢©»J*4¶œ’ŽŽ’žÌ" *¸›Ž“žÄ+,j±¥ ¡£©°¼ÌsK:.(!#0ù­–“”š«@ 3¬—ŽŒ”¥E 2¶ž—•—«Ï8(#""%+08CW׸ª£Ÿž ªÎ/!N¥•Ž—«2 H¦–Ž’›®>!$9Õ²ª¨¨©¬­±ºÁn:+!"7¿¢˜‘•ž¾) "Ì‘Œ›¸,&b«™™œ£±Þ=/,+++,-/8Jϯ¢œ™˜«ô'/°šŒË# -¶œ“– ½5"#.GÊ·®««©§¦§ª¶Õ<'(_¨™ŽŽ•¤N >¦•‹”£q#!<¹£œš›Ÿ¨´Ê]B92.+''*0G¼¥œ–•˜Ÿº2!ù “ŒŽ˜­5 !U§˜’‘•­d."#)4FuǺ³¬¦¢Ÿ ¥°g..º’›º* &đޒœ¸/)Qµ§  £§­¶ÃÓ_B4*" $-S®ž–’“—£k# 1®˜Ž‹Œ‘žÖ"0ºž—”•š¥»G.'%&)-2;E^ηª¢œ¥¹EbÒÅÁ¾½¿Éç[MD?>ETõÍÇÄÃÍÛåïõümij^WTYnÛÌÉÅÅÍÙô\PLMQZiìÛÔÖÞâñi^[YX`szk_YZccYZmtnlc\]\Z_ghjwúô|s|ve]dvúëáèòwigddmþåÚÛÜÝÞêyw~ìááÝ×ÕÚßãò{yxðäÝÚÝÞßäëôúûèßÛÔÑÐÙæÿojjöäÛÕÏÏÓÒÙäôsc\^amõìÞØØÜéîùts|÷úûwzôñëÞÙÙÖÕØÛàîncdhnüêÜÓÎÍÔãûd[ZVV]júêçáÞãæåítmk`Z^dju~ôëàÞÝÝáèãâêm]^fooñãßÞäèíyi^[\bdafqø÷ïîöþng`___`]\bhc_^[Z\\_]\^XRQMMNNRRQUWSSTVYWXWRNLKMQSRQQQQUYXWVXZZYXXZ[__fmilinljj_YUVWZ^__[\ZXWTRQNLOOQTWZ[\]_[WYYZYVVVWY\__bhoneedbcgklþîðòõïëæÞÛãôôóìåèêìóïîìëêïöôûqiihfemzvmmnjh`_]ZZ^ahong_fhf`^b`\_efgggfefjimrmjgbacgionmllkcif`^ZVSV]adfgib__\[XVWROTY][\]_][][USWZZZ]\\^fqnhcedcjlqkdipwqnnmjec_cf__\\]]^\]a`__higffa\_db`llimzñííîîëçãçìíåÞáâáßÞÝÝÙÖÚÛßââëïïòëëåçðäÚÝÞÞåâèíêèâàßÜÛßàäàÜßßêôûìããßÜÙÝÜÜáâæßÛÚØÚÜÜÛÖÔÓÒÓÓÔ×ÕÖÙ×ÖÖÖÒÔØÛÝÞßÝÝÝÞãçäÝÚ×ÔÕÙÛÞâßâéæåßÝÝÛÝßÝÜßßãæìúòïðìâßààááäâÞÞßßßÝÜÞßÝÜÛÜáêöòóïçäçíîéêíîõîæçéæçîíåãßÞâçåëèÞÜÛÜßæçâÛÝÜÜÜÛÜÝÜØÙÚÙØØÜÞÞÞáàÞÝÞæåáèêææãäçåßàâêô~zñçèêæèèïýtnxû}}ïþhbflgdjidglmhagfaa_\\^cikjjkljipommkgglniküùöõðìöûðööëìíñðìîìçìö|unlmdb^_][_ae__^]a^^`aba`_eimvvvys{÷mivøïòïúzôðøþöìíöôììù÷éèèããàÞäæãéëëïöõêáÝßæñïåèéòðîøôõñèåîõîîîîzqrûïöíéïñéçëëñÿrnuûðíìö~öóïìï{x|wumny|ûûûýwwnxúýymlimhcnzrkmrmjhb_aaa^]aeacgjlle_^`llhablpq|ynkcche``ekjdaaeb^cgh^]]\^]fvspvoha`gebb_`^]__ejhhjmkmÿ{w~~ü}smrqnup}îëôxv|}|}riinqnu|qlmtrorqd_ejny}tw{~xnhcfjjljloiehoronrùòôîëîíèääëëêîëçâééäéééîðêìðîôòíûyqruomknnnjoohok`]][]__c\[adeck|ymfnpjnúíôíçëïëäçãáçèæÞÛÚØÖ××ÙÛÛÞÝßáÞÝßáéöíäâí~yrw|ôùïî~øûøwowsjoúúrhp~~÷îìéðïìú}üy}÷ûõþ{ovôþúøúøð÷üún|öyøîöxqvúðòïìïóûöëêöwpgbgrumplacmyxwwpgbhrxy÷özmllbiuupflh_iptquqg[[fhhlkkijw}}ÿýõÿtnkt|{ôêèééêïñïïóùpmp{~wvxóðùwznegda]\^^_fjjggab^\]Z]^aabiliflohifb^\\]immhdhpnmt|ÿqqyúóìêîéëéèëåãÜÝçëåàäëëêìååìîìêííëòýnluvmq}wxtýêèêáàëèéíïìèçàÝÞáßÙ×××ÙÚÚÙÜÜßçäàÜÛÙ×ÚÞåéèêèîøïîêíø~üðñùyqliikifiliea]_`]YYYWXXY[YW]_^\\^\XTWXYZ[[Z[]_]ajyzhddhijccjnqmhcjýúsnokhddjg`[[]\[Z]_[WYZWUTY]ZXWYZWW\ahe]\\\]_fc]^^^__bmnic^^_bk~|wyuzxkhn~uvqkhhtneaaaaitxlgnyytsy|ljxúû~ypoox~qhhgiolilox{÷îÿ{öîìëîéäèàÚÚÜàæâãææßÝáæìõëìöùúõðëææéèìîï÷þýôùýwsxwpkf`ae__ceijkghc_cfiov{ohoxôóúùüþ{voxuntytpml{öùöïëûqûøñëöúîìñòðùúóñ|onnljlpvzumkmlnknrddmÿóüôíîéââäááÞàèÝÙØ×ÓÏÎÍÏÓÐÏÏÐÎÍÌÌÍÊÉÉËËËËÌÌÍÎÍÌÏÏÎÎÎÍÍÏÐÑÓÒÐÓÖÖØØÔÓÔÓÔÒÐÔÖÖÔÖ×ÔÒÓÓÙÜØÙÛÛ×ÒÓÕÒÔØÚ×ÔÔרÚÝÜÞÜÙÛÞßÝÜÝÞáççèëéèêïîðú~óìõùuutxüöñbaresip-1.0.0/share/callwaiting.wav000066400000000000000000002350421372575704200172760ustar00rootroot00000000000000RIFF:WAVEfmt @€>dataö9"AWþcdþXC%ÿáªÿš¥ºþ×úþ<Tÿaeþ[Hþ* ÿæÇÿ­žÿš£¶Òþòþ5Pþ`fý]Lý0þìÌþ± ÿ™ ²Ìýìý0L^þeaÿO6ÿóÿѶ£ýšžý­Çÿæ ÿ*Hÿ[eÿaT<ÿúØÿ¹¥þšªÿÁáÿ$CýXdþcWAÿ!ÿÝ¿ÿ¨œÿ›§½Ûýþ=Vÿbe[þE(ÿäĬž›ÿ£¸ýÔöý9þQbÿd]Jÿ- ÿéÊþ¯Ÿÿ™¢´þÎðþ4þM`fÿ_Nþ3ðÿδý¡šþž°Êÿé ÿ-Jÿ\eþaRû8ýõÕ¸¤þšžý«Äÿã(ÿE[ÿdcVÿ=ýÛÿ¼§þ›œ©¿ÿÝ"ÿ@WþcdYþB%þàÂþ©›¥ºþ×úÿ;Tüaeþ[H+þ çþÆ®žÿš£¶Òóÿ5Paf^Lþ0í̲ ÿ™ ÿ±ÿËíþ1þK^þeaþO6ÿóÒ¶£›þ®þÆç +ÿG\þdbT<úغ¥ÿšªÂþàý$CýXdÿcWÿ@"ÿÿÞ¿©œÿ›§½ÿÚýÿ>Vþbe[þE(ÿäĬþ›¤þ·Õýõ9ÿQbeþ\Jý- þéÊþ¯Ÿÿ™ÿ¡´þÎðý3Nü_fþ_Nÿ3ÿðýδý¡šþž°þÉêü .ýI]eþaRý8ÿõÕ¸þ£›ÿ¬Äýãÿ'F[þdcV>ýýÚ½ü¦œý›©þ¾Þþÿ"ü@WýcdYýB%ýáÿÁª›¥ý¹Øúùý;Tþaeü[Hÿ* çÿÆ®ž›£ÿµÒÿò6þOaüe^þK1í̲ šÿŸ²Ìÿìÿ0L^ÿeaPÿ5óþѶÿ¢›ÿ®þÆçý +ýG\ÿdbTþ;ÿùغÿ¤›ý©Âáÿ%ýBYþcdWý@"ÿÿÿÝ¿ÿ¨œœÿ¦½ýÚýÿ=Vÿbe[Fÿ'äþìý›ý£¸ÿÔöý8Rbþd]ûI.þ êÊý¯Ÿÿ™¢þ³Ïüïþ3N`fÿ_Nÿ3ðÿδÿ¡šÿž°ÿÉêÿ .ÿI]ÿdbRÿ8ÿõÕ¸ÿ£›ÿ¬Äÿã(þE[þdcV>ÿýÿÚ½§ÿ›œÿ¨¿ÿÝÿ!AýVdþcYCý$ÿàÂÿ©›ý¤ºú×úû<ÿSÿaeü[Hý* ÿæÇ®ÿ›ÿ¢¶Òÿòþ5Pü`fû]Lÿ0ÿíý˲ÿŸÿ™ ü±Ìüìý0L^ÿeaþO6þóÒÿµ£þšžþ­Ççÿ +üG\üdbþS<ÿúØÿ¹¥ÿšªÿÁáü%üBYýcdþVAþ!þÝ¿þ¨œœ§½Ûÿüþ=VþbeÿZF(äÿìþ›ý£¸ýÔöÿ8Rbÿd]ÿI. êþɰÿžš¢´þÎðþ4Nÿ_fþ_Ný3þïÏÿ³¢ÿ™Ÿÿ¯Êÿé ÿ-J]ÿdbÿQ9ÿöÕÿ·¤›ü¬üÃäÿ(ÿE[ÿdcVÿ=ýþÚ½þ¦ÿ›œü¨¿þÝ"ÿ@WdÿcYÿB%þáûÁªûœ›û¤ºü×úþ<ÿSbe\ÿG+ ÿæÇý­žþš£ÿµÒÿòÿ5Pÿ`fÿ]Lÿ0íþ˲ýŸšþŸ²þËíþ1Lþ]fÿ`P6óþѶÿ¢ÿšžý­Çÿæ ÿ*Hû[eûaTþ;þùØÿ¹¥›ÿœªÿÁáý%ýBYücdþVA"ýÿÞý¾©ý›œý¦½ÿÚýÿ=VÿbeþZFý'þãĬý›¤þ·Õûõþ8Rÿaeÿ\Jþ- êÿɰýžšý¡´ýÎðÿ4Nþ_fþ_Nþ3þïÏþ³¢þ™Ÿþ¯Êþé ü-Jþ\eÿaR9öÕÿ·¤þšžþ«Äþãþ'FÿZecÿUÿ=þüÛÿ¼§ÿ›œþ¨¿Þýÿ"ü@WþcdYC%ÿàÂþ©›ÿ¤ºþ×úÿ<Tÿaeý[Hü* çÇÿ­žüš£üµÒóÿ6Pÿ`fÿ]L1ÿíÿ˲ ÿ™ ²ÿËíý1ÿK^fü`Pû5ýòÒ¶ÿ¢›ÿ®Çÿæ ý*Hü[eüaTÿ;ÿúþ׺¥þšªÿÁáý$CüXddÿVAþ!ÿÝ¿ý¨œû›§ÿ¼ÿÚýþ>Vce[ÿE(þäÿÃÿ«žüš¤þ·Õöÿ9ÿQbÿd]þI.ý êýɰüžšü¡´Ïÿï4ýM`þe`N4ÿðÿδ¢ÿ™Ÿÿ¯Êþé .J]ebRþ8þõÕÿ·ÿ£›þ¬ÿÃÿãþ'FþZeþbVÿ=ÿýýÚ½ÿ¦œœÿ¨¿Þþÿ"ý@WÿcdYÿB%üáûÁªüœ›¥ÿ¹Øÿùÿ;Tþaeý[Hÿ*ÿ çüÆ®ý›£þµÒÿò6Paf^Lÿ0þìÌÿ± š ÿ±Ìÿì1ÿK^fÿ`P6þóûѶÿ¢ÿšžÿ­Ççþ +Hý[eýaT<ÿùØÿ¹¥›ÿœªÂþàý$CYþcdýVA"þÿÞþ¾©ÿ›œ§ÿ¼Ûÿü>ÿUcÿd[þE(þäÄÿ«žþš¤þ·Õö9ÿQbe]Jÿ- ÿéʰÿžšÿ¡´Ïýïý3Nÿ_fÿ_N4þðýδÿ¡šŸ°ÿÉêþ .ÿI]eþaRý8ÿõÕ¸ÿ£›ÿ¬ÿÃäÿ'F[ÿdcÿU>ÿýýÚ½§þ›œý¨¿ÿÝþ!AüVdücYÿBÿ$ûàÂü©þš¥þ¹Øÿùÿ<ýSbÿd\ÿG+þ çýÆ®ý›ÿ¢¶þÑóþ6ÿOaÿe^þK1ýíÿ˲ ÿ™ ÿ±Ìíþ0Lý]faþO6ÿóÒ¶þ¢›ý®ÿÆçÿ +ÿG\eÿaT<ÿúÿ׺¥ÿšÿ©Âÿàÿ$CÿXddÿVAÿ!Þÿ¾©ÿ›œ§ÿ¼Ûÿü>ÿUcÿd[ÿE(ÿäÿìþ›þ£¸ÿÔö9ÿQbeý\Jý- ÿéʰŸþ™¢ÿ³Ïðÿ4N`f`þM4üðÿÎÿ³¢šûž°úÉêý .þI]ýdbÿQ9öþÔ¸ÿ£ÿšžü«Äýã(ÿE[ÿdcV>þüÛþ¼§þ›œþ¨¿Þþÿ"þ@WþcdüXCü$ÿàªÿš¥þ¹Øúÿ;Tûaeý[H+þ çÇý­žüš£üµÒþò6Pÿ`f^L1ÿìÌþ± š ²Ìÿìÿ0Lÿ]fÿ`Pþ5þòÒÿµ£›ÿ®ÿÆç ý*Hý[eÿaTþ;ýùØÿ¹¥þšý©Âÿà%ÿBYddWÿ@"þÿÞÿ¾©ÿ›œÿ¦½ÿÚýý>ûUcþd[F(þäýìþ›¤ý·Õýõþ8Rbÿd]þI. ÿéÊþ¯Ÿšÿ¡´ÿÎðý4ýM`fþ_Ný3ÿïÿδý¡šüž°üÉêû .þI]ÿdbÿQ9þöþÔ¸¤›ž¬Äÿã(F[ÿdcÿU>ýýÛþ¼§û›œþ¨¿Þÿ!AýVdýcYûB%ùáûÁªþœ›¥ÿ¹Øÿùÿ;Tbÿd\Hþ* þæÇ®þ›þ¢¶ýÑóÿ5Pþ`f^ÿK1ÿìÌþ± ý™ ý±Ìÿìÿ0L^fÿ`P6þóýѶÿ¢›þ®ýÆç ÿ*Hÿ[eÿaTý;ýùØý¹¥ÿšÿ©Âþàÿ$CÿXddWÿ@"Þ¿©þ›œÿ¦ÿ¼Ûþüÿ=VÿbeþZFÿ'äÿìžþš¤ý·Õÿõþ8Rýaeý\Jþ- êÿɰŸÿ™¢ÿ³Ïÿïþ3Nþ_fÿ_N4ðÏ´¢šþž°Êê þ-J]eþaRü8ûõÕÿ·¤›þ¬þÃäþ(ÿE[ecVÿ=ýþÚ½ÿ¦ÿ›œü¨¿þÝþ!AþVdÿcYC%áÂý©þš¥ºû×úü<þSbeÿ[Hþ* ÿæÇ®ÿ›ý¢¶þÑó6ÿOafÿ]Lþ0íÌÿ± þ™ ÿ±ÿËíþ1ýK^faP6ÿòÒûµ£üšžÿ­ÿÆçû +ûG\ÿdÿaTþ;þùØþ¹¥ÿšÿœªüÁáþ%CYÿcdüVAþ!Þ¿ÿ¨œþ›§ý¼Ûÿüÿ>ýUceÿZFÿ'þãÄý«žýš¤þ·Õöþ9þQbeþ\Jÿ- êÿɰŸÿ™¢´Ïðÿ4ÿM`þe`þM4ÿðÏþ³¢ý™Ÿý¯Êýé þ-J]þdbýQ9ýöÿÔ¸¤ÿšž¬þÃäÿ(ÿE[þdcýU>ÿüÛÿ¼§œÿ›©ý¾Þýÿ"þ@WþcdÿXC%ÿàÂý©üš¥ºþ×úþ<ÿSbþd\þG+ÿ çÇ®ÿ›ÿ¢¶ÿÑóþ6ÿOafþ]Lþ0ÿì̲þŸšþŸ²Ìþì1þK^þeaPÿ5þòÒ¶ÿ¢›žÿ­Çýæ ý*Hý[eüaTü;ÿùØÿ¹¥›þœªüÁáÿÿ$CþXddþVAþ!Þ¿þ¨œþ›§½þÚýþ>Vce[ÿE(þäþìž›¤þ·Õö9ÿQbe]J.þ êþɰŸþ™¢þ³Ïð4þM`þe`þM4üðþδ¢þ™Ÿÿ¯Êýé û-Jý\ebýQ9ÿõÕ¸ÿ£›žþ«Äþãý'FýZeÿbÿU>ýýüÚ½ÿ¦ÿ›œý¨¿þÝÿþþÿÿÿþÿþþÿþþÿþþÿÿÿÿÿÿþÿÿþÿÿþÿÿþÿÿþþÿÿþÿÿÿþþÿýþÿÿþÿÿÿÿþÿÿþÿÿÿþÿÿþÿþþÿÿþÿÿþÿÿþÿÿÿþÿÿþÿÿþþÿýþÿÿþÿÿÿþÿÿþÿÿþÿÿþÿýþÿüþÿþþÿÿþÿÿÿþÿÿþÿÿÿþÿÿþÿÿþÿÿÿþÿÿþÿÿÿþÿþþÿýþÿýþÿýþÿýþÿÿþÿÿþÿþþÿþþÿÿþÿÿÿÿÿÿÿþÿþþÿüþÿþþÿÿþþÿþþÿÿþÿþÿüþÿþþÿÿÿþÿÿýþÿûþÿÿþÿþÿûþÿýþÿÿþÿÿÿÿþþÿýþÿÿþþÿýþÿÿÿÿÿþÿÿýþÿüþÿûþÿýþÿÿÿÿÿþþÿÿÿþÿþþÿþþÿÿÿÿÿþþÿÿþÿþÿþþÿÿþÿÿÿÿÿÿÿþþÿþþÿÿþÿÿÿþÿþþÿþþÿýþÿþþÿþþÿÿþÿþþÿÿþÿÿþÿýþÿýþÿÿþÿÿþÿÿþÿÿþþÿÿþÿÿþþÿþþÿýþÿþþÿýþÿýþÿÿþÿÿþÿÿþÿÿÿþÿÿþþÿýþÿýþÿüþÿûþÿþþÿÿÿþÿÿþÿÿþþÿüþÿüþÿÿþÿÿÿþþÿýþÿþþÿÿþÿýþÿþþÿÿÿÿþÿÿþÿÿþÿÿþÿÿüþÿýþÿýþÿüþÿûþÿûþÿýþÿÿþÿÿþÿÿÿÿþþÿþþÿÿþÿþÿýþÿþþÿþþÿÿþþÿüþÿÿþþÿÿþþÿüþÿÿþÿÿþÿÿþÿþþÿüþÿýþÿýþÿýþÿÿÿþÿþþÿÿÿþÿþþÿÿÿÿþÿþþÿÿÿÿÿÿÿþÿÿþÿÿýþÿüþÿüþÿüþÿþþÿÿÿÿÿþÿþþÿþþÿÿÿÿÿþÿþþÿþþÿÿÿÿþþÿüþÿþþÿÿÿþÿÿÿÿÿþÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿýþÿüþÿÿÿþÿÿþþÿýþÿÿþÿÿÿÿþÿÿþþÿþþÿÿÿþÿÿÿþÿÿÿÿþÿÿÿþÿûþÿüþÿÿþÿþÿþþÿÿþÿÿþÿüþÿúþÿüþÿýþÿÿþÿþÿÿþÿÿÿþÿÿþþÿÿþÿÿþþÿÿþÿþþÿýþÿÿþþÿþþÿÿÿþÿÿÿþÿÿþÿþþÿýþÿýþÿýþÿÿþþÿýþÿÿÿþÿÿþÿÿþÿÿÿþÿþþÿÿþÿÿÿþÿýþÿÿüþÿúþÿÿþÿþÿÿþþþÿûþÿûþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿþþÿÿþÿÿÿÿÿþÿÿþþÿþþÿÿÿþÿÿÿþÿÿþÿþþÿýþÿüþÿüþÿþþÿÿÿþÿÿþÿÿÿþÿÿþÿÿÿþÿýþÿþþÿÿÿþÿÿÿþÿÿþÿÿþÿÿþÿÿþÿÿÿÿþÿÿþÿÿÿÿþÿýþÿÿþÿþÿýþÿþþÿÿþÿÿÿþÿÿþÿÿÿÿþÿþþÿÿþÿüþÿýþÿÿþÿÿÿÿþÿÿÿÿÿþþÿþþÿþþÿûþÿúþÿýþÿÿÿÿþÿýþÿþþÿÿýþÿüþÿüþÿÿþÿÿÿÿþÿÿþþÿþþÿÿþÿþþÿýþÿýþÿÿÿþÿÿþþÿþþÿÿÿþÿÿþÿÿÿþÿýþÿþþÿþþÿÿþÿÿÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿÿÿþÿÿþÿþþÿÿþÿÿÿÿþÿÿþÿÿþÿÿÿþÿÿþÿÿýþÿþþÿÿþþÿýþÿüþÿÿþÿÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿÿþÿÿþÿþþÿÿÿþÿÿþÿþÿüþÿýþÿÿþÿÿþþÿýþÿþþÿþþÿÿþÿÿÿÿ"þ@WýcdÿXC%üáûÁªþœ›¥ý¹Øÿù<ÿSbeÿ[Hý* çÿÆ®žÿš£ÿµÒóÿ5Pÿ`f^ýK1þíÌü± þ™ ²Ìí1ÿK^þeaþO6ýóüѶþ¢›ÿ®ÿÆçÿ +þG\üdbûS<ýúÿ׺¥›ªþÁáþ%ÿBYdþcWÿ@"þÝ¿ý¨œÿ›§½ÿÚýþ=VþbeÿZÿE(ýäüìžÿš¤þ·Õöþ9ÿQÿaeþ\J.þ êÊþ¯Ÿý™¢´ÿÎðÿÿ3Nü_fý_N4þðÿδ¢þ™Ÿÿ¯Êêÿ .J]eÿaRþ8ÿõÕ¸ü£›ü¬Äþãý'FþZecþU>ýýþÚ½ÿ¦œÿ›©¿ÿÝÿ!AÿVdücYûB%üáÿÁªÿœ›ÿ¤ºÿ×úþ<þSbeÿ[H+ÿ çÇÿ­ž›ÿ¢¶Òþòù5Pú`fþ]Lÿ0ÿì̲ÿŸšÿŸ²þËíÿ1ÿK^faPþ5þòÒÿµÿ¢›ý®ýÆçÿ +þG\þdbTÿ;þùغÿ¤›þœªÂáý$CüXdûcWý@"ÿÿÞ¿©þ›œþ¦½Ûýÿ>þUceÿZFþ'ÿãĬž›¤¸Õöþ8Rÿae]þI. þéÊÿ¯Ÿšþ¡´ýÎðþ3Ný_fÿ_Nÿ3ðÿδý¡šýž°üÉêþ .Jÿ\eÿaRþ8ýõÕý·¤ÿšžý«Äýãÿ'FÿZeÿbV>ÿýÿÚ½ÿ¦œÿ›©ÿ¾Þýÿ"AÿVdÿcYÿB%ÿáÿÁªÿœ›¥þ¹Øüùþ;Tbe\ÿG+ý çûÆ®ü›þ¢¶Òýòþ5Pafÿ]L1íÌÿ± š ÿ±Ìýìü0Lþ]fþ`Pþ5ÿòÿѶü¢›ý®þÆçþ +Hý[eüaTþ;ÿùØý¹¥þšªÿÁáÿ$CÿXddWAþ!ÿÝ¿ÿ¨œÿ›§½ýÚýþ>Vcÿd[ýE(ÿãÄþ«ž›ÿ£¸ÿÔöÿ9Rüaeû\Jþ- êÿɰÿžš¢ÿ³Ïýï4ÿM`þe`Nÿ3ðÏ´ÿ¡šŸý¯Êüé .ÿI]eÿaRþ8öýÔ¸ü£›žÿ«Ääÿ(ýE[eÿbV>þýþÚ½§ÿ›œ©þ¾Þ"AWÿcdYCþ$ýàÂÿ©›¥ÿ¹Øúÿ<Tüaeþ[H+ÿ çÿÆ®ÿ›ÿ¢¶ÿÑóý6ÿOafü]Lý0ÿì̲ šþŸ²üËíÿ1L^ýeaúO6ýóÒýµ£þšžÿ­Çýæ þ*H\eÿaTþ;þùØþ¹¥ÿšªÿÁáþ$CýXdÿcWA"ÿÿÞü¾©ü›œ§½Ûýÿ>þUcÿd[Fþ'ýãÄÿ«ž›ÿ£¸ÿÔöÿ9ýQbüd]ÿIÿ- ýéÊü¯Ÿþ™¢´Ïð4N`þe`üM4ýðÿδ¢šþž°þÉêÿ .Jÿ\eþaRÿ8öÕÿ·¤ÿšžþ«Ää(þE[þdcÿU>ýÛÿ¼§œþ›©ý¾Þÿÿ"ÿ@WddÿXC%᪛þ¤ºØúÿ;Tbe\Hÿ* çÇ®žþš£ýµÒÿò6ýOaÿe^Lý0üìÌû± þ™ ²ýËíÿ1ÿK^ÿeaÿO6þóþѶÿ¢›žÿ­Çÿæ +ÿG\ÿdbTÿ;úþ׺ý¤›þœªÿÁáÿ%ÿBYÿcdWA"ÿÿÞ¿©œœÿ¦½ÿÚýÿ=Vcþd[ýE(ÿãÄÿ«ž›ÿ£¸ÿÔöÿ9ÿQbÿd]ÿI.ÿ êÿɰŸÿ™¢´ýÎðþ4Nü_fÿ_Nþ3ýïÏ´þ¡šÿž°Êê .J]þdbþQ9ýöþÔ¸ÿ£›ÿ¬Ääþ'FüZeûbVþ=ÿüÛ½ÿ¦œþ›©¿ÿÝþ!AWddYCÿ$þàªÿš¥ý¹Øþùÿ;Tÿae\ÿG+ÿ çÇþ­žýš£ÿµÒó6Pþ`fü]Lý0íþ˲üŸšþŸ²ÿËíþ0Lÿ]faÿO6þóýѶþ¢›ÿ®ÿÆç ÿ*Hÿ[eÿaTÿ;ÿùØÿ¹¥ÿšÿ©Âÿàÿ$CÿXdÿcWÿ@"ÿÿÞ¿þ¨œý›§ÿ¼ÿÚýý>þUce[ÿE(þäÄÿ«žþš¤ÿ·Õÿõý8Rýaeý\Jý- þéʰÿžšÿ¡´þÎðþ4Nü_fÿ_ÿM4üðüδü¡šÿž°Êþé .ÿI]eþaRý8ÿõÕ¸ÿ£›ÿ¬ÿÃä(ÿE[þdcþU>ýÛý¼§ü›œþ¨¿Þÿ!AWÿcdÿXC%ÿછþ¤ºü×úý<Tÿae\þG+ ýæÇü­žþš£ýµÒó6Pÿ`fþ]Lþ0íÿ˲ ü™ ü±Ìþì1L^fÿ`Pü5üòÒýµ£›ž®Çç +H\ebT<úØÿ¹¥þšªÿÁáÿ%ÿBYÿcdÿVAþ!ýÝ¿þ¨ÿ›œû¦½üÚý>Vcÿd[þE(þãĬÿ›ÿ£ÿ·Õþõÿ8Rbe]ÿI. êÊþ¯Ÿþ™¢þ³Ïüïü3Nÿ_fþ_Nþ3ÿïÏ´ÿ¡šŸÿ¯Êêþ .üI]ýdbÿQÿ8ÿõÕ¸¤›ž¬Äþãý'FüZeübVþ=ýÿÚ½þ¦œþ›©þ¾Þþÿ"þ@WþcdYCÿ$ýàÂþ©›¥ÿ¹Øþù<Tbeÿ[Hý* üæÇþ­ž›£¶Òÿò6þOaýe^þK1þí̲ÿŸšþŸ²ÿËÿì1L^fþ`Pþ5óÿѶ£ÿšžý­Çüæ ÿ*ÿG\þdbÿS<úþ׺ý¤›ÿœªþÁáý%CþXdþcWþ@"þÿÞ¿©ÿ›œÿ¦½ÿÚýÿ>þUcýd[ýE(ÿäÿìžÿš¤¸þÔöþ8Rÿae]ÿI. ÿéÊÿ¯Ÿþ™¢þ³Ïÿï4ýM`ýe`ÿM4þðüδý¡šþž°ÿÉê .J]þdbþQ9þöÿÔÿ·¤ûšžû«Äþã(F[ÿdcV>ÿüÛ½ÿ¦œþ›©ÿ¾Þ"AÿVdÿcYÿB%ýáýÁªþœ›ý¤ºü×úü<ýSbþd\þG+ý çÿÆÿ­žÿš£¶þÑóþ6þOaÿe^þK1íÌþ± ý™ ÿ±ÿËíý1þK^faÿO6ýóýѶþ¢›ž®Çþæ þ*Hÿ[ebT<þùØÿ¹¥þšý©Âþàþ$CþXddþVAþ!Þÿ¾ÿ¨œû›§û¼Ûÿüÿ>þUcþd[F(þãÄÿ«žþš¤þ·Õöÿ9þQbþd]J. êÿɰþžšÿ¡´Ïð4ÿM`f`Nÿ3ðÏþ³¢û™Ÿþ¯Êêÿ .ÿI]þdbRÿ8öÿÔ¸¤ÿšž¬ÿÃäý'FþZecÿU>ÿýÿÚ½§þ›œþ¨¿Þþÿ"þ@WÿcdÿXCþ$üàÂÿ©›þ¤ºÿ×úþ;Tþae\ÿG+ý çýÆ®þ›ÿ¢¶Òýòû5Pþ`fÿ]Lÿ0þìÌÿ± šþŸ²Ìÿìü0L^ÿeaûO6ýóÒÿµ£›ÿ®ÿÆçÿ +þG\ebT<ÿúÿ×ÿ¹¥ýšü©Âþà%CÿXdþcWþ@"ÿÝ¿ü¨œþ›§þ¼Ûþü>ýUcüd[ÿE(þãÄÿ«žÿš¤¸þÔöü9ýQbeÿ\J.ý êýɰþžšý¡´úÎðý4ÿM`f`N4þðÿδ¢þ™Ÿÿ¯Êêþ .þI]þdbþQ9þöÕÿ·¤þšž¬ÿÃäý(þE[eÿbVÿ=ÿüÛÿ¼§þ›œ©þ¾Þÿÿ"AþVdþcYýB%ýàÂý©›ý¤ºý×úþ<Tbþd\ýG+ÿ ÿæÇÿ­ž›ÿ¢¶ÿÑóÿ6ÿOaÿe^ÿK1ÿíÿ˲ÿŸšýŸ²ýËíý1þK^ÿeaÿO6þóÒÿµ£ýšžü­Çþæ +þG\eÿaTþ;úØÿ¹¥ýšÿ©ÿÁáÿ$CþXddþVAþ!þÝ¿ü¨œü›§ÿ¼Ûýÿ>þUcýd[Fþ'ýãÄý«žýš¤ÿ·Õÿõÿ8Rbÿd]þI.ý êþɰŸý™¢þ³Ïþï4ÿM`þe`Nÿ3ðÿδþ¡šŸÿ¯Êþé þ-J]ebþQ9þöþÔ¸þ£›þ¬ýÃäÿ(FýZeýbVý=ÿüÛ½ÿ¦œœþ¨¿ÿÝÿÿ"ü@WýcdÿXCÿ$ÿàªýœ›ÿ¤ÿ¹Øüùü;Tüaeý[H+ çÇÿ­ž›ÿ¢¶ÿÑóý5Pý`fÿ]L1ÿíþ˲þŸšÿŸ²Ìíÿ1ÿK^ÿeaÿO6ÿóÿѶÿ¢›žÿ­Çÿæ +ÿG\ÿdbTÿ;þùØü¹¥ûšªþÁáý%CÿXdÿcWAÿ!þÝ¿ü¨œý›§½ÿÚýÿ=Vcþd[ýE(ýäÿìž›ÿ£¸þÔö9Rþaeþ\J.ÿ êýɰþžš¢ÿ³Ïðý4üM`üe`üM4ýðþδþ¡šþž°Êÿé ý-Jû\eüaRþ8ýõÕü·¤üšžý«Ääý(ýE[eÿbV>ÿýýÚ½þ¦œœÿ¨¿þÝÿÿÿþÿþþÿÿÿÿÿþÿþþÿÿÿþÿþþÿÿþÿýþÿÿþÿþÿþþÿÿþÿÿÿÿÿþÿÿÿÿÿÿþþÿýþÿÿÿþÿþþÿÿÿÿÿÿþÿÿÿÿÿþÿÿÿþÿýþÿþþÿÿÿþÿÿÿþÿýþÿÿþÿÿÿþÿÿþþÿüþÿýþÿÿþþÿÿþÿþÿüþÿýþÿÿÿþÿÿþþÿÿþÿÿþÿþþÿüþÿûþÿýþÿþþÿÿþÿÿþþÿÿÿÿÿÿÿþÿþþÿÿþÿÿÿÿþÿÿþÿÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿþþÿýþÿÿþþÿûþÿýþÿþþÿÿþÿÿþÿÿÿþÿýþÿþþÿÿÿþÿÿÿþÿÿþÿÿþÿÿþþÿýþÿÿþÿÿÿÿÿýþÿúþÿüþÿÿþÿþÿýþÿÿþÿþÿþþÿÿÿÿÿÿþþÿÿþÿþÿüþÿþþÿÿÿþÿÿþÿÿÿÿÿÿþÿþþÿþþÿÿÿÿþÿÿþÿÿþÿþþÿüþÿýþÿýþÿþþÿÿþÿÿþÿÿþþÿýþÿÿþÿþþÿüþÿûþÿüþÿûþÿþþÿÿÿþþÿýþÿþþÿýþÿÿþÿÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿüþÿýþÿÿþþÿÿþÿÿþþÿýþÿþþÿÿþÿÿþÿÿþÿÿþÿýþÿýþÿÿÿþÿÿþÿÿÿþÿÿÿþÿÿþÿÿÿÿþÿþþÿþþÿÿþÿÿÿÿþÿÿþÿÿÿÿÿÿþÿÿÿþÿÿÿþÿÿþÿÿÿþÿÿþÿÿþÿýþÿûþÿüþÿþþÿÿýþÿþþÿÿþþÿÿþÿÿÿþÿÿþÿÿýþÿýþÿýþÿÿþÿþÿýþÿÿÿþÿÿþÿþþÿüþÿýþÿýþÿüþÿýþÿýþÿýþÿÿþÿÿþÿÿþÿÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿÿþÿÿþþÿýþÿþþÿÿÿþÿþþÿþþÿýþÿÿþÿÿÿþþÿÿþÿÿÿþÿÿÿþÿÿÿþÿÿþÿÿþþÿüþÿýþÿþþÿþþÿþþÿÿþÿÿÿþÿÿþÿÿÿÿÿÿÿÿÿþþÿþþÿÿþþÿþþÿÿþþÿýþÿþþÿýþÿýþÿýþÿýþÿþþÿÿÿþÿÿÿþÿýþÿÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿþþÿÿþÿÿþÿþÿýþÿýþÿÿþÿþþÿÿþÿÿþÿýþÿýþÿþþÿÿÿþÿþþÿÿÿþÿþþÿþþÿÿÿÿþþÿÿÿþÿýþÿüþÿýþÿÿÿþÿýþÿþþÿÿþþÿüþÿþþÿÿÿþÿÿÿÿÿÿþÿþþÿÿÿþÿÿÿþÿÿþÿÿþÿþþÿÿÿþÿþþÿþþÿþþÿþþÿþþÿÿþþÿÿÿþÿþþÿÿýþÿþþÿÿÿþþÿûþÿþþÿÿþÿþþÿýþÿüþÿÿþÿÿÿÿþÿýþÿþþÿüþÿûþÿýþÿÿþÿþÿüþÿýþÿþþÿýþÿÿþþÿýþÿÿþÿÿÿÿÿþþÿþþÿÿþÿÿþÿþþÿüþÿüþÿÿýþÿþþÿÿþþÿÿþÿÿÿÿÿþÿÿÿÿýþÿÿþþÿûþÿýþÿýþÿÿþÿþÿýþÿÿþÿþÿÿþÿÿþþÿÿÿþÿþþÿÿÿþÿþþÿþþÿþþÿýþÿÿþÿÿÿþÿÿþÿÿþÿÿþþÿüþÿýþÿþþÿþþÿýþÿþþÿÿþÿÿþþÿÿþþÿüþÿúþÿûþÿýþÿÿþÿÿÿþÿÿÿþÿÿÿþÿÿþÿÿÿÿþÿþþÿýþÿÿþþÿþþÿÿýþÿþþÿÿÿþÿÿþÿÿÿþÿþþÿýþÿýþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿýþÿþþÿÿÿÿþÿþþÿÿÿþÿÿÿþÿÿþÿÿþþÿÿþþÿþþÿÿþþÿýþÿýþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþþÿýþÿþþÿÿÿþÿÿÿþÿÿÿþÿÿÿþÿþþÿÿÿþÿÿÿÿÿÿþÿÿþþÿþþÿÿÿÿÿÿÿþÿýþÿúþÿúþÿýþÿÿþþÿÿþÿþÿýþÿýþÿýþÿýþÿÿþÿüþÿúþÿüþÿÿþÿÿÿþÿÿþþÿüþÿüþÿþþÿÿþÿþþÿþþÿÿþÿÿÿþþÿÿþÿþÿüþÿþþÿÿÿÿþÿþþÿþþÿþþÿÿþÿÿþþÿþþÿÿþÿÿÿÿÿýþÿûþÿûþÿþþÿÿÿÿþÿþþÿÿýþÿüþÿÿþÿÿÿþÿþþÿþþÿÿýþÿüþÿýþÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿÿÿþÿüþÿüþÿþþÿþþÿÿÿÿÿþÿþþÿþþÿÿÿþÿÿþÿÿþÿÿþþÿýþÿýþÿþþÿÿýþÿýþÿÿþþþÿýþÿþþÿÿÿþÿÿþþÿþþÿÿýþÿÿÿþÿÿÿþÿÿþÿþþÿÿþÿÿÿÿþÿÿþÿÿþÿþþÿÿþÿÿÿÿþÿýþÿÿÿÿÿþÿÿÿÿÿÿþþÿþþÿÿþÿÿÿÿþþÿþþÿþþÿÿþÿþþÿÿÿþÿþþÿþþÿüþÿÿýþÿüþÿýþÿÿþÿþþÿþþÿÿþþÿÿþþÿþþÿÿþÿÿÿþÿýþÿýþÿýþÿþþÿÿþÿÿÿÿþÿþþÿüþÿýþÿÿþÿÿÿþÿþþÿÿþÿþÿþþÿÿýþÿþþÿÿÿþÿýþÿüþÿÿþÿÿþþÿþþÿÿþÿÿÿÿþþÿþþÿÿÿþÿþÿûþÿûþÿüþÿýþÿÿþþÿþþÿþþÿýþÿÿþþÿýþÿÿþÿþþÿüþÿýþÿÿþÿÿþþÿþþÿÿüþÿüþÿÿÿþÿÿþþÿþþÿÿýþÿþþÿÿþÿÿÿþÿþþÿÿÿþÿÿÿþÿýþÿýþÿþþÿÿüþÿüþÿÿþþÿýþÿÿþÿÿÿþÿÿÿÿþÿÿþÿÿÿþÿýþÿÿþþÿýþÿÿþÿÿþÿÿÿÿÿþÿÿÿÿÿþþÿÿþÿÿþþÿÿþÿÿþÿÿþÿÿÿþÿýþÿýþÿþþÿÿÿþÿÿÿþÿþþÿþþÿÿÿÿþþÿÿþÿþÿþþÿþþÿýþÿüþÿüþÿþþÿþþÿþþÿÿýþÿüþÿþþÿÿÿÿþÿÿþþÿþþÿÿþþÿÿÿþÿÿþÿÿþÿþþÿÿþÿÿþÿÿþÿÿÿþÿÿþÿÿÿÿþÿÿÿþÿþþÿÿÿÿþÿÿÿþÿýþÿÿÿþÿÿþþÿûþÿýþÿþþÿÿüþÿüþÿÿÿþÿÿÿþÿýþÿþþÿýþÿüþÿýþÿþþÿÿþÿÿþÿþþÿüþÿûþÿýþÿÿþÿÿÿÿþÿþþÿÿþÿÿþÿÿÿþÿÿþÿÿÿþÿÿþÿÿÿþÿÿþþÿÿþÿÿÿþþÿþþÿÿþÿÿÿÿÿÿþÿþþÿþþÿÿÿÿÿÿþÿþþÿÿýþÿüþÿþþÿÿÿþÿüþÿüþÿÿþþÿþþÿÿþÿÿþÿýþÿýþÿþþÿÿþþÿýþÿýþÿýþÿþþÿþþÿÿÿþÿþþÿÿþÿþþÿüþÿÿþÿÿÿÿþÿÿþÿÿþÿýþÿûþÿüþÿþþÿþþÿÿÿþÿþþÿýþÿþþÿÿýþÿþþÿÿþÿÿþÿÿþþÿþþÿÿÿþÿÿýþÿüþÿþþÿþþÿÿþÿþÿüþÿýþÿÿþÿÿÿÿÿÿþÿýþÿþþÿÿÿÿþÿýþÿþþÿýþÿÿþÿþÿýþÿþþÿýþÿûþÿüþÿüþÿýþÿýþÿþþÿþþÿüþÿÿþÿÿÿýþÿüþÿþþÿýþÿþþÿÿÿþÿÿÿÿþÿÿÿÿþþÿÿýþÿüþÿÿþþÿûþÿüþÿýþÿýþÿþþÿÿþþÿýþÿþþÿÿþÿÿÿþÿÿþÿÿþþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿÿþÿÿþÿÿÿÿþÿÿüþÿûþÿÿÿþÿÿþÿÿÿþþÿýþÿýþÿýþÿýþÿÿþÿÿþÿÿÿÿÿþÿÿþþÿÿþÿÿþþÿþþÿþþÿþþÿÿþÿÿÿþÿÿýþÿþþÿÿýþÿþþÿÿÿþÿÿÿþÿÿÿþÿÿþÿþþÿüþÿüþÿÿþÿÿÿþÿÿþÿÿþþÿÿþÿÿþþÿÿþÿÿþþÿþþÿýþÿüþÿýþÿýþÿüþÿûþÿýþÿÿþÿÿÿþÿþþÿüþÿûþÿýþÿþþÿþþÿþþÿÿþÿþÿþþÿÿþÿÿÿÿÿÿÿÿþþÿþþÿÿÿÿÿÿþÿÿþÿþþÿÿþÿþþÿþþÿÿþþÿþþÿÿþÿÿÿÿþþÿþþÿÿþÿÿÿþÿýþÿþþÿÿÿþþÿýþÿýþÿüþÿýþÿþþÿÿþÿÿþÿÿþÿÿÿþÿÿþÿÿþÿÿÿÿÿÿþÿýþÿüþÿþþÿÿÿþÿþþÿþþÿÿþþÿþþÿÿÿÿþÿýþÿüþÿÿüþÿøþÿúþÿüþÿüþÿþþÿÿÿþÿýþÿýþÿþþÿÿþÿÿþÿþþÿÿþÿÿÿÿÿþÿÿÿþÿýþÿûþÿüþÿÿþþÿþþÿÿþþÿýþÿÿþÿÿþþÿþþÿýþÿÿÿÿÿþÿþÿþþÿýþÿÿþÿÿýþÿÿþþÿüþÿÿþÿÿÿÿþÿÿÿÿþÿüþÿûþÿþþÿÿüþÿûþÿþþÿÿþþÿýþÿýþÿÿþÿÿþÿÿþÿÿþÿÿÿþÿÿþÿÿÿþÿþþÿýþÿýþÿÿþÿÿÿþÿþþÿÿþÿÿþÿÿÿÿþÿÿÿþÿÿÿþÿþþÿÿýþÿüþÿþþÿÿÿþÿþþÿþþÿÿÿþÿþþÿþþÿÿþþÿÿýþÿüþÿüþÿüþÿÿþÿþÿþþÿÿÿþÿþþÿÿÿþÿÿþÿþÿþþÿÿÿÿþÿÿþÿÿÿþÿÿÿþÿþþÿÿýþÿþþÿÿÿÿþÿÿÿþÿþþÿÿÿþÿþþÿýþÿüþÿþþÿÿþþÿÿþÿÿÿþÿÿþÿÿþÿÿÿþÿÿþÿÿÿþÿþþÿüþÿüþÿÿþÿÿÿþÿþþÿÿþÿÿþþÿþþÿÿþÿÿÿÿÿþþÿþþÿüþÿûþÿýþÿÿþÿÿþÿÿÿÿÿþÿþþÿÿÿþÿþþÿþþÿÿþÿþþÿýþÿÿþÿþþÿþþÿÿþÿÿÿþÿþþÿþþÿÿÿþÿÿþÿÿÿþÿÿþÿÿýþÿÿþþÿúþÿùþÿúþÿþþÿÿÿÿþÿþþÿýþÿýþÿýþÿÿþÿÿþÿÿþÿÿýþÿÿÿþÿÿþÿþþÿýþÿÿþÿþþÿüþÿþþÿÿþÿÿÿýþÿýþÿÿÿþÿÿþÿÿþÿÿÿþÿÿÿþÿþþÿÿÿÿÿÿÿþÿýþÿüþÿýþÿþþÿÿÿþÿÿþÿÿÿþÿþþÿÿþÿÿÿþÿÿÿÿþÿÿþÿÿþÿÿþÿÿýþÿýþÿÿþÿÿÿþÿÿþÿÿþÿÿþÿÿÿþÿÿþÿÿþÿÿþÿþþÿþþÿÿÿþÿþþÿþþÿÿþþÿÿýþÿÿþÿþÿÿÿþÿÿþþÿþþÿÿþÿÿþÿþþÿÿÿþÿÿÿþÿýþÿýþÿþþÿÿýþÿûþÿüþÿþþÿÿÿÿÿþÿÿÿÿÿþÿÿþÿýþÿþþÿÿýþÿÿþþÿýþÿþþÿþÿüþÿüþÿÿþÿÿÿÿþÿÿÿÿÿþÿÿþþÿþþÿÿþÿÿþÿÿþÿþþÿÿþÿÿþÿýþÿýþÿþþÿÿþÿÿþÿýþÿþþÿÿÿþÿÿÿþÿýþÿüþÿÿþÿþÿþþÿþþÿÿÿÿÿÿþÿþþÿÿÿÿÿÿþÿÿÿþÿýþÿþþÿÿÿþÿÿÿÿþÿÿþÿýþÿýþÿÿþþÿüþÿúþÿúþÿûþÿüþÿÿþÿþÿýþÿÿþÿþÿÿþÿÿÿþÿÿþþÿÿþÿþþÿüþÿüþÿþþÿþþÿþþÿÿþÿÿþþÿÿþÿÿÿÿÿþÿþþÿÿþÿÿþþÿÿþÿþÿüþÿýþÿÿþÿþþÿÿþÿþÿþþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿþÿþþÿÿþÿÿÿþÿþþÿþþÿüþÿûþÿüþÿÿþÿþþÿÿÿþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿÿþþÿüþÿþþÿÿþÿÿÿþÿþþÿÿþÿÿÿþÿÿþÿÿþÿÿÿÿþÿÿþÿþþÿÿþÿþþÿÿÿþÿýþÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿÿþÿÿþþÿýþÿþþÿÿþÿÿÿÿÿþÿþÿüþÿûþÿýþÿüþÿýþÿýþÿýþÿÿþÿÿþÿýþÿÿÿþÿþþÿÿþÿþþÿþþÿÿÿþÿþþÿÿþÿÿÿþÿýþÿþþÿÿÿþÿÿþÿÿþÿÿÿÿþÿÿÿÿÿþÿÿþþÿþþÿÿÿþÿÿþÿÿþÿÿþÿþþÿýþÿýþÿýþÿþþÿÿþÿÿÿþÿýþÿþþÿÿþÿÿÿþÿÿþÿÿýþÿýþÿÿÿþÿÿþÿÿÿþÿÿÿþÿÿþÿÿþÿüþÿûþÿþþÿÿÿþÿÿþþÿüþÿüþÿÿþÿÿÿÿþþÿüþÿÿþÿþÿüþÿüþÿÿþÿÿÿÿÿÿþþÿÿþÿÿþÿÿþÿÿþþÿþþÿÿýþÿþþÿÿþÿÿÿÿþþÿþþÿÿÿÿÿÿþÿÿÿÿþÿýþÿýþÿýþÿÿþÿþÿüþÿÿþÿþÿþþÿÿÿÿÿþÿÿÿþÿþþÿþþÿþþÿýþÿÿÿþÿÿþþÿþþÿÿÿÿÿþÿþþÿüþÿýþÿÿþþÿþþÿÿþÿÿþþÿÿþÿÿþÿýþÿýþÿþþÿÿþþÿûþÿüþÿÿþÿÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþþÿþþÿÿþþÿýþÿÿþÿÿÿþþÿÿþÿÿÿþþÿýþÿÿþÿÿÿþÿÿÿþÿÿÿÿÿÿþÿÿþþÿÿþÿÿþÿÿÿþÿÿþÿÿþÿÿþÿÿþÿüþÿûþÿþþÿÿÿþÿÿþÿÿþþÿüþÿüþÿÿþþÿÿþÿÿÿÿþÿÿþþÿÿþÿÿÿÿþþÿþþÿþþÿþþÿýþÿþþÿÿÿþÿÿþÿÿþþÿûþÿüþÿÿÿÿþÿýþÿÿþÿÿÿÿþÿÿÿþÿþþÿÿþÿÿþÿþþÿýþÿþþÿÿÿþÿÿÿþÿÿÿþÿýþÿÿþÿþÿýþÿüþÿüþÿüþÿÿþÿÿÿÿþÿþþÿþþÿÿþþÿÿþÿþÿýþÿýþÿÿþÿÿÿþÿþþÿýþÿÿþÿÿÿþþÿÿþÿþÿþþÿÿþÿþÿþþÿýþÿþþÿþþÿüþÿÿþÿÿÿÿþÿþþÿþþÿÿÿþÿÿþÿÿÿþÿþþÿþþÿÿÿþÿÿÿþÿþþÿþþÿþþÿÿÿÿÿþÿýþÿþþÿÿÿþÿÿþÿýþÿýþÿþþÿÿýþÿþþÿÿþÿÿÿÿþÿÿþÿþþÿÿþþÿüþÿþþÿÿþÿýþÿýþÿþþÿÿþþÿüþÿÿþÿÿþÿýþÿþþÿÿÿÿÿþÿþþÿþþÿÿÿÿÿþÿþþÿÿþÿþÿüþÿüþÿýþÿÿÿþÿÿþÿÿÿÿþÿýþÿÿþÿþÿÿþÿÿÿÿÿÿþþÿþþÿþþÿþþÿÿþÿþÿþþÿÿýþÿýþÿÿÿþÿÿþÿÿÿÿÿþþÿÿþþÿþþÿýþÿþþÿÿþþÿÿÿÿÿþþÿÿþþÿþþÿÿÿÿÿÿÿÿþÿÿþÿÿÿÿÿþþÿÿþþÿÿþÿÿÿÿÿÿÿÿþÿþþÿýþÿüþÿþþÿÿþþÿÿþÿÿýþÿýþÿÿÿþÿÿþÿÿÿþÿÿþÿþþÿþþÿÿüþÿüþÿýþÿÿþÿÿþÿþþÿüþÿûþÿÿþÿÿÿþþÿÿþÿÿÿÿþÿÿþþÿÿþÿÿÿÿÿÿþþÿÿþþÿýþÿÿÿþÿÿþþÿÿþÿÿþÿÿþÿÿþþÿÿþÿþþÿþþÿÿþÿÿÿÿÿþþÿÿþÿþÿþþÿýþÿÿÿÿÿÿÿÿþÿþþÿÿýþÿþþÿþþÿÿþÿþþÿýþÿüþÿüþÿþþÿþþÿþþÿÿþþÿÿÿþÿÿÿþÿÿÿþÿÿÿþÿþþÿÿÿÿÿÿÿÿÿþÿÿþÿþÿÿþÿÿýþÿÿþÿÿþÿþþÿýþÿüþÿýþÿýþÿüþÿþþÿþÿýþÿýþÿþþÿýþÿüþÿüþÿþþÿÿÿþþÿýþÿþþÿÿþÿÿÿþÿÿþÿÿÿþÿÿþÿÿþÿÿþÿÿÿþÿýþÿþþÿþþÿÿÿþÿüþÿþþÿÿÿÿþÿýþÿüþÿÿþÿþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿüþÿýþÿÿþÿÿþÿÿþÿÿþÿýþÿýþÿÿþÿþÿýþÿþþÿÿÿÿÿþÿÿÿþÿýþÿÿþÿþþÿýþÿÿþþÿþþÿÿÿþÿÿÿþÿÿþÿÿþÿþþÿÿþÿÿþÿýþÿýþÿýþÿýþÿÿÿþÿÿüþÿþþÿÿýþÿýþÿýþÿþþÿÿþÿÿþÿÿþÿÿÿþÿÿþþÿÿþÿÿÿþÿÿþþÿýþÿýþÿÿþÿÿþÿÿþþÿýþÿÿþÿÿÿþþÿýþÿþþÿþþÿÿþÿÿÿÿÿÿÿþÿÿÿþÿÿüþÿþþÿÿýþÿÿþÿÿÿþÿüþÿüþÿþþÿÿþÿÿÿþÿÿþÿýþÿûþÿýþÿþþÿÿÿþÿüþÿþþÿÿþþÿÿþÿÿÿþÿýþÿþþÿÿþÿÿþÿþþÿýþÿýþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿÿþÿÿþÿÿÿþÿÿþÿÿÿþÿÿþÿÿÿþÿÿÿþÿýþÿþþÿþþÿÿÿÿÿÿÿÿþþÿüþÿüþÿÿþÿÿýþÿýþÿÿÿþÿÿþÿÿþÿýþÿÿÿþÿþþÿýþÿýþÿÿÿþÿþþÿÿþÿÿþÿÿÿÿþÿÿþÿÿþÿÿþÿÿÿþÿÿþÿÿÿþÿÿþÿÿÿþÿÿþÿÿþÿÿþÿÿþÿþþÿþþÿÿýþÿÿþÿÿÿÿþÿÿþÿþþÿýþÿÿýþÿüþÿÿÿþÿÿýþÿþþÿÿÿÿþÿÿþþÿþþÿÿÿþÿÿÿÿÿþþÿþþÿþþÿÿÿÿþþÿÿÿÿÿÿþþÿûþÿûþÿýþÿÿþþÿÿÿÿÿÿþÿýþÿþþÿÿÿþÿÿÿþÿÿÿÿþþÿÿÿÿþþÿþþÿÿþþÿÿþÿÿÿþþÿýþÿÿþÿÿÿÿþÿÿþÿÿÿþÿÿþÿÿþÿÿþÿÿþÿþþÿþþÿÿþÿÿÿþÿÿþÿÿÿþÿÿÿþÿÿýþÿÿþÿÿþþÿÿüþÿüþÿÿþþÿýþÿÿþÿÿÿÿþþÿþþÿÿþþÿþþÿþþÿÿþÿÿþþÿÿÿþÿÿÿÿþÿþþÿÿþÿÿÿÿþÿÿÿÿÿþþÿþþÿÿþÿÿþþÿÿþÿÿþÿÿÿÿÿþÿÿÿþþÿüþÿýþÿýþÿÿþÿÿþÿÿþÿÿþÿþþÿÿþÿÿþþÿýþÿúþÿûþÿÿþþÿÿþÿþÿÿþÿÿÿþÿüþÿüþÿýþÿþþÿýþÿýþÿÿÿþÿÿþÿÿþÿÿþÿÿÿþÿÿþÿÿÿÿþÿÿþÿÿÿþÿÿþÿÿþÿþþÿÿÿÿþÿþþÿÿþÿÿÿÿþþÿýþÿÿþÿþþÿýþÿýþÿÿÿþÿýþÿþþÿÿþÿÿÿþÿþþÿþþÿþþÿþþÿþþÿÿýþÿýþÿÿÿÿÿÿþþÿýþÿÿþþÿüþÿüþÿüþÿüþÿüþÿÿþÿÿþþÿþþÿÿþÿþÿýþÿÿþÿÿÿÿþÿÿÿþÿÿþÿþþÿþþÿÿÿÿþÿýþÿÿþÿÿþÿýþÿþþÿÿÿÿÿÿÿÿÿþþÿþþÿýþÿþþÿÿÿÿþþÿýþÿüþÿüþÿÿþÿþÿþþÿÿþÿýþÿüþÿþþÿÿÿþÿþþÿýþÿýþÿýþÿÿÿþÿþþÿþþÿþþÿÿÿÿþÿþþÿÿÿþÿþþÿÿþÿþþÿÿþÿÿþÿÿþÿÿþÿþþÿÿÿþÿþþÿýþÿýþÿÿþÿÿþÿÿÿþÿÿþÿÿÿÿþÿÿþÿÿÿýþÿûþÿýþÿþþÿÿþþÿÿþþÿûþÿýþÿÿþÿÿþÿÿÿÿþÿÿþÿÿÿþÿýþÿÿþþÿûþÿþþÿÿÿþÿÿÿþÿÿÿÿþÿþþÿýþÿýþÿÿþÿÿþþÿýþÿüþÿúþÿúþÿÿÿþÿÿþÿÿÿþÿÿþÿÿþÿÿþþÿýþÿÿþÿÿþþÿýþÿÿþÿÿÿþþÿþþÿÿÿþÿÿÿþÿýþÿþþÿÿýþÿüþÿÿþÿþÿüþÿÿþÿþÿÿþÿþÿüþÿþþÿÿÿÿþÿÿþÿÿþÿÿþÿÿþÿÿÿþÿýþÿüþÿþþÿþþÿÿÿÿÿÿþÿþþÿþþÿÿÿÿÿÿþÿÿþÿÿÿÿþÿüþÿüþÿÿþÿþÿÿþÿÿþþÿÿþþÿüþÿüþÿýþÿýþÿüþÿÿþÿþÿþþÿÿÿÿÿÿÿÿÿþþÿÿÿÿþþÿýþÿüþÿýþÿÿþþÿÿþÿÿÿþÿÿÿÿþþÿüþÿýþÿÿÿÿÿþþÿÿþÿþþÿÿÿþÿüþÿþþÿÿÿþÿÿÿÿþÿüþÿþþÿÿþþÿÿþÿþþÿþþÿÿþþÿýþÿÿÿþÿÿþÿÿÿþÿÿÿÿþþÿþþÿÿþþÿÿþÿþÿýþÿÿþÿÿþþÿüþÿýþÿÿÿÿÿÿÿÿýþÿüþÿûþÿÿþÿþÿüþÿÿþÿþÿÿÿþÿþþÿÿÿÿÿÿþÿþþÿþþÿÿÿþÿþþÿþþÿþþÿÿþþÿÿýþÿüþÿÿÿÿþÿÿþÿÿÿþÿÿÿþÿÿþÿÿþÿÿþÿÿþÿÿÿÿþÿÿþÿÿþÿÿþÿÿÿþÿþþÿÿþÿÿÿÿÿþÿþþÿÿþÿÿÿÿÿÿþþÿýþÿþþÿþþÿÿÿþÿÿÿþÿþþÿÿþÿÿþÿýþÿþþÿÿÿþÿÿþÿýþÿýþÿÿþÿÿÿÿÿÿþÿþþÿþþÿþþÿþþÿüþÿýþÿÿÿþþÿüþÿýþÿÿþÿÿþþÿüþÿýþÿþþÿþþÿÿþÿþÿýþÿýþÿÿÿþÿÿþþÿÿýþÿüþÿýþÿÿÿþÿÿþÿþÿþþÿÿÿþÿýþÿÿÿÿÿþÿþÿüþÿûþÿüþÿýþÿÿýþÿýþÿþþÿÿþÿÿÿÿþÿüþÿüþÿþþÿÿþÿÿÿÿþþÿüþÿûþÿýþÿÿþÿÿþþÿýþÿÿþÿÿÿþÿÿþþÿÿþÿþÿúþÿþþÿþÿüþÿÿþÿÿÿÿþÿüþÿüþÿýþÿþþÿýþÿýþÿþþÿÿÿþÿþþÿÿÿþÿýþÿþþÿÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿþÿþþÿýþÿþþÿÿÿþÿÿýþÿýþÿÿÿþÿÿþÿÿÿþþÿûþÿúþÿýþÿþþÿÿþÿÿþÿþþÿÿþþÿþþÿÿþÿýþÿþþÿÿÿþÿÿþÿþþÿÿÿÿþÿüþÿüþÿþþÿÿýþÿþþÿÿÿþÿÿÿþÿþþÿýþÿýþÿÿþÿÿþþÿÿþÿÿÿþÿÿþþÿýþÿþþÿüþÿúþÿûþÿýþÿþþÿÿþÿÿýþÿýþÿÿþÿþÿüþÿýþÿÿþþÿÿþþÿþþÿÿþÿÿÿÿÿÿþÿÿÿÿÿþÿÿþþÿýþÿÿþÿÿÿÿþÿþþÿÿþÿÿþÿþþÿýþÿÿþÿÿÿþÿÿÿþÿÿþÿÿþÿÿþÿÿÿþþÿüþÿþþÿþÿþþÿüþÿûþÿýþÿþþÿÿÿÿÿÿþÿüþÿüþÿýþÿÿþÿÿþþÿüþÿýþÿÿýþÿýþÿþþÿÿÿÿþÿÿÿÿÿþÿÿÿÿÿþþÿþþÿÿþÿÿþþÿýþÿýþÿÿþþÿûþÿþþÿÿÿþÿÿÿÿÿþÿÿÿÿÿÿþÿÿÿþÿÿþÿþþÿÿþÿÿÿÿÿÿþþÿÿþþÿüþÿýþÿþþÿÿýþÿüþÿýþÿþþÿÿÿÿþÿÿÿþÿþþÿþþÿþþÿýþÿÿþÿÿþþÿÿþþÿüþÿýþÿþþÿÿÿþþÿÿþÿÿÿÿþÿýþÿþþÿÿÿþÿþþÿÿÿþÿþþÿýþÿüþÿýþÿÿÿÿþþÿþþÿüþÿúþÿûþÿÿþÿþþÿþþÿÿþþÿþþÿþþÿÿþÿþÿþþÿÿþÿþÿþþÿÿþÿÿÿÿÿþÿÿÿÿþþÿþþÿÿýþÿþþÿÿÿþÿÿþÿýþÿþþÿÿÿÿþÿýþÿýþÿþþÿþþÿþþÿüþÿúþÿýþÿÿþÿÿÿÿÿþþÿþþÿÿþÿÿÿÿÿÿþÿþÿýþÿÿþÿþÿýþÿüþÿÿþÿÿÿÿÿÿÿþÿÿÿÿÿÿþÿþþÿÿÿÿÿÿþÿÿÿýþÿýþÿÿþÿþÿÿþÿýþÿüþÿÿþþþÿúþÿüþÿþþÿýþÿÿÿÿþÿüþÿúþÿúþÿýþÿÿÿÿÿÿÿþÿÿÿþÿÿÿÿþÿÿþÿþþÿÿþÿþþÿÿþÿÿÿþÿýþÿÿÿþÿÿþÿÿþÿÿþÿÿýþÿþþÿÿþÿÿÿÿÿþÿÿÿÿÿÿþÿþþÿþþÿÿÿþÿþþÿþþÿÿÿÿÿýþÿûþÿÿþÿÿÿýþÿýþÿÿÿþÿÿþÿþÿþþÿÿýþÿýþÿÿþÿÿÿÿþÿÿþÿÿÿþÿÿþÿÿÿÿþÿÿþÿÿÿþÿÿÿþÿÿþÿÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿÿþÿÿþÿÿþÿýþÿÿþÿÿÿþþÿýþÿÿþþÿûþÿûþÿýþÿýþÿÿþÿþÿüþÿüþÿþþÿÿÿþÿÿþÿÿÿþÿÿþÿýþÿýþÿþþÿýþÿþþÿÿýþÿüþÿüþÿþþÿÿÿþÿþþÿÿÿÿÿÿÿþÿûþÿýþÿÿûþÿüþÿþþÿþþÿþþÿÿÿÿÿÿÿÿÿþÿþþÿþþÿÿþþÿþþÿþþÿüþÿþþÿÿÿþÿÿþÿýþÿÿþÿÿÿÿþÿÿþÿþþÿýþÿüþÿüþÿþþÿÿÿÿþÿÿþÿÿþÿÿþÿÿþÿÿÿÿþÿÿþÿÿÿþÿýþÿýþÿþþÿþþÿÿþÿÿÿÿþÿÿÿþÿýþÿþþÿÿÿÿÿþÿýþÿüþÿÿþÿþÿþþÿÿþÿÿÿþÿÿþÿÿþÿÿÿþÿýþÿýþÿþþÿÿÿþÿþþÿÿÿÿÿÿÿþÿûþÿüþÿÿþÿþÿÿÿÿþÿþþÿÿþþÿÿþþÿýþÿþþÿÿþþÿüþÿþþÿþþÿÿÿþÿÿÿþÿþþÿÿûþÿúþÿýþÿÿþÿýþÿüþÿþþÿÿÿþÿþþÿÿÿþÿÿÿþÿÿþÿÿþÿþþÿþþÿÿþþÿÿþÿÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿÿÿþÿÿþÿÿÿÿÿÿþÿÿÿÿþÿÿÿþÿÿÿÿÿýþÿüþÿüþÿÿþÿÿÿÿþÿþþÿýþÿýþÿþþÿÿÿÿþÿÿþÿÿÿþÿÿþÿþþÿÿÿþÿÿþÿþþÿÿþÿÿþþÿÿÿþÿþþÿÿÿÿÿÿþÿÿÿÿþÿýþÿþþÿÿÿÿþÿýþÿüþÿþþÿÿÿþÿýþÿûþÿüþÿþþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþþÿûþÿüþÿþþÿÿþÿÿÿÿÿþÿþþÿþþÿÿÿÿÿÿþÿÿþÿÿþÿþÿÿþÿþþÿýþÿþþÿÿÿþÿÿþÿÿþÿÿþÿÿþþÿÿþÿþÿýþÿÿÿÿÿþþÿþþÿþþÿÿþÿÿÿþþÿþþÿÿþÿÿÿÿÿÿþÿÿþÿþÿýþÿÿþÿþÿýþÿüþÿþþÿÿÿþÿÿþÿÿÿþÿÿþþÿýþÿÿþÿÿþÿÿþÿÿÿþÿÿþÿþþÿÿþÿÿÿþÿþÿþþÿýþÿþþÿÿþÿÿþþÿýþÿÿþÿÿÿþÿÿþÿÿÿÿþÿþþÿÿÿÿþÿÿþþÿýþÿÿþÿÿþÿÿþÿÿþþÿýþÿýþÿÿþÿÿÿþÿÿÿÿþþÿüþÿúþÿüþÿÿýþÿýþÿýþÿþþÿÿþÿÿÿþÿÿþþÿýþÿýþÿÿþÿÿÿþþÿÿþÿÿþÿüþÿýþÿÿþÿÿþÿÿýþÿþþÿÿÿþÿýþÿþþÿÿýþÿýþÿÿþÿÿþÿþþÿýþÿÿþþÿþþÿÿÿþÿÿÿþÿÿþÿþþÿÿÿþÿþþÿÿþÿÿÿþÿýþÿþþÿÿþþÿÿþþÿþþÿÿþÿÿÿÿþÿþþÿÿÿþÿýþÿýþÿÿÿþÿüþÿýþÿÿþþÿüþÿûþÿüþÿÿþÿÿþÿýþÿýþÿýþÿþþÿÿÿþÿÿÿþÿýþÿþþÿÿÿþÿÿÿÿÿÿÿÿþþÿÿþÿþþÿÿþÿÿýþÿÿÿþÿÿÿþÿýþÿÿÿþÿÿþÿÿÿþÿÿþÿýþÿþþÿÿýþÿþþÿÿÿÿÿþÿþþÿÿþÿþþÿÿþÿÿþþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþþÿýþÿþþÿÿÿþÿÿÿþÿÿþÿÿÿþÿÿþÿÿþþÿýþÿÿþÿÿÿþÿþÿþþÿÿþÿþÿÿþþÿþþÿÿþÿþþÿÿþÿÿÿþÿÿþþÿýþÿÿþÿÿþÿþþÿÿþÿÿþÿþþÿþþÿÿþÿÿþÿýþÿþþÿÿþÿÿþÿÿþÿÿÿÿþÿÿýþÿûþÿûþÿýþÿÿþÿþþÿþþÿÿþÿÿÿÿþþÿÿþÿÿÿþÿÿþþÿÿþÿÿþÿÿþÿÿÿþÿýþÿÿþÿþÿýþÿÿÿþÿýþÿýþÿþþÿÿþÿÿþÿÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿýþÿýþÿþþÿÿüþÿüþÿÿþÿÿþÿÿþÿÿþÿÿýþÿýþÿÿÿþÿÿþÿÿÿþÿÿþÿÿÿÿþÿýþÿþþÿÿÿþÿÿþÿÿÿþÿýþÿÿþÿþÿþþÿÿþþÿÿþÿþÿýþÿÿþÿÿÿþÿÿÿþþÿüþÿýþÿÿþÿþþÿÿþÿÿüþÿýþÿÿþþÿÿþÿÿÿÿÿÿÿþþÿþþÿÿþÿþþÿýþÿÿþÿÿÿþÿÿÿÿÿÿÿÿÿÿÿýþÿüþÿýþÿÿÿÿþþÿÿÿÿÿÿÿþÿýþÿþþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþþÿýþÿþþÿÿþÿÿþÿÿÿÿþÿÿýþÿýþÿÿþÿþþÿýþÿÿþÿÿýþÿýþÿÿÿþÿÿþÿÿüþÿûþÿÿþÿÿÿÿÿÿÿÿþÿþþÿÿÿþÿýþÿýþÿþþÿÿÿþÿÿüþÿýþÿÿþþÿÿþÿÿþÿþþÿûþÿûþÿþþÿÿþÿÿþÿÿþÿÿÿýþÿÿþÿÿÿþÿþþÿýþÿýþÿüþÿþþÿÿþÿþþÿþþÿÿþÿüþÿüþÿÿþþÿÿÿþÿÿÿþÿÿÿþÿÿÿÿþÿýþÿüþÿþþÿÿÿþÿÿÿÿÿÿÿþÿÿþÿÿÿÿÿþþÿÿþÿÿÿÿÿÿÿþÿþþÿÿÿÿÿÿÿþþÿüþÿýþÿÿþÿÿþþÿÿþÿÿþþÿÿþþÿÿþÿþÿÿþÿÿþþÿÿþÿÿþþÿÿþÿþþÿþþÿþþÿþþÿÿþÿþÿþþÿÿþÿÿÿýþÿúþÿûþÿþþÿÿÿÿÿþÿÿÿÿÿÿþÿþþÿÿÿþÿþþÿýþÿþþÿÿþÿÿÿÿÿþþÿüþÿÿþÿÿýþÿþþÿþþÿÿÿÿÿÿÿÿþÿÿÿþÿýþÿüþÿþþÿþþÿþþÿÿÿÿþÿþþÿÿÿÿÿÿÿÿÿþþÿþþÿþþÿþþÿþþÿýþÿüþÿüþÿýþÿüþÿþþÿÿþÿþþÿþþÿÿÿÿþÿþþÿþþÿÿþþÿýþÿýþÿüþÿýþÿýþÿüþÿþþÿÿþþÿÿÿÿÿþÿþÿÿþÿÿþþÿÿþÿÿÿþþÿüþÿýþÿÿÿþþÿþþÿÿÿþþÿþþÿÿÿþþÿþþÿÿÿÿÿþÿýþÿþþÿÿýþÿþþÿÿþÿþþÿüþÿýþÿÿþÿÿÿþÿþþÿþþÿÿþÿÿþþÿÿÿþÿþþÿÿÿÿþÿÿÿþÿÿþÿÿþþÿÿüþÿüþÿýþÿÿþÿÿþþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿþþÿÿþþÿýþÿþþÿþþÿþþÿÿÿþÿÿÿÿÿÿþÿÿÿÿÿþþÿÿþÿÿþþÿÿþþÿüþÿýþÿÿþÿÿÿþþÿÿþÿþÿüþÿýþÿÿÿÿÿþþÿüþÿýþÿÿÿþÿÿüþÿûþÿþþÿÿÿþÿÿþþÿþþÿÿÿþÿÿÿþÿÿýþÿþþÿÿýþÿýþÿÿÿþÿÿþÿÿÿþÿÿþÿÿþÿÿþÿÿýþÿýþÿÿÿþÿÿþÿÿÿþÿýþÿÿþÿþÿýþÿþþÿÿÿþÿÿþÿÿÿÿþÿþþÿÿÿþÿþþÿþþÿÿÿþÿþþÿþþÿÿÿÿÿÿÿÿþÿÿÿÿÿþþÿüþÿüþÿþþÿÿþþÿÿþÿÿÿþþÿþþÿÿþÿÿÿÿÿÿþÿþþÿÿþþþÿüþÿýþÿýþÿýþÿÿþÿÿÿÿÿÿÿÿþÿÿÿþÿýþÿÿÿÿÿÿþÿþþÿÿþÿþÿüþÿüþÿýþÿþþÿÿÿþþÿþþÿÿþþÿÿþÿþÿþþÿÿýþÿüþÿþþÿÿÿþÿþþÿÿÿþÿÿÿþÿþþÿýþÿüþÿüþÿþþÿüþÿüþÿüþÿüþÿýþÿÿþÿÿÿÿþÿÿþÿÿþþÿýþÿþþÿþþÿýþÿÿþÿÿÿÿþÿÿþÿÿÿþÿÿþþÿýþÿþþÿþþÿþþÿýþÿüþÿþþÿÿþþÿÿþþÿüþÿÿÿþÿþþÿÿþþÿÿÿþÿþþÿÿþÿÿÿþÿÿÿþÿÿþÿÿÿþÿýþÿýþÿþþÿýþÿþþÿÿÿþÿþþÿÿþÿÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿÿþÿÿþÿÿÿþÿÿÿþÿþþÿÿÿÿþÿÿÿþÿÿþþÿþþÿÿÿþÿÿÿÿþÿýþÿüþÿþþÿþþÿþþÿþþÿýþÿÿþÿÿÿþþÿûþÿûþÿþþÿÿþÿÿþÿÿþþÿþþÿÿþþÿýþÿýþÿÿþÿÿÿþÿÿÿþÿþþÿÿÿþÿþþÿÿÿþÿýþÿþþÿþþÿÿþÿþþÿýþÿýþÿýþÿýþÿþþÿÿýþÿþþÿÿÿÿþÿÿþÿÿÿþÿÿÿþÿÿþÿÿþÿýþÿþþÿÿÿþÿÿüþÿýþÿÿþÿÿþþÿüþÿýþÿÿþÿÿþÿþþÿÿþÿþÿþþÿÿÿþÿÿÿþþÿüþÿýþÿþþÿÿÿÿÿÿþÿþþÿÿýþÿüþÿÿþÿÿþþÿÿþÿÿÿþÿÿþÿÿþÿÿÿþÿÿÿþÿÿþÿÿÿþÿÿÿÿÿÿþÿþþÿÿÿþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿýþÿþþÿÿþÿÿÿþÿýþÿþþÿþþÿýþÿüþÿýþÿÿþÿþÿýþÿÿþÿÿÿþþÿÿýþÿýþÿÿÿþÿÿÿÿÿþÿÿÿÿÿþÿþþÿþþÿþþÿÿþÿÿþþÿüþÿýþÿÿþÿÿþÿÿþÿÿÿÿÿþþÿþþÿüþÿüþÿüþÿüþÿýþÿþþÿÿþÿÿþÿþþÿÿþÿÿÿþÿþÿýþÿÿþÿÿÿþÿÿþÿÿüþÿûþÿþþÿÿÿþÿÿÿÿþþÿýþÿÿþÿþÿþþÿÿÿþÿþþÿÿÿþÿþþÿÿÿþÿÿÿþÿÿþÿÿÿþÿýþÿûþÿýþÿÿÿþÿÿÿþÿþþÿÿÿþÿÿþÿþÿûþÿýþÿþþÿýþÿüþÿÿþÿÿÿÿÿÿÿÿÿÿÿþÿþþÿÿÿÿÿþþÿÿüþÿûþÿþþÿÿþþÿÿþÿþÿüþÿþþÿÿþþÿÿþÿÿýþÿýþÿÿþÿÿþÿÿþÿÿÿþÿÿþÿÿþÿÿÿþÿÿþþÿÿþÿÿÿÿýþÿúþÿýþÿþþÿÿÿÿÿÿþÿÿÿþÿÿþÿÿþÿÿþÿÿþþÿþþÿÿþþÿüþÿüþÿÿþÿÿÿÿÿþþÿþþÿÿþÿÿÿÿÿþÿÿÿþÿÿþÿÿýþÿýþÿþþÿýþÿþþÿÿÿÿþÿýþÿþþÿÿþÿÿÿþÿÿþÿÿÿþÿÿþÿýþÿýþÿÿþÿÿÿÿþÿÿþþÿýþÿþþÿÿþÿÿþÿýþÿþþÿÿÿþÿÿÿþÿýþÿÿþÿÿþÿþþÿýþÿýþÿýþÿþþÿÿþÿýþÿþþÿÿÿþÿÿþÿÿþÿÿþÿÿþþÿûþÿýþÿÿþÿþþÿþþÿÿþÿþþÿÿþÿÿþþÿýþÿÿþÿÿÿþÿÿÿþÿÿÿþÿÿÿþÿÿþþÿÿþÿÿÿÿþþÿþþÿÿþÿþþÿýþÿþþÿÿÿÿÿÿÿÿÿÿþþÿþþÿÿþÿÿþþÿüþÿÿþÿÿÿþÿþÿÿþÿÿþþÿÿþÿÿþþÿýþÿÿþÿÿÿÿþÿÿÿÿÿÿþÿÿþþÿÿþÿÿþþÿüþÿúþÿüþÿÿþþÿýþÿþþÿÿþÿÿÿÿþþÿýþÿþþÿÿÿþÿýþÿûþÿüþÿþþÿÿÿþÿÿÿþÿýþÿÿþÿÿÿþÿÿÿþÿýþÿÿþÿÿÿþÿÿÿÿÿÿÿÿþþÿüþÿûþÿþþÿÿüþÿûþÿýþÿÿþÿÿþþÿþþÿüþÿýþÿÿþþÿþþÿÿþÿÿþÿÿÿÿÿÿþÿÿýþÿýþÿÿþÿÿÿÿÿÿÿýþÿûþÿýþÿþþÿýþÿýþÿþþÿþþÿÿÿÿþÿýþÿþþÿÿþÿþþÿÿÿþÿþþÿþþÿÿÿÿþÿüþÿþþÿÿÿþþÿÿþþÿÿþÿþÿÿþÿÿÿÿÿÿþþÿÿþÿÿþþÿýþÿÿþÿÿÿþÿÿÿþþÿÿþÿÿÿÿÿÿÿþÿÿÿÿþþÿüþÿýþÿÿþÿÿþþÿÿþÿþþÿüþÿûþÿýþÿýþÿþþÿÿþÿÿþÿþþÿÿÿþÿýþÿüþÿýþÿÿÿþÿþþÿÿþÿÿÿþÿþþÿýþÿþþÿÿþÿþÿýþÿüþÿþþÿÿþÿýþÿþþÿÿÿÿþÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿþþÿüþÿþþÿÿÿÿþÿýþÿþþÿÿþÿüþÿüþÿÿÿþÿÿýþÿûþÿþþÿÿýþÿÿþÿÿþÿÿþÿÿÿþÿÿþþÿûþÿýþÿÿÿþÿÿÿþÿýþÿÿþÿÿÿþÿÿþþÿþþÿþþÿýþÿþþÿÿþÿÿþÿÿÿþÿþþÿÿþþÿþþÿÿþÿÿÿÿÿýþÿýþÿþþÿÿÿþÿþþÿÿÿþÿÿÿþÿÿþÿÿÿÿþÿÿþþÿýþÿÿþþÿÿþÿÿÿþÿþÿüþÿýþÿÿþþÿÿþÿþÿþþÿüþÿüþÿÿþÿþÿÿþÿÿÿÿÿÿþÿÿþÿÿÿþÿÿþÿÿÿþÿþþÿüþÿýþÿþþÿûþÿûþÿÿþÿþÿÿþÿÿþþÿÿþÿþþÿüþÿüþÿÿþþÿþþÿÿÿÿÿþÿþþÿþþÿÿþÿÿÿþÿÿþÿÿþÿþþÿÿþÿÿÿÿþþÿýþÿþþÿÿÿþÿÿÿþÿÿþÿÿþÿþþÿÿþÿÿÿÿþÿÿþÿÿÿþÿÿþÿÿÿþÿÿþÿÿÿþÿÿÿþÿÿÿÿÿÿþÿÿþÿÿÿÿþÿþþÿÿÿþÿÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿýþÿûþÿþþÿÿþÿüþÿûþÿÿþþÿýþÿþþÿÿþÿÿþþÿþþÿÿþþÿþþÿÿÿÿÿþÿýþÿýþÿÿÿÿÿÿþÿÿÿÿÿþþÿþþÿÿÿÿÿÿþÿþþÿþþÿÿþþÿþþÿÿÿþÿþþÿÿþÿÿÿþÿÿÿþÿÿþþÿýþÿþþÿÿÿþÿÿþÿýþÿûþÿüþÿþþÿÿÿÿÿÿÿÿþÿÿÿþÿüþÿýþÿÿþÿÿÿÿþþÿþþÿÿþþÿþþÿÿþþÿþþÿÿþÿþÿýþÿüþÿþþÿÿýþÿþþÿÿÿþÿýþÿþþÿÿÿÿþÿÿÿþÿþþÿÿýþÿüþÿÿþÿýþÿýþÿýþÿýþÿþþÿÿÿþÿÿþÿþþÿýþÿýþÿÿþÿÿþÿþþÿþþÿÿþÿÿÿþÿþþÿþþÿþþÿÿþÿÿþþÿÿþÿÿþÿÿÿÿþÿÿþþÿýþÿÿþÿÿÿþÿÿÿÿþþÿþþÿþþÿþþÿþþÿÿÿÿÿÿþÿþþÿþþÿþþÿÿþÿÿÿÿÿÿþþÿþþÿÿÿþþÿýþÿÿþÿÿÿÿþÿþþÿþþÿþþÿÿÿÿþÿýþÿþþÿþþÿýþÿþþÿþþÿÿÿÿÿþÿþþÿþþÿÿÿÿþÿÿÿÿÿÿþÿýþÿÿþþÿýþÿþþÿýþÿÿþÿÿþþÿýþÿýþÿÿþÿÿþÿþþÿüþÿýþÿÿþÿÿþþÿýþÿÿþÿÿÿþþÿýþÿþþÿýþÿýþÿÿÿþÿþþÿýþÿþþÿÿÿþÿÿÿþÿÿþþÿÿÿþÿýþÿÿÿÿÿÿþÿÿÿÿþÿþþÿÿÿþÿþþÿÿÿþÿýþÿþþÿÿþÿÿÿÿÿÿþÿýþÿÿþþÿÿþÿþÿÿþÿÿþþÿÿþÿÿþÿþþÿÿþÿþþÿüþÿÿþÿþÿÿþÿþÿþþÿþþÿüþÿýþÿÿþþÿþþÿÿÿþÿýþÿþþÿÿþÿÿþÿýþÿýþÿýþÿýþÿÿþÿÿþþÿÿþÿÿþþÿýþÿþþÿþþÿÿþþÿÿÿþÿÿþþÿüþÿþþÿÿÿÿÿþÿþþÿÿþþÿÿÿÿÿþÿþÿþþÿýþÿýþÿÿþÿÿÿþÿÿÿþÿÿþÿÿÿþÿÿÿþÿÿþÿÿÿþÿÿþÿÿþÿÿþÿþþÿþþÿýþÿÿþÿÿÿþþÿýþÿþþÿüþÿüþÿýþÿþþÿÿÿÿÿÿÿÿÿþþÿÿþÿÿþþÿÿþÿÿÿÿþÿýþÿÿÿþÿþþÿþþÿÿÿþÿþþÿÿþÿÿþÿÿþÿÿÿþþÿÿþÿÿþþÿÿþÿÿþþÿýþÿÿþþÿýþÿþþÿýþÿüþÿÿþÿÿþþÿþþÿüþÿÿþÿÿÿþÿþÿþþÿÿþÿÿÿþÿþþÿþþÿÿÿÿÿþÿþþÿÿþÿÿÿÿÿÿþþÿÿþÿþÿüþÿÿþÿÿÿÿþÿþþÿÿÿþÿþþÿÿÿÿÿÿÿÿÿÿÿÿþþÿþþÿÿþÿÿÿþÿÿþþÿÿþÿÿþÿþþÿÿÿþÿÿþÿÿþÿýþÿýþÿÿþþÿýþÿÿþÿÿÿÿþþÿÿþÿþÿþþÿÿþÿÿÿÿþþÿüþÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿüþÿýþÿÿþÿÿÿþþÿþþÿÿþÿÿÿÿÿÿþÿÿÿÿÿþÿþþÿÿþÿÿþÿÿÿÿþÿþþÿþþÿÿþÿÿÿÿÿÿþþÿýþÿÿþÿÿÿþÿÿÿÿÿþþÿýþÿüþÿüþÿüþÿýþÿÿüþÿüþÿÿþÿÿýþÿýþÿÿþÿÿþþÿûþÿüþÿýþÿüþÿýþÿýþÿýþÿÿþþÿýþÿþþÿÿÿþÿÿþÿþþÿüþÿÿþÿÿÿÿÿÿÿþÿÿþÿÿÿÿÿÿþþÿýþÿÿþÿÿÿþÿÿþÿÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿÿÿýþÿþþÿþþÿüþÿýþÿþþÿÿþÿÿþÿþþÿýþÿýþÿþþÿÿÿþÿþþÿþþÿþþÿþþÿÿÿÿÿÿþÿþþÿþþÿÿÿÿÿÿÿþÿþþÿÿþÿÿþÿüþÿüþÿþþÿÿþÿþþÿÿÿþÿÿÿÿþÿÿþÿþþÿÿþÿþþÿÿÿÿÿÿþÿÿÿþÿÿþÿþþÿýþÿþþÿÿÿþÿþþÿþþÿÿÿþÿþþÿÿüþÿûþÿÿÿþÿÿÿþÿÿþþÿÿþÿÿÿþÿÿýþÿüþÿýþÿþþÿþþÿýþÿÿþÿÿþþÿÿþÿÿþþÿÿþÿÿÿþÿþþÿýþÿýþÿÿþÿÿþÿÿÿÿþÿÿþþÿÿþÿÿÿüþÿýþÿÿÿþÿÿþþÿûþÿýþÿÿþÿþþÿÿþÿÿüþÿûþÿüþÿþþÿÿÿÿÿÿþÿÿÿÿÿþÿÿÿþÿýþÿþþÿÿÿþÿýþÿþþÿþþÿÿþÿÿþÿÿÿþÿüþÿüþÿüþÿüþÿÿþÿÿÿÿÿÿþþÿþþÿÿþÿÿþþÿÿþÿÿÿþþÿüþÿÿþÿÿþþÿþþÿüþÿûþÿþþÿÿÿþÿÿþÿÿüþÿøþÿùþÿûþÿþþÿÿÿþÿÿÿþÿÿþÿÿþÿÿþþÿýþÿþþÿÿþÿÿýþÿþþÿÿþÿýþÿýþÿþþÿýþÿýþÿþþÿÿþÿÿþÿÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþþÿûþÿüþÿþþÿÿþÿÿþÿÿþÿÿþÿÿþþÿþþÿþÿýþÿÿþþÿýþÿÿÿþÿÿþÿÿÿÿþÿÿÿþÿþþÿÿþþÿÿüþÿûþÿýþÿþþÿþþÿüþÿüþÿýþÿÿþÿþÿüþÿûþÿþþÿÿÿþÿÿÿþÿÿÿþÿÿþÿÿÿýþÿýþÿÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿÿþÿÿüþÿúþÿþþÿÿÿþÿýþÿýþÿÿÿÿÿþÿþþÿÿþÿÿÿÿÿþþÿÿþÿþÿýþÿÿþÿÿÿþÿþþÿÿþÿÿÿþÿÿÿÿþþÿþþÿÿþÿÿÿÿÿÿþþÿûþÿýþÿÿþÿþÿþþÿýþÿÿÿÿþÿÿþÿÿÿþÿÿÿþÿÿÿþÿýþÿüþÿüþÿÿþÿÿÿÿþÿþþÿÿþÿþÿýþÿüþÿýþÿÿÿÿÿÿýþÿûþÿýþÿÿþÿÿÿÿÿýþÿþþÿÿÿþÿÿÿþÿþþÿþþÿþþÿþþÿÿýþÿüþÿþþÿþþÿþþÿÿýþÿúþÿÿþÿþÿÿþÿþÿþþÿþþÿüþÿÿþÿþÿýþÿÿþÿÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿýþÿýþÿþþÿÿþÿÿþÿýþÿþþÿÿÿÿÿþþÿþþÿþþÿÿþÿþÿþþÿþþÿÿþÿÿÿþÿþþÿþþÿýþÿÿþÿÿÿþþÿþþÿÿýþÿýþÿýþÿýþÿÿþÿÿþÿÿþÿÿþÿÿÿþÿýþÿüþÿÿþþþÿûþÿüþÿÿþÿÿÿýþÿþþÿÿþÿþþÿýþÿÿþÿÿÿþÿÿþþÿþþÿÿþÿÿÿÿÿþþÿýþÿÿþþÿûþÿýþÿþþÿþþÿÿþÿþþÿüþÿýþÿÿþÿÿÿÿþþÿüþÿüþÿÿþÿÿÿÿÿþÿþþÿÿþÿþÿþþÿþþÿþþÿþþÿÿþÿÿþþÿþþÿÿþÿÿÿÿÿÿþÿÿÿþÿÿÿþÿÿÿþÿÿÿÿþÿÿþÿÿÿþþÿþþÿÿÿÿþÿþþÿÿþþÿþþÿþþÿÿþÿþÿþþÿþþÿþþÿÿÿÿÿþþÿÿþÿÿÿþÿÿþÿÿÿþÿÿþÿÿÿþþÿýþÿÿþÿÿÿÿþÿÿþÿÿÿÿþÿÿÿÿÿþþÿÿÿþÿýþÿýþÿþþÿÿýþÿÿþÿþÿýþÿþþÿÿþÿþþÿýþÿÿþÿÿÿþÿÿþÿÿÿþÿÿþþÿÿþÿÿÿÿþþÿýþÿýþÿýþÿüþÿÿþÿÿÿþþÿÿþÿÿÿþÿÿÿþÿÿÿÿþÿþþÿþþÿÿþþÿýþÿÿþÿÿþþÿÿþÿÿþþÿþþÿÿþÿþþÿþþÿýþÿÿþÿÿÿþÿÿÿÿÿÿþþÿþþÿþþÿýþÿÿþÿÿþþÿüþÿýþÿÿþÿÿÿÿÿÿÿþþÿþþÿþþÿÿþÿÿþþÿÿÿÿþÿþþÿÿÿþÿÿÿÿþÿþþÿþþÿÿÿÿþþÿþþÿÿþÿÿÿÿÿþþÿÿþþÿÿþÿþÿýþÿÿþþÿÿþÿÿÿÿÿÿþÿÿÿÿþÿÿþÿÿþÿþþÿýþÿýþÿÿþþÿýþÿþþÿþþÿüþÿüþÿýþÿÿþÿÿÿÿþÿÿþþÿÿþÿÿÿÿÿÿþþÿþþÿÿÿÿÿýþÿþþÿÿþÿþÿþþÿÿþÿÿÿþÿÿÿþÿÿÿþÿÿþÿÿþÿÿþÿþþÿþþÿÿþÿÿÿÿÿÿÿþÿÿþÿÿÿþÿÿþÿÿþÿÿþÿÿþÿþþÿÿÿþÿýþÿûþÿúþÿüþÿÿýþÿüþÿÿþÿþÿýþÿüþÿüþÿþþÿþþÿþþÿÿþþÿþþÿÿþÿÿþÿÿÿÿþÿÿþÿÿÿþÿÿþþÿýþÿÿþÿÿþÿÿþÿÿÿþÿÿÿþÿþþÿþþÿÿÿÿÿþÿþÿþþÿÿþÿþÿýþÿýþÿÿÿÿÿþþÿýþÿÿþÿÿÿþÿÿÿÿþÿÿþþÿýþÿÿþþÿýþÿÿþþÿÿþÿÿþþÿüþÿýþÿÿþþÿüþÿýþÿÿþÿþÿÿþÿÿÿþÿþþÿýþÿÿþÿÿÿþÿÿþÿÿÿþÿÿþÿÿþÿþþÿýþÿýþÿÿþÿÿþÿÿþÿÿþÿÿÿþÿÿþÿýþÿýþÿÿÿþÿÿþÿÿþÿÿÿþÿÿþþÿûþÿþþÿÿÿþÿÿþÿÿÿþÿÿþÿÿþÿþþÿÿþÿþþÿûþÿûþÿÿþÿþÿþþÿýþÿüþÿüþÿþþÿÿÿÿÿÿÿþÿþþÿþþÿÿÿÿÿþÿÿþÿýþÿýþÿþþÿÿþþÿÿþÿÿþþÿþþÿÿþÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿýþÿüþÿþþÿÿÿÿþÿýþÿýþÿüþÿþþÿÿüþÿüþÿþþÿþþÿýþÿûþÿüþÿþþÿýþÿüþÿýþÿÿÿþÿÿþþÿýþÿþþÿýþÿýþÿÿþÿÿÿþÿþþÿýþÿÿþÿÿþÿþþÿÿþþÿûþÿûþÿýþÿþþÿÿüþÿþþÿÿþÿÿþÿþþÿÿþÿþþÿþþÿÿÿþÿýþÿýþÿþþÿÿþÿÿÿþÿýþÿÿþÿþÿÿþÿÿÿÿþÿÿÿÿþÿþþÿþþÿþþÿýþÿÿþþÿüþÿûþÿþþÿÿÿþÿÿýþÿþþÿÿþÿÿþÿþþÿÿþÿÿÿþÿýþÿþþÿþþÿýþÿÿþÿþÿýþÿþþÿÿÿþÿÿÿþÿýþÿüþÿüþÿþþÿÿþÿÿÿþÿÿÿþÿýþÿýþÿÿÿþÿýþÿýþÿþþÿÿþÿÿþÿÿþÿÿÿþÿþþÿýþÿÿþþÿýþÿÿÿþÿÿþÿÿÿÿþÿÿþÿÿÿþÿÿþÿÿþþÿýþÿÿÿþÿÿþÿÿþÿþþÿþþÿÿþÿÿÿÿþÿüþÿýþÿþþÿþþÿþþÿÿþÿÿþÿýþÿÿþÿÿþÿýþÿÿþÿÿþÿýþÿýþÿüþÿùþÿüþÿÿýþÿÿþÿþÿûþÿþþÿþÿÿþÿÿþþÿÿÿÿÿÿÿÿÿþÿþþÿÿþÿþÿþþÿÿþÿÿÿÿÿÿÿþÿþþÿþþÿÿÿÿÿÿÿÿÿþÿþþÿýþÿþþÿÿþÿÿþÿÿÿþÿÿÿþÿÿÿþÿþþÿÿþÿÿþÿÿþÿÿÿþÿÿÿÿþþÿÿþÿÿþþÿÿþþÿÿþÿÿÿÿÿþþÿýþÿÿýþÿûþÿýþÿþþÿüþÿÿþÿÿþþÿÿÿÿþÿÿÿÿþþÿüþÿüþÿþþÿþþÿÿþÿÿÿÿÿþÿÿÿÿÿÿþÿÿþÿþÿýþÿýþÿÿýþÿüþÿýþÿþþÿÿÿÿÿÿþÿÿÿÿþÿýþÿüþÿüþÿÿþÿþÿþþÿÿÿÿþÿþþÿÿÿþÿþþÿÿÿÿÿÿþÿÿþÿÿÿÿÿÿÿþÿþþÿþþÿþþÿþþÿüþÿýþÿÿþÿÿþÿüþÿüþÿýþÿþþÿÿþÿÿþÿÿÿþÿÿþÿÿþÿÿþþÿýþÿþþÿÿÿþÿÿþþÿÿþþÿÿþÿþÿýþÿÿþþÿÿþÿþÿþþÿýþÿþþÿÿÿÿÿþÿþÿÿÿÿÿÿþÿþþÿÿÿÿÿÿÿÿþþÿÿþÿÿþþÿþþÿüþÿýþÿÿÿþÿÿþþÿÿþÿÿþÿÿÿþÿþþÿþþÿÿþþÿþþÿÿÿþÿÿþÿÿþÿÿýþÿþþÿÿýþÿýþÿþþÿÿþÿÿþÿÿÿÿþÿþþÿÿþÿÿÿÿÿþþÿþþÿþþÿþþÿÿþÿÿþÿþþÿþþÿÿþÿþþÿÿþÿþþÿýþÿýþÿÿþÿÿÿÿþÿÿþÿÿþÿÿþÿÿüþÿþþÿþÿûþÿýþÿÿÿþÿÿþþÿûþÿûþÿþþÿÿÿþÿÿþÿÿÿþÿýþÿýþÿýþÿÿÿþÿÿþÿþÿþþÿÿüþÿûþÿýþÿýþÿýþÿÿþÿÿþÿÿþÿÿÿþÿÿÿþÿÿþþÿÿþÿþþÿüþÿýþÿÿýþÿÿþÿÿýþÿýþÿþþÿÿÿÿþÿÿÿÿÿÿþÿþþÿþþÿÿÿþÿüþÿþþÿÿþÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿþþÿÿþÿÿÿÿÿÿÿÿÿþþÿüþÿüþÿÿþÿÿÿþÿÿÿþÿÿþÿÿþÿÿÿþÿýþÿýþÿþþÿÿþÿþþÿýþÿýþÿÿþÿÿþÿþþÿýþÿÿþþÿüþÿýþÿÿþÿÿÿþþÿÿþÿÿÿþÿÿþÿþþÿýþÿýþÿÿþþÿüþÿýþÿþþÿþþÿþþÿýþÿúþÿýþÿÿúþÿûþÿþþÿþþÿûþÿüþÿüþÿþþÿþþÿþþÿÿþÿþÿþþÿÿÿÿþÿÿþÿÿþÿÿþÿÿþþÿÿþÿÿÿþÿþþÿþþÿÿþÿÿÿþÿþþÿÿýþÿÿþÿþÿÿþÿÿþÿÿþÿÿþÿÿÿÿþÿÿþÿÿþÿÿÿþÿÿÿÿÿþÿÿþÿþþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþþÿüþÿûþÿýþÿÿþÿÿþÿÿþÿÿþÿÿÿþÿÿÿþÿýþÿÿÿþÿÿþÿÿþÿÿþÿÿÿþÿÿþÿÿÿþÿÿÿþÿÿþÿÿþþÿÿþþÿÿþÿÿþÿÿÿÿÿþÿþþÿüþÿûþÿûþÿýþÿþþÿÿüþÿüþÿÿþÿÿþÿÿþÿÿýþÿûþÿþþÿÿþþÿÿÿÿÿÿþþÿýþÿÿþþÿýþÿýþÿþþÿÿþþÿÿþÿÿþþÿüþÿýþÿÿþþÿýþÿÿþÿÿÿþÿþþÿÿþÿÿþÿÿþþÿüþÿýþÿÿþÿÿÿÿþþÿüþÿþþÿÿþþÿÿþÿÿþÿþÿüþÿþþÿþÿýþÿÿþÿÿÿþÿÿþþÿþþÿÿÿÿþÿýþÿÿþþÿûþÿüþÿþþÿÿÿþÿýþÿüþÿþþÿÿÿÿþÿÿÿÿÿÿÿþÿþþÿüþÿûþÿûþÿüþÿüþÿÿþÿþÿÿþÿþÿþþÿÿþÿÿÿÿÿþÿÿÿÿÿþÿÿÿÿÿþþÿÿþÿÿÿÿþþÿþþÿþþÿýþÿýþÿÿÿÿÿÿÿÿÿÿÿÿþþÿþþÿþþÿþþÿÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿþþÿÿþÿÿýþÿýþÿÿþþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿþÿþþÿþþÿýþÿüþÿüþÿÿþÿþþÿýþÿþþÿþþÿÿþþÿüþÿýþÿÿþÿÿþþÿýþÿÿþÿÿÿþÿÿÿþÿþþÿÿþÿÿþþÿÿþÿÿÿÿþÿÿþÿÿýþÿþþÿÿþÿýþÿýþÿþþÿýþÿþþÿþþÿÿÿþÿþþÿÿþÿÿþÿþþÿÿþÿýþÿüþÿÿÿþÿþþÿÿþÿÿÿþÿþþÿÿþÿÿÿþÿÿþÿÿþÿÿþÿÿþþÿÿþþÿýþÿÿþÿÿþÿÿþÿÿýþÿýþÿÿýþÿýþÿÿþÿÿÿþþÿÿþÿþÿÿþÿÿþþÿÿþþÿÿþÿþÿþþÿÿþÿÿÿþþÿÿþÿÿÿþþÿÿþÿþÿýþÿÿþþÿýþÿÿþÿþþÿýþÿþþÿÿþþÿýþÿþþÿÿþÿÿÿÿÿþþÿþþÿýþÿÿþÿþÿÿþÿþÿüþÿÿþÿþÿþþÿÿþÿÿÿÿÿþþÿÿýþÿüþÿÿþÿÿþÿþþÿþþÿÿþþÿýþÿÿþÿþþÿþþÿýþÿÿþÿÿÿþÿÿþÿÿþÿÿÿÿþÿÿþÿþþÿÿþÿÿþÿÿþÿÿþÿÿÿþÿÿþÿÿþÿÿþÿÿÿþÿÿþÿÿþÿþþÿýþÿÿþÿÿÿþÿÿþÿÿþÿþþÿÿÿþÿþþÿþþÿÿÿÿÿýþÿúþÿûþÿýþÿýþÿÿþÿÿÿþÿÿþÿÿÿþÿÿþÿÿÿþÿÿÿþÿÿþþÿüþÿýþÿýþÿûþÿüþÿÿýþÿþþÿÿÿþÿÿþÿÿþÿÿþÿÿþÿÿÿþÿþþÿÿÿþÿþþÿýþÿüþÿüþÿÿýþÿúþÿýþÿÿÿÿÿÿÿÿþÿÿþÿþÿýþÿþþÿÿÿþÿÿþÿÿÿþÿÿþÿÿÿþÿÿÿþÿÿþþÿüþÿûþÿûþÿþþÿÿþÿÿÿþÿþþÿüþÿüþÿÿþÿþÿÿþÿÿÿþÿÿÿÿÿÿÿÿÿÿÿþÿþþÿÿýþÿüþÿýþÿþþÿÿþþÿþþÿÿÿþÿÿÿÿþÿýþÿþþÿÿÿþÿÿþÿÿþþÿýþÿýþÿýþÿþþÿÿþÿÿÿþÿýþÿÿÿþÿÿþÿÿÿþÿÿÿÿþÿþþÿÿÿþÿÿþÿÿÿÿþÿÿþþÿÿþÿÿÿþÿÿÿþÿÿÿþÿÿþþÿþþÿÿþÿþþÿÿÿÿÿýþÿýþÿÿÿÿÿÿþÿÿÿþÿÿÿþÿÿþÿÿÿþÿÿþÿÿþÿÿÿÿþÿþþÿýþÿûþÿþþÿÿýþÿÿþþÿþþÿÿÿþÿÿÿþÿÿþÿþþÿÿþÿÿÿþÿüþÿûþÿüþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþþÿýþÿÿþþÿþþÿüþÿüþÿÿþÿÿÿÿÿÿÿÿþÿÿþÿþÿÿÿÿÿþÿýþÿüþÿÿþÿþÿþþÿÿÿÿþþÿÿþÿÿþÿÿÿþÿþþÿþþÿÿþþÿÿÿþÿÿýþÿüþÿÿÿÿÿÿþÿÿÿþÿÿþÿÿþÿÿþÿÿþÿÿÿÿþÿÿÿÿÿþÿÿÿÿþÿÿþÿÿÿþÿÿþþÿüþÿþþÿÿÿÿÿþÿÿÿþÿýþÿýþÿþþÿÿýþÿþþÿÿÿþÿýþÿüþÿþþÿÿÿÿÿÿþÿÿýþÿûþÿþþÿÿþÿþþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿþþÿýþÿýþÿýþÿþþÿÿýþÿüþÿþþÿÿÿþÿÿÿÿÿþþÿþþÿÿýþÿÿþþÿüþÿÿÿþÿÿþþÿþþÿÿÿþÿÿþÿÿÿÿÿþÿÿþÿÿÿþÿÿþÿÿþÿþþÿýþÿþþÿÿþþÿþþÿÿýþÿÿþþÿþþÿÿÿþÿÿþÿýþÿýþÿÿþþÿüþÿýþÿÿþÿÿÿÿþþÿüþÿýþÿÿÿÿþþÿÿÿÿÿýþÿúþÿýþÿÿþÿþÿþþÿÿþÿþÿÿþÿÿÿþþÿýþÿÿþÿþþÿÿþÿÿýþÿüþÿýþÿÿýþÿüþÿþþÿþþÿÿÿþÿþþÿþþÿÿÿþÿýþÿýþÿûþÿûþÿýþÿÿÿþÿÿÿÿÿþÿÿÿþÿýþÿÿþþþÿþþÿÿþÿþþÿþþÿÿýþÿÿÿþÿÿþþÿþþÿÿÿþÿÿþþÿýþÿÿþÿÿþþÿÿþÿÿþþÿÿþÿÿþþÿýþÿþþÿÿþþÿÿþþÿüþÿþþÿÿýþÿþþÿÿÿþÿÿþÿýþÿþþÿÿþÿÿþÿÿþÿÿþÿýþÿýþÿýþÿÿÿÿÿÿÿÿþþÿþþÿþþÿÿÿÿþÿÿþÿÿÿþÿÿÿþÿÿÿþÿûþÿüþÿýþÿÿÿÿÿþÿÿÿÿÿÿþþÿþþÿÿýþÿýþÿÿÿÿÿÿþÿÿÿÿÿÿþÿÿþÿÿÿþÿÿÿþÿÿþÿÿþÿÿþÿÿþÿýþÿþþÿÿýþÿýþÿþþÿÿþÿÿþÿþþÿÿýþÿþþÿÿýþÿüþÿþþÿþþÿþþÿÿýþÿýþÿÿýþÿýþÿÿþÿÿþþÿþþÿÿþÿþþÿÿüþÿüþÿþþÿÿþÿþþÿÿÿþÿýþÿüþÿýþÿþþÿÿþÿÿÿþÿÿþÿÿþþÿýþÿþþÿÿþÿÿþÿÿÿþÿþþÿÿÿþÿÿþþÿýþÿÿþÿÿþÿÿþÿÿÿþÿÿþÿýþÿþþÿÿýþÿýþÿýþÿûþÿüþÿÿþÿÿÿþþÿÿþÿÿþþÿÿþÿÿÿþÿÿþÿÿÿþþÿÿþþÿÿþþÿÿþÿÿÿþÿÿÿþÿþþÿýþÿþþÿÿþþÿÿþÿÿþÿÿÿÿÿþþÿÿþÿÿÿÿÿþþÿþþÿÿýþÿüþÿÿþÿþÿþþÿÿþþÿýþÿþþÿÿÿþÿÿþÿÿþÿÿþÿÿÿþÿþþÿÿþÿÿþÿÿÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿüþÿûþÿþþÿÿþÿýþÿþþÿýþÿûþÿýþÿÿþÿþþÿÿüþÿúþÿüþÿþþÿÿÿþÿþþÿþþÿÿþþÿþþÿþþÿÿþÿþÿûþÿýþÿÿýþÿþþÿÿÿÿþÿÿÿþÿýþÿÿþÿþÿÿÿþÿüþÿÿþÿþÿüþÿýþÿÿþÿÿÿÿÿþÿÿþþÿÿþÿþþÿüþÿýþÿÿÿÿþþÿþþÿÿþÿÿþþÿþþÿþþÿûþÿúþÿýþÿÿÿÿþÿþþÿÿÿþÿþþÿþþÿþþÿÿÿÿÿÿþÿÿÿÿþÿþþÿþþÿÿÿÿÿÿÿÿÿþÿýþÿÿþÿþÿÿþÿÿþþÿþþÿÿþÿÿÿÿÿþþÿþþÿýþÿþþÿýþÿûþÿûþÿüþÿþþÿÿÿþÿýþÿþþÿÿûþÿüþÿÿÿþÿþþÿþþÿÿÿÿÿÿÿþÿüþÿýþÿÿüþÿûþÿÿÿÿÿþÿþÿþþÿÿþÿþÿþþÿÿÿÿÿÿÿþÿþþÿÿýþÿþþÿÿÿÿþÿþþÿÿþþÿþþÿÿþÿÿýþÿüþÿúþÿûþÿýþÿÿþþÿþþÿÿÿÿÿþÿþþÿþþÿýþÿþþÿÿÿþÿýþÿÿþÿÿÿÿþÿýþÿÿþÿÿÿÿþÿÿþÿÿþÿÿþÿÿÿÿÿþÿþþÿÿÿÿÿþÿÿþÿþþÿýþÿüþÿÿþÿÿÿÿÿÿÿÿÿÿÿþÿþþÿÿÿþÿÿþþÿýþÿÿÿþÿÿüþÿüþÿþþÿÿþÿþþÿÿÿÿÿÿÿþÿüþÿüþÿþþÿþþÿýþÿüþÿþþÿþþÿþþÿÿþþÿÿþÿÿþþÿþþÿüþÿúþÿûþÿÿþþÿþþÿþþÿþþÿÿÿÿÿÿÿþÿüþÿýþÿÿþþÿÿþÿþþÿþþÿýþÿÿþÿþÿýþÿþþÿÿþÿÿþÿþÿÿþÿÿþþÿÿþÿÿÿþÿÿþþÿýþÿÿþÿþþÿüþÿþþÿÿÿþÿÿþþÿþþÿÿþþÿþþÿÿÿþÿÿþÿÿþÿÿþþÿþþÿÿÿþÿÿýþÿÿþþÿýþÿýþÿÿþÿÿÿÿþÿÿþÿÿýþÿÿþÿÿÿþÿÿÿÿþÿÿþþÿýþÿÿþÿþþÿüþÿýþÿÿþþÿÿÿþÿÿýþÿüþÿÿþÿþÿÿþÿþþÿþþÿÿþÿÿÿþþÿÿþÿÿÿþÿÿÿþÿÿÿþÿÿþþÿþþÿÿþÿÿþÿÿÿþÿþþÿÿÿþÿýþÿýþÿþþÿÿþþÿÿþþÿüþÿûþÿûþÿþþÿÿþÿÿþÿÿþÿÿÿþÿÿþÿþþÿýþÿþþÿÿþÿýþÿýþÿýþÿÿþÿÿÿÿÿÿýþÿýþÿÿþÿÿþÿÿþÿÿÿÿþÿýþÿÿÿþÿþþÿÿÿþÿÿÿþÿÿþÿÿÿÿþÿýþÿÿþÿþÿþþÿÿÿÿÿÿÿÿÿÿÿÿþÿýþÿüþÿþþÿÿÿþÿýþÿüþÿÿþþÿüþÿýþÿÿÿþÿýþÿþþÿýþÿþþÿþþÿÿÿÿÿþÿÿþÿÿÿþÿÿÿþÿÿþÿþþÿýþÿÿþÿÿÿÿÿÿþþÿýþÿýþÿüþÿüþÿþþÿÿÿÿþÿúþÿúþÿýþÿÿþÿÿþþÿýþÿýþÿýþÿýþÿÿþÿÿþþÿþþÿþþÿþþÿþþÿþþÿüþÿüþÿýþÿþþÿÿþÿÿþþÿÿþÿÿþþÿÿþÿÿÿþÿÿÿþÿÿþÿÿþþÿÿþÿþÿüþÿýþÿÿþÿÿÿþÿÿþÿÿÿþþÿüþÿýþÿÿþÿÿþÿÿþÿÿþÿÿÿþÿÿþÿÿÿÿþÿÿþÿÿÿþÿþþÿÿþÿÿþþÿüþÿýþÿÿþÿþþÿüþÿýþÿüþÿüþÿýþÿþþÿÿÿÿÿýþÿÿþÿþÿþþÿÿýþÿýþÿÿþÿÿüþÿýþÿÿþÿÿÿþþÿþþÿýþÿÿþÿÿÿþÿÿþÿÿÿþÿÿþÿÿÿþÿÿþÿÿþÿÿþþÿÿþÿÿÿþÿýþÿýþÿÿþÿÿþÿÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿþÿþþÿÿÿÿþÿüþÿýþÿÿþÿÿþÿÿÿÿþÿÿþÿÿÿþþÿûþÿýþÿÿþÿÿþÿþþÿüþÿûþÿýþÿÿþÿÿþþÿþþÿþþÿþþÿþþÿþþÿÿþÿÿÿþþÿÿþÿÿÿþÿÿÿþÿÿþÿÿÿþÿÿþþÿýþÿþþÿÿþÿÿþÿÿþÿÿÿþÿÿþþÿÿþÿÿÿþþÿÿþÿÿÿþÿÿþÿÿþÿÿÿþÿÿÿþÿýþÿýþÿýþÿþþÿÿÿþÿÿÿÿÿþþÿþþÿÿþÿÿÿþþÿÿþÿÿýþÿÿþÿÿÿþÿÿþÿÿÿþÿÿÿþÿýþÿýþÿûþÿûþÿþþÿÿþÿÿþÿÿÿþÿÿÿþÿÿþÿÿÿþÿÿÿÿþÿÿþÿÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿÿþÿÿþÿþþÿÿþÿÿþþÿþþÿþþÿþþÿýþÿýþÿÿÿþÿÿþÿÿþÿýþÿûþÿþþÿÿÿÿþÿýþÿþþÿÿþþÿýþÿüþÿýþÿþþÿÿÿÿþÿþþÿþÿýþÿýþÿÿþÿÿþÿþþÿþþÿÿÿþÿÿþÿþþÿþþÿÿÿþÿÿÿþÿÿüþÿýþÿÿþÿþþÿþþÿÿþÿÿþþÿüþÿýþÿÿþþÿÿþÿþÿÿþÿþÿüþÿþþÿþþÿýþÿÿþÿÿýþÿÿþÿÿþþÿþþÿþþÿþþÿþþÿþþÿÿÿÿþÿþþÿÿÿþÿÿþþÿûþÿüþÿþþÿÿÿþÿÿÿþÿÿþÿÿÿþÿÿþþÿþþÿþþÿÿþÿÿÿÿÿþÿÿþÿÿýþÿþþÿÿÿþÿÿþÿÿþÿÿþÿÿÿþÿþþÿýþÿÿþÿÿÿþÿÿþÿÿþÿÿÿÿþÿÿþÿÿÿþÿÿþþÿÿþþÿýþÿÿÿþÿÿÿþÿÿþÿÿþÿýþÿþþÿÿÿÿÿÿÿÿþþÿþþÿÿÿþÿÿþþÿûþÿûþÿýþÿüþÿûþÿýþÿþþÿÿþÿÿþþÿþþÿÿþÿÿÿÿþÿþþÿþþÿÿþÿÿþÿûþÿûþÿýþÿüþÿÿþþÿüþÿýþÿýþÿýþÿÿþÿÿþþÿýþÿÿþÿÿþÿýþÿþþÿÿÿÿþÿÿþÿÿþþÿÿþÿÿÿÿþþÿÿþÿÿüþÿýþÿýþÿÿþÿÿÿÿÿÿÿÿþÿüþÿüþÿÿþÿÿþþÿÿþÿÿÿÿþÿÿþÿÿÿþÿÿþÿÿÿþÿÿþÿÿÿþÿÿþþÿýþÿþþÿÿþÿÿþÿýþÿþþÿÿýþÿýþÿÿþÿÿÿþÿþþÿþþÿÿÿþÿÿýþÿþþÿÿþÿýþÿþþÿÿýþÿüþÿÿþÿÿÿÿþþÿüþÿÿþÿþÿüþÿüþÿþþÿþþÿþþÿýþÿüþÿÿþÿþÿþþÿÿþþÿüþÿýþÿÿþÿÿþþÿþþÿþþÿÿÿþÿÿÿþÿÿÿþÿÿÿþÿþþÿÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿüþÿþþÿÿþþÿÿÿÿÿÿÿÿÿþÿÿþÿþÿþþÿýþÿÿÿÿÿþþÿÿþÿÿþþÿÿþÿÿþþÿÿþÿÿÿÿþþÿþþÿÿþÿÿÿÿÿÿþþÿÿþÿÿÿÿÿÿþÿÿÿþþÿÿþÿÿÿþÿÿýþÿýþÿüþÿýþÿÿÿÿÿÿÿþÿýþÿþþÿÿýþÿÿþþÿþþÿÿýþÿýþÿýþÿþþÿÿÿþÿþþÿþþÿÿÿþÿüþÿüþÿÿþÿÿÿÿÿÿÿþÿÿýþÿþþÿÿþþÿÿýþÿþþÿÿýþÿþþÿÿÿþÿýþÿüþÿþþÿþþÿþþÿþþÿþþÿÿþÿÿþÿýþÿüþÿþþÿÿÿþÿÿýþÿþþÿÿÿþÿÿÿÿÿÿÿÿÿÿþþÿûþÿûþÿþþÿÿþþÿýþÿþþÿþþÿÿÿÿþÿþþÿÿÿþÿþþÿÿÿþÿþþÿÿÿÿÿÿÿÿÿÿÿÿþþÿÿþÿÿÿþþÿýþÿÿþÿÿþÿÿþÿÿÿþÿÿÿþÿþþÿÿÿþÿþþÿÿÿÿþÿþþÿÿýþÿþþÿÿþÿýþÿþþÿÿþþÿÿýþÿüþÿÿþÿþÿþþÿÿþÿýþÿýþÿÿÿþÿÿþÿÿÿþÿþþÿÿÿþÿÿÿþÿýþÿýþÿþþÿÿÿÿÿþÿýþÿýþÿÿýþÿýþÿÿÿÿþÿüþÿþþÿÿþÿþþÿÿÿþÿÿÿþÿþþÿÿÿþÿþþÿÿÿÿÿÿþÿþþÿüþÿüþÿþþÿþþÿþþÿÿÿÿÿþþÿÿþÿþÿüþÿÿþÿÿÿÿþÿþþÿÿÿÿþÿýþÿþþÿÿÿÿþÿÿÿÿÿþÿÿÿÿÿþÿýþÿüþÿþþÿÿþÿýþÿþþÿÿÿþÿÿþÿÿþÿÿþÿþþÿýþÿÿþþÿýþÿýþÿýþÿÿÿþÿýþÿýþÿþþÿÿþÿÿÿþÿÿþÿÿÿÿþÿÿÿÿþÿÿþÿÿþþÿýþÿýþÿÿþÿþþÿþþÿýþÿÿþþÿÿþÿÿÿþÿþþÿÿþþÿúþÿûþÿÿþÿÿþÿÿÿÿüþÿúþÿûþÿýþÿÿþþÿÿþÿþÿýþÿÿÿÿþþÿýþÿýþÿþþÿþþÿþþÿÿýþÿüþÿþþÿÿþÿþþÿÿþÿýþÿûþÿþþÿÿþÿüþÿûþÿþþÿÿüþÿýþÿÿþþÿüþÿýþÿÿþÿþþÿüþÿýþÿýþÿÿþÿÿÿþÿÿÿþÿÿþþÿýþÿÿþÿÿÿþÿÿþÿÿÿÿþÿÿþÿÿþþÿûþÿüþÿÿþÿþþÿþþÿÿþþÿÿþÿÿþÿÿÿþÿÿþÿÿþÿÿþþÿýþÿÿþþÿüþÿüþÿüþÿüþÿþþÿÿÿþÿÿÿþÿÿþÿþþÿýþÿþþÿþþÿþþÿþþÿþþÿüþÿýþÿÿþþÿþþÿþþÿüþÿýþÿþþÿþþÿüþÿüþÿÿþÿþÿþþÿÿþÿþÿþþÿÿþÿÿÿÿÿþþÿþþÿþþÿÿÿÿÿÿþÿþþÿþþÿÿÿþÿÿÿþÿýþÿýþÿüþÿüþÿÿþÿÿÿÿÿÿÿþÿÿÿÿÿþþÿýþÿûþÿûþÿÿÿþÿþþÿþþÿÿýþÿûþÿÿþÿþÿýþÿþþÿÿþÿÿÿÿÿÿþþÿÿþÿÿÿþÿÿÿþþÿüþÿÿþÿÿÿÿþÿþþÿÿýþÿüþÿþþÿÿÿÿÿÿþÿÿÿþÿüþÿþþÿÿÿÿþÿÿþÿÿþÿÿþÿÿÿÿÿÿÿÿÿþÿÿÿþÿûþÿüþÿÿþÿþÿýþÿþþÿÿÿþÿÿþÿÿþþÿüþÿþþÿÿÿÿþÿÿþÿÿÿþÿÿþÿÿþþÿÿÿþÿþþÿÿÿÿþÿÿþþÿþþÿÿþÿÿþÿÿüþÿûþÿþþÿÿþÿÿþÿÿþÿýþÿþþÿþþÿÿþÿÿþþÿÿþÿÿÿÿÿþÿÿÿÿÿÿÿþÿþþÿþþÿþþÿþþÿÿþÿýþÿþþÿÿÿþÿÿþÿþþÿÿÿþÿÿÿÿÿþÿÿÿþþÿþþÿÿþÿÿÿþÿþþÿþþÿÿÿþÿýþÿþþÿÿýþÿýþÿÿþÿÿþÿþþÿýþÿÿþÿÿÿþÿÿþÿÿýþÿþþÿÿÿþÿþþÿÿþÿþÿüþÿÿþÿÿÿÿþÿÿÿþÿýþÿþþÿÿþÿÿþÿÿþþÿýþÿÿþÿÿþÿýþÿÿÿþÿþþÿÿÿþÿýþÿûþÿüþÿÿÿþÿÿÿþÿÿÿþÿþþÿÿÿÿÿÿÿÿþþÿüþÿþþÿÿÿþÿÿÿþÿÿþþÿüþÿüþÿýþÿÿÿÿþÿýþÿüþÿÿþþþÿüþÿþþÿÿýþÿýþÿÿþÿÿÿþÿÿþÿÿÿÿþÿýþÿüþÿþþÿÿÿþÿÿþÿÿþÿÿÿþÿÿþÿÿþÿÿÿþÿýþÿþþÿÿýþÿþþÿÿÿþÿÿÿþÿþþÿþþÿþþÿüþÿýþÿÿÿÿÿþþÿÿÿÿÿÿÿÿÿþÿÿþÿýþÿûþÿþþÿÿÿþÿÿÿþÿþþÿÿýþÿýþÿÿýþÿýþÿÿÿþÿÿþÿÿþÿÿÿÿþþÿýþÿüþÿýþÿþþÿýþÿüþÿþþÿÿÿþÿÿþÿÿÿþÿÿþÿÿþÿýþÿýþÿÿÿþÿÿþÿÿÿþÿÿþþÿÿþÿþÿþþÿÿþÿþÿýþÿüþÿüþÿýþÿÿþÿÿþÿþþÿÿþÿþÿüþÿýþÿÿþþÿþþÿþþÿþþÿÿþþÿþþÿÿþÿÿÿÿþþÿýþÿüþÿüþÿÿþÿþÿþþÿÿþÿýþÿûþÿýþÿÿþÿÿþÿÿÿþÿÿþÿýþÿþþÿÿÿÿþÿÿþÿÿþÿþþÿýþÿÿþÿÿýþÿýþÿÿÿþÿýþÿþþÿÿÿþÿÿþÿÿþþÿÿþÿÿÿþÿÿÿÿþþÿýþÿýþÿþþÿÿýþÿüþÿþþÿÿÿÿÿþÿþþÿþþÿÿýþÿûþÿýþÿÿÿþÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿþþÿþþÿÿþþÿþþÿÿþþÿÿþÿþÿþþÿÿþþÿÿÿþÿþþÿÿÿÿþÿÿÿÿÿþþÿüþÿýþÿÿÿþÿþþÿÿþÿþÿþþÿÿþþÿÿþÿÿþþÿþþÿÿýþÿþþÿÿþÿýþÿÿÿþÿÿþÿÿüþÿúþÿúþÿýþÿÿþÿÿþÿþþÿÿþÿÿþþÿÿþþÿÿþÿþÿþþÿþþÿüþÿþþÿÿþÿýþÿÿþÿÿÿÿþÿüþÿþþÿþþÿþþÿÿþþÿþþÿþþÿþþÿÿþÿÿÿþÿüþÿúþÿýþÿÿþþÿþþÿÿþÿÿÿÿÿÿýþÿÿþÿþÿþþÿÿþþÿÿÿþÿþþÿþþÿÿþþÿüþÿýþÿÿþÿÿþþÿþþÿýþÿþþÿÿþÿþþÿÿþÿÿþþÿÿÿþÿþþÿÿþÿÿÿþÿþþÿþþÿÿþÿÿÿÿþÿÿÿþÿÿÿÿÿûþÿûþÿÿþÿÿÿþþÿÿþÿÿþþÿþþÿÿþÿÿÿÿÿÿþÿÿþþÿýþÿýþÿÿÿþÿÿþÿÿÿÿþÿÿÿÿÿÿþÿÿþÿÿÿþÿþþÿÿþÿþÿþþÿÿþÿÿþþÿüþÿþþÿþÿýþÿþþÿÿÿÿþÿÿÿÿÿÿþÿÿþÿÿýþÿÿþÿÿÿþÿÿÿþÿýþÿüþÿÿÿþÿÿÿþÿýþÿÿþÿþÿýþÿþþÿÿÿþÿÿþÿÿþÿýþÿþþÿÿÿþÿýþÿüþÿþþÿÿþÿþþÿþþÿÿÿÿÿÿÿþÿþþÿÿÿþÿýþÿýþÿþþÿÿþÿÿþþÿýþÿýþÿÿþÿÿþÿÿÿþÿþþÿÿþÿÿþþÿÿþÿÿÿÿþÿÿþÿÿÿÿþÿÿÿÿþÿþþÿÿþÿþÿÿþþÿýþÿþþÿÿÿþÿÿþþÿûþÿüþÿþþÿÿþÿþþÿþþÿÿÿÿÿÿÿÿþÿþþÿþþÿÿþÿþþÿÿþÿÿÿþÿÿþÿÿÿþÿÿÿþÿÿþÿÿÿÿÿþÿÿýþÿûþÿÿýþÿüþÿüþÿüþÿÿþÿþÿþþÿÿÿÿÿÿÿþÿþþÿþþÿÿÿþÿþþÿÿÿþÿþþÿÿýþÿüþÿÿþÿÿÿþÿþþÿþþÿýþÿþþÿþþÿýþÿþþÿÿÿþÿýþÿþþÿÿþÿÿþÿÿÿþÿÿÿÿÿÿþÿÿþþÿþþÿÿþþÿþþÿþþÿÿþÿÿÿÿþþÿüþÿþþÿÿÿþÿÿþþÿýþÿüþÿýþÿþþÿÿÿþÿÿþÿÿþÿÿþÿþþÿýþÿýþÿÿþÿÿþþÿÿþÿÿÿþÿÿÿÿþÿÿþþÿýþÿÿÿþÿÿþÿÿþÿÿþÿýþÿûþÿüþÿÿÿþÿÿÿþÿÿÿÿÿþÿÿþÿÿÿþÿþþÿþþÿÿþÿþÿÿþÿÿÿþÿÿþþÿÿþÿÿþÿÿþþÿþþÿÿþÿÿÿÿÿþþÿÿþÿÿþþÿÿÿÿÿüþÿûþÿýþÿþþÿýþÿûþÿþþÿÿüþÿýþÿÿþþÿþþÿÿþÿÿþþÿÿþÿÿþþÿýþÿÿþÿÿÿþÿÿþþÿýþÿÿþÿþþÿýþÿþþÿÿÿþÿÿÿþÿÿþÿÿÿþÿýþÿþþÿÿýþÿþþÿÿÿÿþÿÿÿþÿýþÿÿÿþÿÿþÿÿÿþÿÿþþÿýþÿÿþÿþþÿýþÿÿþþÿÿþþÿÿþÿÿÿþÿÿÿþÿÿÿþÿÿþþÿûþÿþþÿÿþþÿÿýþÿÿþÿþÿýþÿþþÿýþÿþþÿÿýþÿÿþÿþÿÿþÿýþÿýþÿÿþÿþþÿÿþÿþÿüþÿÿþÿÿþþÿÿÿÿþþÿþþÿÿþÿÿÿþþÿþþÿÿýþÿûþÿüþÿÿÿÿþÿÿþÿÿÿþÿýþÿûþÿýþÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿÿþÿÿÿþÿÿþÿÿþÿÿÿþÿÿþÿÿÿÿþÿÿþÿÿþÿÿÿþÿÿþÿÿþþÿÿÿþÿÿÿÿÿÿþÿþþÿÿþþÿÿþÿþÿÿþÿÿþþÿþþÿÿþÿþþÿþþÿÿþÿÿÿÿÿÿÿÿþÿÿþþÿûþÿþþÿÿüþÿûþÿýþÿÿþÿÿýþÿüþÿüþÿþþÿÿÿÿþÿýþÿÿýþÿýþÿÿÿþÿÿþÿÿÿþÿÿþÿþþÿýþÿýþÿýþÿÿþþÿýþÿÿþÿþþÿýþÿýþÿýþÿþþÿÿÿþÿÿþÿÿÿþÿÿþÿÿþÿýþÿýþÿþþÿÿþÿÿÿþÿÿþÿÿýþÿÿþþÿûþÿûþÿüþÿÿÿþÿÿþÿþþÿýþÿÿþþÿÿþÿÿþþÿýþÿÿþÿÿÿþÿÿþÿÿþÿÿþÿÿÿþÿÿþÿÿþÿýþÿÿÿþÿÿþþÿüþÿÿÿþÿÿÿþÿÿþÿÿþÿÿþÿÿþÿþþÿýþÿÿþÿÿþþÿþþÿÿþÿÿþþÿüþÿûþÿûþÿÿþÿÿþþÿÿÿÿÿýþÿûþÿúþÿýþÿÿÿþÿþþÿþþÿÿþÿþÿþþÿÿþÿþÿþþÿþþÿÿÿþÿýþÿþþÿÿÿþÿÿÿÿÿþÿýþÿüþÿýþÿþþÿþþÿÿþÿþþÿÿÿÿþÿýþÿÿþþþÿýþÿþþÿÿþþÿýþÿÿþþÿÿþÿÿþÿÿÿÿüþÿüþÿýþÿþþÿÿþÿÿþþÿÿþÿÿýþÿÿþÿÿýþÿýþÿÿÿþÿÿÿþÿÿÿþÿþþÿÿÿþÿÿÿÿÿþþÿýþÿÿýþÿüþÿþþÿþþÿþþÿÿýþÿýþÿÿûþÿüþÿþþÿÿþÿÿþÿÿþÿÿþÿÿýþÿþþÿÿýþÿþþÿÿÿþÿÿÿþÿüþÿþþÿÿþþÿýþÿþþÿÿûþÿüþÿÿýþÿüþÿÿÿÿþÿýþÿþþÿÿþÿýþÿýþÿüþÿûþÿýþÿþþÿþþÿþþÿþþÿþþÿÿÿÿþÿÿþÿÿþþÿÿþÿÿþþÿþþÿþþÿÿþÿþÿýþÿýþÿÿüþÿûþÿýþÿÿÿÿÿþÿÿýþÿûþÿýþÿþþÿüþÿüþÿýþÿþþÿÿÿÿÿÿÿÿþÿþþÿÿþÿÿÿÿÿÿþþÿþþÿþþÿÿþÿÿþþÿýþÿýþÿþþÿÿþþÿûþÿûþÿþþÿÿÿþÿÿþÿÿÿþþÿüþÿýþÿÿþÿÿÿþþÿýþÿÿþþÿýþÿÿþÿÿÿþÿÿþÿÿÿþÿÿþÿÿÿþÿÿþÿÿþÿÿÿÿþÿþþÿÿþþÿþþÿÿþþÿÿþÿÿþÿÿþÿÿþþÿýþÿÿþÿÿþþÿÿþÿÿÿþÿÿþþÿýþÿýþÿýþÿÿþÿþþÿÿþÿÿÿþÿþÿþþÿþþÿÿÿÿÿþÿþþÿýþÿüþÿýþÿÿþþÿÿÿÿþÿÿÿþÿýþÿüþÿþþÿÿþþÿþþÿþþÿüþÿýþÿÿþÿÿÿÿÿÿþÿÿÿþÿÿþÿÿÿþÿýþÿüþÿþþÿÿþÿþþÿÿÿþÿþþÿÿþÿþþÿÿÿþÿþþÿÿÿþÿþþÿþþÿýþÿþþÿÿÿÿÿþÿÿÿÿþþÿþþÿÿþÿÿÿþþÿÿþÿþÿþþÿÿýþÿýþÿÿÿþÿýþÿÿþÿÿÿþÿÿÿÿÿþÿÿÿÿÿÿÿþÿýþÿüþÿþþÿÿÿþÿÿþÿÿÿþÿÿþÿÿÿþÿÿÿþÿýþÿüþÿüþÿþþÿÿþÿÿÿþÿþþÿþþÿþþÿÿÿÿþþÿÿþþÿþþÿþþÿþþÿÿþþÿÿþÿþÿþþÿÿþÿþÿÿÿÿþþÿÿÿÿþÿþþÿüþÿüþÿÿþÿÿÿÿþÿÿÿþÿÿþÿÿþþÿüþÿýþÿÿþþÿÿþþÿÿþÿþÿþþÿþþÿþþÿþþÿþþÿþþÿÿþþÿÿþþÿüþÿþþÿÿÿþÿÿþÿþÿýþÿÿþÿÿþÿÿþÿþþÿþþÿþþÿþþÿÿþÿÿýþÿüþÿýþÿÿýþÿýþÿÿþÿÿþÿüþÿüþÿÿýþÿüþÿþþÿÿþÿÿÿþÿÿþÿÿýþÿýþÿÿÿþÿÿþþÿûþÿûþÿûþÿþþÿÿþÿÿþÿÿþÿÿþÿÿþþÿüþÿûþÿûþÿþþÿÿÿþÿÿÿþÿÿþÿÿþþÿþþÿÿþÿÿþÿþþÿÿþÿþÿþþÿÿþÿÿÿÿÿþþÿÿþÿþÿýþÿÿþþÿýþÿÿÿÿÿþÿþÿÿÿÿÿþÿÿÿÿþÿÿÿþÿþþÿÿýþÿüþÿÿþÿþÿþþÿÿÿþÿÿÿÿþÿþþÿÿýþÿýþÿÿÿþÿþþÿýþÿþþÿÿýþÿþþÿÿÿþÿÿÿþÿÿþÿÿþÿÿþþÿÿþÿÿÿÿþÿÿþÿÿþÿÿþÿÿýþÿýþÿþþÿÿþÿÿÿÿÿÿþÿþþÿþþÿýþÿûþÿýþÿÿÿþÿÿÿÿÿÿþÿýþÿþþÿþþÿÿþÿÿýþÿüþÿþþÿÿÿÿÿÿÿÿÿÿÿÿþþÿÿþÿÿÿþÿÿÿþÿÿþþÿýþÿýþÿýþÿýþÿþþÿÿþÿÿÿþÿÿþÿÿÿÿþÿþþÿþþÿýþÿÿþþÿþþÿþþÿýþÿüþÿüþÿÿýþÿüþÿÿýþÿýþÿÿþþÿüþÿþþÿÿÿÿþÿýþÿýþÿþþÿÿÿþÿÿþÿÿÿþÿüþÿüþÿþþÿÿÿþÿÿÿþÿÿþÿÿÿÿþÿÿÿþÿýþÿþþÿÿÿþÿþþÿÿÿÿÿÿþÿÿþÿþÿýþÿýþÿÿÿþÿüþÿüþÿþþÿþÿþþÿÿýþÿüþÿüþÿþþÿþþÿÿþÿÿþÿýþÿýþÿÿÿþÿýþÿþþÿÿÿÿÿÿÿÿÿÿÿÿþþÿþþÿþþÿûþÿúþÿýþÿÿþÿþþÿÿÿþÿþþÿÿÿþÿÿÿþÿýþÿÿþÿÿþÿÿþÿÿþþÿýþÿÿþÿÿÿþþÿþþÿÿþÿþÿûþÿùþÿýþÿÿþÿÿÿÿþþÿýþÿýþÿþþÿÿÿÿÿÿþÿþþÿþþÿÿýþÿýþÿþþÿÿþÿþþÿýþÿüþÿþþÿþþÿýþÿüþÿÿþÿþÿþþÿÿÿÿþÿüþÿüþÿÿþÿþþÿüþÿýþÿÿþÿþþÿýþÿÿþÿÿýþÿýþÿÿÿþÿýþÿÿþÿÿþÿþþÿüþÿýþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿþÿþþÿþþÿÿÿÿþÿýþÿüþÿþþÿþþÿÿÿÿÿþþÿþþÿÿþþÿüþÿýþÿÿþþÿýþÿþþÿÿþÿþþÿÿþÿÿÿþÿÿÿÿÿÿûþÿûþÿýþÿþþÿýþÿüþÿýþÿÿþÿÿÿÿÿÿÿýþÿüþÿüþÿþþÿþþÿÿÿþÿþþÿÿþÿÿþÿþþÿÿþÿÿþÿþþÿÿÿÿþÿþþÿÿþÿÿÿþþÿÿþÿÿþþÿþþÿÿþÿþÿþþÿÿÿÿþÿÿÿþÿþþÿÿþÿþþÿÿþÿþÿÿþÿÿþþÿþþÿüþÿþþÿÿþþÿþþÿÿÿþÿþþÿýþÿýþÿüþÿÿþÿþÿüþÿÿþÿþÿûþÿúþÿüþÿüþÿüþÿýþÿÿþÿÿÿþÿÿÿÿÿÿÿÿÿÿþÿþþÿþþÿÿÿÿþÿþþÿþþÿÿþþÿþþÿÿÿÿÿÿÿþÿÿÿÿÿÿþÿþþÿÿÿÿÿþþÿþþÿþþÿþþÿþþÿÿÿÿÿþþÿþþÿþþÿþþÿþþÿÿþÿÿÿÿþÿÿþÿÿÿþÿÿþÿÿþÿÿþÿÿÿþÿÿþÿÿÿýþÿüþÿÿþÿÿþÿÿþÿÿþÿþþÿþþÿýþÿüþÿýþÿÿþÿÿÿÿÿþþÿþþÿýþÿÿþÿÿÿþÿÿþÿÿþÿÿÿþÿÿþÿÿþÿÿýþÿûþÿûþÿüþÿÿüþÿýþÿÿþþÿÿþÿÿþÿÿþÿÿÿþÿÿÿþÿÿþÿýþÿýþÿÿþÿÿþÿþþÿÿþÿþÿþþÿþþÿþþÿÿýþÿüþÿÿþÿþÿþþÿþþÿÿþÿÿÿþÿÿÿþÿÿþþÿýþÿÿþÿÿÿþþÿÿþÿÿÿýþÿüþÿýþÿÿÿÿþÿýþÿüþÿýþÿÿþþÿüþÿüþÿÿþþÿýþÿüþÿûþÿþþÿÿþÿÿþÿÿÿÿþÿÿÿþÿÿþÿÿÿþÿÿÿÿÿþÿÿÿþÿÿþÿÿÿþÿÿþÿþþÿýþÿýþÿýþÿýþÿÿÿþÿýþÿþþÿÿÿþÿÿÿþÿÿþþÿûþÿþþÿÿþÿüþÿüþÿþþÿÿÿþÿþþÿÿÿþÿýþÿüþÿþþÿÿÿÿþÿÿþÿÿÿþÿÿþþÿÿþÿÿþþÿÿþÿÿþþÿÿþÿÿþÿþþÿþþÿÿþþÿýþÿüþÿÿþÿÿþþÿÿþÿÿýþÿûþÿþþÿÿÿþÿÿÿþÿÿÿþÿÿþþÿýþÿýþÿÿþþÿþþÿÿüþÿûþÿûþÿþþÿÿÿþÿÿþÿÿþÿýþÿÿþÿÿÿþÿÿÿþÿÿÿÿÿþþÿÿÿþÿþþÿÿÿÿþÿþþÿÿýþÿüþÿüþÿýþÿÿþÿþÿþþÿþþÿÿÿÿþÿýþÿüþÿÿþÿÿÿÿþÿþþÿþþÿÿþÿÿþÿýþÿýþÿÿþþÿûþÿûþÿþþÿÿþþÿýþÿýþÿýþÿÿþÿÿÿþÿÿÿþÿÿüþÿüþÿÿÿþÿýþÿýþÿþþÿÿÿþÿÿýþÿûþÿþþÿÿýþÿþþÿÿýþÿþþÿÿýþÿýþÿÿþÿÿÿþÿþþÿüþÿþþÿÿþþÿþþÿýþÿÿþÿÿÿÿþþÿþþÿÿþþÿÿÿþÿüþÿûþÿüþÿþþÿÿÿþÿÿÿþÿþþÿþþÿþþÿÿþÿÿÿþþÿüþÿüþÿýþÿÿþÿÿÿÿþÿÿþÿÿÿþÿÿþÿþþÿÿþÿÿýþÿýþÿÿþÿÿÿÿÿþþÿÿþÿÿÿÿÿÿÿÿÿþÿÿþÿÿýþÿþþÿÿþþÿÿýþÿþþÿÿÿþÿÿÿÿþÿÿþÿÿþÿüþÿüþÿÿÿþÿÿÿþÿþþÿþþÿÿÿþÿþþÿÿÿÿþÿýþÿþþÿÿþÿÿþÿÿþþÿþþÿÿüþÿüþÿþþÿÿþÿþþÿÿÿþÿþþÿÿÿÿþÿûþÿûþÿÿþÿþÿþþÿþþÿÿÿþÿþþÿþþÿÿþÿÿþþÿýþÿþþÿÿþÿÿýþÿûþÿýþÿþþÿÿþÿÿþþÿþþÿÿþÿþþÿÿþÿÿþþÿÿþÿÿÿÿþÿÿþÿÿÿþÿÿþÿþþÿÿþÿÿüþÿþþÿÿýþÿýþÿýþÿýþÿÿþÿÿþþÿÿþÿÿÿþÿÿþþÿýþÿÿþÿÿÿýþÿýþÿÿýþÿýþÿÿþÿÿÿÿÿþÿÿýþÿþþÿþÿüþÿýþÿÿþþÿþþÿÿþÿþþÿÿþÿÿÿÿþÿýþÿýþÿþþÿýþÿýþÿÿÿþÿÿþþÿýþÿþþÿÿþÿÿþÿÿþÿýþÿýþÿþþÿÿþÿþþÿýþÿÿþÿþÿþþÿýþÿÿÿÿþþÿþþÿþþÿÿÿÿÿÿþÿÿþÿþÿþþÿÿþÿÿÿÿþÿÿÿþÿÿþÿÿþþÿýþÿþþÿüþÿúþÿþþÿÿþÿÿÿÿþÿÿþÿÿþþÿþþÿþþÿÿþÿþÿþþÿÿþÿÿÿþÿþþÿþþÿÿþÿþþÿýþÿþþÿÿþþþÿüþÿýþÿÿÿÿÿÿþþÿþþÿÿþÿÿÿÿÿÿÿÿÿþÿþþÿþþÿþþÿÿþÿþþÿüþÿþþÿÿÿÿÿþþÿþþÿÿÿÿÿÿþÿÿþÿþþÿýþÿþþÿÿþÿþÿþþÿþþÿýþÿýþÿþþÿþþÿÿþÿÿþþÿþþÿüþÿÿþÿÿþþÿÿþÿÿþÿÿþÿÿþÿÿÿþÿÿþÿÿþÿÿþÿÿþÿþþÿýþÿýþÿÿþÿÿýþÿÿþÿÿþÿþþÿýþÿýþÿýþÿýþÿþþÿÿþÿÿþÿÿÿþÿÿþÿÿýþÿýþÿÿþÿÿþÿÿÿþÿÿþÿÿÿþÿþþÿüþÿþþÿÿÿþþÿûþÿýþÿÿþÿÿÿýþÿüþÿþþÿÿÿÿÿÿÿÿþþÿüþÿûþÿýþÿÿþÿÿþþÿüþÿýþÿÿþÿÿÿþÿÿþÿÿþÿÿþÿÿÿþÿþþÿÿÿþÿþþÿýþÿýþÿÿÿþÿýþÿýþÿþþÿþþÿÿÿþÿþþÿÿÿÿÿÿþÿþþÿþþÿþþÿÿþÿþþÿÿþÿÿþþÿÿÿþÿýþÿÿþÿþÿýþÿÿþÿÿÿþÿÿþþÿýþÿþþÿÿÿþÿÿþÿÿþÿüþÿüþÿþþÿÿþÿþþÿýþÿýþÿþþÿÿþÿÿþÿÿÿþÿýþÿþþÿÿþÿÿþÿÿÿþÿÿþþÿþþÿÿÿþÿÿýþÿûþÿüþÿýþÿÿþþÿüþÿýþÿÿþÿþþÿþþÿÿþÿÿþÿþþÿþþÿÿÿÿþþÿþþÿÿþÿÿþþÿþþÿÿþÿÿþÿÿþþÿýþÿÿþÿÿþþÿýþÿÿþÿÿýþÿýþÿÿþþÿûþÿüþÿþþÿýþÿýþÿþþÿÿþþÿþþÿÿÿÿþÿÿþÿþþÿÿþÿÿÿÿþÿÿÿÿþÿÿÿþÿÿþÿÿÿþÿÿÿþÿþþÿÿÿþÿÿþÿþÿýþÿüþÿÿþÿÿÿþÿÿÿÿÿþÿÿÿþÿýþÿþþÿÿýþÿþþÿÿþÿÿþÿþþÿÿþÿÿþÿýþÿýþÿþþÿÿÿÿþÿýþÿýþÿÿýþÿýþÿÿþÿÿÿÿÿÿÿÿÿþÿýþÿûþÿüþÿÿþþÿýþÿÿþÿÿýþÿýþÿÿÿþÿþþÿÿþÿÿÿþÿýþÿþþÿÿþÿþþÿýþÿÿþÿÿÿÿÿÿÿÿÿþþÿþþÿÿþÿÿÿþþÿýþÿÿþÿÿÿþÿÿþÿÿþþÿþþÿýþÿÿÿÿÿþÿÿÿþÿÿÿþÿÿÿþÿþþÿÿÿþÿÿÿþÿüþÿûþÿüþÿÿþÿÿÿþÿÿþÿÿþþÿÿþÿÿþþÿÿþÿÿþþÿÿþÿÿþÿÿÿÿþþÿÿþÿÿÿÿþÿýþÿþþÿÿþþÿýþÿþþÿþþÿýþÿÿýþÿûþÿÿþÿÿÿÿþþÿþþÿÿýþÿýþÿþþÿÿþÿþþÿüþÿÿþþþÿüþÿÿþÿÿÿÿÿþÿýþÿÿþÿþÿüþÿüþÿþþÿÿÿþÿÿÿþÿýþÿþþÿÿÿþÿýþÿýþÿþþÿÿÿþÿÿþÿþþÿÿþþÿúþÿúþÿüþÿÿþÿþÿÿþÿÿÿþÿÿþÿÿÿþÿþþÿÿÿþÿýþÿüþÿûþÿüþÿþþÿÿþÿÿþÿÿþÿþþÿýþÿýþÿÿþÿÿþÿÿþþÿýþÿÿþÿÿÿÿÿÿýþÿúþÿúþÿýþÿþþÿýþÿüþÿüþÿþþÿÿþþÿÿþÿÿþÿýþÿýþÿÿÿþÿÿþÿÿÿþÿÿþÿÿÿþÿÿÿþÿÿþÿÿÿüþÿûþÿÿÿþÿÿþÿÿÿþþÿýþÿýþÿþþÿÿþÿÿÿÿÿÿþþÿüþÿüþÿýþÿýþÿÿÿÿÿþÿÿþþÿÿþÿÿÿþÿÿþþÿÿþÿÿþÿÿþÿÿÿþÿÿþþÿÿþÿÿÿþÿÿýþÿýþÿÿþÿÿÿþþÿÿþÿþþÿüþÿýþÿÿþÿÿÿÿÿÿþþÿþþÿÿþÿÿÿÿÿÿýþÿüþÿÿþÿþÿÿýþÿüþÿÿÿþÿÿÿÿþÿÿþÿÿÿþÿÿþÿÿÿþÿÿÿþÿÿÿþÿÿþÿÿþÿýþÿÿþÿÿþþÿþþÿýþÿþþÿÿþÿÿþþÿÿþþÿýþÿÿþþÿþþÿÿÿþÿÿüþÿþþÿÿÿþÿÿüþÿûþÿûþÿþþÿÿþÿþþÿûþÿýþÿþþÿÿþþÿýþÿýþÿþþÿÿýþÿýþÿþþÿÿþÿÿÿÿþÿÿþÿþÿýþÿþþÿÿÿÿÿþÿýþÿüþÿþþÿÿÿÿþÿýþÿýþÿüþÿüþÿÿþÿÿÿÿÿÿÿÿþÿþþÿÿÿþÿÿþÿþÿþþÿÿþþÿÿþÿÿÿþÿÿÿþþÿýþÿÿþþÿÿþÿþÿüþÿüþÿþþÿþþÿþþÿÿÿÿÿÿþÿýþÿûþÿþþÿÿÿþÿÿþþÿþþÿýþÿÿÿþÿþþÿþþÿýþÿþþÿþþÿþþÿÿÿÿÿÿÿÿÿÿþÿýþÿüþÿÿÿþÿÿÿþÿþþÿÿÿÿþÿýþÿÿþþþÿüþÿÿÿÿþÿûþÿýþÿÿýþÿüþÿþþÿþþÿþþÿÿþÿÿþþÿÿþÿÿÿÿÿÿÿþÿþþÿýþÿüþÿûþÿÿþÿÿÿþÿÿÿÿÿþÿþþÿÿÿÿÿÿþÿþþÿÿÿþÿþþÿÿþÿÿÿÿÿþÿþþÿþþÿÿþÿÿþþÿÿþþÿýþÿÿþÿÿþÿÿÿþÿÿþÿýþÿüþÿþþÿÿþÿþþÿþþÿþþÿÿþÿÿÿþþÿüþÿüþÿýþÿÿþÿÿÿÿÿÿÿþÿþÿûþÿüþÿÿÿþþÿýþÿÿþÿÿÿÿþÿÿÿÿÿÿÿþþÿÿþÿÿþþÿýþÿÿþÿÿÿþÿþÿýþÿÿýþÿþþÿÿÿþÿÿþÿÿþÿÿþþÿýþÿÿþþÿþþÿüþÿýþÿÿþþÿÿþÿÿÿÿÿÿÿþþÿÿÿÿþþÿÿþÿþþÿýþÿýþÿüþÿþþÿÿÿþÿþþÿÿÿÿÿÿÿÿþþÿþþÿüþÿûþÿúþÿüþÿþþÿþþÿÿÿþÿüþÿþþÿÿÿÿþÿÿþÿýþÿüþÿýþÿÿþÿÿÿþÿÿþÿÿÿþÿÿÿþÿÿÿþÿÿüþÿûþÿýþÿþþÿýþÿÿþþÿýþÿÿþþÿýþÿÿþÿÿÿþþÿüþÿýþÿþþÿþþÿÿÿÿþþÿÿþÿÿþÿÿÿþÿþþÿþþÿÿÿÿÿÿþÿþþÿþþÿþþÿÿÿþÿþþÿÿÿþÿÿþÿýþÿþþÿÿÿþÿÿÿþÿÿýþÿýþÿýþÿúþÿüþÿÿþÿÿþÿÿþÿÿÿþÿÿþÿÿÿÿþÿþþÿÿþÿÿþÿÿþÿÿþÿÿÿþÿÿþÿÿþþÿþþÿÿþÿÿÿþÿüþÿüþÿýþÿýþÿÿþÿÿÿþÿÿþÿÿÿÿÿþþÿþþÿÿþÿþÿýþÿÿþÿþÿýþÿþþÿþþÿþþÿÿþþÿþþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿÿþÿÿþþÿÿþÿÿÿþþÿüþÿýþÿÿþÿÿþþÿüþÿýþÿÿýþÿÿþÿþÿÿÿþÿûþÿþþÿþþÿÿþÿÿÿþÿÿýþÿþþÿþÿþþÿÿüþÿÿþÿÿÿþÿÿÿÿþÿÿþÿþþÿüþÿýþÿÿÿþÿÿÿÿÿþÿþþÿýþÿÿþÿÿÿþÿÿÿÿÿþÿÿÿÿÿþÿÿÿÿÿþþÿÿþÿÿþÿÿÿþÿÿþÿÿÿÿþþÿþþÿÿÿÿÿÿÿþÿÿÿÿÿþÿÿÿÿÿÿþÿûþÿýþÿÿÿÿÿÿÿþÿÿþþÿþþÿÿÿÿÿÿÿÿÿþþÿþþÿþþÿýþÿüþÿþþÿÿþÿýþÿüþÿýþÿþþÿýþÿþþÿÿÿþÿÿÿþÿýþÿýþÿýþÿþþÿÿÿþÿÿþÿþþÿúþÿùþÿüþÿÿþþÿýþÿýþÿÿþÿþþÿûþÿûþÿÿýþÿüþÿýþÿþþÿüþÿûþÿÿÿþÿÿþþÿýþÿýþÿÿþþÿúþÿþþÿÿýþÿÿþÿÿþÿþþÿÿþÿÿÿÿÿþÿÿþÿýþÿýþÿþþÿÿþÿÿþþÿÿþÿÿÿÿþÿÿþÿþþÿýþÿþþÿþþÿþþÿþþÿÿþÿÿÿþÿÿþþÿÿÿþÿþþÿÿÿÿÿÿÿþÿüþÿÿþÿþÿÿþÿþÿÿÿÿÿÿþÿýþÿüþÿþþÿÿÿÿÿþÿÿÿÿÿÿþÿþþÿÿþÿÿÿÿþÿÿþÿþþÿþþÿÿÿÿþþÿÿÿþÿÿþÿþÿÿÿþÿýþÿÿÿþÿÿþÿÿÿþÿÿþÿÿþþÿýþÿÿþþÿÿþÿÿÿþÿÿþþÿüþÿþþÿÿþÿÿþÿþþÿþþÿÿýþÿúþÿýþÿþþÿýþÿýþÿÿþÿÿþþÿþþÿýþÿÿþÿÿþþÿüþÿüþÿÿüþÿýþÿüþÿûþÿþþÿþÿýþÿüþÿýþÿýþÿÿÿþÿÿþÿþÿýþÿþþÿþþÿüþÿþþÿÿþÿþþÿÿþÿÿþþÿüþÿýþÿÿþÿþÿÿþÿÿýþÿÿþÿþÿüþÿþþÿþþÿÿþÿþÿüþÿýþÿþþÿÿþÿÿþÿÿÿþÿÿþÿÿÿþÿýþÿÿþþþÿûþÿüþÿþþÿÿþÿÿþÿÿÿþÿýþÿýþÿþþÿÿþÿÿþÿÿÿþÿÿþÿÿÿÿÿþÿÿÿþÿüþÿÿþÿþÿýþÿÿþþÿÿýþÿûþÿýþÿÿþÿÿþÿÿþþÿýþÿüþÿûþÿüþÿÿþÿÿþÿÿþÿÿþþÿýþÿÿþÿÿþþÿÿþÿÿÿÿþÿüþÿÿþÿþÿüþÿþþÿþþÿÿþÿþÿþþÿþþÿþþÿÿÿþÿÿþþÿûþÿþþÿÿþÿþþÿýþÿÿþÿÿþþÿÿþþÿýþÿþþÿýþÿþþÿÿþÿþþÿÿýþÿüþÿþþÿÿÿÿÿþÿÿþÿüþÿþþÿÿÿÿþÿÿÿÿÿÿÿþÿýþÿýþÿÿþÿÿþÿþþÿýþÿýþÿþþÿýþÿÿþÿþÿüþÿýþÿÿþÿÿÿÿþÿÿþÿþþÿýþÿþþÿÿÿþÿÿÿÿÿÿÿþÿþþÿþþÿÿþÿþþÿÿÿþÿÿÿþÿþþÿÿÿþÿþþÿÿþÿþÿÿþÿþþÿþþÿýþÿþþÿÿþÿþÿüþÿýþÿÿÿþþÿÿþÿþÿüþÿüþÿýþÿÿþÿÿÿÿþþÿýþÿÿþÿÿÿþÿþþÿüþÿýþÿÿûþÿúþÿþþÿÿÿþÿÿþþÿÿþÿÿÿþÿÿÿÿÿþÿÿþÿþþÿþþÿþþÿþþÿüþÿüþÿþþÿýþÿþþÿÿÿþÿÿÿÿþÿýþÿüþÿÿÿþÿýþÿþþÿÿÿÿþÿýþÿþþÿÿþÿþþÿýþÿÿþÿÿÿÿÿÿÿþÿþþÿÿÿþÿþþÿÿþÿÿÿþÿüþÿýþÿþþÿþþÿýþÿþþÿÿýþÿýþÿÿþÿÿþÿÿÿÿÿÿþÿÿÿþÿüþÿüþÿÿþþÿþþÿÿÿþÿÿþÿýþÿþþÿÿÿþÿÿþÿÿþÿýþÿÿþÿþþÿþþÿþþÿÿþÿÿÿþþÿýþÿþþÿÿÿÿþÿýþÿþþÿÿþÿÿþÿÿþÿÿþÿÿÿþÿÿþÿþþÿþþÿÿþþÿÿþþÿþþÿþþÿýþÿüþÿýþÿÿÿÿþþÿþþÿþþÿþþÿÿÿþÿþþÿÿþÿþþÿÿþÿÿÿýþÿûþÿýþÿÿþþÿÿþÿþÿÿþÿÿÿþÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿþÿþþÿÿþÿþÿüþÿÿþÿþÿþþÿÿÿþÿÿþÿÿþÿÿÿþÿþþÿþþÿþþÿýþÿÿþÿÿÿþÿÿþÿÿþþÿýþÿÿþÿÿÿÿþþÿþþÿÿþÿÿÿþÿüþÿüþÿÿþÿÿÿþÿþþÿÿþÿÿÿÿÿÿþÿÿÿÿþÿþþÿÿþÿÿÿþÿÿþÿþþÿýþÿþþÿÿþþÿýþÿÿþÿÿüþÿýþÿÿþÿþþÿüþÿýþÿþþÿÿþÿþþÿÿÿÿþÿþþÿüþÿüþÿÿþþÿþþÿÿÿÿþÿÿþÿÿþÿÿÿþÿþþÿÿÿþÿÿÿþÿÿþÿÿÿÿþÿÿþÿþþÿÿþþÿüþÿþþÿÿýþÿýþÿÿþÿÿÿÿÿÿÿþÿþþÿÿýþÿüþÿþþÿÿÿþÿÿþÿÿþÿÿþÿýþÿýþÿÿÿÿþÿÿþÿÿÿþÿÿÿþÿýþÿýþÿýþÿÿþÿÿÿþÿÿþÿÿÿþÿÿÿþÿÿþÿÿÿþÿÿÿþÿýþÿþþÿÿþÿýþÿýþÿýþÿýþÿÿþÿÿþÿÿþÿÿüþÿùþÿûþÿþþÿþþÿüþÿûþÿýþÿþþÿþþÿþþÿþþÿþþÿÿþÿÿÿÿÿÿÿÿÿþÿþþÿÿþÿþÿþþÿÿþþÿþþÿþþÿþþÿÿþÿÿÿÿþÿþþÿÿÿþÿÿþÿýþÿþþÿÿýþÿýþÿýþÿýþÿýþÿýþÿýþÿÿþÿÿýþÿÿþÿÿþþÿÿþÿÿþÿÿÿÿÿÿþÿþþÿÿÿþÿÿþÿÿÿþÿÿþÿÿÿþÿÿþÿÿÿþÿÿþÿÿÿþÿÿþÿÿþÿýþÿÿÿþÿÿþþÿþþÿÿÿþÿÿþÿþþÿýþÿýþÿÿþÿÿÿþÿÿþÿÿþþÿýþÿÿþÿÿþþÿþþÿþþÿþþÿþþÿÿÿÿÿÿþÿÿÿÿýþÿþþÿÿÿÿþÿÿþÿÿÿþÿÿÿþÿÿÿþþÿýþÿÿþÿÿÿþÿÿþÿÿÿþÿÿÿþÿÿþþÿýþÿÿþÿÿüþÿüþÿûþÿýþÿÿÿþÿþþÿüþÿüþÿÿþÿÿþÿÿþÿÿÿþÿÿþÿÿÿþÿÿÿþÿýþÿÿþÿÿÿþÿÿþÿÿÿþÿýþÿýþÿüþÿýþÿþþÿýþÿþþÿÿÿÿþÿþþÿÿýþÿþþÿÿÿþÿþþÿþþÿÿÿÿþþÿþþÿÿþÿþÿüþÿýþÿÿÿþþÿþþÿÿÿÿþÿþÿüþÿüþÿÿþÿÿÿþÿýþÿþþÿýþÿþþÿÿÿþÿÿÿÿþÿþþÿÿþÿÿÿÿþÿÿþÿÿÿÿÿþÿÿÿÿþþÿüþÿüþÿÿþÿÿþÿþþÿÿÿþÿþþÿÿþÿÿþÿÿþÿÿýþÿýþÿýþÿýþÿýþÿýþÿÿþÿþþÿüþÿýþÿþþÿþþÿüþÿýþÿÿþÿÿÿÿþþÿüþÿÿþÿÿþþÿþþÿÿþÿÿþþÿÿþÿÿÿþþÿýþÿÿþÿÿÿþÿýþÿüþÿüþÿÿÿþÿýþÿþþÿÿþÿþÿüþÿûþÿþþÿÿþÿÿÿþÿþþÿÿÿÿÿÿþÿÿþþÿÿþÿþÿüþÿýþÿþþÿþþÿÿþÿÿÿþÿþþÿüþÿÿÿþÿþþÿÿþÿÿþÿþþÿÿþÿÿÿÿþÿÿÿÿÿþÿþþÿþþÿÿþþÿþþÿÿþÿÿÿÿÿþþÿþþÿþþÿþþÿþþÿÿÿÿÿÿþÿÿÿÿþÿÿþÿþþÿÿþÿÿþþÿÿÿþÿÿþÿþþÿÿþÿÿÿÿÿþÿýþÿüþÿýþÿÿÿÿÿÿÿÿÿÿþþÿÿþÿÿþþÿÿþÿÿþþÿþþÿþþÿþþÿþþÿÿþÿÿþþÿÿþÿÿýþÿýþÿþþÿÿþÿÿÿþÿþþÿÿþþÿþþÿÿÿÿÿÿÿÿþþÿÿþÿÿÿþÿÿÿþÿÿÿþÿÿþÿþþÿþþÿÿÿþÿÿÿþÿÿþþÿûþÿþþÿÿÿýþÿþþÿþÿüþÿÿÿþÿÿþþþÿûþÿûþÿþþÿÿÿÿþÿþþÿþþÿÿÿþÿýþÿþþÿÿþþÿþþÿÿÿþÿÿÿþÿÿüþÿýþÿþþÿþþÿÿþÿþÿýþÿüþÿþþÿþþÿþþÿþþÿÿþÿÿÿÿÿþþÿÿþþÿüþÿýþÿýþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿüþÿûþÿÿÿþÿÿÿþÿÿÿþÿÿþþÿýþÿþþÿÿþÿÿÿÿÿÿÿÿÿÿÿþþÿÿþÿÿÿþÿÿþÿÿÿÿÿþÿÿÿÿÿþÿÿÿþÿÿÿÿÿþÿþþÿÿþÿþþÿüþÿûþÿýþÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿýþÿþþÿýþÿýþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿÿþÿÿþÿÿÿþÿÿþÿÿÿþÿÿþÿÿýþÿýþÿÿÿþÿÿþÿÿÿÿüþÿüþÿýþÿþþÿþþÿþþÿÿþÿÿÿÿÿÿýþÿüþÿÿþÿþÿþþÿÿÿÿþÿþþÿþþÿÿÿÿÿÿÿÿÿÿþÿÿþÿþÿýþÿþþÿÿþÿÿüþÿýþÿÿüþÿþþÿþþÿýþÿÿþÿÿÿÿþÿÿþÿÿÿÿþÿþþÿÿÿþÿÿÿþÿÿÿþÿÿÿþÿþþÿÿÿþÿþþÿÿÿþÿþþÿÿÿþÿþþÿÿÿþÿÿþÿÿþþÿüþÿüþÿþþÿÿþÿþþÿþþÿüþÿüþÿýþÿþþÿþþÿÿþþÿþþÿþþÿþþÿÿþþÿþþÿÿþÿþþÿþþÿÿþÿÿþþÿÿþÿÿÿþÿÿþÿÿþÿÿÿþÿþþÿÿþÿÿÿÿÿþÿÿþÿÿþþÿýþÿýþÿÿþÿþÿþþÿþþÿÿþÿÿÿþÿÿþÿÿÿþÿÿþÿÿÿþÿþþÿýþÿÿþÿÿÿþþÿÿþÿÿÿþÿÿÿþþÿýþÿýþÿýþÿþþÿÿþÿÿÿÿþÿÿþÿÿüþÿùþÿúþÿýþÿûþÿüþÿÿýþÿýþÿþþÿÿþÿÿÿþþÿúþÿûþÿÿÿÿÿÿÿÿþþÿþþÿþþÿþþÿþþÿÿÿÿÿþÿþþÿÿþÿþÿüþÿýþÿÿþÿÿþþÿþþÿüþÿüþÿÿþÿÿÿÿÿÿÿÿþþÿþþÿÿÿþþÿüþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþþÿûþÿþþÿÿÿþÿÿüþÿýþÿþþÿþþÿþþÿÿÿþÿýþÿþþÿÿÿþÿÿþÿÿþÿþþÿÿþÿÿÿÿþÿÿþÿýþÿýþÿýþÿþþÿÿþÿÿþÿÿÿþÿÿÿþÿÿþÿÿþÿýþÿýþÿþþÿÿÿþÿÿþÿÿÿþÿÿþÿÿþþÿÿÿþÿÿþÿýþÿýþÿÿÿþÿÿþþÿýþÿÿþÿÿþÿþþÿÿþÿÿþÿÿþþÿüþÿýþÿþþÿÿÿþÿÿýþÿýþÿÿþÿÿÿÿþÿÿÿÿÿþþÿþþÿÿþÿÿÿÿÿÿÿþÿÿÿþÿÿþþÿûþÿþþÿÿþÿÿþÿÿÿþÿÿþÿÿÿÿþÿþþÿÿþÿþþÿþþÿÿþÿÿÿÿþþÿýþÿÿþÿÿþÿþþÿýþÿÿþÿÿýþÿþþÿÿÿþÿþþÿÿþÿÿþÿÿþÿýþÿûþÿýþÿÿÿþÿþþÿÿÿþÿýþÿûþÿúþÿþþÿÿþÿÿþÿÿÿþÿÿþÿþþÿþþÿÿÿÿÿÿþÿýþÿüþÿþþÿÿÿþÿýþÿýþÿþþÿÿþÿÿþÿÿÿþÿÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿþþÿÿþÿÿÿÿÿÿþÿþþÿþþÿþþÿÿÿþÿþþÿÿþÿýþÿþþÿÿÿþÿÿÿþÿþþÿÿþÿýþÿüþÿÿÿþÿþþÿÿÿþÿýþÿýþÿýþÿÿþÿÿþÿÿÿþÿÿþþÿýþÿýþÿýþÿÿþÿÿþÿÿþþÿûþÿüþÿþþÿÿÿþÿþþÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿÿÿþÿþþÿþþÿÿÿþÿþþÿþþÿÿÿÿÿÿÿÿÿþÿþþÿþþÿÿÿÿÿÿÿþÿþþÿÿþÿÿÿþÿþþÿþþÿþþÿÿÿÿþþÿþþÿÿþÿÿÿÿÿýþÿüþÿüþÿþþÿÿÿþÿÿþÿÿþþÿûþÿýþÿÿþþÿÿÿþÿÿþþÿþþÿÿþÿÿÿÿþþÿþþÿþþÿÿþÿÿþþÿÿþÿÿþþÿÿþÿÿÿþþÿÿþÿÿþþÿüþÿýþÿÿþþÿÿþÿÿþþÿýþÿÿÿÿþþÿýþÿýþÿþþÿÿÿÿÿÿÿÿþþÿÿþÿÿþÿþþÿÿþÿÿÿÿÿþþÿþþÿÿþÿÿþþÿÿþÿÿþþÿÿÿþÿþþÿÿÿþÿþþÿÿþÿÿþÿÿþþÿýþÿýþÿÿþÿÿþþÿÿþÿÿÿþÿþÿÿþÿÿþÿÿþþÿûþÿþþÿÿÿÿþÿüþÿýþÿþþÿþþÿÿþÿÿÿþÿÿÿþÿþþÿþþÿþþÿþþÿÿþÿÿþþÿÿþÿÿþþÿþþÿÿþÿÿÿÿÿÿÿÿÿýþÿüþÿýþÿÿþÿÿþþÿýþÿÿþÿÿþÿÿþÿÿÿþþÿûþÿüþÿÿþÿÿÿþþÿýþÿûþÿûþÿúþÿýþÿþþÿÿþþÿûþÿýþÿÿýþÿüþÿüþÿÿþÿþÿýþÿÿþÿþÿÿþÿÿýþÿýþÿýþÿþþÿÿÿþÿÿÿþÿýþÿûþÿüþÿÿþÿþÿþþÿþþÿþþÿÿþÿÿþþÿÿþÿÿþþÿþþÿþþÿþþÿÿÿþÿÿÿÿÿÿþÿÿÿÿÿÿÿÿþÿÿþÿþþÿÿþÿÿÿþÿÿþþÿüþÿüþÿÿþÿþÿþþÿÿÿþÿýþÿüþÿþþÿÿÿÿÿÿÿÿÿÿþþÿÿþÿþÿþþÿÿþÿÿÿÿÿþþÿÿþÿÿÿÿÿÿýþÿüþÿüþÿüþÿÿþþþÿüþÿüþÿýþÿüþÿþþÿÿþþÿÿÿÿÿýþÿÿþÿþÿüþÿÿÿþÿþþÿÿÿþÿÿÿþÿþþÿÿÿÿÿÿÿÿÿþþÿüþÿÿþÿÿþþÿÿÿþÿÿÿÿÿÿþÿÿÿÿÿþÿÿÿÿÿÿÿÿþÿÿþÿÿþþÿýþÿýþÿýþÿýþÿûþÿüþÿÿÿþÿþþÿÿþþÿüþÿÿþþþÿþþÿÿþþÿþþÿÿþþÿþþÿÿýþÿÿþÿÿþÿýþÿÿÿþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿÿÿþÿýþÿÿþþÿÿþþÿÿþÿþÿÿþÿþÿþþÿÿÿþÿýþÿÿþÿÿÿþÿÿþÿÿÿþÿÿþÿÿÿþÿÿþÿÿýþÿýþÿÿÿþÿÿþÿÿÿþÿýþÿÿþÿþÿýþÿþþÿþþÿÿÿþÿþþÿþþÿÿÿþÿþþÿÿþÿýþÿþþÿÿüþÿþþÿÿþþÿþþÿþþÿþþÿþþÿÿþÿÿÿÿÿÿÿýþÿþþÿÿÿþÿÿÿÿþÿÿÿþÿýþÿþþÿÿÿþÿÿÿþÿýþÿþþÿþþÿÿþÿþþÿþþÿÿÿÿÿÿþÿýþÿþþÿÿÿþÿÿþÿÿÿþÿþþÿÿþÿÿÿþÿÿþÿÿüþÿûþÿýþÿÿþÿþþÿþþÿÿþÿÿÿþÿûþÿýþÿÿþþÿÿÿþÿþþÿÿÿþÿÿþþÿþþÿÿþþÿþþÿÿÿþÿÿþÿÿþÿýþÿýþÿýþÿþþÿÿÿþÿÿþÿÿþÿýþÿÿþÿÿþÿÿþÿÿþÿÿÿýþÿýþÿÿÿþÿÿþÿÿþÿÿþÿÿþÿÿÿþÿÿÿþÿÿÿþÿÿÿþÿÿþÿýþÿüþÿÿýþÿÿþÿþÿþþÿÿþþÿÿþþÿÿþÿþÿþþÿÿÿÿþÿýþÿþþÿÿÿÿÿÿþÿÿÿÿÿþÿÿÿÿÿÿÿÿþÿÿþÿÿÿþÿþþÿÿÿþÿþþÿÿÿþÿþþÿÿÿþÿþþÿÿÿþÿýþÿüþÿþþÿÿÿÿþÿýþÿÿÿþÿýþÿþþÿÿÿþÿýþÿþþÿÿþþÿþþÿÿÿþÿÿÿþÿþþÿþþÿÿþÿþþÿÿþÿÿÿÿþÿÿþÿÿÿþÿþþÿþþÿÿþÿÿÿÿÿÿþÿÿþÿÿÿþÿýþÿÿþÿÿþþÿÿþÿÿÿþÿÿþÿÿþþÿþþÿÿþÿþÿýþÿýþÿÿÿþÿþþÿýþÿüþÿüþÿþþÿþþÿþþÿþþÿÿÿþÿþþÿÿþÿÿþÿÿþÿÿýþÿÿþÿÿÿþÿÿþþÿýþÿÿþÿÿÿÿÿÿÿÿþÿþþÿþþÿÿþÿÿÿÿÿÿÿÿþÿûþÿúþÿýþÿÿþþÿþþÿÿþþÿûþÿûþÿÿýþÿûþÿÿþþÿÿþÿÿÿþÿÿÿÿÿþÿþþÿþþÿÿþÿþÿüþÿÿþÿþÿþþÿþþÿÿÿþÿþþÿÿÿÿþÿþþÿþþÿþþÿÿþÿþÿþþÿþþÿÿþÿÿÿþÿýþÿþþÿÿÿÿþÿÿÿþÿüþÿûþÿüþÿÿÿþÿýþÿþþÿÿÿþÿÿþÿÿþÿþþÿýþÿýþÿýþÿýþÿýþÿþþÿÿÿþÿÿþÿþþÿýþÿýþÿÿþÿÿþþÿÿþÿÿþÿÿÿÿþÿÿþÿÿþÿÿþÿÿþÿÿÿþÿþþÿþþÿÿþþÿýþÿÿþÿÿþÿÿþÿÿþÿÿþþÿûþÿüþÿÿþÿÿþÿÿþÿÿþþÿýþÿÿþÿÿþþÿÿþÿÿþþÿþþÿüþÿýþÿÿþþÿÿþÿÿÿþþÿýþÿÿÿÿþÿþþÿÿþÿÿþÿþþÿýþÿþþÿÿÿþÿÿÿþÿÿþÿþþÿýþÿÿÿþÿÿþÿÿþÿýþÿþþÿÿýþÿþþÿÿÿþÿýþÿüþÿüþÿýþÿÿþÿÿÿÿþÿþþÿÿþÿÿþþÿþþÿþþÿþþÿÿþÿÿÿþÿýþÿþþÿþþÿýþÿÿþÿÿÿþþÿýþÿüþÿýþÿÿÿÿþÿýþÿÿþÿþÿýþÿþþÿýþÿþþÿþþÿþþÿÿþÿÿþþÿÿþÿÿÿÿþÿþþÿÿþÿþþÿþþÿÿþþÿÿþÿÿÿþÿþÿüþÿýþÿÿýþÿüþÿÿþÿþÿþþÿÿýþÿýþÿþþÿÿÿþþÿþþÿÿþþÿþþÿÿþÿÿþÿÿÿþÿþþÿýþÿþþÿÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿýþÿþþÿÿûþÿüþÿþþÿÿÿþÿþþÿþþÿÿýþÿüþÿþþÿýþÿþþÿÿÿÿþÿþþÿÿþþÿþþÿÿþÿÿþÿÿÿþþÿýþÿÿþÿÿÿÿþþÿþþÿþþÿþþÿÿþþÿÿþÿþÿýþÿÿþþÿÿþÿþÿþþÿÿÿþÿÿþÿÿþþÿýþÿþþÿÿýþÿÿþÿÿþÿþþÿýþÿýþÿýþÿþþÿÿþÿÿÿþÿÿþÿÿþÿÿþÿÿþþÿÿþÿÿþþÿÿþÿÿÿþÿÿÿþÿþþÿÿÿþÿÿþþÿýþÿÿÿþÿÿþÿÿÿÿþÿýþÿþþÿÿþÿþÿþþÿþþÿýþÿüþÿþþÿÿÿÿÿÿþþÿþþÿÿþÿþþÿþþÿÿþÿþþÿþþÿýþÿÿþÿÿÿþÿÿþþÿþþÿÿÿþÿÿÿþÿÿÿþÿÿÿþÿþþÿÿýþÿüþÿýþÿþþÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿüþÿúþÿýþÿÿþÿÿÿÿÿÿýþÿüþÿÿþþÿþþÿþþÿýþÿþþÿþþÿýþÿÿþÿþþÿýþÿÿþÿÿÿÿÿýþÿüþÿÿþÿÿÿÿþÿýþÿÿþÿþÿýþÿÿþÿÿþþÿþþÿÿþÿÿÿþþÿþþÿÿþþÿÿþÿþÿüþÿÿþÿÿÿÿþÿýþÿýþÿþþÿÿþþÿÿýþÿþþÿÿþÿüþÿûþÿüþÿÿÿþÿþþÿÿÿÿÿÿþÿþþÿÿþÿÿÿþÿÿþÿÿýþÿþþÿÿÿÿþÿÿÿþÿýþÿÿýþÿþþÿÿüþÿþþÿÿÿÿÿÿþÿÿþÿÿÿþÿÿÿþÿÿþÿÿÿÿþÿÿþÿÿÿÿþÿÿþÿÿþþÿÿÿþÿÿþÿþÿÿÿþÿþþÿÿÿþÿþþÿþþÿÿÿÿÿÿÿþÿþþÿÿþÿÿÿþþÿüþÿþþÿÿÿÿÿÿþÿþÿþþÿÿþÿþÿüþÿýþÿÿþÿÿþþÿýþÿÿþþÿýþÿÿÿþÿþþÿýþÿýþÿÿþÿþþÿýþÿýþÿÿþÿÿýþÿþþÿþÿýþÿþþÿÿÿþÿÿþÿÿþÿÿÿþÿýþÿÿþþÿüþÿÿÿþÿþþÿÿþþÿÿþÿÿÿþÿÿÿþÿÿþÿþþÿýþÿÿþÿÿÿÿÿÿÿÿþÿüþÿþþÿÿÿÿþÿÿÿþÿÿþÿÿÿþÿÿþÿÿÿþÿÿþÿÿÿþÿýþÿþþÿÿÿþÿÿþÿÿþþÿýþÿýþÿÿþþÿýþÿÿþÿÿÿÿþÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿþÿüþÿûþÿýþÿþþÿÿþÿÿÿÿþÿÿþÿÿþÿÿþÿýþÿýþÿþþÿÿþÿÿþÿÿÿþÿÿþÿÿþÿþþÿýþÿÿþÿÿþþÿýþÿýþÿÿüþÿûþÿÿþÿÿÿþþÿÿþÿÿþþÿþþÿÿþÿÿÿÿÿÿþþÿÿþþÿýþÿþþÿýþÿýþÿýþÿþþÿÿÿþÿþþÿÿÿþÿþþÿýþÿþþÿÿýþÿþþÿÿÿþÿÿþÿýþÿÿþÿÿþÿýþÿÿþÿÿþÿÿþÿÿþþÿÿþÿÿþÿþþÿýþÿýþÿÿþÿþþÿÿþÿÿþþÿÿþÿÿþþÿýþÿÿþþÿýþÿþþÿþþÿþþÿÿÿÿÿÿþÿÿÿÿÿþÿÿþÿþþÿÿÿþÿÿÿþÿþþÿÿþÿÿÿþÿýþÿûþÿüþÿÿýþÿýþÿýþÿþþÿÿýþÿþþÿÿÿþÿÿþÿÿþÿþþÿýþÿþþÿÿþþÿÿÿþÿÿÿÿþÿýþÿþþÿÿÿÿÿÿÿÿÿÿþÿÿþþÿýþÿÿþÿÿÿþÿþþÿüþÿþþÿÿÿþÿþÿýþÿþþÿÿþÿÿþþÿþþÿÿýþÿþþÿÿþÿýþÿüþÿÿÿþÿþþÿÿÿþÿýþÿþþÿÿÿþÿþþÿÿýþÿÿþþþÿúþÿþþÿÿýþÿýþÿþþÿÿþþÿýþÿþþÿÿþÿÿþÿýþÿþþÿÿÿþÿÿýþÿÿþÿþÿüþÿüþÿÿþÿþÿýþÿüþÿüþÿÿþÿþÿÿþÿÿÿÿÿþþÿþþÿÿþþÿþþÿþþÿüþÿýþÿÿþÿÿÿÿþþÿüþÿÿþÿÿþþÿÿþÿÿþþÿÿþÿÿþþÿÿþÿÿþþÿýþÿÿþÿÿþÿÿþÿÿÿþÿÿþÿÿþÿÿÿþÿÿÿþÿÿÿþÿÿþþÿýþÿýþÿÿþþÿýþÿÿÿþÿÿþþÿýþÿþþÿÿþþÿþþÿþþÿýþÿýþÿÿþÿÿþÿÿþÿþþÿþþÿýþÿÿþÿÿþÿþÿÿÿþÿþþÿÿÿÿþÿýþÿÿþÿÿþÿýþÿüþÿþþÿýþÿüþÿüþÿþþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿþþÿÿþÿÿþþÿÿþÿþÿÿþÿÿýþÿýþÿüþÿþþÿÿþÿÿþÿþþÿÿþÿþÿÿþÿÿÿÿþÿþþÿÿÿþÿÿþÿÿþÿÿþÿÿÿþÿÿÿþÿÿþþÿþþÿÿÿþÿÿýþÿýþÿýþÿýþÿýþÿýþÿÿþÿÿþþÿýþÿÿþÿÿÿþÿþþÿÿþÿÿþþÿÿþþÿÿþÿÿÿþþÿûþÿþþÿÿÿþÿÿÿþÿÿþÿÿÿþÿþþÿÿÿþÿÿÿþÿýþÿþþÿÿþÿÿÿþÿýþÿÿÿþÿýþÿýþÿýþÿþþÿÿþÿÿþÿÿÿÿÿþÿÿÿÿÿÿÿþþÿÿþÿÿþÿÿÿÿþÿþþÿþþÿýþÿÿþÿÿÿþÿÿÿþÿÿþÿþþÿýþÿýþÿüþÿûþÿûþÿýþÿýþÿÿþÿÿþþÿÿþÿÿþþÿüþÿúþÿüþÿÿþÿþÿÿþÿÿýþÿýþÿÿÿÿÿÿÿÿÿÿÿÿþþÿÿþÿþÿýþÿÿþÿÿþþÿüþÿýþÿþþÿþþÿÿÿÿþÿýþÿþþÿÿÿÿþÿÿþÿÿþÿýþÿþþÿÿÿþÿÿþÿþþÿÿþþÿûþÿþþÿÿüþÿûþÿþþÿÿÿþÿÿþÿÿþÿÿþÿÿþÿÿÿþÿÿÿþÿþþÿÿÿÿþÿýþÿþþÿÿþÿüþÿüþÿþþÿÿÿþÿÿþþÿþþÿÿüþÿûþÿýþÿÿþÿÿþþÿýþÿÿþþÿÿþÿÿÿþÿÿÿÿÿþþÿýþÿþþÿÿýþÿüþÿþþÿÿÿþÿýþÿüþÿþþÿÿÿÿþþÿÿÿÿþþÿþþÿÿþÿÿþþÿþþÿÿþÿþÿþþÿþþÿÿþÿþþÿÿþÿÿÿþÿÿÿþÿÿþÿÿþÿÿÿþÿÿþþÿþþÿÿüþÿýþÿÿþÿÿþÿÿþþÿüþÿÿþÿÿþÿýþÿþþÿÿÿþÿþþÿÿÿþÿþþÿÿýþÿýþÿýþÿýþÿÿþÿÿþÿÿþÿÿþÿýþÿüþÿþþÿþþÿÿþÿþÿþþÿÿþÿÿÿÿÿÿÿþþÿþþÿÿÿÿÿþÿþþÿÿýþÿýþÿþþÿÿþÿÿýþÿýþÿÿþÿÿÿÿþÿÿþÿÿþÿÿÿÿÿþÿÿþÿþþÿÿþþÿþþÿÿÿþÿÿþÿÿþÿÿþÿþþÿýþÿÿþÿÿÿþþÿýþÿÿþÿÿþÿþþÿÿþÿþþÿþþÿüþÿýþÿÿþþÿþþÿÿÿþþÿÿþÿÿþþÿÿÿþÿÿþþÿþþÿÿþÿÿÿÿÿþÿÿþþÿÿÿþÿÿûþÿûþÿÿþþÿþþÿÿþþÿÿþÿÿþþÿÿþÿÿþÿÿþÿÿþÿýþÿþþÿÿþÿþþÿýþÿüþÿýþÿÿþÿÿÿþÿÿÿÿÿþþÿýþÿÿþÿÿþÿýþÿþþÿÿÿþÿÿÿþÿÿÿþÿýþÿþþÿÿÿþÿþþÿÿÿÿÿÿþÿþþÿþþÿÿÿÿþÿýþÿüþÿýþÿþþÿÿÿþÿÿÿþÿÿýþÿüþÿÿþÿþÿþþÿþþÿÿÿÿþÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿþþÿüþÿüþÿýþÿþþÿÿÿþÿüþÿÿþÿþÿüþÿýþÿÿþÿÿÿþþÿýþÿýþÿÿþÿÿÿþÿÿÿþÿýþÿÿþÿÿþÿÿÿþÿþþÿþþÿüþÿüþÿÿþÿÿÿþÿÿþÿþþÿÿþþÿûþÿúþÿýþÿÿÿÿþÿüþÿýþÿÿþþÿýþÿÿþÿÿþÿýþÿýþÿþþÿÿþÿÿÿþÿÿþþÿýþÿýþÿýþÿÿýþÿýþÿþþÿÿþÿÿÿÿÿþÿþþÿþþÿüþÿýþÿÿþþÿÿþÿþÿüþÿýþÿÿþþÿýþÿþþÿÿþÿÿþÿÿþþÿýþÿÿþÿÿÿÿÿÿýþÿüþÿþþÿþþÿþþÿÿÿÿÿÿþÿÿþÿþþÿþþÿÿþÿÿþÿþþÿÿþÿÿÿþÿÿÿþÿÿÿþÿÿþÿÿþÿÿþÿÿþÿþþÿÿþÿÿþÿþþÿýþÿýþÿÿÿþÿÿüþÿúþÿþþÿÿþþÿýþÿþþÿÿÿþÿþþÿÿþÿÿÿÿÿþÿÿÿþÿûþÿüþÿþþÿýþÿüþÿÿþÿÿÿÿþÿüþÿþþÿþþÿþþÿþþÿýþÿþþÿýþÿýþÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿþÿþþÿþþÿþþÿÿÿþÿþþÿÿþÿýþÿþþÿÿÿþÿÿþÿÿÿÿþÿÿÿÿÿþþÿÿþÿÿþþÿÿþÿþþÿþþÿÿþþÿþþÿÿÿþÿÿþÿÿþÿýþÿüþÿÿýþÿþþÿÿþÿýþÿþþÿÿýþÿýþÿýþÿýþÿÿþÿÿþÿÿþÿÿþÿýþÿþþÿÿÿÿþÿýþÿþþÿÿþÿÿþÿÿþÿÿÿþÿÿþÿÿþÿýþÿþþÿÿÿþÿÿÿÿþÿÿþÿÿÿþÿÿþÿÿþÿÿÿÿþÿÿþÿÿÿÿþÿÿÿÿÿÿÿÿýþÿüþÿýþÿþþÿýþÿüþÿüþÿþþÿþþÿÿÿÿþþÿþþÿýþÿþþÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿþÿþþÿÿþÿÿÿÿþþÿýþÿÿþÿÿÿÿþÿÿþþÿüþÿýþÿýþÿýþÿÿþÿÿÿþÿÿÿþþÿþþÿÿþÿÿþþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿýþÿüþÿþþÿÿÿþÿþþÿþþÿÿþÿþþÿÿÿþÿÿÿþÿýþÿüþÿüþÿÿþÿþÿûþÿûþÿÿýþÿüþÿûþÿúþÿûþÿÿþÿÿÿþÿÿþþÿÿÿþÿÿþÿÿÿþÿýþÿÿþÿÿþÿþþÿÿþÿþþÿüþÿýþÿÿþÿÿÿÿþÿÿþÿÿÿÿþÿÿþÿÿþÿÿþÿÿýþÿýþÿÿÿÿþÿþþÿýþÿýþÿÿþÿÿÿþÿÿÿÿþÿþþÿÿþÿÿþÿÿþÿÿÿþÿÿþÿÿÿÿþÿÿþÿþþÿþþÿÿÿÿþþÿþþÿÿþÿþÿüþÿýþÿÿþþÿÿþÿÿÿþþÿþþÿÿþÿþþÿþþÿÿýþÿúþÿýþÿþþÿÿÿþÿüþÿýþÿüþÿüþÿÿþÿþÿýþÿþþÿþþÿÿþþÿüþÿýþÿÿÿÿÿþþÿÿþÿþÿûþÿúþÿûþÿÿþÿþÿÿþÿÿþþÿÿÿÿÿýþÿüþÿþþÿÿÿÿþÿÿþÿÿÿþÿÿþÿÿþÿÿþÿþþÿüþÿûþÿýþÿþþÿýþÿýþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþþÿýþÿÿþÿÿÿþþÿýþÿýþÿÿþÿÿþÿÿþÿÿþþÿýþÿþþÿÿþþÿüþÿÿþÿÿþþÿþþÿÿþÿþÿüþÿüþÿÿþÿþÿýþÿþþÿÿþÿÿÿþÿýþÿþþÿþþÿÿþÿÿþÿþþÿÿÿþÿÿþÿýþÿýþÿÿþÿþþÿüþÿýþÿÿþÿÿÿÿÿÿÿÿþÿþÿþþÿýþÿÿÿÿÿÿÿþÿþþÿÿýþÿüþÿÿþÿÿÿÿþÿþþÿþþÿÿýþÿüþÿÿþÿÿÿÿÿÿÿÿþþÿþþÿÿþþÿÿþÿþÿþþÿÿþÿÿÿþÿÿþÿÿþÿþÿþþÿþþÿÿÿþþÿÿþÿþÿýþÿþþÿþþÿþþÿþþÿÿþÿÿÿþÿÿþþÿþþÿýþÿüþÿüþÿþþÿþþÿÿþÿÿþÿÿþÿÿþÿÿýþÿýþÿÿÿÿþÿÿþÿÿþþÿûþÿüþÿþþÿÿþÿþþÿýþÿþþÿþþÿÿþÿþþÿÿþÿÿÿþÿÿþÿÿþÿÿþÿÿÿþÿÿþþÿÿþÿÿÿþÿþþÿþþÿÿýþÿþþÿÿÿÿþÿýþÿþþÿýþÿûþÿýþÿÿÿþÿÿÿÿÿÿþÿþþÿÿþÿÿÿÿÿþþÿþþÿÿþÿÿÿÿþÿþþÿþþÿÿþÿþþÿþþÿÿþþÿþþÿÿþÿÿÿþÿÿÿÿÿþÿÿþÿýþÿýþÿýþÿüþÿúþÿûþÿÿþÿþÿüþÿýþÿÿÿþÿÿþþÿÿþÿÿþÿÿþþÿýþÿÿþÿþþÿüþÿüþÿÿþÿÿÿÿþÿÿþþÿÿþÿþþÿþþÿþþÿÿÿÿÿþÿÿþÿÿþÿÿþþÿþþÿÿþþÿýþÿüþÿÿþþþÿýþÿÿþþÿÿþÿÿÿÿÿþþÿþþÿÿþþÿýþÿÿþÿÿÿþÿÿþÿÿþÿÿþÿÿþþÿýþÿÿþÿÿþþÿÿþÿÿþþÿýþÿÿþÿÿþÿýþÿÿÿþÿýþÿýþÿûþÿüþÿþþÿÿþÿÿþÿÿþþÿûþÿüþÿÿþÿýþÿûþÿþþÿÿÿþÿÿþÿÿþÿÿÿþÿþþÿûþÿüþÿÿÿþÿÿþÿÿþÿÿÿþÿÿþÿÿþþÿÿþþÿþþÿÿÿþþÿýþÿþþÿþþÿþþÿþþÿýþÿüþÿýþÿÿÿþÿÿþÿþÿýþÿüþÿþþÿþþÿÿÿÿÿÿþÿÿþÿþÿýþÿÿþÿþÿþþÿÿûþÿýþÿÿûþÿüþÿþþÿÿÿþÿýþÿýþÿÿÿÿÿþþÿÿþþÿþþÿþþÿûþÿúþÿüþÿÿþÿþÿýþÿüþÿüþÿýþÿÿÿþÿýþÿûþÿüþÿþþÿÿÿÿÿþþÿüþÿûþÿýþÿÿüþÿüþÿÿþÿÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿÿþÿÿþÿþþÿþþÿÿþþÿÿþÿÿÿþÿÿÿÿÿþÿÿÿþþÿþþÿÿþÿÿþþÿÿþÿþÿþþÿÿþÿþÿþþÿÿþþÿþþÿÿÿÿÿÿþÿþþÿÿÿþÿþþÿýþÿüþÿüþÿþþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿþþÿÿÿþÿÿÿþÿýþÿüþÿüþÿþþÿÿþÿþÿÿÿþÿþþÿÿÿþÿþþÿÿÿÿÿÿþÿþþÿÿÿþÿÿþÿÿÿüþÿüþÿÿþÿÿÿÿÿÿÿþþÿþþÿýþÿþþÿÿþÿþþÿÿþþÿüþÿþþÿÿþÿÿÿÿÿþþÿÿþÿÿÿþÿþÿüþÿýþÿþþÿÿþÿÿÿþÿÿýþÿþþÿÿÿÿþÿþþÿþþÿÿþÿÿþþÿÿþÿÿÿþþÿÿþÿþÿüþÿüþÿýþÿÿþÿÿÿþþÿýþÿÿþÿÿÿþÿþþÿýþÿþþÿÿüþÿüþÿÿþþÿýþÿýþÿýþÿÿþÿþþÿÿþÿÿþþÿÿþÿÿÿþÿþþÿÿÿÿÿÿÿÿÿÿþÿÿþÿýþÿýþÿÿþÿÿþÿÿþþÿýþÿÿþÿÿþÿÿÿþÿýþÿýþÿüþÿþþÿÿÿþÿýþÿþþÿÿÿÿþÿþþÿÿþþÿþþÿÿþÿÿþþÿþþÿÿÿþÿýþÿýþÿÿþþÿýþÿÿþÿÿþþÿýþÿÿþþÿþþÿÿÿþÿÿÿþÿþþÿþþÿýþÿÿþÿÿþþÿÿþþÿþþÿÿþÿÿÿÿÿþÿÿþþÿþþÿÿþÿÿþÿýþÿþþÿÿÿþÿÿþÿÿÿþÿÿþÿÿýþÿýþÿÿþÿÿþÿÿÿþÿÿþþÿþþÿÿÿþÿÿüþÿûþÿÿþþÿÿþÿÿÿÿÿþþÿÿÿþÿþþÿþþÿÿÿþÿüþÿüþÿþþÿÿÿÿþÿþþÿÿþÿþÿÿþÿÿþþÿÿÿþÿþþÿÿþþÿüþÿþþÿÿþÿþþÿÿþþÿþþÿÿÿþÿýþÿýþÿýþÿÿþÿÿÿÿÿþÿÿÿþÿÿþÿÿýþÿýþÿÿþÿÿþÿÿþÿÿÿþÿÿÿþÿýþÿþþÿÿüþÿüþÿÿÿþÿÿÿþÿýþÿýþÿýþÿýþÿÿþþÿüþÿüþÿÿþÿÿÿþÿÿÿþÿÿþþÿþþÿþÿýþÿþþÿÿÿþÿÿþþÿýþÿþþÿÿÿþÿÿþÿÿÿþÿÿþÿÿÿÿÿþþÿþþÿÿþÿÿÿÿþÿÿþÿÿþÿÿþÿÿþÿþþÿýþÿýþÿÿþþÿýþÿþþÿÿÿÿþÿÿþÿÿþþÿýþÿÿþÿÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿþþÿýþÿÿþÿÿÿÿþÿýþÿÿþÿÿþÿÿþÿÿþþÿýþÿÿÿþÿÿþÿÿÿþÿýþÿþþÿÿþÿÿÿþÿÿþÿÿÿþÿÿþÿÿÿþÿÿþÿÿÿÿþÿÿÿÿÿþÿýþÿüþÿÿþÿþÿÿÿÿÿÿþÿþþÿýþÿýþÿüþÿþþÿÿýþÿþþÿÿýþÿýþÿÿþÿþþÿÿþÿÿþÿûþÿûþÿüþÿÿþÿÿþÿýþÿþþÿÿÿþÿýþÿüþÿüþÿþþÿÿýþÿüþÿþþÿþþÿþþÿÿþþÿÿýþÿþþÿÿþþÿýþÿýþÿÿþÿþÿþþÿÿþÿþÿüþÿÿþÿþÿüþÿüþÿþþÿÿÿÿþÿÿÿþÿÿþÿÿýþÿÿþÿÿÿþÿÿþÿÿÿÿþÿÿþþÿÿþÿþÿüþÿÿþÿþÿýþÿÿþÿþÿýþÿþþÿÿÿþÿÿþÿÿþÿýþÿþþÿÿþþÿþþÿÿÿÿþþÿþþÿÿþÿÿþþÿÿþÿÿÿþþÿüþÿýþÿÿþÿÿÿÿÿþÿþþÿÿÿÿþÿþþÿÿþÿýþÿüþÿþþÿÿþþÿýþÿþþÿÿþÿÿÿþÿýþÿüþÿÿþÿÿþþÿþþÿÿþÿÿÿþÿþÿÿþÿÿþÿÿÿÿþþÿýþÿþþÿÿÿÿþÿÿþÿÿÿþÿÿþÿÿÿÿþÿÿþÿÿÿÿþÿýþÿüþÿÿþÿþÿüþÿýþÿÿþÿÿþÿÿþÿÿÿÿþÿüþÿûþÿúþÿþþÿÿüþÿþþÿÿþþÿþþÿÿþÿýþÿûþÿúþÿüþÿÿÿþÿÿþÿÿÿþÿþþÿýþÿüþÿÿÿþÿþþÿýþÿýþÿüþÿûþÿüþÿüþÿþþÿÿÿÿþÿþþÿÿþÿÿþÿýþÿýþÿÿÿþÿÿþþÿýþÿÿþÿÿþþÿÿþÿþþÿþþÿýþÿþþÿÿþÿÿÿÿÿþÿÿþÿÿþÿÿÿÿÿþþÿÿþÿÿþÿÿþÿÿÿþÿýþÿÿÿþÿýþÿÿþÿÿþÿÿþÿÿþÿÿþþÿÿþÿÿýþÿúþÿúþÿþþÿÿþÿÿþÿþþÿÿþÿÿþþÿÿþÿÿÿþÿýþÿÿþÿÿþÿÿþÿÿÿþÿÿþþÿþþÿÿÿþÿÿÿþÿÿþÿÿþÿÿþÿÿþÿÿÿþÿÿþþÿýþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿþþÿýþÿÿþþÿÿþÿÿþþÿÿþÿÿþþÿÿþÿÿÿÿþÿÿÿÿÿÿþÿÿþþÿýþÿýþÿþþÿÿþÿýþÿýþÿÿÿþÿÿþþÿüþÿûþÿûþÿýþÿüþÿûþÿüþÿÿüþÿüþÿÿþþÿýþÿÿþÿÿÿþÿÿÿÿþÿÿþÿþþÿýþÿýþÿÿþÿÿÿÿÿþÿÿÿÿÿþÿÿÿÿÿþÿÿÿþÿÿÿÿþÿÿþÿÿÿÿþÿÿþþÿÿþÿÿÿþÿÿþÿÿÿþÿÿþÿÿþÿÿþÿÿÿþÿÿþÿþþÿÿþÿÿÿÿþÿÿÿÿÿþÿÿÿÿÿþÿÿÿÿÿþÿÿÿÿþÿÿþÿýþÿýþÿþþÿÿÿÿÿÿÿÿþÿþþÿÿþÿÿþÿþþÿÿÿþÿÿþÿÿÿþÿÿþÿÿÿþÿÿþÿÿÿþÿÿþÿÿÿÿþÿÿþÿýþÿýþÿÿþÿþÿÿþÿÿÿÿÿþÿÿÿÿþÿþþÿÿþÿþÿÿþÿÿÿþÿÿÿþÿÿþÿÿþÿÿþÿÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþþÿÿþÿÿÿþÿþþÿýþÿÿÿþÿÿþÿÿÿþÿÿþÿÿþÿÿþþÿþþÿÿþþÿÿþÿÿþÿÿÿÿÿÿÿÿþþÿþþÿÿþÿÿþÿÿÿÿÿþÿþþÿþþÿýþÿþþÿÿþÿÿÿÿÿÿÿÿþþÿýþÿýþÿÿþÿÿÿÿÿÿþÿþþÿÿÿþÿÿþÿÿÿþþÿýþÿÿþÿÿÿþÿÿÿÿÿþÿÿþÿþþÿÿþÿþÿþþÿþþÿÿÿÿÿÿþÿþþÿþþÿÿÿþÿüþÿûþÿýþÿÿýþÿüþÿþþÿþþÿþþÿþþÿýþÿýþÿÿÿþÿýþÿþþÿÿÿþÿþþÿÿþÿþþÿÿÿþÿûþÿûþÿýþÿýþÿýþÿþþÿÿþÿÿýþÿüþÿÿþÿÿÿÿÿÿþþÿÿþÿÿÿÿþÿÿþÿÿÿþÿÿþÿþþÿÿþÿþþÿÿþÿÿþþÿÿþÿÿÿÿþþÿþþÿÿþÿþþÿÿþÿÿÿþÿÿþþÿüþÿþþÿþÿüþÿÿþÿþÿüþÿýþÿÿþÿþÿþþÿÿÿÿÿÿþÿÿÿþÿÿþÿÿþÿÿþÿÿÿÿþÿÿþþÿüþÿýþÿÿýþÿýþÿÿþÿÿÿÿÿÿÿÿþÿÿþÿýþÿþþÿÿÿþÿÿÿþÿýþÿýþÿÿÿþÿÿþþÿýþÿÿÿþÿÿÿþÿþþÿÿþÿÿþÿÿþþÿýþÿÿþÿÿþÿÿþÿÿÿþÿþþÿÿÿþÿþþÿþþÿþþÿÿþÿÿþþÿÿþÿÿþÿÿþþÿýþÿýþÿÿþþÿûþÿýþÿýþÿýþÿýþÿþþÿýþÿþþÿþþÿþþÿÿÿþÿþþÿÿþÿÿþÿÿþÿÿþÿÿÿþÿÿþÿÿþþÿÿþþÿýþÿüþÿýþÿÿþþÿÿÿþÿÿþÿÿÿþÿÿþþÿýþÿÿþÿÿÿÿþÿÿþþÿýþÿÿþÿÿýþÿýþÿÿþÿÿþÿÿþÿÿþþÿýþÿýþÿÿþÿÿþÿÿþÿýþÿýþÿþþÿÿþÿÿÿþÿÿüþÿþþÿþÿúþÿúþÿýþÿýþÿþþÿÿýþÿþþÿÿÿþÿÿÿÿÿþþÿÿþÿÿÿþÿÿÿþÿþÿþþÿÿÿÿÿÿÿþÿþþÿÿÿÿÿÿþÿþþÿýþÿþþÿþþÿþþÿÿþþÿÿþþÿýþÿÿÿþÿÿÿÿÿþÿÿÿþÿýþÿþþÿÿÿþÿÿÿþÿÿýþÿýþÿÿÿþÿüþÿûþÿýþÿÿþþÿþþÿÿÿþÿÿÿþÿÿÿþÿÿþÿÿþÿþþÿÿþÿÿþÿÿÿÿþÿÿþÿÿÿþÿÿþÿþþÿýþÿýþÿýþÿÿþÿÿþÿÿþÿÿÿþÿÿþþÿýþÿþþÿýþÿýþÿÿÿþÿÿþÿÿþÿÿþÿÿþÿÿþÿýþÿýþÿþþÿÿþÿÿÿþÿÿþÿÿþÿÿÿþÿþþÿÿþÿþþÿýþÿýþÿÿÿþÿÿþÿÿÿþÿÿþÿþþÿÿþÿÿþÿþþÿýþÿýþÿÿþÿÿþÿþþÿÿþÿÿþÿÿÿþþÿüþÿýþÿÿýþÿúþÿüþÿÿþÿÿÿþÿÿÿþÿþþÿÿÿþÿÿÿÿÿÿÿþÿüþÿüþÿüþÿüþÿüþÿþþÿÿÿÿþÿýþÿþþÿÿÿÿÿÿÿÿÿþþÿÿþÿÿÿÿþÿÿþÿÿÿþþÿýþÿÿýþÿýþÿÿÿþÿþþÿÿþÿÿýþÿþþÿÿÿþÿýþÿýþÿÿýþÿþþÿÿþÿþþÿýþÿÿÿþÿÿþÿÿþÿÿþþÿýþÿÿüþÿýþÿÿþÿÿÿÿÿþÿÿþþÿÿþÿÿÿþÿÿÿþÿÿþþÿþþÿÿþÿÿÿþÿÿÿþÿþþÿÿþÿýþÿüþÿÿþÿþÿüþÿýþÿÿþÿþþÿÿþÿÿþþÿÿþþÿýþÿÿþÿÿÿþÿÿþÿÿÿþÿÿþÿÿþÿþþÿÿÿÿÿÿÿÿÿþþÿbaresip-1.0.0/share/error.wav000066400000000000000000000406101372575704200161240ustar00rootroot00000000000000RIFF€AWAVEfmt @@factNAdataNAþþÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿ~ÿÿÿÿÿÿÿ~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿ~ÿÿÿÿÿÿÿþþÿÿÿÿÿÿþ~ÿÿÿþÿÿ~ÿÿ~ÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿþÿÿÿþÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿ~ÿÿÿÿÿÿÿÿ~ÿ~ÿÿþÿÿÿÿÿ~~ÿÿÿÿÿÿþÿ~ÿÿÿÿ~ÿÿ~þ~ÿÿÿÿþ~ÿÿÿÿ~þÿþþ~ÿÿÿÿÿÿÿÿÿÿþþÿÿþÿ~ÿÿÿÿþ~ÿÿÿÿÿþÿÿÿ~~~ÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿþ~ÿÿ~~ÿ~ÿþÿÿÿÿÿÿ~ÿÿÿÿÿÿÿÿþÿþÿÿ~ÿÿÿÿþÿþÿÿ~ÿÿ~~ÿ~ÿÿÿþÿÿÿÿÿþÿþÿþþÿ~ÿÿÿÿÿþ~~þÿÿþþþ~ÿ~ÿÿÿÿÿÿÿ~ÿ~~ÿþÿÿþÿÿþþÿÿÿÿ~ÿÿÿþÿÿÿÿ~ÿ~ÿÿ~~ÿ~ÿ~~ÿ~ÿ~~ÿþþÿÿþÿþþÿÿÿÿÿÿþÿÿÿÿ~ÿÿÿÿ~ÿÿÿÿÿÿÿÿÿÿÿþÿþÿþ~þ~ÿÿÿ~ÿÿÿÿ~~~~~~}~~~~~þÿÿÿ~~ÿÿÿÿþþþþþýþþþþþþÿþ~ÿÿÿÿÿ~ÿ~~~ÿ~~~~ÿÿÿ~ÿÿÿÿ~ÿÿÿÿÿÿÿþ~ÿ~ÿÿ~ÿÿÿ~~~ÿ~~ÿ~~þÿþÿþÿþþþþþþÿþþþÿÿÿþþþÿÿÿÿþÿÿþÿþÿþþÿþÿþÿÿÿ~ÿÿÿÿÿÿÿÿÿ~~~~~~~~~~ÿ~ÿÿÿÿÿÿÿÿÿÿÿÿþÿþþþÿþÿÿÿþþÿÿÿÿ~ÿÿÿ~~~~ÿÿ~ÿþÿÿÿÿÿþþÿþþÿÿÿþþþÿÿÿÿ~ÿ~ÿ~~~~~~~ÿÿ~~~ÿ~ÿ~ÿÿÿÿÿþÿ~ÿþÿ~ÿþþÿ~ÿÿÿÿÿÿþÿÿÿþþþþþþþþþþÿþÿÿÿÿÿ~ÿÿÿ~~~~}~~}~~~~~~}~~~~~ÿÿ~ÿÿÿÿþþþÿþþþþþÿþþþþÿþþÿÿþþÿÿÿþþÿþþÿþÿþþþþþÿþþþþþþþþþþþþþþþÿþþÿþþÿ~þþþþþþþþþþþþþþþýýþýþþþþþÿÿ~ÿ~~~~}}}}|}}}~}}}}~~}}~ÿÿ~ÿ~ÿ~~ÿÿÿ~~~ÿÿÿÿ~~~~ÿ~}}~}}}~~}~}}}~~~}~}~~~~~~~~~}~}}}}~|~uoqutqopuw}úøõïíìêêêêëìíðôöùü~{yxtrroooooppsuvwyz|~þüûúùùøùøøøøøùúúûýÿ~|zyxwutrponnnmmmnnnpvyzz}üøôðïôöøöïðîéèåæêïïï÷îòíîöó}qhjhlsmqunj`\\]_cgc_aj}úÿðñîéçààÞÞÞÞßææáêçêêéæåéö÷÷qg_a]]YWXWUQXYTW[@Jñ72_ÂÐ̼¹¼ÂÀÅÊÇÝ=NßÔÂÄ»·»ÁÂÕ{XG?5.4989>JNJP^l÷ûáÓÕÓÿ¾¹´¯®®­ª¨©©ª©¬Ï6.(!%+1>=HUJ=66;<47AMkÒÀµ¯­¨£¡¡ŸžžžœžŸ·,#,6_îÝÅV71+$&"%4?l»´­©ª§Ÿž¢ žœšš–•˜ª7%)3ï´¹¹ÇS=."!'.Gȵ­ª¦¢Ÿž  œ›—–˜¨9(!&9É¿¿ÅnN6(" "'+<ྱ¬§¡žžžœž›™™—£>,! -IïÉÊäõS5/,*,/8WÍ»®§¢žœœœœœ››š››©H,!%-DÙÙm\iS<219<9êÁÈýõŽÒYRéÏóLK}XGCNÇ·¹Ö\oÍÍçJ7;HãmdÊÔumÖÉÏVBNÞÎyYþØÎÜp÷ßgHEóÁ½ÍqbÚßMFOÚÌèU_É»ÂÞ|ßÓÞ^ZøÌÕìÚߨâïrféöSMYäÛz_|ßÞ`OZþîmWOgïãdOXx÷`QMOXTNJLR[|ongWKIOqoTNRjèæþàÜÞú{ôpsiwéæúm_ìÛxYWiåérzÝØÞùjþléÞÜÝèüãÒÜ{aqßÎ×}YiÑÅÏü_OéÊÑ^QoÕÎÞõh^múéàûdZoÝßk\]Yföp^ZiÎÇÌ×úkvåìñçüxùèîi_kßÛõPHTÞÔç÷jmêuelþÖÍÒÖßZP`víøU_èëÚçZkÜ××bIQéÔÜýxâÜyU\tæÎÎâo]Yhì×ßhmqpåäjiéÔÕiRS\ýùòðâÐÜl_\mz^TZõ×ÙæëôeYU[æÞêgZ]|ìo`U\ûåiTMNjÜÞäzOMSYi}eýuöÙémdðèÙÌÎÓÍÏÕÑרÐÏÙÚåÜÙìoUHHIA?>:<;967>N]WJAFNê˼¶±²·µ¬¤žœœ›œœ¯' :ȽþA61,&':qÍÇÉÛûOKY̶©¢£¢ž™”‘Ž˜N :«£¬»~>-$,k¹»ÚB568416DÓº¹¹³§žž¡¤¡™“‘ž2 $½¬²u99=1("8î²Ý?32+*-:繺ÀÔÖº§ŸŸ£¦£œ—’‘ / ׫«·þC8-& (B¿¯¶û;378.,.;ÚÁËàZ×°£Ÿ¤¨©¢š’¦  )± ¦ÂB52/'%C¹¬³÷8.4/,,,?ʹ·¿íι¥Ÿ ¤§¤›“ަ!  "¿Ÿ£·K40/)$8½­°Ç:.+,469LÝ¿Îä̸¨Ÿ¡¥«¬¡™‘Ž•Á .®ž¥Ï5*,4/'"%5®±Ð4))1NÙÞ^KPæÆ¼±¬¢Ÿ¢¦¬¬¢š’’¨* À¡£¶A-/63*#".ö´¬ºK5./9=9;Dе´¼Íϸ¥ŸŸ§°¯¤™¡*  »ž ¹:*.>@.!&Z®¤¯\.*1Zø>0)0ﳫ®»Â¼­©¨ªª¦ž˜‘“¡, ØŸ¬P.-7=0& &>¶©¬Í9.1=?4,+7ׯª®Ëké³£¡¥®¶¬“–½ 0©ž§Å729A8* ,æ­§¯Ò8,-2;;<>Pؼ¹¹¿½¹­«¬®¯¨ž—’•­% ßž­P-,3:3("%;ºª«À>--5G?813K¾°­·ÑæÉ®¥¢¥ªª¢™’–ª$ !Ä¢¢·?./4+)0FÇ»¿ÝHE:3+-6MÒÌ×ZHFMdÞÛÜáׯ¼´®«««¬­¬«¦¦­ß. )DO\vûñíçÝÕÏÌÌÉɽ¹¶¶¸»¼º¶³°µ½ÜG7//3;AD?:458?IMLFA@ENcõãæçÞÔËÅ¿¼ºº»½¾½º¸¶¶º¿ÏfH;99:>>?><==ADDA>>?HSi÷ûtguÝÎÆÃÃÃÃÀ¿¿ÀÁ¿½º¹º½ÅÎÜçívbPG@>=>>?@?ABCCDEGIOZkòéßÝ×ÕÎËÊÇÈÊÎÎÌÆÂ¿¾ÅÊÓÚÜßäáél^SRXUSOJIMOMKHIHKR\gnk]btÞßãÞÞÜâçäÓÕÖÒÒÎÐÓÔÙãáéíÜÛïpefary`faVR]nYMTTYZcYSXZþxìoYgr^ôÕרîÞÒýÞÛôãàÛÚâßÍìdãùØÒúmÞÙsbcütëä`a_YiqhZ]db]]e\_üllýRj÷zrmíéïR|Óîg|kãÒéfáØ_êÚïdêzÝÚuâYükøsæÔORjêýYbÚpxf^åõõpúoß÷sóÕßêÌzÖÕÚïzØëóöÝ^qÓÜkpbþÝbé{c\sô]X[tk_o~kayíïø\]mÝèo÷hîÞçøeÖüuéûÞíÞöçuìm]â÷mh_vr^ek]ühYwSè_d]XútújçìmtÛwåm^éänhïênhëàçðíléîß×bOÜîcã[[Vk×gjpXj`àû_l_ùû`éûlvvhZÕïe]ÚßdúâÒ]]tÞÚú_`zþÛäZoÝû~k[ÞVsÛfäm|~í`ðÔ_^ëÞugâßêagëïÿäÞýëúêÝ}jôåâázaaåßûøõöýéihkâÝuxvò_îìdêçîjm÷öæóíêfëûmëùòmánýèoòktnßékzïxþogìî}Ybðel÷ðrlìöîvdóøoøæñdñufòmåëüvtñzêbpëõæpg}÷oöô~mhiôoi~qóuuvywúuió÷þu{{pûöø~úïït~÷üõõîøúòy{v|üüý~ûuwt÷t{~|tvzvùysw{{{ûîþîwúìóøõêï}öò}óööü÷~õøût÷woøoumxmknrwslqrjmtspüyúu}v|üròþ|üÿ~êùúóxýúò{}úz~wy}sv|}r{{nwtzvyÿý~võûyøøüö{éìyîùíõûíúéévööïöùùûí~~z~|þxüus{vqsumpl}z}p{ûúmwï}}øðpôý|ìôvó÷ôzûúüïþô|õy~x~ö|q}òyüüzýtuûr}vøõöíõ|þíòûýõê÷÷÷ëä}øíësúòzíóõìpîìnð|ï}r~õ{÷utöþroôy}oþîsoílts÷cyêsëúpöîoëtësíþ{èvùûîþþkéíx{óýixl÷örwvuntkôdgryô_ûkfvóïïïìwmàîèèñç÷ðöîãíùøîoñîsèîuúy}yljymb`}tctkj]v_~ýæéaÝaêmaïhßZdÙ~wdkÕjjcõ×V[{Ù[sûkæYnì_ÛYmÍOÞlãnuÞ~årâlúúænÞWÞÜþâgrNM?mïSÚËÚÔ×ëßëerfYøgjÜÞòÔßÛÕóá×çóÞîùòït~siã÷oæÞûtï}öjf{o^fêüíã{õêhnàõhðe^e\dmbU^RJIDFDCDHOMKU[QVn]ZnÞȾ¶°¬¥Ÿž›™ C22*8T:Ft6-5//6C@YÈ´©£ž›š––+9 !í®¿¶ª?*.!(/E»¶¬«¹¼`8@=9îÓ¸¨Ÿ ›—š˜‘—;8,7½ÃÓ°Å2-,#%2IMï¹·µåON;NâìÛÆ^Zí]dÛ½¼µ©©©žœ–“‘£¹v)5溳ËÍà0.5.09>FOÙõqáïzþÏϽ¶·¬¦¦žš™–“¯¸="(<Ô·¾ËÄN171,77C_О·®¬ª¦ ¥¥œœ–•¢O/#+H»²¿ÏZ3 %$1lÎÆÀÖW@1//08Hñɾ·³±­ª«§¥¤Ÿ›—”—¶*%+<Å®´ÖR6&&,=μ¶¾b=5*(.:KfÅ»¹¸¹µ®¯¯¦¢£›š•”˜µ,6Ѻ³µÉ6%#7ðȶ¬´v7)*');S~ʺ·¹½»³­®®¦¡¢˜˜–”L&ì¹³µ½N))X·²»¿Ì>+&'*.?ôÁº¼¿ÈÈź®¬ª¢žš——Ÿà##U´¯¹ÏV/ "+>Ѷ­µ×@0(#$+>ؾº¹ºÂÎÙк¬¨§¥¡žœœ›š—œ÷"S°®ÊH?0!'2Hͯ¯»M1+%&*2O×ÒËÆÁÇÏÊÁ¿¶¯¨Ÿœ››˜š°*0į·V5/( .Jƺ¸»ÍH/&$*/;aɼ½ÈËÉÉÍÉ·«§§¤Ÿœžž™š¬0 ,õ¶µî2))& '=÷»ÂÏz:,*,4AOãÏÅ¿¾¿ÄËÍÈ»¯«¦ žœœžžœ º%&0lºµð/'$&%&,EÁ¶¸È÷W>2+)/@ðÎŽººÈúìϺ¯­ª£Ÿž¢£ šš¤F$+9Ô¸¿H,&%''&,I¼®²ÍSB>8//7RȾÀÆÊÇÅÎÜãË»¯ª¥¡ŸŸŸ¢¤¡Ÿ¡º,"-3Lù×ÒÏÍËÉÉËÎÎÇ»±«¥ ŸŸ¢§§¦¢ªß(#,5=PòeH6,+,/8B_̼»ÇpD==?BGWûÖÐØÞßÝØ×Õζ­¨¥¤¦§§¦£ ¢«Ù*!+5>KeeP;/++/7CVÜÉÃÆÞO?:503A_ÐÌÔßëßÛéfOMRgßÕÑÒÔÐÍÉÅÄÁ¾ºµ±¯®­¬¬ªªª®ÃD(%.8BFLW`bO?636?XæÖÜåèÜØÜìi^auäØÕÕÕÒÎÊÆÄÁ¾¼¹µ±®­¬¬­¬¬¯Ä?)'/8=>DOrífH:69C]ãàìvýàØØågXW^ñÞÚßçÞÒÈÁ¾½¼º·²®­¬­¬¬ªª²Î7'$*/57;CSüíZD;8=GZnla^iîÞÜëoceúãÜßèä×ËÁ½»º¸¶³±¯¯¯¯¯®­¯½d4)%$(+.028>Mi~bNFFKWhd\TS^ÿÝ×ÖÖÙØØÙÙÚÙ×ÑÊþ¼»ººº¹¹¹¸¹¸¸·¹¾ÏY=50/00//14:ALU[\cnïåèök_`h}éâÝÜÛØÔÓÒÔÕÔÑÏÎÍÍÌÌÌÌÌÌÌËËÌÍÏÓÚä{_TMJGD@?>>?ADGKMPV]eoyû÷ñìçäáàßÞÞÝÜÜÜÛÛÚØ×ÖÖÖ××רØÛÝßåéï÷~vpljgdb_^^\\\[\[\^``beijlosy}ýú÷öóòïïîíìêéèçååååååæèéêìíïòõùþ{uoljgecba```bceghkmptwz}~þýýûûûûüüüþÿþÿþýüûøöôóòòòññòòóôõ÷øúüþ~~}||{{{{{{{||}}}}|{{zyyxwvvutssrsstuvwy{|~þýûûúúúúúûûüýýþþþþýýüüüüüüüüüûýýþÿ~}|{zzyyxxxxxxxyyzz{|}~ÿþþýýüûûúúúúúûùùúúùùùúúúúúúûûüüýþ~|{{zzxxwvwwxwxyz|||~ÿÿþýüûüûûüüüüüýýýýþþÿÿÿþþþþýþýýýýüüýýýþþ~~~}}}|||{||{}}~~~þþþýýýýüüüýýþÿ~ÿ~~}}||{{{{{{{{{|}|||z{{{{{{zz|{{{|}}}}~~þþþþýüûüüþþþýþ~z{|{zxxxx{~|}|}~ÿ~~|~üûyzùù~{}vþyyyy~úùûùxúþõø|{}÷ùüþöþýüûú}v}xþwomwõ~úzurñþóÿõrîTí0[7çã p9™ªöåeªœæŒˆˆˆˆˆˆˆh<`È6ŽÙHI"=HˆH¿¿Ó/gèFDDDDDDD46²g~,PÕÁ`Œ;€ª@½'÷{ºbo òˆˆˆˆˆˆˆˆöÄm<ó"è"Ú´Äb@4 ”–žD"@2 ôô‰„;[à úo{†pî§ ²vAxžµ©óÂß¶¥0dϼh_¼• µ¾ÔÔÔ×ÓËÝz»“À®]@k+ÐÙ tw--.|³Öqɤ»“¶ðA"ႺðwÏëߌDÂ]ß §G´ Àm<3¦_Š¥ªA<î´ž`ÿràcöàû@s°¾hÐ`€Í½¿·÷/¿ì®[[ tu¹Ûè骫ÝÿؽˆÇÝïѨûÙÚ tt¸ NÕmC6"""""""¢^ ÙÆ3ñöH±¬µèî6عxòI`íZàoû3fÓj]Ø6À¦¨p€6'M€Ü=ÜfaåZ´yž;‰0p#"""""""Ê„!Û$!ªÉf»ô…‚Àˆˆˆˆˆˆˆˆ(3†l“„¨nÉxyÚÂýÏgÑp²Mo{6Û…«‰Š‘ˆ;î%DDDDDDDD1>™$’^¢)Óåª 7›ïѨûˆˆˆˆˆˆˆˆ†Çm²HFZ†ÛÄÚþ‹Qv²MmíÃm®*j H¸SºÑвM‘Ê®L‹H_È–^ÑÆù؈ˆˆˆˆˆˆˆ†Çe²¨E2ÓŪ U Üß±PRÂyÙˆˆˆˆˆˆˆˆ²Áú¤/|0T¸&œ¬ˆˆˆˆˆˆˆh Ù@*< ƒ6""""""""ÊC6.ª:Ö-!"""""""šx²Q? JDDDDDDD”;†l µº(åŽ!Q²ˆ!Q²ˆ!Q²ˆ!Q²ˆ!Q²ˆ!Q²ˆ!Q²ˆ!Q²ˆ!Q²ˆ!Q²ˆ!Q²ˆ!Q²ˆ!Q²ˆ!Q²ˆ!Q²ˆ!Q²ˆ!Q²ˆ!Q²ˆ!Q²ˆ!Q²ˆ!Qü±nQÁT—Ýïs}”VDP‹"/A,RŠn[ŽX¬Ì·¦R=Ä‚@[1Í:Û¯‘Ê.lAѱ¾+D4 Vª‡­Må@4Ï+A"Yß+GÒTx¾T°ÚÝlŒß/ÖÙݯº@K$1Öwa¢º¾±±lߦWO<Ä$ß;§sᡞ­CkK‚x]ÀÖ-@M ñ¸ûÙÙ $’@iIêoJ©ªêÿ·ïS¦»w± â@y9ÐÞlß47Ûî-ÛÛ¶µu¶¶Ç“ÛJlò‚×ÒÖ…—ç¿‚]Lº÷ÆÆÆF³ mÃÁõÛ6½ï”™uGF"R‡]Ûê AêëjQóÐÙìØîöG?$“{Þ÷×=…ûi2 ”ô>6‘¨Û?£QÀ÷XíÚåö¼ö6`ûvEGW×®¶ŽÖ-m]»cAâµ’ ¹Îóô‰«÷3Ø,«0éûå+®øBéüõ»N8Ôë~ßœ˜¸þ5¢uØÝ\‡ ^Ù׿µßrÚ`ý«ß¥ÔÕ‘ˆë_áûW“|´Cñò-Ï`W#`Gõ~Ш±n’••]¶g¨‹1ð< s'°÷Ù6‘TU…jnŸµÔ˜©X"; jNÿP¿żúRX[ ˜:?V:MÕÖALG`µ ¾×Ž@;µzÚP_ÝŠó$µ6Rî.x*‚C÷©AP:Ûób‡¨è±*8^lQñþ‰Cu= ë²ÐMFñpR»žÃ…•M áÆ)UÁeð0>ÚC¬»()ƒ&*ü R©>ªƒ%ø¿Qy¯ØT ­B¤¤¶´Æ7¶^­T Ì®dDw!iÚÚQ^ÙÏH÷ˆ·g2kÔ(ª[fÂøûñƒ‘òx‘©Ý®ÚN1÷Ú x6ò¦£‰ï#ƒ»óúëËNëZÿ/•ÓcBMôˆÄã@wïîßÞ¼õÐÓ44¸kו•©©©ZZ€¶6w~ø7¥„dU•û0W^îB¶žà¸ã€Š `Û6`¿ýÜe[·7kÖÏ<ìØáßöv ™„Z UEÒâˆùÉ. îš¹ {ó‘·<üKÎ>iº¿sêOAY¬o½åž“IwÐÜÒâ>×Ô¸ýtóæÌ·ÈýuOá~ S§º}±¢˜>(+s¿××»Ç= Ü6mÞxxí5`ýz÷\´¶‰Dß~šP¼å‰ü§µ¿GñÖ˜ÞÇQtýõeé龨zvÕ‡Q‚#aĶj¿åþ:´Áú׊ ´-XàöYkÝy¹ô¯Àãóã¨wÈÞÝ¿N* Ù&‹½1dkl4ˆ?ÏÄ*Þß?VU†È!ˆ””äu{ªÛEí_a¼ÇlÒ>‡ÒÎçð¹ê¦"·š²uesï—oa?¥À–eÚ\$·î,×ýª {›¨ùmày£oñ€º@j0°%‚ÎQD;J`½Rø¦*¾J•ª­Q‘ZˆÔ¨‡ÈTµ:Ó¡2"S²ýwºÍxh”âcظ¦•S5¦ü½êɈ”6d}]Õ]"z‹1þ’]«ñÏåÛ! sóÖxŸ©GÍ5¦Š\?vD.WØäÜO¯‹âjkÍmX“ý¹¼íÊ+kÎi°_Á±sV`Æ´*ôô¸æ7ßto½åN›7»À}àèìt¡†ï»Ÿa¥EÐÛåz^ÿ¿Gƒç¹S.ï5Éäèµ1½}á9Àì•”¸ƒëòrWqqÜqÀÑG‘Ù¦HOþ³;|ñE`çN »ý^ ¹Õ³öry«G玼•+WzGn~ñ£6åRì;mb1ötu¹Çc¸ý44Ôó=ûëx•¾Ÿzž{G£.Ø)-uÛÔÖûïvpè¡@ÅLs$¬yxüq`õê¾çD‰ýõ+FÍ¿A‚»öÖ ·¿\}õ;§Ä¿Œù5+0¥¦eenÿ̶ Üo Ù_‡ë'G³O,¦áú×™3][SrHÞý«nóE¿-Oá™Q¿TT Ù&‹C¶°éîv_|Œ›í ”¢aî±^4úY-©þ'˜ð ˶ä|À¤mù¹…ù,Vc…´çx”­Æû|Ts 1þ9êábxÑéCm< 6ÆRÛ¹ý6ÜÌíéó¬¬M;xÈuÿy\ ·ØDü~TD_UIÌðDP;/‚ ,†š†JKJh94RéE£•€©QãÕ2FëLSÅtf2b*F»åEÙ?Ú¸Ðó+¦¥Õ'y2{RX~d#æj|^Þ,ü'F-ñjÛÞcMäBøÑ32mšÞg¤ú‘¡§4|ÿs¿gýt̯0wa5P Øô<ððÃÀsϹª”;݇ŒdÒuÈÔ¦^¢EyMI¸¿Œ§6¥Koß`û9Dܤç¹Ú`ölàÈ#cæŸ`¯÷ßÜ~»«&li&“{ÜoUü½SôÃU«0z#FÀ½7ü¸á‡×Ý£9f& 4½ìªOxxþyWÑ~ û´ `¼îãÑPûi¿ËqUlaØ9gp Àᇇ `€N`óÃÀ]w=¬[ttÀÚoñ‚Vèûå<0ò÷nô¬ºúÛgõ¾ÃnÂÜ…µã©ïýd¾F½ò¬ž+Ï`Ç(ÝE*2†l“EŽ![8ļ³Ólc²5®™îUÔŸ©^ô‹(­>pZx`”þmLÿ¿­M$ýC–<˜à½4HxÁÅ2äãIYjl4¨þÒ©\yßP› |C ŸwÏs_€†Q«ç¹/”ÊÊRÏs,æ¶QuûG{»›2!u_R÷ô¸/Õ ÷3òÛÏ{÷Šäw°5òôˆTLÑï¾ñ£`Ê~—„÷«p窊²5|ÿ³§˜Xå(­ž—õÿÎkÂËFõËÁïÏ8Oâ¹ßÀ^LUpUóBã•ü›z±¶ÉPýFø9ØO›•6u?Ãc»tAê'¢ªô€>«ç6 OÑö,¯iÎíÎN,æ[s£ßÃŽÿ jNì=÷%à¾û€•+W_::=° Ñ#"Ïs;|i©ªwÊ)ÀÙgÓ°¸ùFàÎ;M›«rT.2OÛkeÎ+ôà÷¾þÎS>vüo°ïÉS€ZoOþÁÝç§ŸvsÙõôäÿ™€ æúnqvI‰þ¼`ðž÷'|@ðÈíÀï~ç*ÛZ[÷ Úp·øúQy­£/ŠGU¿úÞwðOï¸þTxžýë8Ó·ßF".t û׳Îf ¸ùZ¿ù&´·Ÿ䆾`ž²WMÄþu²cÈ6Yä9\4O£²5®Y`*~ƒòºÃ†jaÅRøEW4ê~¯ªrKxÚÚR?ÃûH¸¦îîT°’Ï}èYÏû>'û œ5ªñjÚÞkýè/3Í”^±†jáÁ±1ºÚ}îò}÷>–Lº‘UUîóq4šú2tßÐ   À Mv'Ý~¾aƒ›Þ£¹Ù͵Tçt Ý×pt‹â;Ö7?Ççe[þÔøc~¸ùrTMÿêpßVŽÇw‡lOÏ4Uû>޲ºY« ÒOý«Ÿ ö…5¢Ÿ¶y¿Ú[ÃÛ¬]¿¹Ì$ê>£‚ïÁD*^<°ÏHÔÂ÷…XÌõ±˜ë/T3Ü—J"nŠ p»ª*×ìÚåú 75ÐîÝîý£wjX›ýû‡?·Ö|+dkq”qEô–oÿ8í” ¼òGàæ›U«€;aÓ+€€]xHE6`Töêr<°¢u ÌT÷Å)ž pŸº!O'œ|ùË^¹ø÷Ö¬Æãƒîç Üî­Òs'Ò «¾ó¥õE7áÐw`*Ðþ(pã.¬Ø²¥_H¡€Bñ ¯ °ÀV#“«2u´YÕf©bŽ=Âzûvßwó¢EÀ—¾L? h}¸î:àoš› Ú híPÝW_Š^sÉÿâSg/FùIÚ‡í_!xD ë¡xË@v]Ó'‡¤j-³ ºŸ§x‚Z ­5Ë %]²¨:X½¸æॗ ÝÝCõ¯ðVéÙ Ú&†l“ÅD Ù¾¾z?¿ºáT7œèÚ†¾¶…IU•;54óg¸ïãJ”˜  kÕ €û¾§ÀMî Ÿpª‚°jÏU(äÔmó`>•\Š?3lFã}¾Wṡ¬ïÿ^tÐႇ‚†j¸ø~*l+륭³3–†áú™^íVR⪸ëêÜKûÔ»À­@ @€xùe7­EK‹»ýx<·é>ª¿×ˆ÷Ï{ËÐ?sÅ®ËPVûM``¥PÿíÒC¥Ôycûò( d“È÷7|ÂÖîû_@ªŠÒ˜TxSVæ‚›’w~8—eOë_‰TTÕ’¯«M¾+b/åq&¶«^ìs±úÑ c4°bm`°>/©¹¶E\¨ÞÕåöUßwÏš(|¿ ocÖ,àÈ @€¶v7÷Žn.ùîî°z:ËçVõv•ݬt}áÐø°ákç_¶ïÇOÿ&y¸ç¿€[n^½/ ±Àmè÷" ¼$kÀ)Ƙê$ü£¬×ø‚CD‰óæçŸœ¾H¼,_¼øâA ÿcVÙO„ í®oå÷_¿ §žRŠØ|`íŸ]@óÜsж6¨*`“¹¸»'x´ülŸ÷ko¦ —á@ ÌEžè’¾°mÚ4àÝï–} @ø¯Ë›o†¶´ Õ7™@÷—g1áfõíÒÏ|}ÿ³Žú6N:ÛqÏ-{ö¯Š;UôòH7Ö°{z<ª’q©"?õ‡õ…mûí|ö³ÀéMßü&°zõA›¿•Uzû¡‰ƒ!ÛdQ¤ÍŸÛ1j¶![YãÓ3{Êgü'ª¦¿/½R­¬ÌjµµÀ'V³ávÞn¸Pd-€]. éèp•k»v¥VŸ‚§LqsSÖ–‡¨°.Œ[»Í ß¶-uPœãð6OÌ'’Kp/ö×D½º¹ÿdÅ\?˜•2ØAr`x^j¨g,æöÉð`8¬L̵B(àI_EÜ”)nŽÝãgûõn÷€×xå7½ÅŽák"¯°íNµÞE¸P6ävÅñÅüx÷75VqY_)<ö~vªé•¢©*¯Á¸LDdðo÷r üó Ù–¯¬ðæœx·ÔÎz[XŽZ©ªrŸï<˜^é‚Úé½'Ø`€õÖ-†¶k—›ƒ8¬¬uUT¹ïKüÜv™‹ñEéÊéŠQ£ú^mûg­»vàœé|¸†ï¥¥©,Üc.TëèÈ-è ÷õôÑJ‹sg¸/t`mxä7N[çPÙ&ø±ó,‘ =9÷V|ôÌ÷þÃA÷à´ÓÜrÛmÀo~ìÚ›L¿õ^$Obo¬àÛ+$ŽÄ©*r—'¨4Ƹ^çœ,û>Ðô pÉ%À‹/¦OšžFU~é?mÏåfçäG—|¢ü’#öyGº/fÏv‘ßpC_P‘°ºÙX]ì?‹Gy@;>µ‹é1+7àLÄbÀ‰'?úû—¸çØÎÁj`»@÷›H+9Þ¾ìÃoûÀ{½GiÀÝw÷ÜlÛ›HÀ·Å­^Xþ †Yî–ÆJ✤FîöÕýû׫€uw»Šá§Ÿ†M ñQ@äfï)û‰Ñm5å‹!ÛdQ„ pÇEÙ©óJg_mêf}4ý ¶²Ò Û™5 X4Ç…bûèð7Ïmt+#oÙâj\ÚàNÆ"WÉÔÐÌ 2 XÀð0€ÖºÅ_Â!A9V0mñ¬ùxr…Ü—Óµ·úñÎãÅ+ S¸–>4½r-uûBGGj$÷sd*¦Ã×AU•›òãÜ…Àþ½—­p÷Z·Ï…U+ù„mýµâ-Áy3 1Wu|]#%ßRáƒç¹P£¦Æ½n÷¼Y›ª ƒúx<µ¨Uê5›úöáåîÿ¤Â¹ô§>×þ(×­ê ªëÜïäõRZQöKaX?>pÜ>Àᎂ[?ʇ[û Lï) 7DùM/xÀªWÜÃ;r|ÒìÔ˜Y€ÏÊÞ:)®x?i=ÇšÈoöûsßO ÿ¬¨pû`$âµíÛ]?0×âÀ†õî÷Ѩ Y.Žžã*a7XýðÒKáPÒ¬ÿçN…y–É„\Qìú .ˆ\°Ï®-x×SPWç&Œ¿ãwP1óŸ þg¬ÛIÃÓ#P“4ò‚ì#"Š à½ï¾ü3`ݽÀ—¾Ý´iÈý:ô¸è³xr”›µuŸ>ãÆ¹çžúiÌŸï¾Yýío×^ƒ&¬þÞýǽu5ʽ‰e~&¢€‰ÅÜ$ó?øP>Xþ X ‹üÚÊ~rT§ÆÆ·ûßj¾…³ß; ¸€íÖ[íÛa“Ib>}*¸i¬ÛIÃÓãQ•HÊs0§ÿúKàÍ¿_ù ôÕW‡ì_Õ“ä<:Êͦ<0d›, Ùú+dS1?Ø|‰©ùÃôêÊJ ¾8ààØ:w[à~otsÑ65'lq sKG ,˜æ _ à‰Ýg°ð -·ÿ'Q#‹±DvÔȉjñJϼí¬Ë5û× 6oR¸D".` C—°ú$¯ê±ˆ"ÁôéÀ1ÇgOs•J¯xp³›þ¢©)ïa¤q£º8Xîß12­9æêž¯ªç_þ¾†**\õûa‡”óáBëpõ·HØÑæ†hw¥EŒ­­.lêîN ÝRÃ}Ãýè¿P–µ¹í¹„l5Ÿ¾±¦ë˜¯“²ŠšpØam­ _OØ8ÀApÕ´ÏxÀ+-nN¿pxbi)pPÌ…póà*p“žp€'7¥æÖΫBRЭÖ,Äry#û+Mßk©•òèˆÄNI?{°p- ÖêëSÕ”a%³{\G¾ß0ÆôóG/rë†ðøã®Ö aÏî½C 7Ø)Þ…m¡‹?ž}ìï>õÀëqòÉ®lóî»W_…uÁÅÑg°z¬ÛHÙÓE("²C€Ò¾Á‹/>øEà_nº ¶£cˆ+ã-ó´î;çúþâwVÿëüèN¼ã ñ8ðç?O> íêB øÈ*{Éð·BãIòhs³@?¤mW_<· øêW¡Û¶ X:_žÅ«£Úà<üñƒ'|êÝ'ÌùŽ>Ú};wÇÀºuaÿzlô<5Öm¤ìé‰( ²M:zŸ IDAT•}ýëŠÀ‡/î½øö·‡ì_Ø.ót¦Ü Î 9Î1d›, ÙÂ!_9Í7ÓkÐíªWc^¢ò©l8Íw@Z]Ý[µ¶Xd€Ypín}íFÝÔ$#{Àäy••®JåÔ£€Ežðè“î¸a÷î„Ý„åŸ –yÿ L¢!¤Û+dJÅ*ø±ùég ×|¿ÿ¼IaåZggߢ^½‹ŒígõHÄ`Æ 7ô©unî‡<Ò»JzÞû¦êcj;ÏÂ…Uf2ZsmâRóÝôó\U ®Ø7•ÏÂ2àL¸êSnXwnщu^‡Ž[Ý{Ù›:»Rüù²Â•b;:RûEȹ!—ÅÙæ]p}õ¶Ã?öš©ª¨«×fÍŽ; X ¿à6zÈ…†á¾†aefi© €æÏ›à¸pî)¿Û¬Yãª#[[s»?îNÁªgŽÅy:û+[â]ÕþÖ/¹e°y×ÒõpØf]«x®¯w£¾¶o¿„ýÕ1(-u¯·ì à/»ç·µ5‡ÀOФñžÃqqÙ„˜ÇqñâÅÞÊêoâ¨Ã¦cÚ47nöñÇa»»¡j>ã?üj¬ÛH¹Ó#qš5r?Ðûú«­uAÛQGßøðüóC¾7«˜óý§‚_Žf{³qÿ\qÚ‘³¿€ÓNså¦ý+´© IÕ'"«ôÄñ Rfúv”m²S€r”•çž üó?ßý.pÇCV³xÁ¬ÒEãyXpcc£ùÖwnÀ¡δiÀÃ/¼#°²,úŒýÙX·‘r§GâDkä ·9¸ôRà„“€ó?“±5e²ŠÏûxÇm²È1d «×ÂpÍù-~°GÈö7昊)Ï›²ªÊ°j©¦8è à ù.\[—ž}ÖM>ßÙ9ú!‹1ÕÕ®MGáVØ}X·.¯¡G«4aÞƒ‹÷Ú¡])ßoª–ŠÒWàE§…g¥/‡ó E£©ùöª«]£1î`tæŒÅr&¾o0eŠ ÛNœá:ÐçÚ\5Ò† .hÉ£ª-©jÞ†åòØ5»¨ Ù€°ºH‰¸$qFuuî¹6 8°ÎUÕÀU¹ÅáæEôá*GëàªÝÖÃ-ßï} ¬…«:67»j%7d7ûþ!›íˆO7Öl8á’#õå3JKѺ¿«8n8à­-®JiË–Ì}AúpÚ’’TØvê~À?˜àÆÝðôuëòˆÔš·a…<”Ó•Æ“+6ÕI¤þ.øÑÓÏNæÃp­¢"5^à¥X½Ú-BÐÝ=ö}†1µµÀI'óö6l^ÝÜâYì¯ «œ€Ñq;ì.tÇ©sÎxÿµÅ¢Eî…ùàƒapq_t•ž1Öí£ü%–Åîº)çÏwó²=ú(póͰÝ݃_Q7OkÉx //Œ~«Ô´¢aZ À“OºávAãkµ<ŽÖ±n#å'y”w–ˆ½è}ß­¯w•AõõÀ×¾»{è%Æè¡ò$ÖŒZcsôûÓ8íƒó*ïG}½û ´v-´¹ «ÆžÖ“ƺ}”?{ŒüYg½ýëᇻþõoËܿ֬ҿßü±noƤ*3Ò 5ù zÚûï'­ÔXÅïÃJ¦pbê’WðòZ௻ªŽÑæ3k-š›'ž0xõUà¸ãÜœ;gŸü­ÂM„ßÑ!}s)eáh‰ØÍzž†½Ò›ê$Zþ<¿6å3ÂERž ¼.¼À-q«ÎfÓ?…á›ÖjúVmi6 ¼nXmWèÙßõ‡kÖ»wçÔ·ÄØûôz­ŸÃÓÿ£ùp‰•¯laƒ0”÷ýÔŠÒûíçV•Žxq;ðàƒ®ÿÈvHf?"µW¼/º -hÇtc1,.C u¨„¯÷½èLkƒ*d&ÓMZkÑÔ$øÓŸõõîýã¸ãÜûÜÚµ@{»>hï ó3ýX°TÆõ\fõÉøç»oÖ¯zWõSÕcÝ6*Œï›Áß@­…lÚÜ?0gŽ?¿eËàWD±sñÖbs3ZðVË<Õl½%èj-+Wy+¶ Ìë þlK܇U…47·ßœu0mL[ÛÐ}®šÅ€·![COç'J÷!jË µÕ}6]2Öm£Âô2…œ À…ýk×ÿó?.lËÔ¿G`L€¡Î“C6”繃ÚßzëÛ.ëƒÀÅ+=sêû¯¶~t©ôÞVxŠÇ]°V§ä\Å!òª@B€ÕƘ—“àa;´a‰$Ш Ã.TB1ÛÀ.VÁ ÃÝtx°ô׿ ÖLw\/Xà‚gŸu!Búê–ÃðÅØ‡åÚà v¹÷ãìïàqŦR‰M]ãW†g¥laÈRVæ¾\œ;8d_7ô²À#;\Hµk× û€Âz¯ï.«‰Çéz çW5CD9|•Óˆ8\n³+ ¼ à^×áGZî•çY‘¨ÏtªŠŽÅš5o¾ lXœrpüñîsûš5@s³ ™”Ü&函B®Mž¢Û½ Q†Û0‘¤‡Lɤ«ôkksûĦMn.ÄpÈ_uµ ÝêkÝSkoÝmxݦ&÷%nKKj(iø?Šå×~göqµ ëë]Ò¡Žƒ›‡ïûo=tueþ>i? Ô{ ‚f´[GuËÝ-Zsæk¯õζ˜?ÅxûUµ RÃaœƒ6_‚à.…ž:‘†¦{?nûˆ•ý&ý¼ôÕ#×oÔÕ¹ãú…»jÈuÑõÃmm9¿g<ëòÅäT<†ó¤+ÃÄ&ݽ§I·nÅ_Ѩÿ‚i8FŒþT?0ÔU‰„bÛ6ƒ‡N>8îh÷~·q#ÐÚj² ­Úÿ6ׇØeæ[ãõy=±ï„ç¹oÇvìpÁðBìi¼4Öm£B% ?ó©*¤³Ó WëQ¶núµ1gö§£ØØŒfñ÷ ­Í¸¶´AUE·ÑouÛ¨0²ñä1òkQýh@ÞxÕ774¸N·gðÁ–$Â…%¯ŒèP\Ebƒ+!rúp›‹JJ3g‡â‚€çŸwóÒ†aPÎÕ5ªévïôñºo˜ë‚Sà{E»½Þ¾Ç÷SÃKËË]_S^î*;;]øÚÒâöD"u*ÖꢟüÑo™åzfzÌL¸yÓæ¸ ÀÏîvÕkÿ—êcªÞ—уUøâž+ÇúWu¿+ˆDî Š(-öÝ×-1»ÆUe%<õšÅ.ðLæ¶ÿèùÁ2ÜÍ…´'óÓÎËÕ/¹4ýÜs¯•—»c¤#N©tU¸õW4•UèÙ÷/ÑâóáäRùkQîÂ:]ºí]ŽÎ´YØOx ›!uCÌ[Z²ßEð=»Ôûj1š]LW1·æ_öéiÆìÙî pÝ:Øx óiUð_cÝ>*\p´l„[·`JK·¿Ý};úÌ3™æ»Úà­Ò¹£ÐĬ¼yêÔç÷™Qs(<ؾÚÒ‚Àê–ÈÓ:s¬ÛF…Óc¼Zµÿþm|ßMòÜÐ<ø l{û×íêÑé/`Û¨44W@ÕEõ»QUå–6m‚Ç5K¼§ƒÿëöQá‚£å%½ŸÊÊ€cuv3÷¯[¼Uì»Æ³ŒCˆJ?–0/õùc°¹ÛPXka­"‘°°Öfw¤°"ø²¶› ]fÞ,÷ÿ˜_À¢¸¨|³]î_¨AG½nMñøãÀ}÷¹ðñÐC3\0iLö/'U|T¦Ûç±RKókÿøâ]Ýõ‰L[Y™ OæÍÎ9X"À9àVŸÜ°ÑMXîæ+|_?²¿ÐÊA/,ÅRY­Ëý3DÌÅÃm®ªèîVlÜ覨Y»ÖUcÍ™ãE·CŽÝ¬È)Òü:)*­µH$,zz\è°q£ [·nuv8—Õ–-n¨e"‘>Gdq {W®ŒÎþâ‡~wrÌ;à78ÀÏ\uû°Ûëjƒãt¹"VÈCƒl¸f{EàyÐWÙ×ÓãŽQׯ6µ¸ÅÂ+–—»}ÇUçö]˜…ü7êôœ®4ÚïóåªÎ;Ó¶Ô—/®ê5u£%<xÛÛ€s*Ý ­«Üþ¨Û':;³|ï 0—év3µh|F¶ê2s¬þ“«¶œª¢«Ë⥗Üó]YéîW.視Ի.ùÙb5½XHË".`kié[ŠÜKŒe»¨xÔ½ìRâq7gF2é:©¡ÍÑ÷ 6¢ËÒâÅðö)ÅBD£îÛ¯öv¨*ŒÈ cÝ6*’d°!ýO 7¼ ³ÓÍS’AyÄ?lDÛ–§M àû©ÕŸzûWcƒûƸiT4òLø›ªº‡›6¹¾5sÿ:COÄ^q ¹·bÈF9IæÙÿüÔR¶r8@N p‘&M™]êý{þÁÚ.¬Úe—zŸU1 ÌߺPÅöüwtàB•\ƒ6(–&]+&xÐvMûtëEoJ?+5Ü+UÁ6{6pÔBàö°n Ö«¯¦ŽÏ†Ü/%×»• \»T~ª0GA0äÌ£€ko2©howЛ7»cêjä¼_ä$™<ˆë5ó'ýˆµ¶oÁ•înwjiqU]i±U¸M1×BÙ:íÜ+÷78àx§Á ?^Ö \»Ò…¿C®ð$æCºÔ8Üäô"u+aL¿ÐÔZ÷Ùóf7•Õo¯¿é†‹Æb©ccrëW@ºõsºÂhZ¼Ò“©'Ü‹HÉû³+//wCÊ88ïàóâVz~À÷»E{z²ßŒêyv™4ŽLu¨h°Ì¿E£íSẴ!%Û¶¹!®É¤ äË˳ï,ä¸VO+F«‹¥Ò$ÐÓãÞ {ƒ @6m˨X<#/¤ÿ­ÖºÒâxܽÉg°ûM”hã²tÜÚ†¨ ÚÛÝ·5½Ã3µã¦Q‘ôxý+ÑTÕ½ÉnÝ x^Æ÷ÑÀÓ#ÞÀ 7gݯÜô€ësãñ¬¶¤ª9&XîßZÄ{1¸ÏU7iÔà­L›ÅãÚ7%ÔìÙ®ˆF³¯X±÷ã= M.OüY};joUºU$å~ŒËáî”»@eÏiâq` #ÅÈVŸgiŽ×QkûæA ûà@°yŒ›FE‹£i3ÃÀ"sEDuŸ‘jW!"ðgôÍÛ“Löí·² ‰1n‰zòZ¿¿UÝàææa¯[™ý+ Ž!e%œ? nSaÛ­ÚªÖœl—úÿˆ%2ü'¹bù²tèRï;„ ‘pmÏ=çª]¦L¦MsL9*‚ùÒ`Wá*Ã*rrMûtÿƒƒ]dŒ[I²¶˜5 8Þhð4€'<ý†ØÙ醉f³/)ìµøùÞL–Èn5æ sðV´µ¶ºùú¶nuŸ‹"7·TžAÛ»Ìuö´~Â|±D;`€·ö;ó?šò €ßøþ7¼£cˆýQõ13ʆ=/Ü“ñ"_ìü° ï_{»[Ü¡­Íí7Ö{\ùÿJåyù_{$¨˜úýüØYá9éÐáœ|aÀö±YnU×Rÿ à–{\Åk"‘Ã|bŽÁrY5ü–Er¾´©5CWq…ÕЛ6¹À0sU¯¾Ÿ}–.Æ®ÆM:.¾Áös`Lj²DFðÆ7‹ŠÈ  ÃSuÏuëð rE͈5,eI¯ª©‰€{Å»1ôD]4±Dy.USß^e¢˜;2*L™&¦õµ½w¿UàÍ1lÙÀþ€û°›Eÿ £w,D9cÈF}Tû¯&š.½¢" ÜF¬€Mä·:ÅLÅ ¶¢l„þ¿Ú¥Þˆüv¸MÃP¥¹Ù…(ååî@Ñ÷sžKiDìSmx ‘èw;?jâsT‚c ÌGø.y-Z1ø Çáß…uBG^tÕÔÄÂ}Ïݸ¸{#ð¿O<tu 1×—êcZï’uðߨ% |n¨‹Ã¾4‘p•M»w§‚ÅôÅfܶ9î7ÀwFkhu6ÌÕ]?U/ú‰=Îï]A´²Ò-вhð©)À‡z/ÿ€ß<àúŠ\6#æsX*«‹Ôüì­vš…2î#‰„bÇ×GTU¹ûŸC_&z[Ám-‚¨M¦†YõV}ªâõ±jdtØ1 3×UTü)#Ѥ\UšDuß·iAUUØsMš«îRU÷¦šHd|£óF´qy2bgÃZ÷!¡oIuö¯{•ä n„#(†é_¿¾ø ¢b™kSvR•iƒ_V^„EUhu‰4Ú%òÿ€a†`4ÕFýˆ4àO€ž9Ôf.Tvï;X*) GQ’IÉeõÃCEƒÛúþ1¿ÿÙø~SµŠ÷™g‡+Çú¾{,¦LöÐ`5€¬ksl­­®B)×IìUí7°R¿‹ó$^´û3œ‹ËÞ4×&ϳ"+3m¦ª½ShººRƒ1î ÕdRú¶ËV ö/¸Agâó2ö«_¹Õ9³}Ü7ÀS~àk¸Q§›{±*.Ít¥ÔpJ·Ê¤çíÙÿˆHÁýͦÚã.¯m‡´½ê®–– AŽ`&¼·ã<äkˆÁyÓñÞÁÖñpí–=úÐpA‡ô¿¼ïk=®Å|,ÇÚ\¯XlæêžKÕóû­âìVus°••¹j×yó€wOÞ·ƒÝ à·O¹Å0âñìï¿n –Ê/Š{/rp¾´éÕñ3Äój÷Þ!ؽÛýºSqSy÷þÇŸ¿cGªêpÈ€MÑ¢bŽÌu^H«ö‡C]V\=ÜozzÜïƒ-4“-#vI~×,¢«:OPÏïWñš¾ŠhÄz(ðŽiÀYpýÅþoƒ"ÚÙ™C(-h²[ÍE¿¹º0ú¸C>ÿ€›ƒ0wÏwI‰ë/sé,äfü¸½¡(íÍS &Îs5ì,Ú{¨º71¦†ò<ô­ÔH“ÇÀ/&H`{• Fôó/aÿ#:ï9,†l4öV5yx°T~?ÖMÙÃé’Ô ñöá6 «—¶KJRópå1<ðû¸NOηɣŪ~l¨ËÂ0)sAÁ«x¸ x¶É4¿öZÿU#óY@ÃB~‚Fõ>Ìì}Š–LÛ¸ýA‘H¸÷Éîn÷3äÂì›®z„wíè‹#!Xîß!À%™¶Iß'ÂyØBé]NûÍš[û6öžvQO¦½=œmèê!õ̉X"»³ÿGÕ‡[HwPa=0hK$RÇ­á—ïù~¶V‘Óó»f‘|¯¥V<ÿ¡ô³Ò¶hÔlG¼·ø¸%¿póFàÉ'Ýu9TC­9wdVÍÝf.n˜t¸/hÚÚÜsíÏÉa~¶Xé½cцŒÀB¤ßdò4IôVM˜ƒ@Ïsí`s¢Ð^IUSßVM@¿÷Ûú‰ó:£‚iXÍ’ßÊW4NðÙ£1§¾9ËcWoS–¼"Šo ·™µŠînWÕÞîÞ×c±üæáØûq½ŽÏòuPóñÁ. ïkïbs§ÄؽX¿ÞMöÎ=Õÿ&s<@SÔaJ|a>Í/Èé’4¢ÃV…Ák<îÂמÞ(ß÷‰Üÿµ5r3®ÑŠÜ¯9þXk®ÏtyúéÕ³®Ò§ÀÞxŸo«f~'A`3†8üKäåœÿÇ´ÝC–ñ§¿F<Ï…j]]®ßˆÇÝþ~¶Ê!_Ú“ÕE\»0‹WzRYòLjù†0`3Æõ••ÀgÕÇÀÍ_ñ÷m^xÁU»æ°Aõ!,—¿ý¾ä«Q¬z&cÕf¸2q{»Û¯ÃÕˆsxÏ8Ôk>Zxcó£¶÷ ¶ •&¤‰^„ßhL¤6SáÜücÝŠüò¡‘&®°Bœ&,†l4¬ôE*tH—g͸@žÍûF‰Ýn¾ÁºLÛ¤W/©ºƒÈpžßÏù[(_Ô>Ñ[ 3þ\Ý9!×> w‰D­˜¸s§;`îèØó=£•"× ló~A÷pÛ áè…Ü÷ #Á/soñ8´BÚ!ú‡l6 çøs+÷¦ÎËû›ÝÊCŽQ1Þðûl·ÛÌ×òú~õÔL‡á3šÛ6}4S"±çôA9˜±ZLÅœzöUð" ö8߸籲˜18iàXSàÆå¯°i“«t ‚Üî¼&ãc6 i‰¼ Õ?gÚ$½Ÿ+ürYmÔŠü+5Zp[ó Òû>ÀoÜ'•¾ ¡‰„•!“Sjõ ±mG>Êáø“T8Ç MX|öhXáûÒÀÏS…lFõ¼ä ¹¯€¦žF±˜Of³i¸P8D0¬JÉ9PQìgì7ómòˆòʆ²ÖUç45o½lÙâ*ØÂðÀÍÅæ¶Í7,QÕäuÅB5JÒˆ¹h¸ÍÜk¤¡GXá—oH¤"‹q½î›óÇ!±ò°ۤM¥’i¤ON«ÓF«þ%›íTä]ù=ôs‡¼]Õ~ÃEÃûö‡ké‚Ý£^ùèÿ¤ëêG–§Ÿö¾ïæ›18üpàdëüÀê]ÈÖÓ“cø®ú..{³˜÷£XT½!W˜ %“ж¶ÔúœænT”˜ö …´1_L°¤…Š&,żô•8VL."f?Hq ·C¬xN{¯ Ô¿Òà²QVÒçDláƒ\‰˜‹ƒåþ­…·l­ÀÃÙV³õô¸ª­D"µ˜D>¡ŠßÀÕ:§ vÏ c•à‚‚žwjowGG‡ ÓW# X•Vä”±Z ¨ÅM@ö+“…ŸóÒ¿˜Ê+| ApeNW¯Æ"a•Z¸°ÿÒé_Vc㚨ú±lÂÙUX*«³ØnP6iÉtyú"2áBñx‘6ðªëŠxkÃ[©ÑÀ÷îL?+}¶X ¨©:8.ÔØànw<¬Yãú‹\û5Þ¿ïNÙ Ù$ªÿi“pxy¤*7ɾ_PÁ÷ñ ®4F£C&èDò4 MäýT{×'ŸHsRqðùžð²Q^ úFEõN»T~Z¼ÖŒQ…ùôp[ véá[Ö¦Í?1›ÍTƒ s¼åþŒ™ùöÉäž‹tuyŽ_«Åfv$~ã•<_Ä ƒ¬ªæÍ­fè‚«b[Ûæ*Ø:;Ã/urz‰£é.Œ+Þ°Ãëth IDATŽÃgÃr]8ÇôW3%"""¢‘ÇòRÀ7*;5é-.f[FÕ<7uаª¥ð :¬äÆÅâ]ÿŒPúyé‹TTÓ§ êÜ0Ñ&k<¿X·ÎU¼æ9Lö¬ŒÃŽÇ ³r¸mÂ}>OÍã˜S5›âr¬TΖLDDD4F²QNò%*è–Èϋژ±²L¶x}¸ÍÒ'jö<€Ì9h97èÃ4G“¨f¬Ò±Öö2ÚÕå*tÂ0!\%2½22o&»J²‘bƒà³ÙnàQ ÿä÷yýoµßÈïšã„W’ñ¹ çdK|Ò[ CËlçgSÁåÃ5I_ÃI ·Ý°·c±9›íжô01µ_°@¢|ä_k¢æWƒ]äy®Š­¢hhæ˜ `\ÀÖÔ.†’ûýõÄ|¹ÀÖže²ŠW†Û,½Ò5y£~3Þ‘Wûˆˆˆˆ¨` Ùht(âcÝ„b2bþ_¦ËÃç°b)=pë¿Rb®«JêÕy5¸èÌúá¶X¥“ª…вxN-ºŠp+ù‹Gžn“ð±ž}¿XÍ£Âñh\¯Õ¹^iÜhCV“o…ƒÍs*ƪÇ`#Åz˜4ñ¬C¶ðgªßÐâlÐ1ò¯¯þÀ‚1~úyés±UUuu@u…[IôXó"ÐܼçjùH„¿|F‘ó­L—‡ónO-ô‘}ßv.,DDDD´w`ÈF9)ZuÅÄ»þ–Ívªý'¼Fó_e´÷?€ktvîW,.Ñà­á¶ ÷“0` ‡À¥ï:EÙŸ£àª£‚|Qº òl6›†÷?½j)ïF{yÃÎ16‘¥?^§ÁBÛB–¹è 8_Úò¾ÿÏÞ™ÇÛU•wÿ÷¬½ÏpÇÌ fD2Ѝ - Vkµ¨¯¬80ŠRµ}ß:]µÕZµVå•W;XA«V´*Z©äDf’„97äŽgØ{=ïë®{ö=÷ ûì}Æ{Ÿïçs>ÉÝã:çì³ö^¿õ{žgÚÁ’O‡Ý4(ªÕS`#æÛ0@¨é[`€]­èË¥V9ÐÕÌ›gBEð<€MÏ÷ßlÝjÂDm²ÿšß3ó=8ŸšWØ¡øy”Ì[7c;zªš®k‰ípŸAA˜‹¸Õ7„™ÑÜÚ†ºöbY¸±k0a»Í³ssÕöYù_fàµQš]/|èý„êiìû2Ŧ‡þ<‘!dâ'¨¾Îàë«mWœ°?bªihößàßã©ý°9©lñÇ1¿¥¦ÿ–JåºÒä|&Fs§s9åqƒ¾à—×í˜5¢Èù¿UØgiîÍšÜi~‹s±-X,_jBD`*¹ÿt¾ö¾Ýò­\KÃøŠwˆÎ-·‰YiÚçS+é‹}à«qš:×ùÇ—¬ì:ÖϸPÑY í­VnbÍü¤³leÏÂÞîäÍfäéÀ!Ëîð=ï)Þ®‰¼¿›•w 3ÆGöf‡Ç®Ý‚Î-ö$‚Ð`…ÓNs»æïK•O%)™êáT2=¬ºFÇæ/ËðÆ£&ÔAD6AˆÂy¸ÁÀéaw±ÎBE`½7ñ1¸œvÖØêúá$¶„ù1óÔûœîb«ƒSøV; ²µÆÃaŒ&ÌF rÝéÎ>ëÒŠô‘V w,µûy‡×*]|¨ÈBTÌ5X+ tƒn¡Èæ)ü¦¡'¸•}Ð+^k Tô÷Û‡dPجh='¡wwä¶·Çq>ákýÓrëMØ0¹PY—ÈçÃß/´Âu‘­&>sƲž—9c¯êRxÃÚ.õ{Ýîð$“@w7@ióeôõkæ¢EP==X–Hœ°,™4‰G3àÙgƒM©àLïÆ_ÌË úøºëxß=rŸ°í~¯ÂìáŽõý/^ÉÞÇìoñ>żWk:”P¹C ‡ #} x£'¥ÑKäÌsÌó‹<` îqýÛZý^„2Ä­’UG¾¹aÅ1gùCßt¡÷9àCŽæ!Eú°Ët$¡p„|Œ:H1z¡ßQÜÇŒ , Â|/ö¥šq”CX”V”""ÀyP `)ú@ŸÝ8>ºá‚986täÐ3C#3ãßÎerè‘ìö7š‚å‚ÐVˆÈ&DbN»Ø&!VßfÒE6êüÛŠÁ*‚µ¢Xhà²Ú÷¬—ÓAÜè±0Ìæº^Ô¿¶…²¤±½š±ÏŠi¶èPHl^p7Òä¶5~^Kp4€ªÕ,; +6ø¾ß–›­H,âáT×5_üœtO=Y ƒ¸œZYÔÙŸ{ƒvÜîà2ëb³ùĺºŒ.16¹þ¹!`×.`t‰^ðÀ4 Ù‘Õª=à¾jš¼½ömÿPóÇÃ8ßäü9Ußxîré¥p®yºëì% ?¥gôB$FÑL$¦WVéí¾c6k.ì£6/×5•=´ž|ÒˆmÛ·Ï<ƒ¾½{ûûÆÇߋ޻x¾ÆÄz>¢@_SÐÿéö㺠™–¼yaV°ÔË.=9íÿþÔ‚©(¸…ç‰ÁX‰¡¡ý‰2¯Mk°P;m$²­È ¹'¥ó¯˜¾´0ÄN‰›UÑ /QbL%r&23t«V'ž¬Xtw'qàÀŠž={Vœ¾mðä“çãàA ¼{Ü»ÇQ¸9 ÿ—ó7c'2HZŽˆl‚͸«’{É:¸,Á‚¥*Ö2ÈdÆÛp _…·QËΉp=3Zu~ð›Zyþ)8P)…¿½Jå_³_{d'‡üû³Pd+ˆŽ¥Ö™W!ŸW¼ Î×ë>zyÿAºÑ¿…o«÷¡«Á¤þ¼ÑgÐÊ/™`ß lÝÝæåyÀDxþy`Ë`ß>“‹-›%ŒÄå4yïVr9Á ~&‚¶$öÚ…¨õ>áŽà,¸3V[g)çÁ}ýá®+NÛÅŸU}*5—žLš<¨Õäy¦®)±ñë©TAE^¼Ø O8xÑ‹€ /†ö?Ü{/ðÈ#ÀΠ±1¤ ç1óûz¿¼ôeÇן¡ÍØÑºODèTл¦u¤“}az$A%|"¹öÚ™6268NfˆYÍÈZ*oh˜û•}f#f ùÉf !®kú×õëuçX ä·wÜüâÀÓOÓòÇ_†löeZ2ë±;£Õ;S'ø?¥ÛÄá&´Ù!*ŒÇCm´¹¤ê“ë|àûõ9Zíh­¾KЭ:?€=vê„ærLà†Ê›ØaVÔùÌÆé4uMN:ŸˆyÚµVǧPÕ°á@ãÖ!9u½Ù‡5˜k.Xå,ìýjªŸÕäû ýû̓Ã#wß ,Yœ~:ðš×']\òAàÜsÿwà7¿žyj|Iß_GÿÈÛFãÞzõ^§ßÿgq ­@D6AˆÊÕÂá6µÅl.)‹­†v¶1ˆfþ´PdÃ><†£:d´Þ(æ÷´Ï1P>GŸ ¡ :ám¨£Y/¿3½:úÞuÆ EïÄþº5*È5ý‡è†üõ umCŽ_vœ¿hô9”ößÃ%f²­cÓVíéú0ìÝbtÔ¸³‚9 £9Ý·E¨xDðŸ(+²Mm§Œ¹*JÿÀL‚þ‹Ù˜¯1 ¿Y‹þU}îOV$½—ÀuÍkoÌZ÷D>ö¼²×$÷3Ó/AHùxœÈÀ äû&®=› ž~Ú8-/V®Ö®5a¥cc@.ÊdJãT ú•¿žnrÔW4üf 28©"ÁÊÇZƒ²YÀ÷+ö³9å5æþ'Ì:Þø(òþ†ÂµDV`³}*`&+òùð³È„}¬±„çÚ£5öûÄK¡ó'{Ùü™Ý™Ì:xД$¿çà´Ó€ ..|ð®§øÎw€‡††Ö èé¯êºÑ[§þÈÝìÿg>A(‹ˆl‚"Æ ú€¿Ü&Á0A›;Ê&¿·Ë" Ì'àk¼ï¤]1ÞEtH;7ð[|èŸ4ýÜ„!ŸóݦŸ·ÄüK&*›£¯Ø•U|-Ät´õb€] М¬¾¬X©J¥æÿÇh\•Z½Ï}-Õ¯áÄFÃB¤®äËikCOr'Xë«K­²ym”G>˜4MŽõ¦‰Šçâ¡è{·_9÷W×¾˜ÍgÉùGPX‚ãtdîºz²é4sJÚy¼Û¥n8NØ~Àcc€çAÏP3éf¥ô§Å><Œq“ëgúÁaŽ9gùÐ×€ù÷˜ÙXwî„Úµ ؼÙ(Ï!¾HE6*„gájßþ÷àÁ]üô§Àµ×çü±éÓo¹xøaÐøx𼊔þ¿Qý‹b} "_÷ODJÐ>™¡!Ð÷jÚ> ´Z—Êeåë«"íX'¼+ð3žiöyÚÏAÊÙ\n]°²ªýîm¨cñWõZÀjôVßH(…†óï =ÁyœUghh1"Ü¢¯ þÚè¸yï¼Òç7á©”y1›à[ŸÎ<øàA©ÔÌ{%óŸj¢g'ÎıÑ߸ „GD6Aˆf”V¦¶™¼}¤Ræ¹ÞV žlØh­(f|·r•º– „ˆþ›|ÖÇü½Îš|Îê0†ªmb¿k{M¸náz¤´ˆF%ócÍ&l^òàÏ$v¨(¤ð`Ì#Tç:zžY­Ð ·!Ý¡ªw6æØÓñ ŸœqöIÍuͳöÂ…Àüù@&cªˆÚJ¢¾?=™$Cí&²×Œ)Új`k?×B±Ëð÷ ®‹ÚÄÙÀž3KÖ¤Ô¯ à8F`[º8öXsC™)z1}^Ï«Rƒø]”sÒCØîò+•â5LøEp](·mOD9¯0gašÿp¡¬}o/ðÇlćR¢CÍj¬Ðù(¦§§-°µkÖo¸Ü€)žÁtmòîŠsþƒ_òwöóã¹o`Çàß®¿Þ$‚ýÛ¿Ö¯%KÔb,K:´•_„ããœ_ "› Ä̓MÅMx²ºÞ„p'Ë‹«MFpu¸ÂIµîTW®Hn"àCM9!ÃõÒv`a4Ä6Sâ‚5Q×Ñ=.ÏþÙ¹`¨­eÚØ8Úg·o§‘8í ÍUô$g'VØSÏÃã³|½o¤Æ§)ü /€RË­v]-béé™J  Pô L¿‰y„¶€CÞM(NA€¯T¤Gãž¹‘Ìc§`ùR—oPP*çÍV­2JðþýFd›ÞoìPê÷×£*=€mî&þ=Å|Z8ÛJ÷Šà!Ô9‹|ßʧ¾8çsíW¢Ø 'pS))l±d³fâËMßZ& ƒê2INÏŸç¿c"çíãC‡€Ûo>ÿy k¹q·­Yå”ô (­éQ>cöOL ­ED6Aˆƒ‹ç«mb‹X¥Ò 3J¨ Òx}Í;Õ}¥ú$ˆ¾Óèó0«spUýÌ[çc¬Ú6¥l@a])­ý:`à˜šwê0<ÏäÓ-þýD°bþA¼VÕÈ{{÷q^æz„„y êõú*ç Æå” âÿÒrël¾mÇ1ßÕ¡Cæ¹Ûlô¼:¸Ø¸£ó±Y(Ä5 3/ž” ‹;²¢èlåÎóà“¦ßãßd‚Àþ~ã°X³ÆTà†.r[xš/ ¾z[ø fü2ÄÖ7×óÜÂÜ@SÁY4%²:äÇMeÛò¹±`¨\(´ ”‚AÏN[ õdÖ@þA#²•Éèï[ÎIº ž¾€™ÁGŽ¿øðÏ_V_ü韋—{žNë=Î/E_½Ú"ňÈ&q«.¬Øçš`ÈO0,°xàTsÈ(ñ»kÚ¡!ó^ú_Ýݨ3(æ?Ä•T5<·e$ªçÛ²‚kñäZÁÅ='³ž“n ^n/RνunNu®¥,_å^ÌäT9/±ú0çU¯emy!ã¢5_V²=DSÑx}}&TÔuͳöððôÉ…XaÑüX¼#´>;¿­¶­HìyÁjĵõzC¤ÖHä|’ à¬õÅ.59ñ@d¬ÃË—/{™é€Ÿ{nF"x}-µ ¹¶hyçA¾ oUÚN)ÉÇ&ÔŽS\܄وl·ßüö·íÃÄx¤ÑífÑîàßÌlfÓvì0×ÜÎ%ŠÈLnë"S϶$7ãq˜8|ØTÝñ3ࢫ³Ï•v³ÀBž ÛëÙA""› ÄaÙj›X'5`—‰ÄÌ<\qL/Å—†Eر¾ ÇWÐyDøT<άNö¯rÛ½üv¨¤ö冨!tPóâa.âëB˜MÓ¹"õ_é¬gG4r]9üœùNEüZU½ú*ú[\KUûŸºr+;PêŠÛ Êv!69( ãdËdL¸|.WØ'Ž›Í'g[ô½Ûˆd¸â Á‰š(·—uÎFvoÀâ4øŠ©J‘míZ“ŸjûvàСÂ|&«?ÜÈv Õ þ€>[v#…Ùqm MEMKAÀÌÆY´s'°eËôηV´³á fyß›VvêzÛ»xúi#v5 Ø×ôÀ™ÁþýÀ¿àpÙe@ooÙ±^ÎÝóšÖØ´Ó„•Ù!&7XÅ\Df°éºFH Š)ÅŽ¶¨8nß¹Ñ÷®#D¬¯pþÆ!uêRI‘î`¥Và*z2þ± —Ÿ³7ÌØ ú+¡ý xhq²µ?¾ßtwX%Òž.uY…¸ÞÈÃÓþò<“sË–B.‹ ô§Ý€÷³F5N˜{ÈObBÌ»ªnC…°ŸRn¦`È(3Gª,Ãjn%·î4Š+Ë ñ(vFùÍh¨‡«o%€÷Œrël(¼ i ^ã“Ñ#õdV‰l®. R óÞÕz½3Ó‹"5°ÃpÀçÌX¨5°cðƒ»w—¬2áôf´¯ªO_`„­jƒÐáp™ð½`¥™2(ªœOVhšã¬I”v“G-]XOÏßÌÌÀ‘#fb¥Bá‹æòN}Aˆ‚ˆl‚Ÿª‰ùíýÑuK‹,wBôÒÍÌxC¤…†b]l€ùîÓiÚêMärçÞDUª``¢óÊ­ VPN&… M ,­M‘±â"/@´ðÞÉg•Èæûº¢°bÓ Ä»0áÂè{w €Õ3WL&Â~à’ùØ&·ÙÐØÖ•‡îBÆälƒJÇBG’wg:1ÙÚ`«Írˆ“­ýQ*úsN#ðʈl­l£ÂHðO¶öú¡¡Š…?´l¢E˜ˆÈ&q¡|UŸ†uwTWŠÇœn¨«æJ¹N#øÝ»®Ú$t´ ÈvµWeÑ6†’Õ·¬ˆœLšBé´)06:jR³sPÖ%ÚE©Cu8J¡C_ƒ1sÚ .—=tv£µ6Éß·n-Ä2A ëXž‰…%Qªð`D*¡r>‘8Ù„ÚȕقzšŒ£idÆB;Á2:Z}bO•¨Ð+1 AˆM"TUÉj÷›³Ë„ÁEuæà¨h; ÀǺº€îîÉüÛ0¢[B$ѺÀÌÑœQ%L&F¼_^nu!7žÖÆÆÌËófö{6ô1*Ä<ËD¶TM×  Ít‹ø z"»È±ù IDATìÕ1©xðT©uìyÀ¡C@6[úþÊpóg¢en6AˆC®\NA¢êù¼HÄ¡F’(=Ýc«¼µåÍœAñ}ó02^½ ¹b<Þˆf sÙ!.ª¼“Í>Ø„TCF£†R9Žÿ‚H; ñÉŒL¹YÍæbs]óÒÚˆ6´Nm-äü2³±Ât–UZm£’&& ‘IŽc®o×~Çv³1žy„ö"Qy€[\0ÅŠ”‘>G…î{u úï’Ë™\!7Rôñ†5LI9‘-XY«Z&›„ÉTxv ‘ÿ¬!è2šF>o&YªÁj[[$Ìqdx'±)ïd VÞó<“Ÿ(“)òwÊ sãAˆLflJd lJ±¡»Û¼’IãjLX]˜g`¡! $Ÿ|\§”[g'®S)#&[±-›5×·­Œìób¹uYâ;RñþaûÒ¹ìÃÇal©ckAD6AˆJU µ¢Z0|ªa µ®BÚœg4£‚["a¶Þ^`Ñ"ó½OL˜¼ÛÌf};‹šk‚„„E•v²˜ ýY>_ˆ©ÖÇE½ö ˜]"Ûp ¬ãSŸqˆif}¸(±„}•6©ò¹-ף꫓•J¡#È(̸¨ÃVu 5Q,¡H$ZR U+Š—1³q0WŸÑqt õED6Aˆ‹Sfqû^p°YGJ2YY|š€Âp«›Ðøó¡R7a.ÉZmaäšÄ6ÎfÂmØ! °{óGKVžŠl±ÄµIØÇ‚Xè0Ô þo S¸$öÁGkР·w:š?ˆµ¸Ÿn«œ*Ba®0e*hAxòþÓ¢åU «ig—;^hDd„¸øý~˜(’HÑ=œZëãj?S‡óùÃóDò\ u ´~%R]%¿‘rN5¥ …)º»M5P"S¬àØcµIàÕŽ„± Þ`·6"ÛÈd¦(+žÙœJ]]F\ŸžKÉ nB«Èµ&qH§‘îZ ¿ò…j»(Ï3×u>?] Ì;iþ®­s8užÏtdùy*ûwñºF¡=‚Ÿ'øA{äÂWÈŽ9.眔K¨|.á(¢$|W« »9GiÊtú û*„‘ÇצPzN‰l&â–_Ç Gœz¿É‹´ÔçNÀùZѯñ <~ý}Fë¯u bgÝ-‚ЩØYdljž<4Ý®ûRÔ>çq}úæF´GÙ!>.4r•7±á?µ¹ðÔò;uÌ„ʬV.½† XVT Vì3Á¢Æ±6ožù{þ|#¬yÐפa\k¿p+€ÝÙ‚smÿþBHœ å2Ç ºQFF¦ÿm]"°µ?YåW+4*†ÚŸ˜u¯U#˜klúÿÃõwšõÍ%»Ò`ùͧ§ÎÑh y B{2i\~]]æÿ]]fùóÏ›¾ ™Ž1¥íê*®Y8z!€N…‘ç‹ù ÿýˆ†ÙÇ:2*‰m`¸šùCIЇü Ø¡HýoäüÒØ]áÌ‚ a!2ùR‰éɇò¯­quy]÷]hž(Ì9Dd„¸ AW2*33´nf~=;óî\ÿt zé™ÊMü%w9ÒI·Ô48Vªþé8f€›JÂ@Óiã0K$ÌëÐ!óz≂h`…¢B‚⊠vV<ÀVjr,Œù ÉËõA ¡`ˆ“-.£«Òü°ý=Xצ-t©ÔY,²EŸP(M±¸nÏü·Þ؉-cSÓ,Y,]jBÍv=Àvî¶o7}Ö6ĶâZ#:p;Cÿ…,ƒÕG5óGÃìc¿¥Ô4±­Ìw³Z³þo~¤ÁŸHMN*œÂ÷M‚b×­û}½›OƱ]ª¶”JóùÝ÷I…y¡±ˆÈ&qqªÇŠ2W.Àì© w=§¹D«Äup“/fæT¦W ¢šëš¿­òÙÛkÜ"€vï6Ï6TÜnp_­Â:S”*V„óeÖ:™Á zJþèìzžîÚr#°…qj‹Ôq ö¶-¶m©T¡úo#H$ OæÏ/–-ްÀÉð›wO> ìÛg}ßo¨¸fy¶Ñ'hW`lҼνG+ÿ§@¥r´ÖÆÕ¦ÈuA“q¼å7^í€^­·"ço O+¥¿FÌÝÏ]„9„½ñ7a €:*íü‚¨–û'½—6óÝl— "² B|ÜÊ"› Sd6ÂŽYÖÀö0ÏkàÑ›Ãç­RÉ®¿bW_£ÑSr“RšëÂ@mè²e&,ëðaÞ91Œž×ØA­„1´¦)§‹ãÌÜ„‘- ÃE™kÙ‚ÔShs#®÷Z¾h‘q“5’ã1N5 `ÕäkL¸ùolðäa#®íØaBÉ›$®ˆÔ¨¡ÍÞÏùL,b‡þfž´.0¥Ø`·|¾´àFHüa­éÃþ<¥ˆ/Ã&üšJÏ ‚ t>DææÛ„*o—^z©óæ-?üêQnþx­ÃN¢pÔ_hlËÁ "› Ä%]ÍËf °sÕ wª“íVvÜ=cçùŽû8‰Óʽ}›+'X´ ™4 úûMh–ãš0¬'Ÿ†‡¸ÖàP¬ªXAÂæo †Í MÆÕ"²…€¹ŒÊ=}›inÝV94ƒÂöè(al2;–RƱúÜsÉÅìºæõÈ#Æ)ËlÆÌ…jù\Á1Û|k!ð}ìoúIÛzÏüºÜ:ltºŒeÕöaf°ïƒ¬Ø–J×ó@™ ÈóÀžWî{=Q3݃ x–µs6{ÿMaª% ‚ tZ›Ù£D¢¡á¢¯;oþžùÉOOJxgé*…™,LêÕî ÿã†4HJ "› ÄeO˜Gô‚ƒI©ð.ˆ7¨ùQvj—Þê8ç^ò&½?ûu?Ù•*µIе¬ÚÝmÆ9==F`K&ͺݻgŸµ<6 õú5ÝMŒ?¡Aß.Þ¨pnš"Ǽ¤øA}ˆôýæû$X7 ¬ûQAŠÅí3Ãó¦7ª™9˜Û'7Ôê&´ÉÍØÄ—òÑz«zÀ×÷Ye˜œÏƒ<”Ë™›Ð’%hx”ÉÙ,téÎ}•VþØHûr>ÿAr36Õÿ] ‚ 4fžr÷ÂóÊΧ´ób¾ØßAÿ…šîÊ>úhr䮞µèÎÛ®]{è¡×CM8æ!š°O%xÝë?WËù!."² B\NãP«@QgˆlÊYð—¯ÑnòŸµJ”tß]kÁpÐTÊTþ\ºX¾ÜTæ;xسDŽ„f³(7ȉÂ>ÿˆ˜îóY=…؇C  ˆý¹ùÈBÊ—Ž¬³Å/lž¨`¨¨Þ„&“”œl¡ ÊÕEãÒJgéœÃOîluÚ Sœ@ßÄðuŸœ7믠Jˆ40)¶år |ÞkK—'œ`n>;wBŽ–w¶1–9ŠðÖÓ·O¿]*’ ‚0+(Tð);û¦Yûéz=ž&¢[z #yí0alù]N×¢#ó—®YuÆÆSO}ù9GG×á;|ž|"ý»€‰‰PÏø ºÍy^ÿm©MЄz "› Äå±ÊN6óÝÄx@Æ‚æ, LîçÇ.ôη´“\\¼¶”k-™,äX:ê(`Õ*ó÷sÏ[·»v™ÐzåY#æÛ9ÿ×Ëà>\GÏÇ="•™ÑSjzõRÑšH•\ŠÂ$Œ¾Ft_Ák]„¶f@wãjmu+ÚDðÿ™/Å¿a›ó ýË«íÇÌàLj×.“üó˜c€SOFGAÛ·ƒFFʉøM:IoàõêMô ÿõ~O‚ M…ÙäGPÕëÊ0áÒNU;Ê– ¢BË‘MâòQ0nlu#¦Ñ¾"Û§¬ žì}§ë…Å«‚âZ°:¨u­-_nĵŋÍÀSO?l\luH¾ƒ ¾  ·c/¶òÕ=’Ó„°ÑTrødÓÂGmž6¡IŒIòPæ…C /µ¿ÙFæn£¬èµ­nD'`œmþ÷|?³k¬®ñµ¨ò#ÐZÃÃPOþ8ÔÁƒà\®œ«ÍÕ¤¿ëmT_v6éwKaA:ßü”™ÁÙ¬ ÉGø‰¸‚¸ׄ–#"› Ì>Ú/ îÒ[uî%×q²ë3Å«J‰k‰„qª-X`ĵ%KLÞ5Çv> <þ¸q±årñÄ5"|K“ú0.§­Ù0ó4gžãˆsMèÔ‘z-xÍ[qM¶Á|³ó×8€ß`€çÜÔÚ$Àœe¤±Ð×ñüØ}“ÿIή´ö<ÐÞ½ ;ïN9ظؾ´m0:ZöZ'æ«ý t*gøUô(f߇)ÂÜ Pu9.aŽA„;´V7;ìßI›q öI¡NˆÈ&³Ã­nÀ4>7|"%ÝŸ³›Z\\,®Ù }V\[µ 8ó`€,€ßížx„†ŽŒÄ˜çˆÕ‡´ƒ¯òåTW¡…÷k„6›VëPÎzAh#̵ð°ÑÓQ~¬ÕK<\ûžs€,|ôÀÃøÔõr–ϘPR˜ÏÂ"øê-šùã ÒE†˜<1õ»ß«õ+^}4èž{€‘‘òBp¾NÓS|¿€žÄH#ß“ BCðý*ôY $ø-f¤Œ©1ž&E7€õ¡[è.x€$6ÚÙaöÑ"3©/„Ýô@pqqÎ5Ç1!¡]]¦BèqÇ'¯ÖX3š~à à‘GLÊÏ‹lÈØ¡À×øûœŸð5Ýíg;&\Ôó cR¢²E˜¡åc„Ë\ŸÖ¡U_‰äbSØ+%·X[1ÛOur/´3t?ú‹ | °ŽA_)çnÓù<Ô3Ϙ•óÎÎ: ôÀÀðp¥Ïiµî¥ßð¥|† ]Aè¸åú¸¼£¿–¾Oxo@7òX†ºó½ íö‚¸ Úß—u1”"Á(ư#¨U/t"² B\>ªTø é0?ßê&`à™4}qâÇœHŸ\l«……¼d]]ÀüùÀêÕÀ‹OÖèð€ž|ض ì^ÛÃð_‡+“÷·zÄb5ëÜÓºPYT*Œ m‰R#àÊÂ6³)ª˜Ë™k»¡¢±ŸM6ðè‚ ƒxàó‹pP¼NçrÀŽÀîÝÀQGÉdÕ{|oZ½·aA¡!ÈOâr*Ê>%7]`n~U2çú‰?щ®o— lýýÀÊ•ÀYgž üi7ðZÛÝþuøáÀÖ­ÀØWœá/Ã({Þú*矚VU¯F¬»'™4® Ú?7Vm[a4Ÿo|nA—nì!>Πþ,“šîÉÙ,°}»ùÁÌŸâ>ÏäµH5¦•‚ õì̱Ì Ù¡¡Ä©´©òšZøÀùÂè[t"ù/Óš0™Íu é´)l°r%°npIð:ðsßÜÜy'ðì³@6!ÿáÖj9Þú]½ÞW½±ïÉqD\:ˆÞä°›jmmù¼ù·AQ#"8³É¿ÀÁà2fFGƒMÞ„ê7å÷;oiX#Aê…Rò€+“ˆÈ& Æ&»oÚùÀÛšu.ç #oÖÉ®vþ@ƒT ˜78ñD༳W÷¯p€=¾àæÇ€{ïöìòù(¢"=Í Õi¸š*&ho$DTè8£¦°k+´ù~Ìe`…®úQÌJ]S¼œ}ß$õ¼P!£ý‰†5R¡^h-9Ùaî B\+.jQÊ„vw›áÄg½³±g˜äúÃët²û[ÁEA-™4!¢kÖ/;8À¹–ø-€o¸uxøaàÐ!Àó"8÷OpŠÎÀi¢NïªaØê¢‚ÐQ\‡L¥Õ¶º¨Í3èºÓ«çÖ½‚–pQ¡sp´ÿ xÁeÌ LLG["Qý „£Yž×…(¸n(!Wê‚R€ëÆŠâ„Ù‚Ü´!.Ë+‹l6_‘Ö…Ä÷ E'ö4ø À—÷÷’êº7¸((°ÙlǼü4#° ` €{|À;MxèØ˜u½ÔüÁ<Ë{Õ:¼*Š‚ Ä€ˆaŒ§eafhm~ÇZÍu ÎÍúŽïüîzM "¯@3c…çÙ¬ù7 §A®{¡6ˆÌÃXJ"ì…&19Ã.¢® ˆÈ&ñI¢lë^"2ÏÒáƒÇšÒ8}ç (¼ŸÃIL=¹Ù*‘q°-Y{,pÆ €‹l0ÀïÜàÁ¦‚èáÃÆÁVs‘†fW½"° BÃ!º¿ú&æeÃEµ.¤g©gˆ43I¸¨ÐQäXÿ¤x3¹\øJ! ,®w»„ÙCY{o>d³•Ÿ)µŒ…øPÈ|()]=úGfÒ± B\Æ*4ìÄŽ}Š,´ a<ÚŽáP‹ÿÏǠܳg,W×5¶U«€SNΰ@Àƒ09Ø~ù¨Øöí3ÏQÞ§£ÔEx'í‹û^A¨1=Tm›àÏ8èj«;’“Mè0’EÅ€Éû^-ÕAÇÔ»]Â,B•xµr·¤Ï,V7¡6FÊèáfÔBÄÈ BçÓàìP‚0 ê7Œ° ÀÍvfC"Š"@å0@!ãO"pýØ:vÜ™Q‚㘨„%KL˜èKR&Dîp€{v톇ÀV³ƒ Ÿô® _Ä~/‚ „‚€'*õD&/Á󦇊–ë¾b…Íz"î)­!á’O 6—D$›¸P*1ž „‹V|žTR±Y¨‘Q8è-±<œu]D6aN N6AˆKn,Yiu±ƒÚqLHe)g[ì|mÌ¿y„JÇ&rÝï—Z¬$ºz5pz/p,€<€Ílß8`r°Eu°ðŒÞ§>ã]‚P#¾Ÿ&ì¶ÁjÊÌÆÑV.".R %7•ÐaœT¦xȤÈêwàCœÛByJ‰l€yت’,"›P+½eôÇ©:É3*Ž™a¶ "› ĥ˩ø€Âlî;é´×Òi#J•›À¶ùÍ¢ @ÉèY Á¹ÑȲb‹¸®y_Ë—§¯^ SEtÀž|ÁÁ–Íš÷åý±R¯ÇÉŒ¾ 4•Ì–j[Ø*£Z›qÛÙñÞ‚"œí?j¤Ôü¹ ´-t|0r¥ÖqH'ÛHCum”0»(%²Ùg¬jטˆB gÊ䢶ž $Ê Â‚0Ë‘Mâ’§²9g 2‘0Bd23Ÿ{lHiœ¢DÎ/#ï\‰›8¡™ÿ¥Ô*[Mtñb`Í`Ì(8 `ŒÀöè£À3ÏĪ$ 0ÿ 爵J„:su_¨¾íì[W©F?` ÊòóË.~×Ï_yÚGZÝŽbˆðXñ²Zîƒ}C­kƒ„YEIwPÈꢎädj¤?]F?Sü€]u…9ˆl‚UYdLÞÙñq#®e2¥ÝûÁçí¨B›ïàÁH;VAùÞ{AjZ˜V±‹mÁà¤yÀbÏØ`;ŒÀ¶u«©¬jl‘\lì¼µïE„!b0ßSi“àoÚVL~6`¦£­Ô~a`RókÚA˜S\Ø•yß… ò»õœcÏlu[‚0°¬äò×?ûi ²uo”0kHxÂE«U¥òÅI¡$n'PµÐ†8'…¹‚ˆl‚ªš#Èæ&Ê媧LjÅ(ž­û1oá4“ú‡R«”2Ž•¾>ãdëpÀ6?fÂDs9+°Ek1WÓÞ¨oA„xQÉ|ŒA˜yFeÑ`n÷`®¶È0·•x"´7ÝtSþØZx^å<ÿ£KQa ØDøR8–ÏXò‡ÀL¯w›„YF©\!«‹‚Edk{êg¯¹2}kˆ²âRÍV˜+´Ù¯V:—]•ÖÛª›étÕTñ`<¿¤‰zÖÉø—Znœl@W—ØæÏ4€!eûï7¶áႸÕŦµó™˜oC„hVÿf»BØ;¦7 :ZV\s"7¡Á´Á °ëŸ¯D6« úÒΊO¬ïº@˯•‘ˆå¾œÈéïÔ«-ÂlÅ-]±Ñóª‹l$…Úž6è_ƒdTçd˜ŠÉRhC˜#´×¯V:vü²‰¸ƒI½mN¶R÷J;()|/ÞJ£ÁŸšq®É÷åº@¿y%&DtÓóÀ“Ošük™Œذ{7ðÌ.`Ïž‚‹Í¾g;ØŽý—Óxô7Ñ^$“MÈÍ' B7„ÙŽ™güöë2êVÆ?ŠP7&¿ä¨)õbʬÇÐùã¼ó€‹.2b[2‰>…7žÂ´óà qt3Û´ít,K^EPvˆÿ€Ö[…ö§L3ƒ«åÈ25«!4TÆ9ÉZW½Þ´\oÂAD6Aˆ o¨´66Ñ+ÅXwG} »q-eëu4ÀXPÉ7+¦Ó&ýë##ÆÁ–ÍÜlù|<Q1Ý}ïö ‰„1Zôô´E#AŸrî©¶M±ÐBd®sÇ)mqÑ%ÝÃB‹ð}ÓÙ·¯Ej¾Î.ÇȰ¿q±ýéåÀWÇ J$Ð¥è¨.íÊ®s"9Ë"@=®sSMþ†±§mf!sIwo˜$ >®!f- Ç]Pjy˜ëM#VŽJAèdˆ'±`£ìŠuëwu½½…Q».*Ç X)òÎepÙ;£ÔrÚz{Íÿ3““mxxºÀ5לϹûc½‰6Ãó€ññÂx´~"« 4·ÓOTÛÌþÞ}¿àj N*‡N×,B°Zm;³³ºpû¾¹ mß|÷»&€sÞ¼õ­À²e ÇÁUú;Ùõ꛼ÝlÓæ3{Þ·4¥þ°Öýˆpõ§Ñ&avâ#úÄN­g[„¹/º§^[Ï–B»""› Äáúò <­¥uÁáe«mæó¥s±EÎ[æŒßiÇ hà¢Jë‰ÌûžÞ8ÙFFŒ©¡náÙäö:©ñpÅ|?VXð}“¯nllzèœäl:EêsQö³×·RÓÿâòaº(mf/ý çeÌ íûæFô«_×\üçgÌ é˜c€®®‚ÐFüg4–Û nQÝt÷Y‹ßqf?}Ævêaïí ÜIÇñÅÈŒæ¢ï‹~6iu!šù˜¨û2á”z¶EÚ•Ò‰ AGj¤ºtz[]/™4!‚Á©LfæöÑl´—÷Œ¸sY˜Ô›+ž• N=ëZ³N߯‹Kë þ’&b¥Yd³óà”×ÙˆÌuPN€Tª~E0¡Qø.~L¹pÛ23´¦©‚¥ú„HýÑúÚwš½$ÿê—§ðÂÕñÝîS‘î;‰U" öv“rnÖ¬ÿW¥nu‚þû­5hb´iðôÓ&>ßÎh¸.Hë©ëÎ_áhº"»úš¯ý‡‡pï@ ëÿçêE¿÷ø]·®˜ØFB$ÀŒ_:kø÷é6Ô!s¡0— Ä.NC"dÏ.ÌyÇE–e+DÿÂlBœl‚‹¾Å•ÖÚ¥ÖF`I§g6MñƒèÊ ýSäËq=§P%o‚Ù²Yàðaó&& ¢[œÂtV>6¥VÛÄ‹°B›­ÐjMh{ÞŽ=†«mVܧ• #Ïóü˜G™$ÿ×k_þ/\ýfô.>n*"‚JÍP%r«n𾊞µÏ{|)"¼bÚ2fhσ>t¼cx×.cÎåJÞo]Âú”C÷|` ­SWK½“–úk¸ © lÛ*W µŸI˜ë,­î"ܰ ?NïØ ¶ïS]w¦z÷å—=Þü G^ôÂ3â…'¯Å§­V¯ö,Ä¡½ÀÝ;Çöír¹°[Fiçh³÷‹0 B1|\=ï.ú©Kƒ„YNU÷xRÆëÕAhGDd„0á¸J7¥Œ ’N„¨à3®‹ @ûñtœ”D§û+EÌX'Šã`*Ì÷à˜¿­yM8¡å-ƒ‰J&‚µ‚«ã˜W>oÜk==…<}RAè$tJ}•²ºªÈf÷6d4xÇu³)¥/Ös\dóÿ- à´ŒKBt>¾”9פŸjb›Ã žåõ굊ôÇ8³ž‡>:EÇâ¿@—ôË<ÀÛ üv7°õ~SJû·¿¶m2™Ükt›“Ôo¥{½ÎI‹ ´CH¡bFØê8ØU—ö³ƲXûkô@D6a–#"› Ä€µ.[•©’e«îÅ­,J¤x€ê/Ñh̯LnsÙìäæÚ¼ßTÊüë™T4±Z>9‡¢ïÝH­—þ*l>¶TÊlž'9Ø„æ2:€¼_tNØ]laÝlÅ×}­b<oðÁÐ;Ì6þêž>î_¶‘PÈõéû•?GÇM½ÌfÈFãAÿ‡~Èga|u)ƒ?ÆÀÒ(Çcfð¤í˜|”Ï›\ÃÃÀÞ½f¦Äª™ù<ày¡…5`¯µÏïInî,·¶Ð¦¤Ð·LF’Ý%€WŸö³Þ€DìAaÐYé‚P+³6G‡ 4f>·Ôr"‚ë ôõqÅæg«G˜(è$nŽ”™8.*æš³íÏå B›-v`ÿïÎÊuXè‚>¶ÒZû™ÙÁðÄ„y‰‹MèDÎ_…ÚŽyJô±Åý_” £–ãVž³y„œÅÇ_Rtw]]•‚Ìú´fµ¯UÐý8DƒúF5ÈË”â5} =¡»)Þ¡M~·‰ èC‡ ‡‡¡ÇÆÌ+|X¨èY>ÊÝÄ/Mn†lB}ЈŸÒwxE=š"ÌF‘Ž{ˆ<*1a6 "› DåNvAô¢âÅvÀh?ZXïáèá¢Ì¿ÁeÔ˜™ _WtØ&§Ó&ìѺ³r93±_áÈIVM®ÞN°æµåÖ+ÍöôG›’ÞWèdöá^„ ÷°ý\½'0„XÉ—;Nv0ýH_°z5°bEùêÅõlsZ×ÐØæ ê¿qä”Ï÷}>  ÷p_“šaп±V—(pÚÔé}ûštnaî[° ŸW×£!Bƒ¨¡JqÃéEoÜC$”/ÜT: „¨õìZ¤û×f‚cÉà/ví¶o/¿›& 6©…m â€ý€Ï1 °ËÀîúÅ âã8¦RcÍÓ <Ä ÷¡ïJO˜sJG/4–¼FF)| ½dBð1Ñ4žwØ?#ð¡¡ÐçÙÆ|‡x!‹4c åmkõû*ÐN!>&”C`Ôga„1Ç÷Çò fLƒ NÛ僻Á裗À=ŠÐ—Óþ¬K[ ňÈ&qØ?OcflNPTéî6¹¸¬ki|ÜRFt‹ábrXŒ_Gn|5¨zøÖÀؘqç%ñ™ÏlC¾ÎGlÌ„õÂj›™ÏÌ†Ô B'££·P¾7”Èf±!Ó@ÁÕV*G[¨cÿ9€Ï×¾gg£zæÿ-P˜Ì9ê(`C7p¨«PÁ¸$ liRÛ4±ðöøiñzÖ"yHkôt+ôƒ1?¯áë$ŽøyŒv3Æ1,Ažnƒ?µ§ 4zÌîÚ+7ZïYR¡®(½ˆX¡‡ð< ?nkÉó'Ì]Dd"Ñ.}+Ñà·¡„ÈD5Ï3!•cc¦™ï×G`!RüFjÜS©å’øÖmBSD=¯Z˜R<¤Ä,Lß$¾‚•¥|Vp ÅÒéÊ¹ØæúïJè Þ1oˆnð¾Á ·†ÝÅ„Ò4a-ªÈæ3q'p9uŽ —¿šÇ‰î7LÒß¼f-p6€¯ï|¿Âù,ö7«™[pÀî7IA„A² BØÔKŠÑT%ÉÞÞBî-+DÙ°ÑX¹Øè¾«ýU „Œ¹®y@¡‚ckE:;ïC³pÈe¹uJ™ÏI)óù«ÊZìõ!úšÐihü}a·µ}žéÿÌ26Ù «qzÄ=;Õ¼0÷šD8ùdàÍöز¥¼HOà¯a€ÄV ‚ ‚Ð`Ddj&b%¸ÙÅ‚lÉ|lVds]󲡢Ö͔ϧA >†·Sc^„C•VÛ$æù¼yÙ2PǰQOõÕéH G]Sjy0ÿT2i®+B©["xAh6×ô"èëÃnÚÌ¿…°Q öû‹bÿý5íÐÉ °ËNòï¬C¶·ظèðå-ÀøxùND;Κ×PAA„¹‹ˆl‚'éžW¼¬”ÀF9bBEs¹:äábh½ŸŽy”ªøŒ¡ªMa†ïrÌ%ÆÕ–H˜ÐÑbwJÍâ¬JΫµÝ-á¹ À ‹߯օâVL°ŸÜ‚B¥ t:ï~¸–탓 A9ʽ×sªæ;gÑÈ@™ÀüD8úhàÅ~àÞ{+†šâx¬YíAA˜ËˆÈ&ÐÌ%s)e„¦®.“+'™4K&cBcçbSøk¼‘&â%^vo˜ÍìÙV-~Vh‹2xv\œ\óN­ å­«´Ú~Fù¼[ÇÆ •fmÒ÷b1RÜ¢BGq- ð‰Zv †Ì»ak»þÝΫi‡NäÝO§4»ÿf\l„žଳ€%>yOe"ñÊ ‚ ‚ 4Ù„HDfϵ6À.H½´x1ÁqŒÈÖ×gŒ64Ð:˜bæbótN}1^ãC’K=[mû^¬ˆäû…œs–8¹–´ï¿:ÚžÍEÿ¤Ú6ÁŠŠÌ[p™ t2Z©¿#Ò4‚íCÌï¤öÃ'þX”óvê„_D"ÕEDp]`Ù2`ÿà©§*LÑ^æ›j—§Ü”-£-“BÛã8…ü‚Ð ØÙ{é_¡£;P•R9¤"ЋsëМֳpb}ñ¢`¨h2iråø¾ ™^ð *\ƒk)«íaùKš0fÓ`…@›À?x½D‰.©m‡ÀL¬èÅ‹‹CEƒE/‚ÃGƒy©ÉýØq\Nã ê²Zv1¹õ´B‘`>_æµ1ŽÐÞ|nÿÿoï¾ã㪮}ÿÖÞgŠ4ê’{Ã6.à‚ÀÀM0v.á&{S °±pÒ¸!(¹„ Ä„›vÓLÂ#qBɃ8`šM1ÁÓŒÁE¶,Ëê3çìõþØ>ÒH–¥éEZßÏGKÖÌ™=£3{ÎYgíµr |©_‹­²Òf±5ø¿÷Ñè ±Mâ?ãÊHÖ:c{ûÁ'FÿÄ¿HVm¤ˆDìÁY‘ŒY¤ÒꪓÝ:\†HÄž\ˆƒˆŠj~“¿žR¦Š²ë¿á'NKùEÚYÝççÃY}ñYl‘HïRQcl0Ř´^Ä·M­úqz#Oïê6ñÙlñK #kRšqvóƒ´ÏÔ g—~–Ÿß}Õ_VŸ½ãK«†)Ü _HÞåø9€-ÉÞ¯>•%ÓDÞíÉ>nQ¸ls€¥Æ/3˜ÞìÝ;øÝ9 /Ëæð´11´µe à¨(:~Z! Y0hÊ…(&2¿= ²‰£òþ±sNx+¨ÓûuÚ[ɧU]ÇBéúþÿ­” C!›ePVÖ»\´7c)õ “{. ôó “@йm€À=Ùk-L9+ÉÅŒÔî˜DŽóÛÁnЄìÿÕ`óƒ“ýëR%?â= –Ÿª‡]øp˜"b†J9µçÑ${)ÖñôT»P©93n¢`i%!&MÞ5 hðØc€ë=¸EàŸáÊZx:Pâ/õ'/Hx|¸c¶Åf‹„òâÞ(’2òùAJv£ìøï·Ì2¿ŽE4¿ŠÉ'çÙBíñ'ÿ¾ø`AÒˆÎÓkù™inÑ-ý~†R¶FN$„Ã6¨¶o°gpð 'MWù æV,å¼3œçáþDo;P·À2 “ ¶)Ï»4©;äÒÍ­‹¡6g8Zp-þ÷ÆpO­6?¸–æ’Ñadó÷­íûJmEârj$`y²wë`K)›Íðšd· }gï|„Ê?ëØFN>àwƒŸ,Œ×ñ¹lÑÔ“¾-©§#‡Öö H‘d0:Îá Ei©|˜ˆ¢aˆ4JKm6ž‡G?s£HæW10yÇŠ#c3Ø€Þ‹'vÉc|ýœÔ#Ƙ?àÇ\“¡áæÎ­]ÓAÎ9ýÿ[)ÛMtâD[Œº´hn¶¶ŽÀóÒ˜$ Œr®IgØ)»‚š@x1Ñ›ÛÀÑÀ3Ô²ÙtÖsá7°"GýÎÿÑñM¬5þÇÞ;G¾Nñß'ñš1Šï=5ˆøà¾ãØ@›dγ\Ý`k²÷ëˆN¿«ùôîXx¾µ}¢ŠÔ<å—"¨ªN: 8%ܵxé¥Á_#nÁMÙ¦‚qáº6ÈV¤Ù""ZÕÕöà§XxžmûKÍÏ‚ütø"-zKž‰¡»ÛÙd~9”*¾ùUA‚lâþÉ­?Ÿ÷ï™þ@QÌÜæâ9Êa&rTŸå“ñYl%%ÀôéÀ„ ös<¾öVZëzïÃ2Š¥·•Ô)V wíó‹˜Ã}:ª¦… ° ÒÜJÆéЦ`I]ÿÀZŸ“^6FvÏÚñköùÝFý¬¶ÔNŠè=5¿‘ˆÖ½IÀÑëÀÊ S!b6êìTî:P}¶äÚü7sq™ÞøB­*°´£ý,éùó <|pè‹7ƨ¯æb¨ ¥ µ}ƒj-ïÅ ço¬uFºbåB§Ñ%%rµf˜ã–ªgª°t¥ƒ‡±cíözæ×XÌ~‰¢%A6ч_#Ê?±ÍDWÌ£¨Wkqu¦7š-zU×'Az¦ÿ³\ mæZe¥=ùomm&[úËDñc\|<#O E^ Õe‹7X¦c*KÀyW&;†¬:}ƒ¥?Ï^è9ó5žÃÏm3/#MóXðç(MãÞÅ8ÆÕüJ¢¬¤=šÕ»ÓÝL sF© {?K÷qó¦áù2U:î5 –„µ¶‰7'œ|pÐ `à«kðÏ"u9VR[.†Ë€½ÒTS#'ÃT§9J (Ç)š [\×µ)¡åå½sJ—Ô·®È?ˆ¨¨F.Îå쎣Q[ Lž ”–‚ˆ¤æå0Ó>ÐüªµtBä¯'úð?ƒŒ±ÙXñÇO™´1ÌÍXÍÓ2ºÑl¸¥¹Ê¨ÀOüãkE••Ù:9cÇÚ û÷Û [[[šËD§Í^µ,Í‘§ï*:Dà¥rW¿îXš]UÁ  q W¥µ‘ Òõ§Ýì„Ã!?{ßH÷˜Qµèw&º]? Ô¹hR†ÌOüÆ…)>C4°Y¢€}ùu`ýãŽþõ"EaqWÐDêÚTî›NíO&:ßYÇg¥ò¸yÕð`XUŽ‘J*+´¶lóæ—Œ°v#°wï¯ñßÌr¬ËÉxhöbp]`Ê ªÊž®ËÕã‹ìS”ÅÿLDvR®¬,šúfÚxÆØ1ß3îÝaÈe›a„€¾YÌŽcÒ3¾$'7”"µÏ£²ÒŒÊ÷¸DæDÐ÷â8ٌۉe‰p‘“ÓчÖö¤Õóz»úuزÈlÂ\ž•gÂzÖoò#~ÐCk›Å6v¬íö6j”}Íöì±ÙliØ9¢NGÄñ:¾œì}2žÍ6ßHv ÙPÒðÜUÑW–”Ø ÆÒRû~9²ÎšºP'"H¨=¿l4¾lH*FÉx7'w<ëjéó ý}C)›S^n_ccì12€žåµ~SQØÌrÜæ?¦zÿTmž1÷bU÷q©>nÎ}sGµª˜ÿ"•VMìœùó‹gÓü`ÛÐuØ´1ésÊÙÚ( vaŒÍ©¨´†fåêñEöiãLèóDvbŽD×ÍÚñaÆù-ß9ÆžÄ(Ó(î¥å¢ÏAðˆÿ$²µ[ÚÛ‹rÉhÀ¸]p] ¶Öf k ˜‘ïq‰Ìq Æ÷ù"{l ÐÙY<ó«8‚ÙD?{ͯ%f—®eýÍ=†¢æ|‡#Ù~ T¨½¿„ô øqg̰YÜÀsÏÙL6ÏK7sKÕã“Ôž‘' WT4óÚTî_{,† ¬ÀºCyÍŽˆ\»éìàŒ¹?3ÆžOúÍôlí¹~Yl„ïvbÈ‚ }_££7ŽHÑ©zµûþî™Ý­}‚×~‘w¿£h$b3Ù‚Aû¯ÖñKØí&äø£Ðóqú|mO{KÉÖgSÎV¬á Cß2ϾõÖ©ªr\#Ej¦6¸ÿAdOøkk‹æJ‡ò`ß<ÕÕ¶Eïᬠ@¬o–ž(^­ô¹`O~7ÙqãìADR†=´µÙ¢… pA5¼:Ét¤ô1=ßûÿ‘HQͯb`d}0Û“ØXÌ‹rAŸ@åæ¹B+V­nëøOvBÿ O ²¶I“ìñZc#°m°k¦÷š)âs±‚^ËØ“È£õ—ÀH)³®€-Õ×Gqä–”î˜c®ùÃÜÒ§ýeüx`ñb`ölðim\·ïËBÀ—±ŒZÇdŽ ´õÏjK&¸`ˆþ¤×òG¾C>u·Q|€M©Þ€Z `ç"Y¶1v¹h‘”ñ–’Ë!Z 'uÂâ8³ «¹:Ç› &õ½ÆÿÒUUNÀ …ìqõÉ'Ÿ›œàºFàž{Žœgú#R×b9µd¶<7ŠÖV`Ç`êT ¢šHq=dË0AÌ=¡=KEǎ픋@©v]tvÚ¶ï@m-Hk¸Œ©Cß[ƒ AÏ…ØžzlµµÀÌ™€çeFŒXÌÖ<í4 ºD>Rs˜`Ã=™ß=ÝpËË‹j~“ ›8‚=ÉÏY€íðƒb*…Í3…²tT}¿u;¡›¾5ØÂaû™}ÜqvÅ`{ûíôlDêZo¹sOFž@¦-£¥ÔÓÝLZu–wÖpJ Ó1éŠ;ƇÞñoOÌš :o ðÎ2„nlb±þ'¾ÔhjÕwz~¼€<‡yœ#³þo1…+Y†Í¯hù;ÖðܤïœKÑvŠÏ^ÓÚتªl¢„R@K °oŸ¿ »÷ (ê¦a#ÏEtCj|? $Åùµ‚`^+¸¥£+,ÓßÛÿw*uƒÿÙ2~<ð¾÷_™ࢗ€»ïhžé‡ù1³ 7ådÜý„`:{‚Ç Ìž Òm$KF‡ /ô¿')SM=ìîü΄‚˜¡C&桳عÓÙN>()A ú£ù›È öœ¾´Žc3ÙÚÚìW °×…hÔvS;8æÖ8Áñù›È ü ç?ûrâÄÄæWQÐ$È&Ø“ÿä5o'­„™5oa›§©[}ƒC¥«€Þ 6Ç¡ž.ÚsæógÙeµ~€­»;Í«ëÌrúfÆžExËénÝÉm&@òØlÀmíㇾefŒûüŸNüëůœtJ.\àO<tvù÷fãžs8°Öƒ˜‘èãõí4Ú7ó/ù`/&˜çhÙ«Ö¸?ÕkÜ‹±šëñC®Åz.ˆjÕ÷ ö³C#ûU^Œcë–”ô”¥è™Ÿ\·· r³mE&\LûX©é`ÌéãªH9ÛÔ/ÿÍd.[PßÞs¥ž¿¸…ÊëNw»ŸOœœûnàK0À²—€¨ïIèâ> ”»:lñ‚0p]û8w.pî¹@I <‚»w÷Ÿà\÷,žÈ÷Ez<6W(.XQSc'×lãƒA(¾ 3)A˜]èê^{ÍίgÜy'ªÚ;¾Àõ¦¶$V’D¦óP Û-¶'0è”U/5ªù§ˆŒ«—´*+&LŸ| @=€o¸åw@SSBn:ØQ³p)½•Õñˆl&Û[oÙ“‚óN.Dh×®`ssìÀ¬ËçøDzLT-ƒ>¼/vMó¢Ev²~ûí!÷ÓXdZ°‡6tà€=€;ï »6û©§€Î½w3ÌxBa,mÉÛUÉaà¸>5­fδA‹¿ýmÈewÔ\ˆ~mϯ{÷ž_ÿX°zï^ç@§Y ˜ïç{Œ"uÕŽºàÞZ—£FÙù5öíòB[ È}£#‘0Y.*z¤›ÁæÇ¸†þ Æä±Ö‹lì.ñEÏÜ.¢&sP¯åœtþó×kuóÏ«ê1¯S(2Á_ê&ON: Xr*pLðÂëÀ}÷¯¼’ð•¢ °ù–Ñ›Ì^JÁÓŒ!:™šÌ›¸ƒ3·ttIƒSqÝ#Wï½f÷ì3§,øðéÀ ÀÇ›€›8`|0«ÓšMòi:`[:CK·;kBŠÙܪÆâ‹ƒÝ,B±ò@ÀÇjm3Í”"(E}ÞϽÍBzßS‘Ho&üܹÀ©§ÚZ¾ æ“ÇÛc ϳžß|ÓWvtøE¹Ïë ËD‹Ü§+pLMðÏœ?6A1á& ›6µ–¿œùZ Løîîãõ-Íw¨1³»LÙØ¿ª²ê±~çÐ lI¨KN³Ù±\ÒÜð3`ÿþ瘾›ÇA©cò`€ £‰±­µ7mÐ\t0j*ƒjÕÎPøÝ]Å€žŸƒšˆÆ×{²ØÊÊls‹ã·iüÍÍCn#À…qÐèff{õæÙg—ÿpê{€ùóQ[{pº*ßc)££Ö³L´¤˜28áû÷~ýõ!ƒÈÑX“TÔÄÌöÊã¦Mö—\ÔÖ¢ÚQßÛUÉù£HÍ«õ¨ +ܤ”ùu#&M²Ýp·m³ÀC` ²4Éd™ò*»zIŸzTË(Æ | 1ÿ0} ;ùKãâ—Âõ;Á6¿§ÕæmbWº£‡ú×¼JÉe›zÖ1ÿÎð: EJ»L-°ÂaÛØ`É›f±À?^°Çf--éŸà+âs ¶ÉA"VŸTkøƒæyEu›z5Ÿí®ÀßlNU –48‘Åç|LO9ñ‡Õc©lÞ<àìIÀ9öøÂóÀ£½»\Í+é±Á‚º””y$¥ñå³¹·òq ¸|¢º¶^Ä»Ú.Ä6Ðæ/ó4Æ~Odƒpþrk¿#ù”)À uÀ1‡··À{[lðzçN»T4Í@à_¶«è¯çªÉ¬eàÓ9|X¾‘¢¸kÍvbZcþ‚Ýx ”Ä2G&ÜøJB£æ+÷Bw¬@`L ˆ ¿B!`ž1xç àæX `Õ_mP9å¡°—Ñz.®:‘Axû˜ èêmÝ <¸XºXºêOÒµÍ-¯œgÆW=‡‚¯H̃KàŒiQO;Š4´î½ê8y2ð À½÷‚£ Tl()Œ“À15è6­jl~õ+ áÝÀùç¯¾Šª7Þø~ëBz«üiï÷ù«HÎÞêóU–€/?©©êëéÓ;ï´W톶?ÛãL·‰‰€h4n~½8çÐo«ª¶¼üÖl3aâ‹hÊ÷XEâÖŸ]óŠz"àÓÓñkÊ›ÕÑÒlÞœÐü_-òJŠ}Žë9HM&;mJÙUSp \8ô;¡2³À¸Á6£µ‚Rþ‰úÑN®¹›˜¯3:ú¿¸¬tORÅž"Ÿš¢TÅ()ÿiGû]¾§·>ÎäÉ6Àv\P [#çþûíIÐ]Þ†B8À­Çå%o¤·¡±6z±~@0Ï#Ù©¡.u÷âþÁ–:öhhP¡®ÆeeÖ£¦]®pJG,–ÖØÎ~øÑ¶ÆÑN~‰ø·f¹óC>3ÑZó6†x e¼O{+ƒw ô»³ßz×keçµ´ôv÷ …z›øêøfUUÀ¬ràD3a_„fØ÷Öƒ¶l¶o·‰±Xî»ÇgÒúKÅãÞ>ÚE€£o¸Ñ\®ÿ+Óc®ô÷cô¿ùGœgaÌvv¼“˜w{žÙçhrØsG±Rc3žsá„Î"¥{Vøûãôv¤ž6 X4xìûà!_}ÒÖöLâse5+© ê\/Ä(£¨”ãØ%Z?ý©}#õ«À# ÖÕíF]uNÙ³î½y®HÀ?æ¡z†Ö[Æ0µO€mñbà”S€;î6m‚‰ ]A•s =„® {HÝõ´Ó&¨¶hhN½øÝ7€Ûo77£ÝÃmeÊ|Nj]¾@]¾@Ý4:¨>ß3áŽe»“½ë]öjݺuàÆÆ!?·ë÷ÐS…7?µÌAMY˜š€ÃóëܹÀí·ªøâÀ#Àíêö¢} òŒ÷ç|W ms=*'yΓ£ƒ˜­m`xôhÛ4hþ|à¯6l€I #®Šqm•@[¡’ ÛH‘½ ›ËJMÆ2Ú=è­Öq%±ym¨B×J)hÝ7+æ¨'¶l Œ¹K~ãy±í ÷¸³ t'‚M!ª+`L­VzHýGª? RJ)‚Ö6»ÀTWÛ9î„9Àb؈Ñß<ú ðüóG­Ã•$ÞÄúÌÜÜβÕ\M003ßC¸•˜n!vŸó@¯ Ýîκ*¥:ÐÀôa*«û„h'¶ ¿©Å{• þüt›-ÕÒÞ>Èßñ27ª9‰f¼èÕîû ÑŸ2ød³†ØÜlV>7ÐïÎú}ë]oTÚ ›:V¨­µ¥z*+cë€j`³@ÇÀ««tØ à5Øø¢ bîßo3ãò‘¹Ö›IkŸO8l†]]è ¶uvÚã÷X pÝÄÆ(A¶ÜÎ3É3O¨È÷PágýýÇÿ\ÑÚ—dzçDï(þÀxØ"}kß~hmMj߯ê¤Bûü`€L½½°AD `8óLàk뀷6ÿýßÀÖ­`×E§Çó¯ÂãK¥!BÁ¹*- \81Äßuz&N´ÁµY³’ \€ÕOq(7£šW¯nø‹Àá€Åœ9À×¾Lœ 4\ üýï@{;Ú]Ó®•ZÙ ï5[Ð’ïq‹¾ç#ó3Ê5ÿd\€&Á_jWUeS…/¶u&î¼Ó.¢x<¨O£­x=û£OäÕ“gû9(¶ÄøùuÛ6pWº=~Ä_ WàQi8Sx6‹ŠãËŸà›Zá8ö@¡®Î.ÃÿÀìÕæßüؽ;‘Ìv£·°ÎÅØEj$È6Rd)ÈÆZÍÅeô|B7^ÍÕ¤Ì0¦v3¿ŽS `6Æ.IK´óiÿ¬éš¡+´Ç••6¸2e 0;bu°Å³~÷¢­{èPÂKx†¾iö¨¯$”eUŒØQ£½Ÿ1ÑGó=”ø[?¬÷xlôh»ªà8»¼Ñl³‡ø»^gOÍO*£„™h-ß›b×Ýã¿óåÎ’~sì·Ÿ¹ëдÎëîîíþYYi/ O™Ì œ Û~VîÁØ û¾Ú±ؽۖóik󗛿Ih|7áPÈήkÿ%²É‚A[;9• [VÝÌ%ªÔÜÎŒgzÓñŸ Éîs}®vÿ÷kvN™2˜6X`!€lÆæÝÿž~èèHvŸ§\KïÆÙ쨜:÷Dzˆg‡_›²2àSŸ.ü4°u pÓMvxw7Œ1`€]à! zЉ^ ¦×nœ½à9¾Ôö“ÚòŠ]¶uà@w¢g8D§á"J~ Li¬yq¨@sèàËud _”|ýŸ«¼ñsVøKEû×^sœÞ¬/?@ÞÝÝûs1ÔY‹ßw€ÞÚ‘²\4‡ÖðB‚ù l2dÆ ,óÿ¤½5Bû~¶Ä׌Ïxô›ØÕÕÙsô93Y°Ÿ) À«65=fkÇbÉïûµÂ\޵)לÌ®W—ðjÿçž@Û’%Àµ×76ÿü'ÐÒö¼‚Ÿ†«þûO”X);WTØ»¦Æ¦aŽcwú—^²ÅIwíJâÂ#}^o1ßÍÎ3IÏÇh >ÕÄU(d3Ú®¹Æv$ùÑ€{ïõ‹âój¸éß⯔ûKPü«åuuö`nî\ûýK/Ù@Åë¯Ã$R3ÐêÒ[¸$ãO$CÜ“ôÅĦ§|"`éR;¿nÙÜu—½‚sè̯y4èüê8ö@!±WãæÎµÁá`°çF2ó«]G[Lñ5ÏA$È6Rd8ȦH}Ú[NÖl“ZƒëæúDníg¶ù2ÿdÇ?wÿv½Ç‡~–M]=Fœ\  `.l½­j-°míîðç'_´ËÂ2‘¹Ø‚øfŸºmØf¯ÍêîùDΣJsýÐý—þ½AÖ’’ÞýcÜ8»ïìÚekíµµž—ÈŸ‰6²¢3±ŒR¯×òã–rËÞ#œò6²ñ2¯Ð³ú•º¥¹Ã ½wG2 ²eÀzÖªÉ|‰mÎŒh®ð/Δ”Øï=ÏΡýÿòr{ñ°™›Á -5PºTØÙiƒ½ù¦_c0å“ôŒèâb¨ßÉóPm‚Ô§º8B![£íc³ÿ¹u«]‡¿w¯t1z¶÷ý@ÇEjz^Ëøˆ±ãôÖÊÊìŽ]WgMcÇö<íÜ <ð€ 67'u|¤<žJÏàì<«Ôxõ´@}üÿ)DZÏù¬³lËëÇ·‘ñýûí~ÚÝ î·äp ÷´ì³™Ñœð¿âk»D"vò5ÊîŸõõvÿݵ øÇ?€'žššZ"Úƒ©A?e¾–½g”®G¥Œÿ?™_ GÂóë„ 6Û²¬ÌÙÆ·¯Gí)Jœäü:“žÁö,=-‘ò.)2d#R7˜åt]ÚZ]D¤ÿ2T¶ÞǵÁ6¿KY™ýª­µÿ:0u0;î>3LÐ àYÛl?¼ü²=:t(ÃKÖˆ箎à겡û/Wë8 —0›ÛÃ.ÆêðÙ²ß)ÖÈ––Úï]×~¶dG¢õµÌäFý¡ŒMWuGÊÙŠíðL„Ÿ˜åúâ~§~Ø}-kç¹S±‘ [ÝÁã)Ê?ÍÖRëø­ ‘ˆ/<ÏÎee6 V^n¿w]„kk³]pÛÚl ¿înû•î…¾möªÿJ®Ãi~™zº“mÓÔ>”µœ>ÝžjmëzíÜ ìÙc_8ÿŠ™bÜ?EÝO™•ÃÄø¯—ßöÙ?é …Ð³Þ/¤9j”=ñ›7Ïžø…J€öVà´Á¦7ÞöíK¨ÉA„½z3ÍÊóK/ÄiFѦþÿßSïjüxà¸ã첇æf{ °s'ÐÔ俹ãS_{ÿõ_s»1ÙWÿ¾öƒi@op"±‡ŠŠÞåÓ¦ÙìŸPÈþ=ž{ÎfmÝ ìÚîêJúX^)žLObgæŸ`æx'©_€ùˆ 2¿æAÿ×+~)Ç`óë¤i<`Ï.»œyófàÕWS›_ýj &»G(yG ²øærç“™ŒñÌ÷˜peÒc!‚ãPŸ:kååö3ÙØ Zs³ý¬‰Åz¿2•±7 gXÑE¸ŒžÉ솋حRAs%| 5ô2Ǹ¥²ÔïˆmÂ[®™Ñ%[«¸Œ4ÿ/˜?±mf‘ºÊ,§ÛúZã}‰oæzLÅF‚lY°†!ð*€ß—‹‡ëߨÀ_Fj¿ìTÑe9Ì÷q@—RÑ] á˜a4½|´ß+¥ìÉòøñ6K*´©ã~5c€ƒí¿ápoç‘’[‘ÈžÀˆÁÅ¿Fþ÷~‹Û©Sm°¢¢˜=¨š Û–Fhö<Üs=ù{ã  ¥ÆM-ΫH}š6{)®vÈžÃ:aKðˆ@Žc_£É“m†› ôvÂì¾ê×FˆÅì¾êŸ,˾:8ÿõa¶sAIIïº{Àf©gž“N€ÝOË´mÏÚ%½=d;'µ´ÑhªÇô;õžœ‰§”M¼ÇMGmÌ üÀdU•ckkí¼)ókfÅï·þÉfIIofå€ó+4m/öî·/¿l—ööË6LÓú)³*ÏHd‘ÙFŠLÙ˜äF}fV–?ÞÎsÈ30%ÍôOÎQ]‚§™¼‹°<øl.¬(­çÕl¾À ùJ’¶°j–UìÏÖ8«x©§ÌŸ‡åµG£•:Û]F÷ ô; ²%F‚lY´®s2y€è¼|%C^eRÂr*êÏ÷$õsbþÄ`·!"Pü20DZ鑈 PøuÁÚÛí÷£FÙtA?…] .´+ÕÕ½ ÀžXO™bÿõO¼ÛÛm&Åöív‰Ys3ÐÞžú‰_¯65šëè/ÈFGû´ñ‰8Õ=:ÔíˆߊÞßOýKžg_c×µû±ì«‰ó÷SÀ×´7Îfb¹® v?mn¶‰W_µ©ÚÛõÇÒÙW•á3èilLóÙä„[¯n'ð¥ƒÝ¦g~¯&ókæÄï·&ØL×`ÐfYúÙñóë‹/öd£©)Sók— rM¡6ê½$È6R¤d#¼È¤æ§U‹j(Ìä¬ÅRæç&díq2†60ǾŒ¡­ùIѸƒËUÔ|‰kó=œÁ©ËÍ2¬å àøO8¬ºÌ |°„”=U‡+¨i ßI-1dËuFT\³¢(’ç·g÷¼¾ËÃŒéûu8H‘É ’Šy1=…dlƒYਮqC2÷éß§O &?p,’ã„üµùJÙ _ Ó_昀Z ºÓÙb.ÈØ³ŒÏ‡6¯Ñ6ØJ8 “ù5 Úoýî^YŸ_õÿ¡§Üÿ—± Ь‘ ÛH‘V¹¦áóÔžÙA39ëp¦ÇæÈpg¹´mWl¾âEôŸñɽÃQ+ŒÅlÅæb®D¡Ü†€¯­~€eÔ’óÇo`…±ÑÙ ÎÇ™ñä£yãz³Býh¿— [b$È–C ¬066O±úO]˜ïá Šaˆp“qԭŸ,t(| ÆÞçÿbÈúµÞb>šïQ …òêi#ïÌ÷XD^t¨ ×[6×£Î0½ *cf‘SLøƒ³™?”ïqˆÄHm¤H5ÈFè⨚Œ«h_F58fÂ혥<³‚•¹®ég~hb]¿Â•‘]yÃðå–Œs®B~nm ü/¦‰«¨0–¸0Ö`ªRæƒ :̳a¯`féõ¡ŠÌ·¼åΆÁn•á [€Vµ¹  VmĦŠÚ`¸DíP耧:@¦“Hu‚½.î„ñº¡À0 ((´V`(xž‚‚´OÚÞ†< Òc4+¥À Àèà ª@¨bÃu Ô‚© u‰6i$È–7ë9èìÃ;Œò>ÎD- 7—À?7¤£YÍ/|jL”þÛÌ[ŒD·©ÍæjŠ¢£:ÊÔ«oü¹|EäÔ«­Q>¹ê94ç{ ©88ÕåAzÀü|EäÓ:õ”YQ,ó« ÛÈa—bž‘ìÝÜîö ¢Kf;‹“ üYþ`–no“ÂŒëm€x˨#‹%â5°B]÷±Z‡NdxïbйÈ^6ã!‚ù©³{ñhVj fC+ALºõ5T—¥Qƒ2R(S戭‘(òÉ#D5y£­A6èÀzÑ|-×øT@¡¼ÛC$ä¡ äTxWh‚Î÷ØF:áiM‡Àî¡n¶F;Ñ#hÍ÷Øò‰…E¨†‡ˆÌ¯…gÀùµÍÃí¢…B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„B!„œ7TIDATB!„B!„B!„B!DvýÂIÕàIEND®B`‚baresip-1.0.0/share/message.wav000066400000000000000000000143241372575704200164220ustar00rootroot00000000000000RIFFÌWAVEfmt @@factšdatašß|ôP×òYãZäMÍ|\ggÛMÉf\ZåÜJÊizTÜÚMÓ[ýSÍÜNè\çMÍçMçþÓJÔçSgÜÓAÍèh[æÔFÔüéTÜÒEÒzÚIûÊFéûÎBéÍMæfÉAçÓSg~ÉAÍÔhShÂFÜæèN}ÁEçgÛIgÁIg[ÉMþÎJ[[¾IþÓ[[[½JgæÜ\S¾A\}Í[N¿J}hÅSIÅMþ[ÁMIÍg~I¿NMÍÜæE¾M\éÒé?½T{\Æi<¼[æMÅg?¿gèA¿þEÅfÛ:¼{FÔåÝ9»jM]ÕÍ8¾y\RÒÎ9ÂþçAÉÆ9ÆúÎ;ÆÍ:ÒwÅ6ÈÊ?w÷¿5ÊÌQUx¼4ÍÕùIù»3ÕÚÎBzº8åéÁ:ý¹Bègº6ý½JfN·7zÁeNE´6jÊÚIF¯;eåÆB>°Ah[ºAA²M\E´AB¹hf=±FAÅÜh8¯IFèÉ}5¯TM\½i2´ZTA¸é5»û{;·Û4ÉÔæ4¶Ó8çÍÍ0¶Ô?[ÅÆ-»ÓMBÂÁ/ÁÎü:¾Â1ÔÉÔ5¾8hÆÁ.Å»=MÉ».κM?θ.ÿ¼ç9Ô´4hÂÉ4å±;MÉ»1[²EBܶ4S¶f=|°8J»Ò:N¯=AÉÆ;I¯A=ܺ<=³\<\²A<´Û>N±F:ÁÆB>¯R7ÕºE7³ø:k·N4¶Õ;R´Z1½ÅA?³ç2¼I5·Í6Ú¹]2¸Æ;Z¸Ü/½¾>BºÍ0ƺM9½Á0å¹\4¾»5S¾Ü1ζ:A¾Å/Ü´E;º4û·\8ɵ7M¸Ô7Ü´:?¿Å4\µB>Á»9M²[9Ô¶Bƾ6JµN<Ú·9E¶z;e°<=»Í>¯M<Ó¸A:°~<[´I6¶ÔBI²[7¿ÉE;±û6Í¿N4¶Ü9e¸f3¹ÓAIºÜ1¿ÉM?»É2É¿]6¼Æ5xÅÕ3¿Å®MMÓÎT8®ZNQ¾Y5¯UY=µU6´[ý6¶Û8ÉgÛ8´Û>æèÍ2¯êJHÌÇ/¹^Þ=¿Ì0ÈÝÅ8ÉÊ7èç¼8ÉÎ=zÒ»/¿åMJè¶.ÅÛèFZº6ÚÎÁAU¿?êú·9èÅAçTµ5éÍE\S´<\ÔæME¶>gèÅA?½?è\´>FÂ\ÔB·FIÉxùE¸ZJÎÚS?¹Sþ}ÁI7³NxF½]8Ázû>¼çAÛÜÚ8¸ÕFìÑÞ=±ãcNÂÒ:ºeh<ÉÛ8ÉéÚ:ÅÊ7êÍÊ5»ÒA\ÜÁ2¸ýSNμ6Åéi<ÅÂ9ÜæÆ;ÂÉ6þÛº4ÅÍIgÛ¶0ÉèhIÓ¹3ÊüÔBܾ:åe¼:Ò¿=Üh·3ÔÍMÛ[²/æèÛS\µ1Îü¿BE¼:ÍZ¸8N»BÎF·5[Á|Û>°6ýÔÍS=±9ÜhÆF:´AÓAºM?¶IÍ:´>B½\Ô5³F[Úéæ2´EþSÍþ2²IÓEÁè;·TÊ7»h>ÉgÉ1·hMæéÅ2ºZúRÚÂ3»NÔ?ÎÅ6¾SÉ2ÅÆ;ÔT¿3¿ÅRåR¸2ÅÝjR]·3ÂjÎ=|´:ÅSÁ;èº<ÒR¸:åÂBÜN¯3èÉ[h>®4ÛÛÍ[<µ;ÜN½NA¸:ÒA¶HN·Fë=­=dÅeÚ6­>gçÜæ2²AùIÅê7³=Ô=µý8¶JÆ7¯i>ÅxÄ2¯QJëÙÂ/±FyNÎÅ-¸IÓ<¾Î.¼S¾6¼Ó6Åfº0¼ÜJé\¹-¹åe\|¼,¶èæ>h½1»[Á8~¼<ÅI¶0Í¿FÔBµ3ÆÍR\I²2ÅÜçEE´8ÅR¾>J·;ÊB·;Q¼Aä>²>iÆN}=°>hèæ[;±?ÜNÅS<³?ÜF¹T<¸EÚ>´e?ÆTÔ7±MJÜæÔ3³BYkÂÑ4¸LãL¾ê7½TÊ=¸ç9ÊhÂ5¹jAÒÝÁ0ºeJ{æÂ1¼ÿçIÓÂ1¿\Æ7ÍÅ8Æ\»3ÂÅAÍ[¾0ÅÊT[T¸/ÁÔæI\µ3ÆiÊ=e¸8ÓS¼:ç¸<æS¸6ä¿JdB±5ÝÑë]>°8äxÉIB³;éJ¿JI´Aå>´IF»TÜ9¯BIÍçÛ7¯BZiÎÚ6´EøLÀë9·NÕ9¹ø8¾ZÉ6¸f=ÎæÉ0ºÿM~ÍÆ0¸ggIÉÂ1½üÔ;ÂÁ2ÉéÅ4ÉÆ=Õù¿1ÊÉE]w¼2ÄÎ]I÷µ3ÊÒê=ݸ6ÚÜÅ8æ½=~þ¼4g¿Tfhµ7[ÉeNZ²8\ÎÉMNµ=[ç¾>E¶I[[¹=E¸g[A´AA¾èh<¶EBÎÍe;µ\IiÂT8´|FI¼f7ºçS>¼}9¿Ó|7»Û:ÓÊæ4¸Ü?[ÉÎ3»ÓIFÆÅ2ÁÔh<ÁÂ5ÎÒÜ7ÂÁ:iÊÁ2Å¿BMÓ¼0ÓÆNE͹5èÍè=Ôº6\ÊÅ:çº>MÔº6\¹JMç·6S¼çIg´6MÅÉ>S´:MÉ¿=E¶MNêºÄËG<¸ì=ÖÀL;·ä>U¿]6ºÎBI¼{;ÆÉM?»Ò:ÚÂ\:¼Î;fÁÜ7ÁÉAIÁÔ7ÊÉM?½É6æÂü:ÁÂ9gÁÓ8É¿BMÅÊ6ÓÅNAÁÆ7zÁê=ÊÄ:UÂÑ8Ù½=RÅÆ5f¼SEÍ¿7{¼ê=Õ¾8U¿Í8i·BMÉÅ8\¹NMæ½;Sºè?}¸FµNIÚ½BE¶gAg¸BA¾ÜBM¶MBÆÉE?µ[>Û¾M;·ýAT»T<¼èII¶[:ÅÎT>¶è?ÔÉe9¹æAhÂý4¼ÔMI¾ç6¾Ô\>¼Î9ÎÍÜ9¿É<~ÍÎ7ÂÍENÎÅ4ÅÎ\EÒÂ3ÊÍé=ξ6çÓÊ9Ô¾>]ݾ8Ù¿JLã»7ÝÈdBy¶:ûÔÓ>þ¶\»BeN¹=dÅM]M¶:]ÎúZB·?fæÎT>¸Aÿ\¼T>ºMæI¸M?Â\è?¹NEÍéÛ:¸RNéÍÜ7¹\fTÂç6¼gçAÁæ:Å}Û:ÁÜBÎçÍ6ÁÛI~ÛÎ5¿æ[NÜÅ6ÅÜþAÓÁ:ÍçÓ<ÓÂ?ÜüÆ;ÎÅIýgÁ:ÛÉ[Mè¾:ÛÔæEæ½?èüÊBf¾Eh~ÁAgÅS[[¾A[ÉgM[¼E\ÜÓMT½J[ýÊNMÅ[SgÂJIÅèT[ÁSNÔÛSJ¿\SæÎ\IÁhShÆ\EÉéNRÅdFÝÒZJÂøMjÎjEÉêTZÅéBÎÒZNÊæEæÎhIÍÜNgÍ~AÍÓNSÍÜBÜÍeNÊÚAåÔúEÍÎFeÒÔ?ÔÍR\ÎÍAÛÎhMÓÊB|Í|JÔÉI\ÎÒ>åÊNZÚÆ?zÉeNéÅAhÊæEþ¾ETÎÍE\ÂJSÛÂFS¾fTè¾ANÂçM\½JMÉÔJM¼MNÜÉIF»UMkÂN@¾ëNQ¾QCÆÙYF»]HÒÎU>ºZN{É[=»ÿMMÁ}=Ææ[F¿û>ÉÔi<¼Ü?éÓÜ;½çI[ÍÍ8Åç[JÆÍ8ÉÜçAÅÍ:ÛÜÍ:ÉÎ?yÚÆ9ÊÌLUÕÁ8ÒÎjMÚ¿7ÜÛÜAè¼:ÜÛÆ=èÁAh}º:þÂSSgº8gÎçMS¶:þÓÍIJ¹Bfü¿BMºI]Zº>J½]ZFµFIÁÜT>´INÜÓS=µN[hÂT<¶[\M¼S?½ûe?¹U>Éêù<¸xBëÍê9¹jM]ÆÚ6¼èTEÁÓ8Áèý>ÁÔ;ÎÚÕ9¿ÍAùÎÉ4ÁÎJRÒÆ5ÆÓ[Fξ6ÓÜÛ>Ó¾:ÛÛÉ8Û¾>gÛ¾8ÛÅMM~º8ÛÊþIh¹;èÓÔF[¸>iÜÁ>T¹FZi»=M¾ZTR¶>NÆåRJ·BRÉÊUE¸MNêÁMB¹UZU½NA¼y]IºR?ÆÛ[=»hEÓÎý:º~JgÅç6¼þSMÁÛ6ÁÛg>ÁÓ:ÍÛç:¾Ô=èÓÍ9ÁÓI[ÓÉ5ÆÍSJÎÁ6ÍÔü>Û¿;ÔÛÎ<Û¾>gçÂ;ܾITè¾:üÂ\Mæ»;|ÅèF[¸ÊÓM\ÎÛ>ÍÜ\SÍÎ?ÜÛ~FÓÉAçÛÛEÜÉMhÜÍ>ÛÎNSÛÆ?ÛÓþMçÂBéÚÔJêÁEkëÌDkÆNckÂBwÈc]Z¾EjÎäMT½F{ÛÔNS¾IhfÅSNÂS~S¾SMÅggI¾MSÓçgA¼S[þÛgA¾[\SÉfFÂ\}JÆüEÉ}æEÁ}JÔçÓ>Á~TèæÔ=ÆiZTÔÍ:É{åMÚÊ?ÎhÔFÔÍAÓÿÉ>ÍÓIçgÅ>Óç[ggÁ<ÛèÛ[hÁ?ÜþÍIg¾IçgÂJgÅSýSÁEhÎhfN¿AÿÛçfJ¿NéûÎTMÁMùRÅRNÂUêJÂURÍdùIÁR\ÜåéF¿\[iÜæAÅ[hSÓèEÆgçIÉçIÓhÛFÅþIÛçÓAÊæShèÍ>ÉéjRäÊ?ÎøÝJÕÌEÚêÒAÚÎN{iÎBÜÓSgþÊBÜÓ|T|ÅEåéÚRûÆFéåÔJeÉRieÅIiÊ\e\ÂJeÚ{TZ¾IiÜÚRTÂNeûÎTRÁZiZÉZNÊieNÂTMÓ|hIÁ[NèÛgIÁg\fÍ|FÆhfTÎüIÍèüMÅ|JÜÛèBÊæSþÜÛEÍè\[ÓÛAÓÛ[MÍÛEçÛçIÓÓJçÛÜJÔÍMhÔÓAÛÔ\[ÚÊFÜÒeNÜÍMüÜæIæÊN[ÛÔJèÉSTÜÍEýÊýSýÊN[ÓèJ|ÉZTÔÓMûÊiMåÎN[Í|N}ÍSNÎÛIgÉ[NÔÓM\ÊûMÚÎNZÍêJêÉZNÕÑLkÊkRäÎNZÍeJéÉSNÔÛMgÉ[SÓÓM[ÅgMÛÍMSÊçMhÊTMÓÜTZÉeNÕÒRNÆùMåÎ\IÉéN}É~IÍÔ\[ÅéJÕÒZJÊãLãÊkDÌÕNZÍÝBÎÒMTÊÛAÓÎ\IÍÓEçÓçIÓÎJ~ÓÜFÜÍMTÜÍEçÎ\SÛÎB|ÍfNèÉI\ÎÛIüÂJSÛÔF[ÅSNÜÉE\ÊhSüÆNSÍéJeÁRTÜÚMU¿]RäÊNRÅdNdÅMNÆäRUÂTIÍÔTMÁfJÜÍ[FÅþMgÉgEÅèSSÅ}FÊÛ[NÆæEÛÔhEÉÜJ~ÓçAÉÛNfÍÜ?ÎÓ[TÊÓAÛÜhIÓÎFçÜçEÓÊFeÚÕBÝÍRUÕÍ>äÎkMäÊBêÒéJéÉIiÜÓIæÊT[çÊE~Í[NèÁAhÎýMüÂJeÒÔJZÅMTêÍM]Â]ZjÆNMÉyUZÅRUÎÚRNÂUMäÎUMÁeNzÍZNÆû[\ÊhIÍ}\MÉ~JÔçgEÉçIçÍçAÉèTfÓèBÊæ[TÎÓIÓÜüMÍÜFéÛÜFÎÒMûÜÒAÒÎTZåÊBêÍdNêÉEùÕúMåÆJ{æÔJ}ÉMþèÓEÿÍ[[gÉIhÎhShÆJgÓè\SÅShÜÓSNÊT[hÎTSÉf\fÉ[TÎæ[TÉgSèÛfNÆhMûÎiEÉzTeÍzFÎåfNÊýIÍÜhIÉçMçÜþIÍèT}ÓÜFÔÛg\ÜÛIÛÜþMÓÔNèÛéJÔÒMiÜÚEÚÎNeåÜFéÒeTÜÍIýÜçMçÉMhÜÛMæÊTfÛÎN}Í[S~ÉMgÓgTfÍM\ÔæShÊTfæÜ\fÉ[h~ÍSSÍgh[Í[\ÔæZTÊ\ZÚÕ\ZÉe]éÒeTÎæf\ÎgMÛþfTÎýSæÜüMÓ}TèÛ~SÓç\[ÛèNÜåeTÜúMäÝùRÚêNêÚyNÕÚZiÜåMÚÜi[ÛÜNèç~SçÛS~ÛèNèÛ[h|æMüÜ\[æÔN~Ûç[çÍSgçèTèÓ[\}ÛSþÔggçÓShÜýfüÎTeÚé]eÍZ]ÝÒZ]ÎiZiÔ\[Û~ggÔ\fÛéieÍe]êÚdUÎødjÝjZÚêjZÒeTÜüf\Üþ[ÿç~TÔæ[üÜåRÒé\eÚzNÕúzTÎåMÚ|üSÓèT}æ}JÜç[gÛçMÛçþ[çÛMÛÛÿSÛÓSÿçÛMçÓ\gýÔJèÛfh{ÒMÚêúZùÎNxøÝNxÒRkyÒRiÎ\}ýÔMhÔhfiÊUyÚê]ZÍR]yÚZTÊ\fýÍ[SÎhf\Ê\[Ó|hSÉ[\ÜþgMÍ[\}Û|JÎie\ÔúMÒeiZÍ{NÔæèNÓÿSèçèJÎü[ûÜÚIÒéieÚÜJÔü|TèÛIæèÛMÛÔ[~ÿÓIÓÛ[gþÎJèæ}\}ÍIüèÛSüÊNéåÔN{Ó[üfÍMýÔ\fhÎN}Ó}T[ÉShççS[ÉSggÓ[\ÍS~gÍTSÍÿþ[É[[Ó~gSÉ[\ÜæfNÊhfüÔüMÉ|iZÓèNÔæ|NÎüSÛ}ýMÉ~TèçèJÎçghÜÛIÓ}\[ÓÜJÜå{NÜÚMåÜûMÚéT|ÛÔJÜÛggçÜJÜæ|TéÒIåéåRäÎNêäÝJéÒRi{ÒMæÔhfýÎJ~ÓgSgÎNgÛÜ\[ÍShèÛSgÊ[[gÍS\Îý[\Ê\[Ûé\ZÉZTÜÚZTÊiZüÔ\SÍf\[ÍfNÔüf\ÎüSæèhSÓ}TèÛgSÍç\gÓ|JÔåZ\ÔåRåêiRÒéNéÚ|JÔæShÛçIÜÛf\ÜæMæÔhSÓèMçÛþSÛÔTfÛ}NÜÛ[\ÜÛMþÔhSçÛMþÔý[æÔTeÛéN|Ò[\ÜæMýÎhSÛÔT}ÍèTèÍShÜæ[hÔ\[æÜTfÍ|TèÛShÔýSþÔ[[ÛÛ[ýÎh[æÜ\|Ó}\èÓ[\ÔçSþÓ[[Ûç[hÔh[æÜ\[ÒéTzÒZ]ÔÚZjÕjZåÜTZÒé\|ÓfTÓç\fÓ[TÜåe\ÎjZåÜ\ZÍ|T}ÛgSÓè\|Ú{NÝäZ]ÕøRÚÝjZÚÜT|ÛfTÛÛ\}ÓéTÜåZiÝäRåÝiRåÜNéæ|TèÛMÿçèTèÓ[iéÚRúÕjdäÕUêÚy]yÒZ]ÝÚRùÎUZåéTeÒe\éÛ[hÔhfhÔ\[Ó~ggÍ[[Ûç[[ÍggþÜh[Í|\eÒZUÕùy]ÎkRÚëkYÑwUëÚxUÕúZúÔiMÛ}\gÛ~SÓÛ~[ÛçSç}ý[Ûé\êäêNÝãclÞØPáínañßOîàîWߨXôíôQöÝkxøÝUzÚZ\|ÛSýÔþgþÓ[ÿçÿ[ÿÓ[hèÛ[hÜheåÜTzÚz]eÚZjÝùdjÝ]zåé\[Ûfh}Ûg\Óÿg~Ûg\ÜþghÜg[ççg[Ûÿ[ÿÛg[ÛþghÜþSÛ|ieÚéTÜåz]ÝäZùêùdÚê]zåy]Ýå{iéúZåéûZåéT{å{\{åfûéüfæè\~çÛSþè\füÔ\{å|\|Ûfü|æfþÓgh~æ[ûÜ\zjê]dÚy]dÚdjÝùejÔ\[æÜh[Ógg~çg[ÛÿggÛÿgÛþggçggçÿg[çÿgþçg[çèþ~Û~\èýfüÜæeåéúeäê]êäyjÝädjÝúZúéifÛèTçÛgfæÜ\}æ}hèæfh~ç[ÿÛ}hèæ[ûéjeúÝjyäyjêåe]éåZåÜifüèh}Û~[çç[gþè\}ÛfhèÛ[ièüfüÜhfæè\~çÿgçÜ\}Û|i|æfiÜüfüé\|æ}h~çgþÿçþ~Û}\}æ}iÜæeûÜûeÚéieÚz]êåd]ÝúeúÜûZåÜ\fæ}hèçggæ}\èüf\èæZûéûfæé\|æ|\}ægþèþ[gç~hÜæ[ýèü[üÜ\eÚé\zåzjêåZùÝjdùê]xäxjxÚd]ÝøZøÝjxbaresip-1.0.0/share/notfound.wav000066400000000000000000000402701372575704200166310ustar00rootroot00000000000000RIFF°@WAVEfmt @@fact}@data}@ÿÿþÿþþÿÿÿÿÿÿÿ~ÿÿÿ~ÿÿÿ~ÿ~ÿÿþÿÿ~ÿþÿÿÿÿÿÿÿÿÿÿÿþÿÿÿ~ÿÿÿ~ÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿ~ÿÿÿÿÿÿÿ~þÿÿÿÿÿ~ÿÿ~ÿÿÿ~ÿÿÿÿÿÿÿÿÿþÿ~ÿÿÿÿþÿÿÿÿþþÿþÿÿÿÿÿÿÿÿÿþÿÿÿÿ~~ÿÿÿÿÿþÿÿÿÿ~~þÿÿÿÿþÿÿÿÿ~þÿÿÿÿ~ÿÿÿÿÿþþÿ~ÿÿÿþÿÿÿþÿÿÿ~ÿ~ÿÿþ~ÿÿÿÿÿ~ÿþÿÿþÿÿÿÿÿÿþþÿÿÿÿÿÿÿÿÿÿÿ~ÿþÿ~~ÿ~ÿÿÿÿÿÿÿÿÿÿþÿÿþþþþþþþþþþþþÿþ~ÿÿÿ~~~~ÿÿÿÿÿÿÿ~þþÿÿÿÿþÿþÿ~ÿÿÿÿÿÿÿÿÿÿÿ~~~~~~~}}~~~~~~ÿ~ÿÿ~ÿ~~~~}~~~~ÿ~ÿþþþþþþþþþþ~ÿÿÿþÿ~ÿÿÿÿÿÿÿÿþþþþþÿÿþþþþþÿÿþþþþþýþþþÿÿþþÿþþÿÿþÿ~~þÿÿ~þÿÿÿÿÿ~~ÿÿÿÿÿÿ~þ~~ÿÿ~~~~~~~~~~~~~~~}~}}~}}~~~~}}}~~~~ÿÿþÿÿþþýýýýýýýþþýþýþþýþþþþþþÿþþÿþþþþþþþÿþÿÿþþÿÿÿÿ~~ÿ~~~~~~~~~ÿ~~~ÿ~~~~~~~~}}~~~~þ~ÿþ~ÿÿÿÿþþþþþþþþþþ~ÿÿ~~~~~~~~ÿ~~~~ÿ~ÿÿþþýþþþþþþþþþþÿþÿþþÿ~ÿ~~~~~}}}}~~~~~~~~ÿÿÿ~þþÿþÿþþþþþþýþþþþþþþÿÿ~~~~~~~~}}}}~ÿÿþþþþþþýüüûûûûüüýýüýýþþÿÿ~~}}||{{{zzzzzzz{{{|}}}}ÿÿÿþýýüûûûûûûûúûûüüüýþÿÿÿÿ~}}}|}||||{{|||}}}~ÿÿþýüüûúúùúùøøùùùúúûüüýþÿ~}|{{zyxwwwvvvvvwwyyz{}~ÿýüûûùùøø÷÷ööö÷ö÷÷øùúûýþÿ}|zxwvtsrrqqqsttwy{}ÿýûùöôòñïïïïïïïïïññóõ÷ùûý~|zwusponnmmmmmmnopruwz}ÿüù÷ôòðïîîííííííîïðòôöøûþ}zwtqonmlkkkkkllmnptwz}ýú÷ôñðîîíììììëììííîïðóõøûþ}zwuronnmllkkkkmmmotux|~üùøöóïîïíííííìíîïïïò÷÷ù~}}|urrpnnllonkknnqqqtsvxzzýüúõòóðîíîîîïîíîíîòñöøöûùþ|||xxuvpnonponmuyxovxtvypý{ÿøøvüøôúùôüéñòôílÝOJM7NÒ~ÛÄ»½ÇÖÅËÞ{~æí_w}êåFI]h|lÒÍØþëàånN^maceuêxovàãßößÕìçÙÓÙÖÒÐââßmV^b]WR[^OGNOJEERQEWkfybîÓØÞËÁ½¾»²°²¯¯®««©¨ª»O8,# "*0>?FKD9:F_Ýﲬ¨¦¥¥ Ÿ ¡ Ÿš™¢¸=+%"#&,=LJ;=K]PPKaÍʽ¿·¯««®¬«§§ªª¦ Ÿ¨¸zB7.%"&%&(-254;DMfþnÜÌž¾¸¼¹´·²¹¹´¶³¹·´¯²¿Ó~üoJ;6321--..598?KOLZßùèÌÎØÆÆÑǾ¾ÅÇÆÊÄÍÏÃÄÄËÌÄÈÏÆÎìÛxùYLG=??>.# #!,SʾÑM@NNÑÙìîηž–—–™”Ÿ> $°›²A&#(9ÚÆÉ[<:Vç¼¾é>=AÁ¦–‘–š›™º |Ÿ›£O) "&-]ËÌI46YÇ´½\=38i®œ‘•š ¡I ³£¡¿/#%'/hNf?=Rľ¹ØD<\A<×·®­«¡›žŸ¥›¥.韧¹-#&'+/1=j4;Bò»ºáSA}¼²¸¯¨žœ£«§š¯&#°£±Y'*+--30=L1=ø¿²½O>9?νºµµ¬›¢ª«œ«,!Á¥´W+,,*)+9bÚ75Dʱ¶|<;B̽¼»´©ž¤¨¦˜¬&#´¤·ì*+*')-?ëO/5A¼­»O:8\ÈÍ»º¯§žŸ¥¦Ÿ˜¾+±ª¾~1/+%'+;áS11H¼­»W9;[Íɾº°¤žŸ¦ª¢–¸,­ªÀc-5-%$-KÃ]-/=¹¬½V>;TÛѾµª¡¢¦©™X<­µÂP25'$;óÊ7+1k²±ÏUFBRuɺ°©Ÿ¡¦«š›;}¦µÉ905&!%6ïÎ2,4Ô®³åF?CYõò­¥žž£¦§–¡% ¼©ÅÎ87,*FÏ_-.=¸®¿JGCOU鯰«¥žž¥«§—¡''¸¨ÌX8?-*vÅP*)=±«ºF:;M_Ù½®©¡œ¤«§“ª-¨¨Óh6:#7˽9',S¯¬ÒEA=FQñ«ª£ž¢§Ÿ”çF§¯ÎX76M½¾/%+Ø«²ÒM>==X¾¯©¢žœŸ¢§›–.ŨÀÆd>/+ÖÂ}))>½³»zrE@>kÈ­¨ œš¡¨ª˜˜&¾ªË·a=',¿µU%/<ö¸Æí;29Ö¸¬¨£šœ¥¤¤”¡+¨²Ê®[5=ÑÍ;3=>×¾¼ÈI8=:Ò¹®¤ŸŸ¤¢¤–™#µ²Ø«º75eef>;4[¼ºÇG0?@c»®©¡žŸ ££™–'!É´Ë«®356Lß]E2?¹´æ=;QH=ɬ§«¥ž›£«¨”¡+ÎÕ¸¡¸()8+ܼÌ:*û³À?9öõ4C¼¶«©¢Ÿ£¢¨™¥)ON¸ž¶)!0&PµÉf9Z¿M*2Il˼ºµ½¿µ·³§¨ª¡ž•%$4$M½À»°G'*(%+/eľµÂçK:17AJhмÀÇÄÀ¶¹³£¥©¤¤˜˜>#98ÍÏΫ¾-+1'",;oϺ·ÉóD45:=BcËÔʺÂÉ´´º«§¦£¡š•¬-0'%>îØµ´N89+',/6HÑÃØÑÆI4<74?[ÎÃ˽¼É»¹¼­§ª¤Ÿžš˜®.,''Bsõ¸¯X1:.&$,WÒǽ»ËÒÍݽ«¦§ Ÿž›œ°0%"9Òľ°³Y5.*%%/OÓÆ¼³¼eL@830:XMnÄÍÊÇÚÈÄ÷»¬©¥ Ÿžœ¦@#".ع»··Ú8.**),>ξÉĺÞ=5787=YÛXþÅÊÝÛÞÊÍÝ¿­§§¤ ŸžŸ¤º. &9È·ÅÃÊI/*(+.1P¼½ÇÅÊú>47<:>_Ìý`ÄÇâÜÞÚÄÆµ¨¥¤ Ÿžž¥©ú" ,E·´ÎÔù=/&%-7>úÁ¾Èß\>38>HfßÌëhÒ×~×Öмº³¨¦¥¡ ŸŸ¥­ï%#+=Ì·ÃélC5+&+2@kȾ¼ÁîK>:88=_ÕÄË`âÊÐÜîí¿·´ª¥£  ¡ ¤®~#$+=±¼vH>9.&*6NÚÎÉÃÂÜG98;BGTÛÁ¼ÁbNâïa`÷¿±®ª§£ŸŸ£¤§­] +4;Ø·»Ô@375/-.>ØÀÄÌÒÉï=53HMñÍÄËT91/8BL[gâËÂÃÏbKIUqçòsWaõÞ×ÜîÚοµ®«©¨¦¦¥¥­Ï/%/=EJcÜÆÉp?2/4=L^[gæÔÊÌîdNVhlo]UcíÏÆÆÇÈÁ¸¯ª¨©©©¨¦©»?#*6@CDMåÎÌvA538Hkû{]dçÐÌÒqXNRcjûúþÚÍÅÀÀ¿¹±«§¦§¨¨©«¿>&)6?DFMzÑÎåK:65=;;CXÞÌÌÖêorüêÞØË¿´¬¦¢ ŸžŸ©Ë1!).3;IëÉÁÈîI:547:::;?KýÒÈÊÔîb\kèÔÉÁ¹°ª¥¡ŸŸžžŸ¥´I*%-3:?KõÌÄÇïG8359=>=<=GlÌ¿¼ÁÎñ_féÍ»´®ª¦¢ŸŸžž¢«À<(%+07>KhÖÊËÚ_E;768:<=AK_ÚÊÃÂÆÍ×ÞÛÓÈ¿¸±­ª§¤¢ŸŸ¡¨·X/$"'+.3:DgÒÄÃÉÝYF=;9;<>BJ[æÌ¿¿ÃÉÍÎËÇ¿ºµ°®¬©¦¤£¥©µâ;+%!!$'+.16>?DKWmæÔËÅÁ¿¿ÁÅÈÇþº·´²°¯­¬¬­µÂk>/*('(*-059=BMbéרâjTJEFHNYjíÜÐËÆÅÅÆÇÈÇÅÁ¾½»º¸¶´°¯¯±·ÁèH8/,+,-/368;>CN^ÿëìw`WPPSYdvìÞÓÌÉÆÆÆÇÉÉÈÆÃÁÀ¿¿½»¹·¶¶¹¾ËyJ;4/..03679;=CKXkòåçíûxro{øêàÚÔÑÎÍÍÎÎÎÎÎÍÌËÊÈÆÄÁ¾¼º¹º¼ÄÓ`G;532468::;AHSeîäâéýofa__dnñá×ÓÏÍÍÌÌÌÌÌËÊÈÆÃ¾º¶²¯¯±¶¿ÚL9/,*,.269;`;ÀÌiF=<<>=:77>SÓþÃË×ÝÖÒÑÕÛÑÁ´ª¦¢¡ Ÿž¡«Ü.! %),0>迹¿ýD96997547ElÌÇÒçÿåÓÍÙû]hλ¯ª©¦¤Ÿœž¨Â7' !#&*4LοÆÙXE?:82149F\oï~üçßçpYXeí×Îø­©£¢¡ŸŸž£²J+#"##%)4QÏÅÏ}\PD9/-/8AIGL`ÜÑú[SYtl[^é̽·¯¬§£¢  Ÿ¡«Î8)$$"#'/Høßêí÷_D5006<<=F[ÛÞ]UVdgZS]êÑÌÄ»±ª§££ žž ­Î=.'# )3CQ_ÛËÖ`>767777?QY`Z\c^OILS\mìÕ屬©¥£Ÿž©»W4)# &,6?MíÖÞ`F=:8568?IOPVøí{wtæßüëׯ¾¸³­©¦¥¢ŸŸ¡¬½W9-%""&*/6AWrøfTLFA><=>@DAENZiúàÓÎÍÎËľº·´¯«©§¦§©®ºÔM;0+(()+.29>IO\^bf]WLFDDBEO_ñäÏÆÄÂÅÂÀÂÁÂü»º¶µ´·»¿ÆÒõTHA;87689<>CHLRX[[\\_^cakdwûõòçêߨÚÏÔÐÕÌÍÌÊÊÉÊÉÐÎÓÕçíògp_[UQKQMMLNROYU[hlfßsnþþúvú~zâyØÒhîÝÖØÎÛÏÙÜרåaÐ×ßtÝ×óëùQv^e]SÇgõfödneõØOnUsLNëkþã]kðbßóväámæßßçùÚë÷øÞèÚÝáêzëåæyþmòldïftwiko÷gãf]kq`aòmcayâôéïú~ßà\î}ì|ãÝÞýîw^æzùéophpø÷xyjWóiûaoUcüaídi_ãþhnúí_aïçùìñôîåqgÿsïfâÚöiw{þzøí}ßj_`ïïjþnm_bèuêöhq_jæÜfsûñûoü\ýæðíñÞînïìêôôñ|yïö|àirîìvfþn|ilúùîr_njq{ü~ïpææxudþì÷ùógêsxîzÜÜs÷÷çiaïlïlfxäêhbðîc^rþýnbpøçòpvjmöûØÜííÿèþml{ntæjÜÜrhíÔuakã~ökuîY{ZhÝtnl`lßfku÷éií{îuþqèl_wøtg÷kïß~aëcßÙõïulpøüu{auß÷hl_[þxiUààklna{íhk]\fphøcoqj`NLUáʽ¸º¾ÇËÏÖÒÌÑéû^[\yàäðuüøoýâér\PKLMPRWYX\]nyôíçñûûoxxxnmkrjgmdbfb\`a]^]ZVVVXZ]`a^[^eoþõôîîìâÜÙÖÔÒÑÐÏÎÎÏÐÒÔ×ÚÛßæîûqlof_ZWUTWWVVSJA<<@OöØØáwkéÎÆÀÀÇÊȽ¸µ´µ¶¶¶¹½ÊïM=60.,*()*.3:AK[uâÔËÈÆÆÂ½º·±­ª¦¢ Ÿ ª¸ÙA/)% !)/;Kzο¼º¼Æí@74//49Aaꮦ¢Ÿœš™™œ¢­ÇE/)$!%+6AUéÎü¼ÀÏYD:668Idϼ¯ª§¤¢¡žœœ ªº×@/)# $).8EfÜËÄÊÔúVD:755:AOöƺ°«¥££¡žœ››ž§·ÎN6+#!',3>VÞ;ÀÔájJ<8439AJkȹ°ª¤¡ŸŸž››¥¸ëI6+" "&*,;HáÉ»½ÐíMC31.3Föɾµ¯«¥£¢¢ ›˜™žº5""3eÍüE9/*$$'0AGU?NHNB?dÏ¿ÁÃÀ·¯ª§Ÿžœ›™–’–¬,+Y±­Á4'!(>Ķ·û>1.+,9Yɸ²¹¶®ª¨¤¢¡Ÿ™–”™º%#4¿©®L)#.ô»¶ÎU@6+->çýº¸±²¶²§£ £¡Ÿš”•¡3$/ø®ªÁ0&1e¼¯±S/)(+3뺲³¾ÄÁ´¯ª£Ÿœš–•Ÿ5&-L­¤·-$*.?Ä®¬¿1$&6^»³°°µ¾É¾®¤Ÿžžžš–”žF*4r¯¤®<!.8Nǯ®»6%#(0?ɹ°°ºÎÔÀ²©¡ŸŸŸœ™”–´!).8Ï¥£À',ê½¹´·ºÈʺ«¥¡žœ™•—¯-HkÉ®ªÅ**dÏÓÆ½¼N/%%-<Ϲ¯²¾ßÕº«¤¡¢¢ ›–”ŸD»¸ÅÉÏÖm<&!(Oı²º¼¿¼¾´¦ŸžŸž™’–½ 9ëÕ¿®ªÆ(,ɯ°½Ëæ]5)#)=Ö¼¶±¹¿Úǵ§žž ¡š“šË "ä¼ÉØ»±È.,È«­»êKD?0*(/H¿¯°¶ÁÀ¼°¤ ¤£Ÿ•–§%?¶ºÔƹ¼= &i®«²ÁWG<9/+,2k¾®²¼Çǽ¯¥¡Ÿžš–£10¸¯¼Ã¾ÀL)"B´ª¬¸ç>3/46NH[O\ÏȾÍÓ¿°¢žžŸš².:´®¸»ÀÍ?$)g±ª­¸ÑB3-2=qÏ×WJ翽ÃáNÚ¼©¡œšžß"M³±··ºÈ=$.|¸¬¬²ÍA0))1Z¾¯´¹ý<@Húéн·®­³®¬¨¥»6%9ÐÁÌÄÃÄå6+%,G˺¹»Ä×MB9F]ÚÅÃÀÌú<39_Ⱦ¾ÅÊÈÈÊ̹®¬¹o8116=DOîÒÑøL<6:AQo×ËÆÆÉØU<15Hư¨¡››«1"8Óº­§¨°þ2('/>iȼ¶¸¿áOJO`wf\[_itqommpwsifnëØÓØâöûìåçìñòíéèçåáÞÝÞãëóîæßÝÞàäèë÷ukilr|þ{upnnnpsuvwvvxz}üøôñîëéçæèîýslkms~öîìî÷vkggjnv|þý|vpmmnoorw|~þ{snllnpu{ûòîìíñõùûþþ~ýú÷õ÷ùüüþý{uoomro}m~i{||upütuqç{æðnoõþótäéõôn}pqúlôóoÜôórkvëõèêzâxíÞårínkpZårßló\ÚïrÛdØbìúAGUOankÎÏÙ×ÚÕùé[ëey]×}ÔùÔÕÐígÜxÖWÙqÌ]kZäýèhÓ^]sNßWöêiUëNïPnÜXãoZä^ZånïcQîäì_ró|\yovxnÚãÒ\]_ã\g^×åêceq`áêåýÙPÙÜåHýqÛfOÓâè]haÒ]eèïSjXñÙdä[_êÛfâ{kcR|õí~cvÙ~ÐëîÐfnÜâßß]êé}ÎêßÏaÕ×ÛðÜÙ÷òÕÌçîöÜÛ|ÞØßÜuãwágýãí~mîïÝ]{àz|jyèeòéë|]a~hoúî\mÛsþêuqïlciwkp`øhözyîov}íhhshc`nóbdfÚyhféó[{[sßímìx|ýÝúY[ãðvo`â÷|lü\ôxfjlu~zhr[tuvgýqüæalñlék_î|ldìügnwpmñhtâab}ßrgüqôøïmwëî^mÜqgè|ôs|ùoòo~ìóeåôláòrxþ}{pzmùèqmìêïÿoàýméëînlyánqñwðüï}ö||âìs{îìôýêýûþïëùíoéîôôééùíþõåðþàùýòóðõïéíý~ðäú}}íñoèõó÷êõ~îïëvóúöýùý{vz|÷ut÷ü{mðoukmëeklùþgqpöjngv{okmyorpmfyýlgíupnøõo}rp~~qúoúí÷vl}úwú|sþìôpÿþðûýíkû÷nñsnîù{n|ôýýhçõûørôø÷~ê~÷xpôvû}{rmô}wutxp{wvr{qt{y|wv{ú|}xñÿýðùöóú|óóøÿ||óyzÿywtv}xr|twn|swõtw{~úz}øøñ÷øóïõùîï÷ôïôúñõýüôùvù{xûouxyxoqw{rsx}p{þûzxøvöÿÿ~ñõxûïôûïòû~ò~øýýøzvÿw}vr|núnwzsry{rzyù{üÿ{ÿôü{îìùùúïý÷ìòò}òõyöðyxnöðwüytyúu{xsuu{}úuûxûóqòüqìñzïðð{íîóüôïôõøéxïü÷éïþtþo~÷~ø{r~}ÿøoþüu{ýú}}oçoýðyòkêåopîëûrïïônòèlônøñvðoúþôjlòóxlñ~òhzôçíforéonõü|÷yöîounmê|mìÿùp÷îs~ûolóõï~v÷mõ÷lè÷}évxíö{vuðükroþóvq}|utnûïóüvonzðöéæ{ùùxïíüçí~÷ùöïrmzgab_vj\c\Zai{âçqir^cÞÛßõzåäÞÜÞÐÌ×àïyybi`VNOU]skWPLJQ_n`TKM_áÖÌÅ¿»º·°¬§£¨¯½Z.%,5=FN;,((,/8FïéÏÆ»±¨žœžœ—“”Ê$:¬§ï(2ÒÄÒ:-xxi¿¿Çm:þ¬œ’‘Ž—:-Í ¬G#$8c×J+5ÚyÎÂÃ{6/`³›’‘‘’“·1Û©¥_!!$6âàI687MÍÄÀü;:@à”’”š$,J¶œŸÁ&#$.Q}K-5;<¹¿Ñ83=j§™’‘–•’» &FÓ¨›­1&+.>NB/+D?È¶ËØ<.8]¯–’“˜“™);Y¼¢ŸÍ!$.-.>9;,7ÌW½ÈIL/6ê½§œ–’•— $òß«²0-.-.+.)-¸ªµËIA1+Tµ¦œ›š—–”N,]»¢¡ï#!3.-872(.eº®ÈX8-2aº¡›–—™˜’— C躡¬:-:-./..&F¬°¾J;82O¾¯¤Ÿš–•”“ž'?-Q­©³D0+(¿±ÊÆ»Ò=6B<;E¹© œ™——•% -%A¬Ÿ¨N(6ËÙïÄÁ]32:9lĸµ±¥›˜——––Q*!'ŸžÅ-$2Yǯ£³@./28N¼±©Ÿœš›››”¢"'!<£š«2"&TÕÁ¬¬Ê518:=N¹¦ Ÿž—–™—šØ((º›žÒ+%<ÔÅ´¸a59L?9Eɰ­ª¥›˜˜œ–’¿'#Óœ›Ç) 0¾Ê²®³_2:7:;Þ³¨¥£œššŸž“¨!1<¥œº/'(+H|Æ«ªú>EP;,@½©ª¥œ™—ž—œ/&&+­š¨?$"##Y¾òĽ¹C/9K^=XÀ«§¥ œ™™›–ž1"&2°œ¦D$ $:·µ¶¹Íù;4-6Ù¿··©¡ŸŸž™˜¿(#oŸŸÆ+#' 0à¿¶¶½Y++=B8>·¦©·¯¢›œ¤ •’Ã(fžœ¹-&'#+»·»¶¼ñ0348+*6KRl»©¬º¼¦Ÿž¡£••?&-#öŸŸÅ'#**.Ö»ÈÌÒN:68=ChÊ»·½¸­§¥§¥¡žœ¬ì.%3H¼²¿B(#$&+,@É·½þSA=75HÜ»¶¼ÎØÊ½¯ª¥¦¤¤¢¢ œ¥a&'(9¾¯Ã3%)./&*=ǹ×OFMA8;MÔÊÃÁÅÉÔ¾´¬ªª§¥¡¢£Ÿ§;')-;¿·Õ4&*14++:õÈà\O[NA=C\ÓÇÉÑËü¸³«¥¦©©§£¡Ÿ ³/$(/LÀ¾ä4**.3-,5ò¼Ä}DJRPC?NÚÈÊÕÑÇ»¸·¯«§©¨§¡ žž§þ"&/7]½×7**/74/4GËÉØMGM]_MN]ÚËÌÌʾ¹·¸¸°®«ª¦¢ žŸªN""*/<åÀÀ\1*).57Kr}]Oa;º¿ÃÀ·®©ª«¬ª¨¥¤¤¦¬½:$ +:JUTOE=51027FFEDC>734:EO[VTWfùx_LFHTíÏÍÔÚ×ÈÀ¾¼»³®ª©¨¨¨¨©ª¬°ÁO-!$-JW_XTTYYVRUZkëÛÔÓÔÒ˼·°«©ª«¬«ª¨¨ª°ÂO/$"+7EOJC?>??><;=BMYfmqkjc][_jùåÛÖÕÕÏÊý¸°«©©©©©©©©¬·ì3!)5GMKFGKOLD>;>BIP]vÝÒÎÔáözýô{_OMPmßÎÌËÌÈü´­©¨¨ª«««¬²ò-#.82.-++,-/4:?KaáÒÌÉÉÌÓÜìjZPMMNQU_}äØÎÈ¿½»º¹¹¹¸¸¸···¹º½ÃÐûRD:51.,++,.16=GYñÕËÆÆÈÌÒÛðhYTRNNQW\ióÛÐÌÉÆÃÀ¾½¼¼¼»ºº¸·¸¹º½ÄÐwTE<62/-,,.05:?LdàÓÌÈÈÌÐØäp[SNNMNU\iøàÖÍÉÇÄÁ¿¾½½½¾½¼»º¸¹º½ÃÎæ[I?:61/-..149?JZþØÎÌÍÏÕÞïj]UPOOSZgxêÚÐËÇÃÀ¿¿¿¿¿¿¿¿¿¾¾¾½½ÂÊÛoQHA=96200258=CLXtá×ÓÕÙßéümc]ZY\boñâÙÑÌÇÃÀ¾¾¾¿¿¿¿¿¿¿ÀÁÃÄÉÒåhOF@=;8643469=DKSbñáÛÚÛàíûskie`cl|íàÖÏËÇÄÀ¿¾¿¿¿ÀÁÁÁÁÂÄÆÉÎØícRID?=;97679;>DJPZjúëäæë÷zqmmlkjp~îߨÐÍÊÉÇÆÅÅÄÅÆÈÉÊÌÍÍÎÒÙä÷i]WOKGC@??@@BCEGKOW]ciklmnpvz~þûóêãßÜ×ÒÏÎÍÍÍÍÎÎÏÐÒÕ×Úßçðxjc^ZWVURPPOOOPQRUX[`gnryýöíçáßßßááßÝÜÚÙÙØÖÕÔÓÖÙÝàçìðzmd^YUTRQRUUY[]]^_aflvýïêäßÝÚØÕÕÔÔÕ××Õ֨רÚÛÜÙÞæëøf_^[MGB@@DLUg{òng[^Yc[~C:MQôÜÊÈÇËÉÌÌÓÏÎÏ×ßÔÒÓßÚíÔãäßÚÓûlêlcm\]OMP[WR]hn^_`W]Sco\\suoùiúðó|üåîþîèëöììõeec^o{ßÏÏÏÒÛßörnjfjrí{ìçåßæÞäë÷zlhbeifmmt}røxq{ortkmthoqnumþlnvgjjhmfnscrvxowþsqsrrppmszyxóþyùþï~î{ýút÷ø÷óæðyêïý}vôû}úïûzøzo}êäæxuùmjoæáoøåþ÷úæßmpîïîwôátmìïípîØëôìçòkzãöqöïîgkáémkïéfcø|ccõåsi{øÿqþâèkjzõfkßâxmý÷ljõóyk~ãòejñýjsðønp}}qôæèÿqøûxvýøsgtúùøëæëïïíúllsklpøõzïê÷xzürikmvyxøûvyzú|oøÿmhk{qm~~{vyôrm}úùxtþvy}ýíïöþy}uüóöïõùzouttýïîóö÷ôûÿ}{vx~û~xzu~~õò÷}qnplvôùýtüùzþõõùrx~powü~xõìüöóîï{ý~mhfmzsþïñø~òïûøvupjv|{÷òêëõòÿvnjoqs}ûøýûïìð÷óõ~ponouöìçãäçíöxwrqqryxýôñôúøû}xxzyÿ|{~{ù÷óô÷ïú{wz{zþ}|{~û~|~ÿ}|xuolklllnxûüõððøxwoklsxx}úñõùõõø|}yups{zúõïïóôüü~z|þþ{|~zy~üÿ}ú÷ýþ÷óøþûýÿ}w||~ýþúûüúý|z{~||þ|yxy{{ýöóö÷öû|yyvwy~úüúùûþ|}}|~~þ}|~þû÷÷õöúþ~|yz}}}ýûùõõøýþ}vw{|ÿúöøûüý}~þþüþ}|{}~ÿýþþ~|zx||{||~ýøö÷÷öúüûýÿÿýýýø÷öóôóøûùüûúüùùøøùùûüûü~ÿÿ~{yzy{z|~}}}}||}}þÿþýüý~~þ~~þýýÿþÿ}~þûûüûüÿ{{||~þþþ~}|||}ÿþÿÿÿÿ~ÿþýûûûüýþþþÿÿÿýýþþÿ~~|}|{||}|||{{{{||}|||{{{|{|zyzz{|}}~ÿ}||{|||}~~þþþ~~}|{{{|{|}}}|}||{{{||||}}}~~~~~~}}}ÿþÿþþþÿþÿþÿþþþÿþþþýýýýþþþÿ~}}}~~ÿ~~~}}}}}}}}}~}}~}}~~~}}}|}}}}}}}}~ÿ~ÿÿÿÿ~ÿþþþþþþþÿ~~ÿÿþþþÿÿÿþþýýþýýüüüûúúúúùùúúùúúúúúúúûúûûüüýýþþþþþ~ÿÿ~~~~~~ÿ~~ÿ~ÿ~~ÿþþþþýþýýýýüüüûüüüüüüüýüýýýýýþþþþþÿÿ~yy{}þûüÿ|{{{{|}||~þþÿ~}{{}}~}|||~ÿÿÿ~}}}~~~}}}}~ÿ~~~~~~~~}}}~ÿ~ÿÿÿþýýýýþýüýýýýüýüüüüüýýüüüýýýýýüüýýýýþþþþþþþþÿ~~}~~}~}}}}|}}}}}}}~~~}~~}~~~}~~~~~~~~~~~ÿÿÿþÿÿÿÿÿÿþÿþþÿþÿÿÿÿÿÿÿÿ~þ~ÿÿÿÿ~ÿ~ÿÿ~~~}~~~~~ÿÿþÿÿ~ÿþþþþþþþýþýýýýýýýýýýýýýýýýýýþþþþþýþþýýýýýýþýþþþþþÿþÿ~ÿ~~~~~~}~~}~}~}}}~}~~~~~~~~ÿ~~~~~~~}~~~}}}~~}~~~~~~ÿÿ~ÿÿÿÿÿÿþþÿþþþÿþþþþþþþþþÿ~ÿ~þþÿÿ~~~~}}}}~}}~~~~~~ÿÿÿÿÿÿþÿÿþþÿÿþþÿþÿÿÿÿ~ÿÿþÿÿþÿþÿþþÿÿþþþþþþþþþþÿ~ÿ~~~~~~~ÿÿÿ~ÿþþþþÿþþþÿþÿÿ~ÿÿÿ~ÿ~~~~~~ÿ~ÿ~~~~~~~~~~~ÿÿÿ~ÿ~ÿÿ~~ÿÿÿþþþýýýþýþþþþýþþþþþÿÿÿÿÿÿ~~~~~~ÿÿ~~ÿ~þÿ~ÿÿ~~~~~ÿ~~ÿÿþþÿÿÿ~~ÿÿÿÿÿÿÿÿþ~ÿÿÿÿÿþþþ~~þÿÿÿþÿÿÿÿÿ~ÿÿÿ~~ÿÿÿÿÿÿÿþþÿ~ÿþÿÿ~ÿ~þÿÿÿþþÿÿÿÿÿÿ~ÿÿÿÿ~ÿÿÿÿ~ÿ~ÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿþ~ÿÿÿÿÿÿÿÿÿÿ~~ÿÿÿÿÿÿþÿÿÿÿÿÿþÿÿÿÿþÿÿÿÿÿþÿ~ÿþÿÿÿÿÿ~ÿÿÿÿþÿÿ~ÿÿÿÿÿÿÿÿÿÿÿÿÿ~ÿÿÿÿÿÿÿÿÿ~~ÿþÿ~~ÿ~ÿÿÿÿÿÿ~ÿÿ~ÿ~ÿÿþÿÿÿÿÿ~ÿ~~ÿÿÿÿÿþÿ~~ÿþÿþÿÿÿþÿÿþÿÿÿÿÿ~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿþþ~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿ~ÿÿÿÿþþ~ÿþÿÿÿÿÿÿÿÿÿ~þÿþÿþÿÿÿÿÿ~ÿþ~ÿÿÿÿþÿÿÿþþÿÿ~ÿÿÿÿÿþÿ~þþ~ÿÿÿÿÿÿ~ÿþÿÿþÿÿÿÿÿÿþÿþÿÿÿÿÿÿ~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿþ~ÿ~ÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿ~ÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿ~ÿþÿÿÿÿÿÿÿ~ÿÿþÿ~ÿÿÿÿÿÿÿÿÿÿ~ÿÿ~ÿÿÿ~ÿÿþÿÿÿ~ÿÿÿþ~ÿþÿÿÿÿÿÿ~þþÿ~ÿ~ÿÿÿÿÿÿÿÿþÿÿÿþþ~ÿÿ~ÿÿÿÿ~ÿÿ~ÿÿÿÿ~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿþÿ~ÿÿÿÿÿÿÿÿÿÿÿÿ~ÿ~ÿ~ÿþÿ~þÿ~ÿÿÿ~~þÿþÿþ~ÿÿÿÿÿÿÿÿÿÿþÿþÿ~ÿþÿþÿ~ÿÿÿÿÿÿþ~þÿÿÿÿ~þÿÿ~ÿþÿÿ~ÿþÿÿþÿÿþ~ÿÿÿÿþÿþÿÿÿÿÿÿÿÿÿ~~~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ~ÿ~ÿÿÿÿÿ~ÿÿÿ~ÿÿÿÿÿÿÿÿ~þÿÿÿÿÿÿÿÿÿÿÿþ~ÿÿþþÿÿÿÿÿÿÿÿÿÿþÿÿÿÿþÿÿÿþÿÿÿÿÿÿÿÿÿÿÿ~ÿ~~ÿÿþÿÿÿÿÿÿÿÿÿ~ÿÿÿÿÿÿÿÿÿÿÿÿþÿÿþþÿÿþÿÿþÿþÿþÿÿ~þÿÿþ~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ~ÿÿÿÿÿÿÿÿ~ÿÿÿþÿÿÿÿÿÿÿþÿÿÿÿÿ~~ÿ~ÿÿþÿÿÿÿÿÿÿ~ÿÿÿ~ÿÿÿÿ~~ÿÿÿÿÿþÿÿÿÿÿÿÿÿÿ~ÿÿÿÿÿ~~ÿÿ~ÿ~ÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿ~ÿÿÿ~ÿÿ~ÿÿÿ~ÿ~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ~ÿþÿÿþÿÿÿ~ÿÿÿÿÿÿþÿÿÿþ~þþþ~ÿÿÿÿÿÿÿÿþÿþÿÿÿÿÿÿþÿÿÿ~ÿÿÿþþ~þÿÿÿþÿþÿÿÿ~ÿÿÿÿ~ÿ~ÿÿÿÿÿÿÿ~ÿÿÿ~ÿÿÿÿÿÿþÿÿþÿÿÿÿ~ÿþÿÿÿþ~ÿÿÿÿ~~ÿþ~þÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿþ~ÿÿÿÿ~ÿÿþÿÿÿÿÿþ~ÿ~ÿ~ÿ~ÿÿÿÿÿþÿ~ÿÿÿÿÿÿÿÿÿ~ÿ~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ~ÿÿÿÿÿÿþÿÿÿÿÿÿÿ~þ~ÿÿÿÿÿþÿÿÿ~þÿÿÿÿÿÿÿþþÿÿÿþ~ÿÿÿÿÿÿÿþÿÿÿþÿÿÿÿÿÿÿÿÿÿ~ÿÿÿÿþÿÿ~ÿÿÿÿ~ÿþÿ~ÿÿÿÿÿþÿÿÿÿÿ~ÿÿÿÿÿÿÿÿ~ÿÿÿÿÿÿÿÿÿÿÿ~ÿÿþÿÿÿÿ~ÿ~ÿÿþÿÿÿÿ~ÿþÿÿÿÿÿ~þÿÿÿÿÿ~ÿÿÿÿÿÿÿþÿþÿÿÿþÿÿÿ~þÿ~þþÿÿÿÿÿ~ÿÿÿÿÿ~~ÿ~ÿ~ÿÿÿþ~~ÿþÿÿÿÿ~ÿÿÿÿÿÿÿÿ~ÿþ~þÿÿÿÿÿÿÿÿÿÿ~ÿÿþÿÿÿÿÿþÿÿ~ÿÿþ~~ÿÿþþÿÿÿÿÿÿþþÿÿÿÿÿÿÿ~ÿÿ~þþÿþÿÿÿÿ~ÿ~ÿÿ~ÿÿ~ÿÿÿÿÿ~ÿÿÿÿÿþÿ~ÿÿþÿÿÿÿÿ~ÿÿ~ÿÿÿÿÿÿÿ~ÿÿ~ÿÿþÿÿÿ~þÿþ~ÿÿ~ÿ~ÿþÿÿÿÿþ~ÿÿÿþÿÿÿÿþÿþÿþ~ÿÿÿþÿÿÿ~ÿÿþÿÿÿ~ÿÿþþþÿÿÿþÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿ~þÿÿÿÿÿÿ~~þÿþÿÿþÿÿÿÿÿ~ÿ~ÿÿ~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ~ÿÿ~ÿþÿÿÿ~ÿÿÿþÿÿþÿÿÿÿ~ÿÿþÿÿ~ÿ~ÿÿ~ÿÿÿÿÿÿÿÿþÿÿÿþþÿÿÿÿÿþþÿÿþÿÿÿÿÿÿÿÿþÿÿ~ÿ~ÿþ~ÿÿþÿÿÿþ~ÿÿÿÿþÿÿÿÿÿÿþÿ~ÿ~ÿÿÿþÿÿÿþÿÿÿÿÿÿÿÿÿ~ÿÿÿþÿÿÿÿÿ~þÿþþÿÿÿÿÿ~ÿþþÿÿÿþÿÿÿþÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿ~ÿÿÿÿ~þÿÿ~ÿþþÿÿÿ~ÿÿ~ÿÿÿÿ~ÿ~þÿþÿÿÿÿþÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿþ~þÿþÿÿÿÿ~þþÿ~ÿ~~ÿÿÿÿÿÿ~ÿÿÿÿÿ~ÿÿþ~ÿÿÿÿÿ~ÿÿÿÿþÿÿÿÿÿÿÿÿÿÿ~þþþÿþþþÿÿÿÿÿÿÿÿÿ~ÿÿÿÿ~ÿþþ~þÿþÿ~ÿÿÿþ~ÿÿÿ~ÿ~ÿÿÿÿÿþÿ~ÿÿÿÿÿÿÿÿþÿÿ~ÿÿþÿÿÿÿÿÿÿÿ~ÿ~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿ~ÿÿÿÿÿÿÿÿ~ÿÿÿÿÿÿÿÿÿþÿ~ÿ~ÿÿÿÿ~ÿÿþÿÿÿÿÿÿÿþÿÿÿþ~~ÿÿÿÿÿþÿþ~ÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿ~ÿÿÿÿÿÿþÿÿþÿÿÿÿþÿÿÿÿþÿ~ÿ~ÿÿÿÿÿ~ÿÿÿÿÿþÿÿ~þÿþÿÿÿþÿ~ÿ~ÿÿ~þÿ~ÿÿÿÿÿÿ~ÿÿÿÿÿþþ~ÿÿÿþþÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿ~ÿÿÿ~~ÿÿÿÿÿþÿ~ÿÿÿþÿÿÿ~ÿÿ~ÿÿ~ÿÿÿÿÿÿ~ÿÿþÿÿ~ÿ~ÿÿÿ~ÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿ~~ÿ~ÿþÿÿþþÿÿþÿ~ÿÿÿÿÿ~ÿÿþÿÿÿþþÿ~ÿÿÿþÿþ~ÿÿÿÿ~ÿÿ~ÿÿÿÿÿÿÿÿÿ~þÿÿÿÿ~ÿ~þÿÿÿÿþþÿÿÿÿþÿÿ~~ÿ~~~ÿÿÿÿþÿÿÿÿÿÿÿ~þÿþÿÿÿþÿþÿ~ÿÿÿÿþÿÿþ~ÿ~~ÿþÿþÿÿþÿÿÿÿ~ÿÿÿÿÿÿÿÿÿÿÿþÿ~ÿÿÿþÿÿÿ~ÿÿÿÿþÿÿÿ~ÿÿÿÿÿ~ÿ~ÿþÿÿþÿþÿÿþÿ~ÿÿÿÿÿÿÿÿ~ÿÿÿ~ÿÿÿÿÿÿÿÿ~ÿÿÿÿÿÿþþÿ~~ÿÿ~ÿÿÿÿÿÿÿþÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿþþ~ÿÿ~~þÿÿ~ÿÿÿÿþÿÿÿÿ~ÿ~ÿþÿ~ÿÿþþ~ÿÿÿÿÿþÿÿÿÿÿÿÿ~ÿÿþÿÿþÿÿ~ÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿþÿÿ~ÿÿÿÿÿ~þÿþÿÿÿÿ~ÿþÿÿÿÿÿÿÿÿ~~ÿÿÿ~ÿþÿÿÿÿÿÿ~ÿþÿÿÿÿÿÿÿ~ÿÿÿÿþÿÿÿÿÿÿÿÿÿþÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿÿÿÿÿÿ~~ÿÿbaresip-1.0.0/share/ring.wav000066400000000000000000000276241372575704200157440ustar00rootroot00000000000000RIFFŒ/WAVEfmt @@factY/dataY/ÿþÿÿÿ~ÿÿþÿÿ~ÿ~ÿÿ~ÿþþÿÿÿÿ~ÿÿÿþÿ~ÿ~ÿÿÿ~þþÿÿÿÿÿÿÿþÿÿÿÿ~ÿÿÿ~ÿÿ~ÿÿþ~ÿÿþÿÿÿ~~þÿÿÿÿÿÿþÿÿÿÿÿÿþÿÿÿÿÿþÿ~ÿÿÿÿÿ~ÿþÿÿÿÿÿÿþ~ÿþÿÿÿþÿÿÿþÿÿÿÿÿÿ~ÿþÿÿÿþÿ~~ÿÿÿÿÿ~ÿ~~~ÿÿÿþÿÿÿÿÿþÿÿ~ÿÿÿþÿÿÿ~ÿÿÿÿÿÿþÿÿÿÿÿÿ~ÿþÿÿþþ~ÿÿÿÿÿþÿþÿÿÿÿÿþÿþÿÿ~þÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿ~ÿÿ~ÿÿÿÿþÿÿþþÿþþþþþýþþýýýýýýüýýýüüüüüüüýüýýýýýþþÿÿÿ~ÿ~~}}}||{{{{{zyyyyyyyyxxyyyyyyzz{{{||}~~ÿÿþýýüûûúúùùø÷÷÷öööõõõõõõööö÷÷÷øøøøùúúûûüýýýþþ~~~}}|||{zzzzzyyxyxxxxxwwxwxxxwwwwvvvvvvtuttssssrrssssttttuvvvwxyz{|}~ÿþýüúùøöõôóññðïïîïîíîîíííííîîîîïïðòòôö÷øùûýÿ}{zxwvusrqpppooonnnonnnoooopppqqrtttuvwxwxyyyyz{{{|{|||||{{{{{{z{|}}~~ÿþþýüüûúø÷öõôòððïîîîííìììëëëëëììììíìííîïïðñóôõö÷ùúüýþÿ|{zxwtuqoonnlkljkjiiiiiijiijjklmlmnopopoqsuwxyz{zþýþýö÷ùýöûøõøô÷ðñðïìðíðìòéñíòëëëíéçíåøÂ×þÜöäú|qÿoxoùíöñööéózú~wofmmdiejlecd`lhehckeofhfkmtos}x{oi~ùúò^rbÕæiågkZîÏáíßgbZ\Ýù^úiioiÛËâèç{m^uÚÏÝ÷etbV|ÜÒÖîäï{hc÷t|ûöwüxöÚÜÒÕâöxeZT_ÿwÒÓÝÞæ~gXNYRTb\mooþns~sþëíãÜèãäîÙÙÜâúo`dfXTSOQJD>:?CBJbÔÿ¼¸¸¸º¾¿ÃÆÊÑÔÓàÛçësL:/*#"+ʺ¯«£œ¡±´¶¼ÈL÷¼½»¼´¬±¼¾Õm:)#?YÈ·­œ´¹ÂÄØ.2èÆ¶¸µ¨©¯´Á¿ÉM@C=K?B>-#'2@_ׯŸ¨®®°­¿üͽ¹¸Ë¸­¯±·¸³ÁseOVD4.+($%6=I\Ë­¬¹·¹²¶ÉÚý¼Éʼ¹º¿ÃÅÊÛþf[LH=916-)&#.48;CbÂÆÇ¿»¶·¿¿»»º¿À»º»½ÂÂÄÊÙÜç|[VLH:=:1.-18:5AKiúåÖľ½¿Â¿¾½À¾À»¼¿ÁÁÄÆÎÛãùúZTPLCD>?>:999>?:762%=³±Ä]\ÇÎN^¹ª°½Ã½¸¼ÒÑ¿¯«¯ÇëL;).¸¬»`BÉÊM2"]¬­Ë>KÆþ@4Lµ§®¼ÊÀµ¼\[®¨®Á×úD,*º¨³U7^ÏZ?CǪ¤¯¿Ð¿¸Ä{Ñ·¨©µÑæQ>&:¬©Ë=5úùO=U·¤©º×é¼¼Ín̸©ª¶Ý[D<%9¯­Ê2-ÖÉáON½¦§¼ìf·°½öÚ¼§©¶ÓRC<&GªªÔ21ÚÎáNk¯¢§·è~·¸ÃÛÆ±¤«·êH@4!Ö©¬W).ÐÎÈSå±¥«»uÛ¶¹ºÒÁ³¦°¾KB?5!p«¬Q+-èǼnæ²§¨µÛÖ¸¹¶Ã»°¨®¼[L=1!M°ªa..kÌ»Ù糨¦¯Î쿾³½¹¯©¯¹`M;/!=·ªÔ-+ZʲÉݺ®¦®Æçʯ¸±²­®¸Ï`=0$%Ó®´;*;ð¸²Ò¿¸­ª·ÎÊÕ·³²®¯²¶¾ê^2+7¼ªË10FЬ¼È¿·¨­¹ÅÝͶ°®°²²¸Â×C/$B·­[18Nº«ÊËij§­ºËhͱ®ª®°´½ÂÎK.#.ȬÌ87Eέ¸¿È¾©¨´Ã^ô¶²ª®±²»½Äe>)<¸©O95H½¯·¶È³¬®²ÆlË»®¨­®¸Á¾ÇP;%@­©c>.F¿«°µë½®¬­Ãñk½°¤¨©½ÄÌÅÝ=)3Σ¼F;;Ò®³»Ì×®«§µÕCç·¦¨­¹Ë¼Ã½M06¼¥ÓX5;Ó«¯°×í¬§¸ÌOí¶¥¤¨¼ÈÇÓÎI7&.ÆŸ¸Ù84î´¯®ÀÕ°²¤¯ÊYOÊ«£¥®ÊÜØÉÊJ2"1¿¡¬ÁI5GÁ±¸½ã²®£©¿O:þ¯¤¢©ÆÊyÈÌw;.&"5ºœ©Â5*<Ä®¯¼Üµ®Ÿ¨ÄK6n¯¢Ÿ¨ÇëqÍÂëI4/)%I¤—­ð%"9³§¤ºZ½³ž¦½=/K±ž¨÷>:ߺ¹Î@/.)"M¤˜¬ï*#<À¨©¶Õº²¤©½V6I¼§¢§½iLmļÈä>6.'"&¿žœ³H"%A±¥¤¹Ëõ¹¥ª·C5>¹¤§Î<5T¾¯¸ÊG4-'%<©š¦½,!,Ϊ¤¯ÕÒ§¨®a77[ªŸ¡±p=>ݺ¯¹p>01,(2®š¡½/*Ô©¢«ÎZ_®¢¨»@5E¶¢ž¨ÂFDж®·âA767/)M«ž®î/)8¾¬¨µârØ­§ªÀO=U·©¥®Ã[Lã½±¶ÉYA8;5.% S«¤²|0.H·¬«ÀgeÄ­¬°ÍM?b¸©©±É[Yض¯²¿[>:?L:, *Ë©ª¾J49ʯ­´ãS{º«ª¹îA@Òµ­®·ÁÅÁ»¶¹ÀÍÞÿ^Q=.)!"H¶«¶û>8W»´·ÉöÞ½®¬µÝKMÚ·®®µÅÑ;¸¸¾É×âþZE5.)"*n±¯ÈN/,&!)XÔÏèbÔ½¶¾çNOͺ¹ÃÚëÎÀ½ÄÈ¿½»½ÊÓÅ»¸¹ÁÐÎÆÈäSF:1.&<}E=OŶ¸»×]ξ¾ÇÞÓÄÀÃÍɼ¹º¼ÆÌž½ÀÇÇÁ½ÁËÓáúeK<2*% $-.+*2NÍÈÍϹ¼ÃÃÁÁÆÊÆÁ¿Áÿ»»½¾½½¾¿ÁÄÊÎÎÏÛjI=5.(#"&***->p×Õ̽³¶Á»¸½ÅÇ¿¼¼¿¾¼»¾À¿¾¿ÃÃÄÅÈÌÐÚyP@8/*$"&))).;YêÞͽ¶ºÂ¿¹¹¾ÅÅ¿¼¾À¿¼¼¾ÁÁÁÃÆÈÉÊÌÏÔÝuOD<3,&#%)(),7MyÜÉ»µµ»¼·µ¹¾À½¼¼¼½½¼½¾¿ÄÄÄÅÇËÌÉÌÖï^NB7.)$$&'&).:MhÛŹµ¹½º¶¹½ÂÁ¾¾¾¿¿¾½¾¿ÃÇÇÈËÎÏÍÌÔærWI<3,($$'((+4EdèÊ»´´¸·²°³·¸···¹º»»¼¾¿ÄÆÇÉÏÖÕÕäeQH>7/+'# ""%)/8GvÈ»µ°®¬«ªª«««¬­¯±´·»½ÁÄÈÎÐÖÝë}^OD=71-*&# !#,/:bƼ³¬ªªª§¨ªªª¬­¯®²¸¶¸¾¾¾ÃÈÌÎái\J=60+'""-2=ûȸ´®«¯¯­²³²²³³¯°³±´··»¼¾À¾ÄÅÄÏØqN?4.*#  )::vûµ²«¯·­´»´´´´°­´¯¯·µ¶¶¹¼¸¼Ã¾ÊØîT@7/,&  !8BIɹµ´®«µ±®·¸²°³²­¯²¯±´¶´µº¸¶¼À¾Íê\H80-("" .DMÙ¼±µ²«°·°´¸¶±¯±¯­¯±²´¶¹·¸»¼¼ÃËØïM<5.*$ #"-ETξ³¯´®®¶´´¶·³¯°¯­®°³´´»º·¼¿¼¾ÆÏÔoC94-(#! %&8U߸®®²¬¯µ´¶´¶´®¯¯¬­¯²°°·¸´¹º½½ÁÓð\?4.*%%$,CñÐÁ³®³°­²··´´¹³­±±¯¯³¸´²ºº¹º¿ÊÈ×UG=2-(% %&.?zÊÀ´­¯¯®®³¸´³·µ²¯°±°±µ¶¶¸º¼¼¿ÉÐÞoJ=6/+'# ''->kÊÁµ¬­®¬¬¯´²¯´µ²¯¯²±°´¶¶¶¹½¼¾ÊÔé^H;51,'%# &%*9NÛϺ­®®¬¬®³µ°´¹¶²²¶¶³´ºº¸¼ÀÄÅÍñ`UE:40-)&$# "((,6IvÛÀ±°¯­¬­±²¯±µ´´³µ·¶·º¼½¾ÂÉÈÏçaYJ=61/+('&%#%*+.5AdôÉ·³²°®®¯±°°³µ¶µµº¹¹½¾¾¿ÁÆÎÏÓ~_RA<742/,**)'(+,.1JA==<;??;B·/ÆKF¿8ÕÒN»@¿ÐS»JÌÇéÓêÃÎR¾fâÙíýQÅBåÒU\×çBÙ[ESàNEØZKpåT_ÛajxÜY}ÎSÎáØÏØÔfÄÉiÏÚÉÒLÎ÷åþ_t×]UFgì;YMYIQMMpbGZÕLUäÜmßË×ÜÐÏÎ×ÍÚßÌÛÝÎÖè×ÛTnàOcRbdN[JjYFZQ]VBOZPJOah]÷íÐÉßÃÈÃÂË¿ÍÃÄÏÌÏÉÙyÔÏ^ýñjLU]BEA@>>:59?@@FY]ðÛÐÆÂÁÁ½ÀÁÁ¾¾ÀÁ¿ÆÊÁÃËÓØÓÑ{^]X\I==?cÊÄÆ¿ºº»»¾ÃÈÃÂÎÕÆ¿ÅÈÈÃÁÍÓÛÚßåä\OXX@::7.)).897:SÌÁ¼»º¸·¸¾ÆÅÄÆÎËþ¿ÃÀ¾ÁÈÌÖÚÜàìeUZZG:41+&#)5827\Æ»·´µ·¶¶½ÊËÅÉÚÕÿ¿½¾ÁÄÅÉÐÓÔâh\SH=6/*&!"+344Aζ³²¯¯°´ºÅËÏÍÏßÜÇÀ¾¿¿¼»¿ÆÇÉÉÏàâhPC7/)"*((;`õ¯¬¨¬¬­¹Â¿ÅÏÌÖſĽ¸¼½º¾¿ÆÊÆËßÒ×ZL?6-'!#Në¼®¬£©«¨®½½ÁÔÏÜÌÂÉÆº¾¿¼¾ÂÆÉÊÏØßá\J?9.(#%"':VÞ·®ª¤ª©ª³¾¼ËÓÕÞÉÇ˾»¾ºº¼½ÂÅÆÔíïcJC93,'!'#)>cÔµ¬¨¤©§©²ººÅÖâÔÐ×Ô¿þº½¾¾¿ÂÎÔÜmJB:2+'"(#*Iþϰª¦£¦¥¦¯¹¶ÀàÝÞçéóÍÂÈ÷º¾»º½ÌÌÐaIA:/*&"$#$=_ã»­ª§©¨«¯µ¸½ÃÆÏÐÌÓåÕÏÖÎÁ¿¿¼·¾ÇÌÚK<4+$"-.¿AN²ÂοÄïÌ´¾¾°±½¹¹ÇÍÍÍÚÕÀ½½¹´½ÃÇåM?3'#!B"<¨êר¼î»È\OéÌÌʸ¶Ãº¸ËÄÆÒÏÇÁ¿»¸·¾¿ÉñM>1)#&<F«HȤÈÕ³ÇTêÔÝÒĺ¿Äµ»Ò¾ÂéÎÄÍ»¿¿»ÇÐæOB4+%$/"=¹DΨÆÅ­¾ù¿ÐwÈþ½ºº¿»½É¿ÍÁ¾Ç¾½ÈËËòS@4,%,#'ð?B¯¾Ñ­´ØºÄ[ÆÇí¾ͽ»Â¾¾ÇÂÂÉÁÈËÃÎÚÑySL;1-%#)$'84:ÔÖ̱²¼³·Ä»½ÊÂÁÊÿÁ¾¿À¾ÀÁ¿ÅÈÈÎÐÒàoYC91*&&&&+.3>ZϽ¶¶³´·µ¶»¼½ÀÁ¿ÀÁÀÂÁÀÃÆÇÍÓ×Ýæþ[OC:3,'$%%'+/6FìÆ¹µ³²³³´·º¼¿Á¿ÀÁÀÂÃÂÄÆÇËÎÏÕÚÛîeQC:1+&&&&*.3>jÌ»´²±°²²µ¹»¾ÁÂÂÃÁÂÄÃÂÆÇËÏÖÛåíy_PE<4-(%%%%*.2AmÊ»µ´²²³´·»½ÁÆÅÅÆÃÄÅÃÃÆÆÉÍÏÓØÝénYJ?7/*&&&&*.4>jË»´²°°±²´¹»¾ÃÅÃÄÄÃÆÆÄÅÇÈËÎÏÒÓØá}YJ>6.*'''',/6B~̾¸·¶·¸¹»¿ÃÈÍÍÌÍËËÍÌËÌÌÌÍÎÏÏÎÑÙædO@8/+('((+/6?bο¸¶´´µ¶¸¼¾ÂÈÉÈÉÈÆÈÇÅÆÄÄÅÄÄÅÅÆËÑé]I<3-)'''),19Iìɽ¹·¶¶¸º½ÀÅÊÎÎÏÑÑÑÑÏÏÕØÙ×ÏÊÈÃÂÄÆÊ×úN=5-)'''(,/6BeÑÁ¼º¸¹¹º½¿ÁÇÉÈÈÈÆÇÆÅÆÇÆÆÅÃÁÀ¿ÀÂÆÎåYD80+)((),/5@ZÖŽºº¹º»½¿ÄÉÍÏÐÏÏÎÏÏÑÓØÝÜÒÍÈþ¾½À¿ÂlOA0+)&&(*-2èÅ˹µÃÀÈ_^kKSüráÃÄÀº½ÁÂÇÙÚñþjËÇܺ¼Ê¸ÁãËc?=/%%,)(EG>¼¾å¸ºõÐ×FLlO_ÌÎͽ¿Æ¾ÂÎÑÓÞáÖÛÝÖÔäνǾ»ÃÅÉédV?6,%&5*/ÌHè¯ÌζÚXwL=GgSñÄÊĹ¿ÅÂÍÞÚævæÜÛØÊÜÄÂ׺ÂÞ¿Ô[ãW<F20.7G4ÙÍC¿ÃJÄÌGlÚK[ÇïݽÍͽÎÕÇÑßÕØïß×ÚÜÑÝÞÛtügd`deybÍÂßľïÍÓOi^EIE803L2;Ë-Wô:ÉÁB»»UÃÉIÛÏMÑÉoÈ¿ÒÀÀÌÉÈÕÛÖô{ìllðk÷ëhúû^}j]øpbÚÖôÊÊãËÏaßùQWL?;2.=/2U7>ÊTz·Üß»îhÅX[ÌdäÃÜÊÀÎÃÀÎÊÈáÚ×}ôê`uôbüóhñÿmîûlïôeÛÜçÍÕ×ËÖÜÏòmpOJF;5<44D;=hN]ÄÒÏ¿ÏÒÅÞÚÍåÛÌÚÏÉÐÌÉÑÎÍÛÜâvnfYZYUY\Y^a\ca]cbcjmo{þûêßÜ×ÔÖÔØÜßõg\OID=9998<>BKZëÏÉÅÀÃÃÁÅÈÇÊÌËÎÎÌÍÍÍÏÏÔÚÝäûvg\\XVWWW[[]dcfmmpysw|y~û{ùêèäßáâåîôo^WOIE>9898:>?HVwÔËÇÂÃÅÃÅÈÇÉÌËÌÍÌÍÎÍÏÒÔÜßè~mc\ZYWZ]^djm}üýðñòíïñîòðïöù~toibfpuüíîëçéëùh^TMH?;<=<@FITmÝÍÉÆÄÈÉÉÍÏÏÖØ×ÛÙÕÖÒÐÒÑÕÚÝåøxkcecchjknlllhikkrx{ùùúúý{volkfeea__^]^cnüêßÛ×ÕÓÔØÞëubXNF????CIMVqßÐÍËÊÍÏÐÖÛÚÞàÝÝÛÖÕÒÏÐÑÓÙÝåúqh_^^\^^^_``abchnyüøòðôðñ÷ú}{{yy{rlkifffdhim÷äÜÖÑÏÎÎÏÑÙæzbUMD?@@@FKN[wÞÐÎÍÍÑÔÒÚÜÙÝÜÖ×ÔÑÑÐÏÑÔØßçópf_ZYXVYYY[[[^]^bdgmns|{ü÷÷ñóúù~qnjgdcbbcdhjlptv|ùòîà×ÓÐÍÌÌËÌÎÒÚâòocZOKD??@?DJMWlèØÐÏÍÎÏÎÑÔÒÓÕÓÔÖÓÓÔÔÕÙÞèôtf_\YXXXY[[\]^_cfjqx~úúü~{xtssmlmihiecedehknsx{ûöòìèåâàßßßßáääåçææçåäæåâãââãâåèéî÷|oh`[UOJD??@@DLOYÿÞÔÍÍÎÎÑÔÕÙÛÚÜÜØØÖÓÔÓÓÖÛÞé÷{lfda`bbcefgihjos}öóðîïóôöúþzuoljheca`_`acfhknqxÿøñíìëééêêëììííìííîïôøýzwrommmmnooqrtxxz~ÿþüûüûúúúûûüüýýþ~|{zz{||}~þýûù÷öôòòðïïîîîîîîïïðóõö÷úûüþÿ~~ÿ~}~}~~}||{|þýú÷õôòòòõøû~yvtolkjfeecbbbabcbcefgjmnt}ý÷ïíéåãáßßßßßááåèêîõø~vqmjjhhlnr}÷ðëæãàßÞßÞßàâäæéíñùzqkf`^]\[\]^chnwüóîëéççççèéëíðöþwokfc_^]]^_cgms|ùñíêèçæææççéêìîóúþyrnmjijjkmosyÿû÷òïîíììììíîïòõúý~yusqoooopqruwy{}~þýüûúúùùùúûûüüýþÿ}}||{{z{z{||}~ÿÿÿþþþýýýþþþýþþþþþþþþþþÿþÿÿþþþþþþÿþÿþþþþþþþþþÿþþþÿþÿ~ÿ~~ÿÿ~~~~~ÿÿ~~ÿþ~ÿÿ~ÿÿÿ~ÿÿþÿÿÿÿÿÿÿÿ~þÿÿÿÿÿÿ~ÿÿÿÿÿÿÿÿÿÿþþÿ~ÿÿ~ÿÿÿÿÿ~þÿþÿÿÿ~ÿÿÿÿþÿÿÿÿÿÿ~þÿÿÿÿÿÿÿÿÿÿþÿÿ~ÿþÿÿÿ~ÿÿÿÿÿ~ÿ~ÿþÿ~ÿ~ÿþÿÿÿÿ~ÿÿþþÿ~ÿÿ~ÿÿÿÿÿÿÿÿþ~ÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿ~ÿ~ÿÿÿÿÿÿÿÿÿÿþÿÿÿ~ÿÿÿÿÿÿÿÿÿ~ÿþÿÿÿÿÿÿ~ÿÿÿÿÿ~ÿÿÿÿÿÿÿÿÿÿ~ÿ~ÿÿÿÿ~ÿÿÿÿÿÿÿÿÿþÿÿÿÿÿþÿþÿÿÿÿþÿÿþÿÿþ~ÿÿÿÿÿÿÿÿÿÿÿ~ÿÿÿÿÿ~ÿÿ~~ÿ~ÿÿþÿÿÿÿÿ~ÿÿÿÿÿÿÿÿÿÿ~ÿþÿþþ~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿ~ÿÿÿÿÿÿþÿÿÿ~ÿÿÿÿÿþÿÿ~ÿÿÿ~ÿ~ÿþÿ~þÿÿ~~ÿÿÿ~ÿÿÿþÿÿÿÿþÿÿÿÿ~ÿþÿÿÿÿÿÿÿÿÿþÿÿþþÿ~ÿÿÿþÿþÿÿÿþÿÿÿÿþÿÿÿÿ~ÿÿÿÿÿÿ~ÿÿÿÿþÿÿþÿ~ÿÿÿÿÿÿÿþ~ÿÿÿÿÿþÿÿÿÿ~ÿþÿ~ÿÿÿ~ÿÿÿÿÿÿÿÿÿÿþÿÿ~ÿÿÿþ~þÿÿÿþÿÿþÿÿÿÿÿÿÿþÿ~ÿÿþÿÿÿþÿþÿÿÿÿÿÿ~ÿÿÿÿÿÿÿÿÿÿÿ~ÿþÿÿþÿÿþÿþþÿ~ÿÿÿÿÿ~ÿÿ~þÿÿÿ~þÿÿÿÿ~ÿÿÿ~þ~~ÿÿÿÿÿÿÿÿþÿÿÿÿÿþÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿþ~ÿÿÿÿÿÿÿ~þÿÿþÿþÿÿÿÿþÿÿÿÿþÿÿÿÿÿÿ~ÿ~~ÿÿÿþÿþÿÿÿÿ~ÿÿ~ÿ~ÿÿÿÿþÿÿÿÿÿÿÿÿÿ~ÿÿÿÿþÿþ~ÿÿÿÿÿÿ~~ÿ~ÿÿÿþÿÿÿþþ~~~ÿÿÿÿÿÿ~ÿÿÿÿÿÿÿ~ÿÿÿþÿÿÿÿÿÿ~ÿÿÿÿÿÿþÿ~þÿÿÿÿÿÿÿÿÿÿþÿÿÿþþþÿÿþþþ~ÿþþÿÿþÿÿÿþÿþÿÿÿ~ÿÿ~þþÿÿ~ÿþÿÿþÿþ~ÿÿÿÿÿÿÿþ~ÿÿþÿ~ÿ~þÿÿÿÿ~ÿ~ÿÿþ~þÿÿÿþÿÿÿþÿÿþÿÿþÿÿþÿÿ~ÿþÿ~þÿÿÿÿÿþÿ~ÿ~ÿþÿþÿÿÿÿÿÿÿÿÿ~ÿÿÿÿÿ~~ÿÿÿþþÿÿÿÿÿÿÿÿþ~ÿÿÿÿÿÿþÿþÿÿÿ~ÿÿÿÿÿÿÿÿÿÿÿÿÿ~ÿÿ~ÿÿÿÿÿ~~ÿÿÿÿÿþ~ÿÿÿÿÿÿÿÿ~ÿ~ÿÿÿÿÿ~þþÿÿÿ~ÿÿÿ~ÿÿÿÿÿÿÿÿ~þÿÿþÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿþÿÿÿÿÿÿÿ~ÿÿÿÿÿþÿÿÿÿÿÿÿþÿÿÿÿÿÿÿ~ÿþ~þ~ÿÿ~~ÿÿþÿÿþþÿ~þÿÿÿÿÿÿÿ~ÿ~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿ~ÿ~ÿÿþÿÿÿÿ~ÿÿÿ~ÿÿ~~ÿ~ÿþþÿÿÿÿÿÿÿÿÿÿÿþþ~ÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿþÿÿ~~ÿ~~ÿþÿÿÿÿÿÿÿÿÿÿ~þÿÿÿÿÿÿÿÿÿÿÿþÿÿþÿÿÿÿÿþÿÿÿÿÿþÿÿÿþ~ÿÿÿÿÿ~ÿÿÿ~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿ~ÿ~~~ÿÿ~ÿÿÿÿÿÿÿÿÿ~ÿÿÿÿÿ~ÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿ~~ÿÿ~~~ÿÿþþþÿ~þÿÿÿÿÿ~ÿÿÿÿÿÿÿÿ~þÿÿÿÿÿ~ÿÿÿÿÿÿ~þÿÿÿÿÿÿÿÿÿþÿÿÿþÿ~ÿ~ÿÿ~~ÿþþ~ÿÿÿÿÿÿÿÿÿÿþÿÿÿ~ÿÿÿÿÿÿþÿ~ÿÿÿÿÿþÿÿ~þþÿþÿÿÿÿÿÿ~ÿÿÿÿÿ~ÿÿÿÿ~ÿþÿÿÿþþÿÿÿÿÿÿÿþÿÿþÿÿ~þÿÿÿ~~ÿÿÿÿþÿþÿ~ÿþÿÿþþ~ÿÿÿÿÿÿÿÿÿ~þ~ÿÿÿÿÿ~ÿþÿÿ~~ÿÿÿÿÿÿÿÿ~ÿÿÿÿÿÿ~ÿ~þÿÿþÿÿÿÿ~ÿÿÿÿÿÿ~ÿÿÿÿÿÿÿÿÿÿÿÿÿ~þÿÿÿÿÿÿþ~ÿÿþÿþÿÿÿ~ÿÿÿÿÿÿÿ~ÿÿ~ÿ~ÿÿÿÿÿ~ÿÿÿÿÿÿ~ÿÿÿÿÿÿÿÿ~~ÿÿþþÿÿþÿÿÿÿÿÿÿ~~ÿÿþÿÿþÿÿÿÿþÿþÿÿÿÿÿÿÿþÿÿÿ~ÿþÿÿÿÿÿÿÿÿÿÿÿþþÿþ~ÿÿÿ~ÿÿþÿÿÿÿÿÿÿ~ÿÿÿÿÿþÿ~ÿ~ÿÿÿÿÿÿÿ~ÿÿþÿÿÿ~ÿþÿÿÿÿÿÿÿþÿÿþÿÿÿÿÿþÿ~ÿÿ~ÿþÿÿÿÿÿþÿ~ÿ~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿÿ~þÿÿÿÿÿÿÿÿÿÿ~ÿÿÿÿÿÿÿÿþþ~ÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿþþÿ~ÿÿÿÿ~ÿ~ÿÿÿÿÿÿÿÿÿÿÿ~ÿÿÿþ~ÿÿÿÿÿþÿÿÿÿÿÿÿþÿÿÿÿ~~~ÿÿÿþÿÿþÿþÿÿþÿÿÿÿÿÿÿÿ~ÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿÿÿÿÿÿÿþÿ~ÿÿÿ~ÿÿÿÿÿ~ÿþÿþÿÿÿÿþ~ÿÿ~ÿÿþ~ÿ~ÿÿÿÿ~ÿÿÿ~ÿÿþÿÿÿÿÿÿ~þÿ~ÿÿÿþÿÿÿÿþ~þÿÿþÿÿÿþÿÿÿþÿ~ÿ~ÿÿÿÿþÿÿþÿþþÿÿÿÿÿÿÿ~ÿÿÿÿþ~ÿÿÿÿ~ÿÿÿÿÿÿÿÿ~ÿ~ÿÿÿÿÿÿÿ~ÿÿÿÿÿ~ÿþÿÿ~þÿÿþ~ÿþÿÿÿÿþÿÿÿÿÿÿÿ~ÿÿÿþþ~ÿÿÿÿÿÿÿÿÿÿÿ~~~ÿÿ~ÿÿÿÿÿÿÿÿ~ÿþÿÿÿÿÿÿÿþ~ÿÿÿ~ÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ~ÿ~þ~ÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿ~ÿÿÿÿÿþ~þÿÿÿÿÿ~þÿÿÿÿÿ~ÿÿÿÿ~ÿÿþÿþÿÿÿÿ~ÿÿþÿÿþþ~ÿÿÿÿ~ÿÿÿÿÿþÿÿÿÿÿÿ~ÿÿÿ~ÿÿÿþþÿÿ~ÿÿÿÿÿÿÿÿÿÿþ~ÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿ~ÿ~~ÿÿÿÿÿÿ~ÿÿÿÿÿÿÿÿÿÿþÿ~ÿÿ~þÿÿÿÿÿ~ÿÿÿÿÿ~ÿþÿÿÿÿÿÿ~ÿÿÿÿ~ÿþÿÿÿÿÿþÿ~ÿÿ~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿþÿÿÿÿÿÿÿþþÿ~ÿÿþÿÿÿÿ~þÿÿÿÿ~ÿþÿÿ~ÿÿÿÿþÿÿÿ~ÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿ~þÿÿÿÿÿÿÿÿÿÿþÿ~þÿÿÿþþÿÿÿ~ÿ~ÿÿÿ~~ÿ~ÿÿÿþ~þÿÿÿÿÿÿÿÿÿÿ~ÿÿÿÿ~ÿÿÿÿÿÿÿ~ÿþ~ÿÿÿÿþÿÿþÿÿþþÿ~ÿÿÿ~ÿÿÿ~ÿÿÿÿ~ÿÿ~ÿþÿÿ~ÿÿÿþþÿÿÿþÿþÿÿÿÿÿÿÿÿ~þÿÿÿÿÿ~þ~ÿÿ~~ÿÿÿÿÿ~ÿÿÿÿÿ~ÿþÿþÿÿÿþÿÿ~ÿ~ÿþ~ÿ~ÿÿþÿÿÿþÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿ~ÿÿ~~ÿÿÿÿÿÿÿ~ÿÿÿÿÿÿþÿÿÿþÿÿÿÿÿþþÿþÿÿÿÿÿþþ~ÿÿÿÿþÿ~ÿ~þÿÿÿÿÿ~ÿÿÿÿÿþÿ~ÿÿÿÿþÿÿÿÿÿÿÿÿÿÿ~~þÿÿÿÿÿÿ~þÿÿÿþ~ÿÿÿÿÿ~ÿÿÿÿþÿÿþÿÿÿÿÿþþÿÿÿ~þÿÿÿþÿþÿÿÿÿÿÿÿÿ~ÿ~~ÿþþÿÿÿþ~ÿÿÿÿÿÿÿÿÿÿ~ÿÿÿÿ~ÿÿÿÿÿÿþ~ÿÿþÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿ~ÿþ~ÿÿÿ~ÿÿÿÿÿÿÿÿÿÿþÿÿ~ÿ~ÿÿÿÿÿÿÿÿÿÿÿÿÿ~ÿÿÿÿÿÿþÿÿÿÿÿ~~~ÿÿÿþÿ~ÿÿÿþÿÿÿ~ÿÿÿÿÿ~ÿÿÿÿ~ÿÿÿÿþÿ~ÿÿÿ~þ~ÿ~ÿþÿÿþÿÿþÿÿÿÿþÿÿ~ÿÿÿÿÿÿÿÿÿÿÿþÿÿ~ÿþ~þÿ~þþÿÿ~þþÿ~ÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿþÿÿ~~ÿÿÿÿ~ÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿ~~ÿÿþÿþÿÿþÿÿÿÿ~ÿ~~ÿÿÿÿÿÿþÿÿÿÿÿþÿÿÿ~ÿÿÿ~ÿÿÿÿþÿÿÿÿÿ~ÿÿÿ~ÿÿþÿÿÿþÿÿÿÿÿÿÿ~ÿÿ~ÿÿÿÿÿ~ÿÿÿÿÿÿ~ÿÿ~ÿÿ~ÿÿÿÿÿÿÿÿÿ~ÿÿÿþþÿþÿ~~ÿÿÿ~ÿÿÿÿÿ~ÿÿÿÿÿÿ~ÿÿþÿ~ÿÿÿÿþþÿÿ~ÿÿþÿ~ÿ~þþÿÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ~ÿÿÿÿþÿÿÿ~ÿþþÿÿÿþ~ÿÿÿ~~ÿþÿÿ~ÿÿþþ~ÿÿÿÿþþÿÿÿÿÿÿÿþÿÿÿ~ÿÿþÿÿÿÿ~ÿ~ÿÿÿÿÿÿ~ÿ~~ÿÿþÿÿþÿÿÿÿÿÿ~ÿÿÿÿÿÿÿþ~ÿþÿÿÿÿÿþÿÿþÿ~ÿÿÿÿÿÿþþÿÿÿÿ~ÿÿÿÿÿÿÿÿ~ÿÿÿÿÿÿ~ÿÿÿÿÿÿÿ~ÿÿÿþ~ÿÿ~~ÿ~ÿÿÿÿÿ~ÿÿÿÿÿÿÿÿ~~ÿÿÿÿÿÿ~ÿ~ÿ~ÿÿÿÿÿÿÿÿÿÿÿÿÿ~ÿÿþÿÿÿ~ÿ~ÿÿ~ÿÿÿÿÿ~ÿÿÿÿÿþÿÿÿÿ~ÿ~ÿÿÿÿÿÿÿÿ~ÿ~ÿÿÿÿÿÿÿ~ÿþÿÿÿÿÿÿÿÿþþÿÿ~ÿÿÿÿÿÿ~ÿÿþÿÿÿÿÿÿÿÿÿÿþ~þÿÿþÿÿÿÿÿ~ÿþ~ÿÿ~ÿÿÿÿÿÿÿÿÿÿÿÿþÿþþÿÿÿÿ~ÿÿ~ÿþþÿÿÿ~ÿ~þÿÿÿbaresip-1.0.0/share/ringback.wav000066400000000000000000002047641372575704200165670ustar00rootroot00000000000000RIFFì WAVEfmt @@factº dataº çÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççççççççççççÛÛçÛÛÛÛÛçÛÛÛÛÛçççÛÛÛÛÛÛÛÛÛçççÛÛççççççççççççççççççççççççççççççÛÛÛÛÛçççÛçççÛççççççççÛçççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççÛÛÛÛÛÛÛÛçÛÛÛççççççÛççççÛçççççççççÛçÛÛçççÛÛÛçççççççÛççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛççÛççÛççççççççççççççççççççççççÛÛçççççççççççççççÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛççÛççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççÛÛÛÛÛÛççÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççÛÛçççççççççççÛÛçÛÛççÛçÛÛÛÛÛÛÛÛÛÛÛÛÛçÛçççççççççççççççççççççççççççççÛÛÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççççççççççççççÛÛçÛÛÛÛçÛççÛÛÛÛÛÛççççççççÛÛÛÛÛçÛÛçççççççççççççççççççççççÛçÛçççÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççççççççççççççççççççççççççççççççççÛççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛÛçççççççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛççÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççççççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççççççççççççççççÛÛÛÛÛÛÛÛÛçÛÛçççççÛçççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççççÛÛççÛÛçÛÛçççççççççççççççÛÛçÛÛççÛççççÛÛÛççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççÛÛçÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛçççççççççççççççççççççççççççççççÛççÛÛÛÛÛçÛççççÛÛÛÛÛÛÛÛÛççççççççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛççÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛççççççÛÛçççÛÛÛÛÛÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççççççççÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛçççÛÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççÛÛÛÛÛÛÛÛççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛççççççççççççççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççççççççççÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÓÉÍÛÿSIAAES矯¬ª¬°¼ç>.'"!$+:粦žœœž¦´[- )E¶¢š•”–›¦É0.ɤ˜’•¯> "I«š‘ŽŽ—¤Û(/ºž”Ž”¶2&ÿ§™’“›«S&">´Ÿ˜“’•›§É2 "4Ó«Ÿš™šž¨¼M-$!(6gº¬¥¢¤§®¼ÛA6/.06ASÛżº¼¼ÁÉÍÛÛÛÛÛÛçÿ[MA<::AMÛ¾²¬©¨©®ºç<.'#"&->É®£››ž§ºI++S°Ÿ˜””–œ©Û,2º —‘–ž¶6$g§™ŽŽ‘™¨S#8°œ’ŽŽ•Ÿ¾.+Í£—”œ¯A#%I¯ž—““–œªÛ.%:Ūžš™›Ÿ©¾E-$#*:纭¦¤¥©°¾çI8204:EgÛÅÁ¾¾ÁÅÍÍÓÍÍÍÍÍÛÿSE<668>Sͼ¯ª¦¦©®¼ÿ:+$ %-EÁ« œš›Ÿ©¾<'-ÿ¬—““—¬[( :´ž•– ¾.*Í¢–ŽŽ’›­A A­š’ŽŽ—£Ó*/¼Ÿ––Ÿ´: )g¬–“”˜ž­g,)E¼¨ž›šœ¢­É>,$ !%->Û¸­§¦¨¬´ÅÿE8648>IgÛÍÉÅÅÉÍÍÍÍÉÅÁÁÉÓgM>6204ESÿÛÍÍÍÍÍÍÍÉÁ¾¼¼¼ÁÍgI:2/.2EM[gçÛÛÛÛÛÓÍžº¶¶¸¾ÍgE6/,-/8Sۨ¢Ÿ ¥®ÁE-$%0ÿ°¢›˜—š ­g-#:º¡˜“‘“˜¡¼4(禘‘Ž’š«I":¯œ’ŽŽ–¡Å++Å –Ž“œ¯:$S¬œ””›©ç+":¼¤›—•—œ§Á<'$4粦Ÿž¢«º[6+&%(-8Sɸ¯¬­¯´¾ÓgMEEEMSgÿçÿÿÿÿçÓÉÁº´²²´¼Í[>2,)+.8[Á®¦ ŸŸ¥¯É>+!&4Û­Ÿ™––š °S*%A´Ÿ—’“™¤É.+É¢—Ž“œ®< Iªš‘Ž—¤ç'0¸ž•Ž•ž¸2(ÿ©š”‘‘–­S(&E¶£›—–™ž«Í8&(:Ó°¥ŸžŸ¥®¾[8-((+0>gŸ°®¯²¸ÅÛÿSMMM[[gggg[S[gçɾ¶°¯®²ºÍ[SÛż¸¸¼¾ÅÍÓÛÛÛÓÛçÿgSE>:868>SÛ¼°ª¦¥§­ºç<,$ $,AÉ­¡œš›ž§¼A)+g®ž˜““–œªç+4¸Ÿ––Ÿ¸2'ç¥˜ŽŽ‘™©M":°œ“ŽŽ–¡É,,É£˜‘•ž²>"&S­ž—””—ž«ç.(>Á©ž›šœ ¬ÁE.% !%->纭§¦§«²ÁçI:648>IgÛÍÅÅÅÉÉÍÍÉÅÅÁÁÅÍçSA:426:MÓº®¨¤¤§­ºÿ8*"$,E¾©Ÿš™šž©Á:&-竜–““—­M' <²•—¢Á,*É¡–ŽŽ’›®< I«š‘ŽŽ—¥ç(0¼Ÿ–‘‘— ¸6 *ÿ«—””™Ÿ¯g,*Iº§ž››£®ÉA-&"#'/AÛ¸®©¨ª®¶ÅÿI<8:EISÿçÛÛÛÛÛÓÉžº¸¶¸¾ÍgI8/,,.8Sɲ©£Ÿ ¥­¾M/$$/[´£œ˜—šŸ¬Û/!4Á¤™”‘’—Ÿ¶8%[©š’’š¨[%4´“Ž•Ÿ¾.(Ó£—ŽŽ’›¬A"!A¯•“š¦Ó- 4Ŧœ—•—œ¥ºA)$2ÿ²¦Ÿ ©¶ç:-'&(,8S͸°­¬¯´¾ÍÿMIEIM[gÿççÿÿÿçÛÍÁ¼¶²²¶¼ÍgA2-)*.8Sů§ žŸ¥­ÅA,!$0ÿ¯¡›——š ®g+":¸ ˜“‘“˜¡¾0*Û¥˜ŽŽ’š«E!>®›’Ž–¢Í*,Á –Ž”²:&S«›”‘‘•œªg+$<º¤›—–˜©Á<('8Û°¦Ÿžž£«ºg:-))+/>[ɸ°®¯²ºÅÛgSMMSS[ggg[[S[gçÍÁ¸²®¯°ºÉ[>0*()-6[¾­¤ŸŸ¤®É<*$4Ó¬ž™––š ²M($E°ž–‘’™¤É--Å¡–Ž“œ°8!Iª™‘ŽŽ˜¥ÿ&2¶ž”Ž•Ÿº2*ç©›”‘’–®M((I´¢›——šŸ¬Í8& *<ͯ¦ Ÿ ¦®¾[:.+*-2Agɺ´²´¶¼ÅÛÿg[[gÿÿÿg[SIIM[çɼ²®­¬¯¸ÍS8,'%&+6g¼«¡žž¥¯Ó6&%8Å©˜•–š¢¶A%'S­œ•“š§ÿ(2¸Ÿ•Ž”¶2%ÿ¥—ŽŽ‘™©M#:°”Ž—¢Å..ɤ™”‘“—Ÿ²E&+[°¡›˜˜›¡®ç4'#-AÅ®§¡ £©²ÉM8.,-/8Içź¶´¶º¾ÉÓçÿÿÿççÿg[MEAAESçɸ°¬ªª®¸ÍM4+%#&+8ÿ¶§Ÿœœž¥²ÿ0$&<¼¥›–”•š¤¼8!)ÿ©›““›«S%8°œ“ŽŽ•ŸÁ-*É¡–Ž’›­> !I«š’‘™¥Û+4¾¢™“’”™£º:$.ÿ¯ š™™¤²g2%%0MÁ®¦¢¢¥«¶ÓM80..2<! A­š’ŽŽ—£Ó)-¼Ÿ•ŽŽ“œ²6%g¨š’“š©['!<¶ ˜“’•›¦Á6""4Ó­Ÿ›™šž¨ºS/& !(4[¼®§¤¥¨®ºÓI:2028ASçɾ¾¾ÁÅÅÍÍÍÍÍÉÍÓÿ[I>866-%!#+<Í®¢œššž¦¸I*)M°Ÿ˜”“–œ¨Û,/¾¡—‘•ž²8$[©™‘ŽŽ˜¦g$4´“Ž”žº/*Ó¥˜‘”œ­I$%E°Ÿ˜””–ªÓ0 %8É«Ÿ›š›Ÿ«¾I/&!!%+:ÿº­¨¦¦ª°¼ÛI<646ŬŸ›™šž§¼>'*[­ž—““–«g)6¸Ÿ•–Ÿº0'Û¤—ŽŽ‘šªE!<®›’ŽŽ–¡É,.Á¢—‘–ž´Ûº®©¨©­¶ÁçM>:84/.08IÓ¸¬¥¢¢¥¬¸g6( #,E¾¨žš˜šž©Å8#,Ûªœ•’’–®I%!<°œ”Ž—¢Å,+Å •Ž’œ¯<!Iª™‘ŽŽ˜¦ç(4ºŸ–‘‘— º6 ,ç«—•–™ °[-+I¼©Ÿœœž¥¯Í>.'$&*2IÓº®«ª«¯¸ÉÿMA<>AI[gçÛÛÛÛÛÓÍÅÁ¼¸¶¶¼ÉÿI8/-,.6IͶª¤Ÿ ¤¬¼[0&".M¸¥™—™žªÍ2!0ɦ𔑒—ž²>"#M«›“Ž‘˜¥ç(0¸ž”Ž“¶2%ÿ¦˜‘ŽŽ’š©M$:²ž–‘“™¤Å00ͨœ—•–›£¶I+"/[¸¨Ÿ ¨´ç<.'&',6MÓº¯­¬®²¼ÉÿSIEEMS[ÿççÿÿÿÿçÍž¸´´¶¼ÍgA2-))-4Iɲ¨¡ŸŸ¤­¾I-"#.g²¢›˜—™ž¬ç. 6¼¢™“‘’—Ÿ¸6&ÿ¨™‘ŽŽ‘™©[%8°œ“Ž•Ÿ¾-*Í¢—Ž“œ®>!#E®œ•‘‘”›¨Û-!8Á¦œ—–˜§¾>)%4ÿ´§Ÿžž£«¸ÿ0+'(,4SÁ®¥Ÿžž¤­Å>+"/ç®Ÿš––™Ÿ¯[+"<¶Ÿ—’’˜¡¾/*Ó¤˜ŽŽ’›¬A A¬š‘Ž–¢Í*.¾Ÿ–Ž”´8'[«›•‘‘–¬g*%<¸¤›——™ž©Å<)(:Û²§¡Ÿ ¦®¾g:.**,2Agɺ´°²¶ºÅÍç[[[[ggggSSMIISÿ;¶¯­­¯¸Í[8-(%&*2S¾­£žž¤®Í:($4Í«˜•–™ °I'$E¯–‘’™¥Í+.¾ –ŽŽ“œ°8"S¨˜ŽŽ˜§g%4¶ž•Ž–Ÿ¼0+Û¨š”‘’—ž¯M()I¶£œ˜˜› ­Ó8("+>Ͱ§¡ ¢¨¯Á[:0-,/8Eÿɼ¶´¶º¾ÉÓçÿÿÿÿÿÿgSSEA>EMÿɺ°¬ªª­¶ÉS6+&#%*6gº© œœž¤¯Û4%%8Á§œ—”•š¡¶>$'S«›”“š¨ÿ(4¶ž”Ž”žº0&ç¥—ŽŽ‘šªI"<¯œ“‘˜£É-/ť𔒓™¡¶A&-[°¢›˜™œ£°ç6' %.Eů§£¢¥ª´ÉS:0./2:º¤š•“•š£¼6 *ç§š““›«M$:°œ“ŽŽ•ŸÁ,+Å –ŽŽ’›®<"I¬›“’š§ç*6¼¢™”’•š¤¼:$ /篡›™šž§¶[2& !'2Sů¨¤¥¨­¸ÍM<2026>MçÍÁ¾¾¾ÁÉÍÓÓÍÉÉÍÓç[I>866  E«š’ŽŽ—¤Û'0ºž”Ž“´4'g¨™’“›«S'"<¸ ™”“–œ§Å4"$6ͬ œš›Ÿ©ºS0&! $*8[¾¯©¦§ª°¼ÛM<646:84/./6EÛº­§¢¢¤ª¶ç8)!"+AÁªžš˜™§¼<&+g«–’’•œ«g(8´ž•Ž–Ÿ¾.(Ó£—ŽŽ‘š¬A A¬›’ŽŽ—£Í+.¾¡—‘‘—Ÿ´:"*g­ž˜••™Ÿ®ÿ. *A¾ª œž¤®ÉE.($%(/AÛ¼°«ª«°¸ÅçSA<°ž•‘“š¥É0 2É©˜–˜œ¥ºE*#0[¸¨ žž¢ª¶ç>/*(*-8Sͺ°®®°¶¾Íç[MMSS[gÿÿgg[[[çÍÁ¸²¯¯°¸ÅÿA2+((+4Mů¥Ÿž¢«¾E-!".g° š––™ž¬ÿ- 4º¢˜’’— º4&ç§™‘ŽŽ‘™©M#:°œ“ŽŽ– Á,+Å¢–Ž“œ¯)'6ÿ´¨¡Ÿ ¤¬¼ÿ[ɺ´°²´ºÁÍçgg[ggÿgg[SIIISÿ;¶¯¬¬®¶Åg)#0ç­Ÿ™–•™Ÿ®S(">´ž–‘’˜¢Å.+É¢—Ž’›®<E¬š‘ŽŽ—¤Û(/¼Ÿ•Ž•ž¶6)ÿªœ•‘’–­[*%>º¦œ™˜šŸ«É:(!)<Ó²§¢ ¢§¯¾g<0--.4Aÿͼ¶´¶º¾ÉÍÛçÿççççg[MIAAEMÿɺ°¬ªª¬´Å[8,&$%*4[¼« œœ¢®Í8&#4ͪ—”•™Ÿ²E&%I®•’™¥Ó*/¼Ÿ•ŽŽ“œ´6#[¨˜ŽŽ˜§[%6´”—¡¾/,Ó§›•’“˜Ÿ°I')M¶¤œ™™›¢®Û8($-AͰ¨¤¢¤ª²Å[<4//2<<>MçŶ­©§¨«´ÅM4*$!#(2g¸¨Ÿœ›¢¯Û2#$8Á¦›–“•™¡¸:"'[ª›”“š©g'6´”Ž•ž¼/(Ó¤—ŽŽ’š¬A!>®œ”‘˜¤Í,0Á¤š”’”™¢¸<&,[²£œšš¥²ÿ4(  &0Mۨ¥¤§¬´É[>4028ASçÍÁ¾¼¾ÁÅÍÍÍÍÉÉÉÍÛgM>:66®›’ŽŽ–¡É+,Å •ŽŽ“œ°8#S«›““š¨g) :º¢™”“•›¥¾:$"2Û®¡œš›ž¨¶[2(" #*6SÁ°©¦§ª¯ºÓS<646:I[ÛÍÅÁÅÅÅÉÉÉÅÅÁ¾ÁÉçgI<4228Aÿ¾²ª¥¤¥«¶Ó>-#!)8Ó¯¢œ™™¥´S+'E²Ÿ˜“’”š¥É/.Å£—‘”¯<!Mªš‘ŽŽ—¥ÿ&0ºž”Ž•žº2'ç§™’”œ¬M&$A²Ÿ™””—œ©Í4#%8Í­¡œ›œ¡ª¼M0(#"&,:g¾°ª¨¨«°¼Ó[>:840./6Aç¾®§¢¡¤ª¶Û<+#!*<ŬŸš˜™¥¸A()S®ž—“’•›©ç+2ºŸ–Ž•ž¸2&ç¦˜ŽŽ‘™©M"8°œ“Ž–¡Å,+ͤ˜’‘–ž°A$'M¯Ÿ˜••˜ž«Û2"(>Ŭ¡œ£­ÁI0)%%)/>ÿ¼°«ª«®¶ÁÛSE>Ûº¬¥¡ £ª¶ç6(!*>¾¨™˜™œ§¾:$+ÿªœ•’‘•œ«S':²”Ž– Á-)Í¢–ŽŽ’›­>E¬š’ŽŽ—¤Û)0¾¡—’‘— ¸:",ÿ¬ž˜•–š ¯g.! ,I¾ª¡Ÿ¦°ÍE0)&'+2EÛ¼²­¬­²ºÅç[IEEIM[gÿÿÿÿÿÿçÓɾ¸´²´ºÅçI6.**,0EÓ¶ª¢ŸŸ¢ªºg0&!+I¸¥œ˜–˜¨Å4!-Ó¨›”‘‘–®E#!A®œ“Ž—£Ó)-¼Ÿ•ŽŽ“²6#[©™‘ŽŽ’™¨['8¶Ÿ—‘’™£¾4 /Óª˜–—›£´M-!#/Sº©¡žž ¨²ÓA0+(*-8MÓ¼´¯®°¶¾ÍçgSMMS[gÿgg[SSgÿÓÁº´¯®°¶ÁçE4,)(*0Eɲ§Ÿžž¡ª¼M." ,S´£›—–˜ž«Ó/2Á£™“‘–ž´:$S©™’ŽŽ‘™§[%2´“”ž¼/(祘‘Ž“›¬I#"A°–’”š¦Í0!6Ũ˜—˜¦ºE+ &4g¸©¡ŸŸ£«¸Û>0+*,0:S;´²²´ºÁÍç[[[[ggggSSMIIMÿÓÁ¸°­¬®´Áÿ>0*&%*0IÅ®¤ž¡«¾A+ !.g®Ÿ™••˜ž­g+6¸ —‘‘— ¼2(祘‘ŽŽ’š«E!:¯›“ŽŽ– É+,Å¢–”°< &S¬•’’•œªç-%<¼¦˜—™ž©Á>*  (8ç´©£ ¢§­¼ÿ>2-,.4A[;¸¶¶¸¾ÉÓççÿççççÿ[SIEAEMÿɼ²­ª©¬²Ág:-'#$)0M¾¬¡œ¡¬Å<'!/Û«ž˜••˜Ÿ¯M(!>²ž–‘’˜£É-+É¢–ŽŽ“œ¯< Iªš‘ŽŽ—¤Û(0ºŸ•Ž–Ÿ¸4*ç©›•’“—ž­[*(E¸¥œ™˜› ¬Í<* #+<Û´©¤¢¤©°Á[<2./0:Ig;ººº¾ÁÍÓÓÛÛÓÓÛÿgSI>:<>Igɸ¯ª§§«²Å[6*%"#(2[º©Ÿœ›œ¢­Í6%"2ɨœ—”•˜ ´A$%M­œ”’™¦Û)/¼Ÿ•Ž“¶4%ÿ¦˜ŽŽ‘™¨S$8²”—¡¾/.ͦ›•’”˜ ²E'+M´¤œšš£¯ç8)! %.EͲª¥¤¦¬¶Ég>6206>MÿÍÁ¾¾ÁÁÉÍÓÓÍÉÉÉÓÛgMA:66:EgŶ­¨¥¦ª²ÉM2(!"(4g¶¦žššœ¢®ç0"#8Á¥›•“”™¢º8!'g¨š“’š©[&6²œ“ŽŽ•Ÿ¾-)Í¢–ŽŽ’›¬A!!E­œ“’™¥Ó,2Á¤š•“•š£¸>&!/ÿ¯£œš›ž¦´ÿ6)" #(2MŰª¦¦¨®¸Í[A866ÿ¾¯¨£¡£©´Ó>,# (8Ó® ›™™œ¤¶I)&E²Ÿ˜“’•š¦Í-/Á¢—Ž”œ°:"S©™‘ŽŽ˜¥ÿ&4´”Ž•žº0)Û¦™“•­I&%A´ ™••˜žªÍ4#':Í­¢œ¢¬¾M2)%$(.<ÿ¾°«ª«®´ÁÛ[E>4-,.2>ç¼­¦¡Ÿ¢©´Û8) ):Ūžš—˜œ¥¸A')S®–’’•›¨ÿ)4¸ž•Ž•ž¸0&ç¥—ŽŽ‘™ªM"<¯œ“Ž—¢É,-É£˜’‘—ž²>#*S¯Ÿ™•–™Ÿ­ç0"*AÁ¬¡žŸ¥®ÅI2*''*0Eç¾²­¬­°¸ÅÛ[IEEIS[gÿÿÿÿÿÿçÓɾ¸´²´ºÅçM8.+)+0>縫£ŸŸ¡©¶ÿ2')A¼¨˜—˜œ¦¾:#+ÿªœ•‘‘•œ¬M%<°”Ž– Á-*É¡–Ž’›®<"I«š’ŽŽ‘˜¦ç(2¼ —’’˜¡º6",ÿ­ž™–—š¡°[/""-M¾«¢žž¡¨²ÍE0+()-6IÛ¾´¯¯¯´¼Íç[MMMS[gggg[S[[ÿÓÁ¼´¯¯¯´ÁçI4,('*/AÓ´¨¡žž¡ªºS/#*I¸¤›—–˜œ¨É2 /ɦ𓑕¯A""I¬›’ŽŽ—¤Ó).ºž”Ž“´4$g§™‘ŽŽ’š©S%:¶Ÿ—’‘”š¥Å2 2ͪž˜—˜œ¤¶M-!%0[ºª¢ŸŸ£ª¶ÓA2,*,/:MÓ¾¶²°´º¾Íçÿg[[gggg[SIIIMgÛÁ¸°­¬®²ÁÿA0*&%)/EͰ¥Ÿž ª¼I,! ,S² š–•—ªÛ.2¾¢˜’‘–ž´8%[¨™‘ŽŽ‘™¨[%4²œ“Ž”Ÿ¼.)ͤ˜Ž“œ®E##E¯–’‘•›©Ó.#8Ũ™—™¨¼E," (6ÿ¶ª£ ¡¥­ºçA2-,-2>SÓÁº¶¶¸¾ÉÓçÿÿÿÿÿÿg[SIA>AIg;´­ªª¬²Áÿ<-'#$(/EÅ­£žœœ ª¾>)!.ÿ®Ÿ˜•”—ž¬g* :¶Ÿ–‘‘–Ÿ¼0)Ó¤—ŽŽ’š¬E!>®›’ŽŽ–¢Í*.¾ –Ž•ž´:'[­–’’–¬ÿ-'>¼¦™˜›ŸªÅ>+""*<Û¶ª¤¢¤©°¾ÿ>4/.08E[Óżº¼¼ÁÉÍÛÛÛÛÛÛçgSI>::>E[ͺ¯«§¨ª°Ág8+%"#(0S¾« œ›œ ¬Å:&!0Óª—””˜Ÿ¯I'"A¯•‘˜£É,,Á –ŽŽ“œ°:"M©™‘ŽŽ˜¦g'4¸ž•— ¼2+穜•’“˜Ÿ°M*)I¸¥ššœ¢®Í:+" %-AÓ´«¥¤¦«´Åg>4026#%M«›“’™¦ç(0¸ž”Ž”¶0&ÿ¥˜ŽŽ‘šªM#<°•‘˜£É//Í¦š•“”™¡´E(-[²¤š›¥°Û8*# "'0IͲ«¦¦©­¸ÉgA864:ASÿÓÉÅÅÉÍÍÍÍÉÉÁÁÅÉÛgM<6226>[Å´«¦£¤©°ÅI/'  '2ÿ´¥™™›¡®ç/!$:¼£š”’”™¡º6 (ÿ§™’’šªM$8°œ“ŽŽ•ŸÁ,*É¢–ŽŽ“›®> "I­œ”“š§ç+6¾¤š–”–›¤¼<&!0ÿ°¤›œŸ§¶g6*$"%*6SŲ¬¨¨«¯ºÓ[E<8:>I[çÛÍÍÍÍÓÓÍÉÁ¾¼¼¾ÅÓ[E80//4>gÁ°¨£¡¢§°ÉA-$ '6篢œ˜™›¢°[,$>¶ ˜“’”™¤Å/+ͤ˜‘Ž“œ­A E¬›’ŽŽ—£Ó(.¼Ÿ•Ž”´6&[ª›“”œ«[)#<¸¢š••—¨Å6%%6Ó®¢œ¡«º[4*%$',:gÁ²­««®´ÁÓ[E>ÿÁ´®¬­°¸ÅÛ[MEEEM[ÿÿçÿÿÿÿçÓɾ¸¶²´¸ÁçM:/+*+0>ÿº«¤Ÿž §²Û6((<Á¨˜–—›¤¸>%)[¬œ•‘‘”›ªg(4¶ž•Ž•Ÿº/'Û¤—Ž‘š«E!<®œ“Ž—¢É+.Å£™“’—Ÿ´<#*[¯Ÿ™–—š ®ÿ0#!,EÁ¬£žž §²ÉE2+()+2AÿÁ¶¯¯°´ºÉçgSMMS[gÿÿgg[[gÿÓż´¯®®´¼ÛM8-)(*.>Û¶ª¢žž ¨¶g2%(A¼§œ˜–—œ¦¾6!+Û¨›”‘•œ¬I$>¯œ“Ž–¡Å+,Á •Ž’›®:#Mªš’ŽŽ‘™§ÿ(6º —’‘“™£¾6!.笞™—˜›£²[."#/M¾¬£ŸŸ¢©´ÓE4-*+/8MÛÁ¶°°²¶¾ÉÛÿg[ggÿÿggSMIMMgÓÁº²­¬­²¾çE2+&&)/AÓ°¦ŸœŸ¨¸S."*I¶£š–•—œ§Í0/Ť™“•°< "I«š’ŽŽ˜¤Û(/ºž”Ž”ž¶2'秘‘’›«S%!<´Ÿ—’’”›¦É0  2ͪžš˜™¦ºI-"&2[ºª¤ ¡¥¬¸ÛA4-,-2/)$$(/Eɯ¤žœœŸ©¼I+,[° ™•”—ªÛ-4¼ —’–Ÿ¶6%[§™‘ŽŽ‘™¨S#8°œ“ŽŽ•Ÿ¾-*É£—‘Ž”œ¯>"%I¯–’’–œ©Û.$:Á¨žš˜šž©ÁA,"!)8縫¥¢¤¨®¾çA6//08EgÓÁº¸¸¼¾ÅÍÓÓÓÓÓÓÛÿ[MA><>E[ͼ°«¨§ª°¾ÿ:-&""&/EÁ¬¢›œ «Á>(.ç­ž—””—ž¬g) <´ž–‘— Á/)Í£—ŽŽ’š¬A A­š’ŽŽ—£Ó).Á¡—–ž¶8(g¬–““—ž®[,'A¼§žš™œ¡­É<+#$,>Û´«¦¤¦ª²ÁÿE6224[͸®©¦¥©¯¾[6*# &/M¼©Ÿ›š›Ÿ¬É8% /Í©œ–“”˜ž¯E%#E¯œ”‘˜¤Ó+-Á •ŽŽ“œ²6#S¨™‘ŽŽ‘™§g%4¶ž•‘— ¾0,Û©œ–“”™Ÿ°I*+M¸¦šš¤¯Ó:+# "&/EÓ¶«¦¦¨¬´ÅÿE:66:ASÿÓÉÁÁÅÉÉÍÍÍÅÁÁÁÅÓÿM>6426>[ɶ¬§£¥¨¯ÁM0' &0[¶¦š™› ­Û2"!4Á¦š•’“˜Ÿ´<"%[ª›“‘™§ÿ'2¸””žº/&ç¥˜ŽŽ’š«I" >¯œ”’™¥Í.0Ŧ›–”•š£¸A(!/g²¥››ž¦²ç:+%"%*4MÉ´¬¨¨ª¯ºÉgE<::>I[ÿÛÍÍÍÍÓÓÍÉÅÁ¼¼¼ÅÓgI:2/.2<[Á²ª¤¡¢¦¯ÅI/%%2ÿ²¤œ™˜›¡®ÿ.#:º¢™“’“˜¡º4)ç§™‘’šªM#:¯œ“ŽŽ– É++Å –ŽŽ“œ¯<#I¬›”“›©ÿ*!8¼¤š–•—œ¦¾<'$4ç°¤žœ ©¸g6+%$',8[Å´­ªª¬²¼ÓgI><>EM[çÛÛÛÛÛÛÓÉžº¸¶¸¾Ó[A4.,,0+"&4Û­ š—˜›¡°S+$A´Ÿ˜“‘”™¥É.,É£—Ž“œ¯< E«š‘ŽŽ—¤ç'/ºŸ•Ž”ž¸4'ÿ©š“•œ¬[(%A¶¢š–•˜©É6%':Í®¤žž¢«¼[6+'')/®›“Ž‘˜¤Ó+0Á¢˜“’˜ ¶>$,g®Ÿš——›¡°ÿ0$".I¾­¤ŸŸ¡¨²ÍI4-*+.8IÛÁ¶²°²¶¾ÉÛÿg[[ggÿg[[SIIS[Ûź°­¬­°¼ÓI4,'&(-<Û¶¨ŸŸ§´g0#(Aº¥›—•—œ¦Á4 -Ó§š“”œ­E#>®œ“ŽŽ–¢Í)+Á •ŽŽ“œ²8$[©™’ŽŽ’™¨ÿ(8¸Ÿ—“‘”™¤¾6!/Û«ž™—˜œ¥¶S.$%0S¾¬¥¡ ¤«¶ÓE6-,-0:MÛÁº¶¶¶¼ÁÍÛçÿÿÿçÿÿg[MEAAE[ÛÁ¶®«ª¬¯¼ÛA0)$$'->Ó°¥žœœŸ§¸M,*M´¡š•”—œ¨Í./Å£˜’‘•ž²:"Mªš‘ŽŽ˜¦ÿ'2¸”Ž”ž¸2'禙‘“›«M$"A²ž—“’•›§Í0 #6ɪžš™šž¨¼I-#!(6gº¬¥¢£§®ºçA6/.06A[ÓÁºº¸¼¾ÉÍÛÛÛÛÓÛçÿ[MA<<.&""&-AÅ­¢›œž©ºE*,[¯Ÿ˜””—«ÿ+4º —‘–Ÿº2&ç¦˜ŽŽ‘™ªM":¯›’ŽŽ– Å-,É¢—•¯>"'S­ž—““–«ç.&<Á©žš™› «ÁA,$#+:縫¦¤¦©°¾çE8204:EgÓž¼¾ÁÅÉÍÍÍÍÉÉÍÓÿ[E<868>SÓº¯©¦¥¨®¼g:+$ %-I¾«Ÿ›š›ŸªÁ:&-ÿ¬—””—­S' <²ž–‘—¡Å-*É¡–ŽŽ’›­> E«š‘ŽŽ—¤Û(/¼Ÿ––Ÿ¸6 *ÿ«œ–“”˜ž®[,*Eº§ž›šœ¢®Í<+# !&->Û¸¬¨¦¨¬´ÅÿE:66:AMÿÓÉÅÁÅÅÉÍÍÉÅÁÁÁÉÓÿS>8224E[ÿÛÓÍÍÍÓÓÓÍÉÁ¼¼¼ÁÓgI:2./2:SÉ´ª¤¡¢¦®ÁM0&%0[¶¥œ™˜›Ÿ­Û/!4Á¤š”’“˜Ÿ¶:!&[ªš’‘™§g&4´“Ž•ž¼.'Ó¤—ŽŽ’›¬I"!A¯œ”“™¦Ó-2Ŧ›–•–›¤º>("0g²¥žœŸ¨¶ÿ8,&$&+6Sɶ­ªª¬²¼ÓgIA®›’Ž– É+-ÁŸ–Ž“°8%S«›””›ªg+":¼¤›––˜œ¨Á:'&6Û°¥žž¢«ºg8,(&(.:[ɶ®¬¬¯¶ÁÛ[IAAEIS[ÿÿÿÿÿÿçÓɾº´²²´¼Íg>2,**.8g¾®¥Ÿž ¥¯É>+ &4Ó­Ÿš——š¡°M)%A²ž—’‘“™¥É--Å¢–Ž“œ¯<"Mª™‘ŽŽ—¥ç'2¸ž”Ž•Ÿ¸2(ÿ¨š”‘–­M(&E¶¢›—–™ž«Í8&)<ͯ¥ŸžŸ¤®¾S6,((+0>ÿŶ°®®²ºÁÛgSMMSSgggg[[SSgç;¸²¯¯²¼ÓS8.)')-8g¼¬£žžŸ¦°Û8(&8ɪž˜–—›£¶A&'M­•‘“š¨ç*2¸ž•Ž”¶4&ÿ¦˜ŽŽ™©M#8°œ“Ž—¢Å--É¥™“‘’—ž²A&)S°¡š——š ®Û4%!+AÉ®¥ŸŸ §°ÅM6-*+-6EçÁ¸²°²¶¾ÉÓÿ[S[[ggg[SMEIM[çż²®¬­°ºÓM6,'%',:ÿ¸© ž¦²ç2%'>¾¦œ—•–›¤¼8"*ÿ©›”“›ªS&:²“Ž•Ÿ¾.)Í¢–Ž’›­> A­›’Ž‘˜¤Û*2¾¢˜“‘“™¢º:$-ÿ®Ÿš˜˜œ¤²g0%$.M¾­¥  ¤ª´ÉI:88:<>AISgçÓÍÉÉÉÉÍÍÍÓÓÓÓÓÓÓÛÛÛÛÛççÿÿÿÿÿÿÿçççÛÛÓÓÓÛÛÛççççççççÛÛÛÛÛÓÛÛÛÛÛççççççççÛÛÛÛÛÛÛÛÛÛççççççççÛÛÛÛÛÛÛÛÛÛÛççççççççÛÛÛÛÛÛÛÛÛÛÛÛçççççççÛÛÛÛÛÛÛÛÛÛÛççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççÛÛÛÛÛÛÛÛÛÛçççççÛÛÛÛÛÛÛÛÛÛÛÛÛçÛçççççççççÛÛÛÛÛççççççççççççççÛÛÛÛÛÛÛççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççÛÛÛÛÛÓÓÓÛÛÛÛÛççççÛÛÛÛÛÛÛÛÛÛçççççççççÛÛÛÛÛÛÛÛÛÛççççççççÛÛÛÛÛÓÛÛÛÛçççççççÛÛÛÛÛÛÛÛÛÛççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççççÛÛÛÛÛççççççççÛÛÛÛÛÛÛçÛÛÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççÛçÛÛÛÛÛÛÛÛçççççççççççççççÛççççççççççÛÛÛÛÛÛÛÛÛÛÛçççççÛÛÛÛÛÛÛÛÛÛÛçÛççÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççççççççÛççÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛçççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççççççÛççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛçÛçççççççççççççÛÛççççççÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛçÛÛççÛÛççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛÛÛÛÛÛÛççççççççççççççççÛÛÛÛÛÛÛÛÛÛÛççççÛÛÛÛÛÛÛççççççççççççççççççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççççççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛÛççÛÛÛÛÛÛççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛçççççççççççççççççççççÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççççççççççÛÛÛÛÛÛçÛÛçÛççççççççççççççççççÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛççççççççÛÛÛÛÛçççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛçççççççççççÛçÛççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛçÛÛÛçÛÛççççççççççÛÛÛçÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççÛÛççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççÛÛçççÛÛçÛççÛÛÛÛÛÛÛÛÛÛÛÛçççççççççÛÛÛÛÛÛççççÛççççççççççççÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛçÛççÛÛÛÛÛÛççÛçççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛçÛçççççççççççççççççççççççççççççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛçççççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛçÛÛÛççÛçççççççççççççççççççÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççÛçÛççÛÛÛÛÛÛÛÛççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççççÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççÛÛÛÛçÛÛÛÛçÛÛççÛçÛÛÛÛçÛÛçÛÛççÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççÛÛççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛçÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛççççÛçççççççççççÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççÛçççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççççççççççççççççççÛÛÛÛÛÛÛÛçççççÛÛçÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççççççççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛçççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛççÛÛÛÛÛÛÛÛÛÛÛÛçççççÛÛçÛÛÛçÛççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççççççççççççççççççççççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛçÛççÛÛÛçÛçÛÛÛÛçççÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛÛÛÛÛçÛççÛççÛÛççççççççççççççççççççççççççççççÛÛççççççççççÛÛçÛÛÛçÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛççççÛçÛççççççççççççççççççÛçÛÛçççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççççççççççççççççççççççççççççççççççççççççÛççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççççÛÛçÛÛÛÛÛÛÛÛÛçççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛçççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛçççççÛççÛçççççççÛçÛÛçÛççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛçççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççÛÛÛÛÛÛÛÛÛÛÛçççççççççççççççççÛçÛÛçÛÛççÛÛÛççÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛçÛÛçççççççççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççÛÛçÛÛÛÛÛçççççççççççÛÛçÛÛÛçÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççççççççÛççççççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççççççÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççÛÛççÛÛÛÛÛÛÛÛçÛÛçÛÛÛÛÛÛÛÛçççÛÛÛççççççÛççççÛçÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççççççÛççççÛçççççççççÛçÛÛÛÛÛÛçÛÛÛÛÛççÛçÛÛÛçÛçççççÛÛçÛçÛÛÛÛÛÛÛÛçÛççççççççççççççççÛÛÛÛÛÛÛÛçççççÛÛçççÛÛçççççççççççÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççÛÛÛÛççççççççççççççççççççççççççççÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛçÛÛÛÛÛÛÛÛÛÛÛÛÛçÛçççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛçÛÛçççççççççççÛççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççççÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛççççççççççççççççççççççççççççççççÛÛÛÛÛÛÛÛçççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛççççççççççççççççççççÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççÛÛÛÛÛÛÛÛÛÛÛÛçÛççÛççÛÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛçÛçÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛÛÛççÛÛÛÛÛÛÛÛÛççÛÛçççççççççççÛçççÛçççÛççççççççççççççççÛçççççççççççÛÛÛÛÛÛççççççççççççççççÛÛÛçÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛÛÛÛÛÛÛÛÛÛÛççççççççÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛççÛÛçÛÛçççççççççççççççççççççççççççççççççççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççççÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççççççççççççççççççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççççççÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛçÛÛÛçÛÛÛÛÛçÛçççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççÛççÛÛçÛÛççÛççÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛÛÛÛçÛçççççççÛççÛçççççççççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛççççççççÛÛÛÛççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛççÛççççÛÛÛçÛÛÛçççÛçççççççççççÛÛÛÛÛÛÛÛÛÛÛÛççÛçççççÛÛÛÛÛÛççççççççççççççççÛÛÛÛÛÛÛÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççççççççÛçÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛÛççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛçççççççççÛÛÛÛÛÛçççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççççççççççççççççççççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛççççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛçççççççççççÛÛÛççççÛÛçççççççççççççççççÛçÛÛÛÛçççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛçççççççççççççççççÛçÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççççççÛÛçÛÛÛÛÛçççççççÛççÛÛÛÛÛÛÛÛÛÛÛçççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççççççÛçÛççççççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛçÛççççÛçÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççÛçÛÛÛÛÛÛÛçÛÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛççççççççÛÛÛÛÛÛÛÛçÛççÛççÛççÛÛÛÛÛÛÛÛÛÛççÛçÛçÛÛÛçÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛççÛçççççÛÛçççççççÛÛÛÛÛÛÛÛççççççççççÛÛÛÛÛÛÛççÛççççççççÛççÛÛçÛÛÛççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççÛÛÛÛÛÛÛÛÛÛçÛçÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççÛÛççççççççççççççççÛçççççççççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛççÛÛÛÛçÛÛÛÛÛÛÛçÛÛÛçççÛççççÛÛÛçÛÛççÛÛÛÛÛçÛÛÛÛÛÛÛÛÛçÛççççÛÛÛÛÛÛÛÛÛÛçÛççççççççççççççççÛÛÛçççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛÛççÛÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççÛÛÛççÛÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççÛçççççÛçÛÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛçÛÛÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççÛÛçÛçÛççççççççççÛççççççççççççÛçÛÛÛÛçççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛÛÛÛÛÛÛÛÛÛçççÛçççÛÛÛçÛÛçÛÛççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççççççççççççççççççççççççççççÛçÛÛÛÛÛÛÛÛÛÛçççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛççÛçççççççççÛççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççççççÛÛççççÛÛçççÛÛÛÛÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççÛÛÛÛÛÛÛçÛçÛÛÛÛÛÛÛÛÛçççççççÛçÛÛÛÛççÛÛçÛÛçÛÛÛÛÛÛÛçççÛÛçÛÛÛÛÛÛÛçÛÛÛÛÛÛçççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛçççççççççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççÛÛÛÛÛÛÛÛÛÛÛÛçççççççççççççççççççÛÛÛçççççççÛÛçÛÛÛçÛÛÛÛÛÛçççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛçÛÛÛÛÛÛÛÛÛÛççÛÛçççÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççÛÛÛÛÛÛÛÛÛÛççÛÛççÛççççççççççççççççççççççççççççÛçççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççççççççççççççççççççÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççÛÛççÛçççççççççççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛççççççÛÛçççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛççççççççççççççççÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççççççççççççççççççççççççççççççÛçÛçÛÛÛÛÛÛÛÛÛÛÛçÛççÛÛÛÛÛÛÛÛççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççÛççççÛÛÛÛççççççççççÛÛÛÛÛÛÛÛççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççççççççççÛççççÛÛÛÛÛÛÛçççÛÛçççççÛççÛÛÛçççççÛççççÛÛççççÛÛÛÛÛÛÛÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛçÛÛçÛççççççÛÛÛÛÛÛÛÛÛÛçÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççççççççççççÛÛÛçççççççÛÛÛÛÛççÛÛççÛçççççÛÛÛççççççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛÛÛçÛçççÛçççççççççÛçÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççÛÛÛÛÛÛçÛççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛçÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççÛççççççççççÛçççÛçÛççÛÛÛÛçççççççççÛçÛÛÛÛÛÛççççççÛçççççççÛÛçÛçÛÛÛÛÛÛÛÛççÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛççççççççççÛççÛçÛçÛÛÛÛÛÛÛÛÛÛÛÛççÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÓÛÛÛÛÓÛÛÛÛÛÛÛÛÛÛççççççççççççççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛçÛÛçÛçÛçççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛçççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛçÛçÛççççÛçççÛÛÛÛÛçççÛÛÛÛÛÛçÛÛÛÛÛÛçÛÛÛÛÛÛÛçÛÛççççççççççççÛççççççççççÛçççÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛçççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛççÛçççççççççÛÛÛÛçççÛççççççççÛÛÛÛÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççÛççÛÛÛÛçççÛÛççççççççççççÛÛçÛÛÛÛÛÛÛÛççççÛÛÛÛÛÛÛçççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççÛçççççççççççççççççççççççççççççççççÛÛÛÛÛÛÛÛÛçÛçÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛççÛÛççççÛÛÛÛÛÛÛçÛçççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛçÛçÛçÛÛÛçççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççççççÛççççççççççççççÛÛçÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛçÛÛçÛÛÛÛÛÛÛÛÛÛÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççÛçÛÛççççççççççççççÛÛÛÛçççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççÛçççççççÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛççççççççççççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛçÛÛÛÛçççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççççççççççççççççççççççççççççççÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛçççççççççççÛÛçÛÛÛçççÛÛçÛÛÛÛÛÛçççççççççççççççççççççççççççççÛçççÛçÛÛÛÛÛÛÛÛÛçÛÛçÛÛÛÛÛçÛÛçÛççççççççççÛççÛÛÛçççççççççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛçÛÛÛçççÛçÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççÛÛçççççççÛÛçÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççççççççççççççççççççççççÛÛÛÛÛÛÛÛÛÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛçççççÛÛççççççÛçççççÛÛÛÛççççççççÛÛçÛççÛÛÛÛçÛÛÛÛçÛÛçÛççççÛÛÛÛÛÛÛÛççÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççÛÛççÛçÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççççççÛÛÛÛÛÛççççççççççççÛççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççççÛÛÛÛÛÛççççççççÛÛÛÛçççÛçÛççÛÛÛÛÛÛÛÛÛççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççÛÛÛÛÛÛçÛççççççççççÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççççççççÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛçÛÛÛÛÛÛÛÛÛÛÛçÛÛçççççççÛÛçÛÛÛççÛÛÛÛÛÛÛçççÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççççÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛçççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛççççççççççççççÛçÛççÛçççççççççççççççççççççççÛççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççççÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛçÛÛÛÛÛÛÛÛÛÛÛççÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛçççççççççÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççççççççççÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛçÛçççÛÛçÛççÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛççÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛçççççççççÛÛçÛççÛÛÛÛÛççÛÛÛÛÛÛçÛÛçÛççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛÛÛÛçÛÛÛÛÛÛçÛççççççÛçççÛÛÛçÛÛçÛÛçÛÛÛÛÛÛÛÛççççççççççççççççççççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççççççççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççççççççççççççççççççÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççççççççÛçççÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççÛÛÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççççççççÛÛÛÛçççÛçÛçççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛçççÛÛÛÛÛçÛÛççççççççççççççÛÛÛççççççççççççççççççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççÛçÛÛççççççççççÛçççççÛççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛçÛÛÛÛÛÛÛçççÛçÛÛÛÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççÛÛçÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛççÛÛÛÛÛççççççççççççççççççççÛÛÛÛÛÛÛÛÛÛÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççÛÛÛçÛÛÛÛÛÛÛççÛççÛÛççÛÛçççççççççççççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççççççççççççÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççÛÛÛççÛÛÛçÛÛççÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛÛÛÛÛççççÛÛçÛÛçÛÛçÛÛçÛçÛÛçÛÛçÛÛçÛçÛÛçÛççÛÛççÛçÛÛçÛçÛÛÛÛÛçÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛçÛçÛççççÛççÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛçÛçççÛçÛççççççççççççççÛÛÛÛÛçÛçÛÛÛççççççÛçççççççççççÛççÛçççÛççççÛçÛççççççÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛçççççÛçççççÛççÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛçÛççÛçççÛçççççççççççççççÛçÛÛçÛçÛÛÛçççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççÛÛççççççççççÛÛÛÛÛÛÛÛÛÛÛççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛççççççÛççççÛççÛÛÛÛÛÛçÛççççççççççççççççççççççççççççççÛçÛÛçççÛÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛÛÛÛÛÛÛÛÛÛÛççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛçÛççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççÛççççÛÛÛÛççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛççççççÛÛÛÛÛççççççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççççççççççççççççççççççççÛÛÛçÛçÛçççççççççççÛÛççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççççççÛççÛççÛÛçççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÓÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççççççÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛÛÛÛÛÛÛÛÛÛÛçÛçççÛÛçÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛçççÛÛÛÛçÛÛÛÛççççççççççççççÛÛççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛççççççÛÛÛççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççççççççççççççççççççççççççççççççççÛÛÛÛÛÛÛÛçççççççççççççççççççççççççççÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççççççççççççÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛççÛçÛÛÛÛÛÛÛçÛÛÛÛÛÛççççÛÛÛÛÛÛçÛçÛçççççÛÛÛÛÛÛÛÛÛÛÛÛÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççÛçÛççÛçÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççççççÛÛçÛÛçççççççççççççççççççÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛçççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççÛÛçÛÛÛçÛÛÛçÛççççççççççççÛçççÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççççççÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛÛÛççÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççÛççççççççççççÛÛÛÛÛÛÛÛçççççÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççççççççÛçÛÛÛÛÛÛÛÛÛÛçÛçççÛÛçççççÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛçÛÛÛÛÛÛÛçÛÛçÛÛÛçÛÛçÛççççççççççççççççÛççÛçÛçççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççÛçÛÛçççççççççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛçççÛÛçÛçÛÛÛççÛççççççÛÛÛÛçÛççÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççççççççççççççççççççççÛÛÛÛÛÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛçççççÛçççççççççççççççççççççÛÛçÛççççççççÛÛÛÛÛÛÛÛÛÛÛççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛÛÛçççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççççÛççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛÛÛççççççççççççççççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççççççççççççççççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛçÛÛÛÛÛÛÛÛççççÛÛçÛçççççççççÛçççÛççÛçÛçççÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛççÛççÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççÛÛççÛÛççççççççÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛçÛÛÛçÛçççççççÛçÛÛÛÛçÛÛçççççççççÛÛççççÛÛÛÛÛçÛççÛÛçÛçÛÛÛÛçÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛçççÛçççÛççççÛÛççÛçÛÛÛÛÛÛçççççÛÛÛÛÛÛÛÛçççççççççççççççççÛÛÛÛçççÛÛÛÛÛÛÛÛÛççÛÛÛççÛÛÛççççççççççççççççççççççÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛçÛççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççççççççççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛçÓÛÓÛçÛÛÛççÛÛÓÛÛÛçÛçÛçÛççÛÛççÿçÛÛÛÛÛÛççÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛÛçÛçÛççÛÛÛçççççççÛÛçÛÛÛçÛÛÛÛÛÛÛççççÛççÛÛÛÛçÛçÛçççÛççççÛçÛççÛççççÛççççÛççÛÛçÛÛÛÛçÛÛçççççççççÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛçÛÛÛÛççÛÛççççÛççççççççççÛÛççÛçççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛççççÛçÛççÛçÛçççÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛççççÛÛçÛççÛççÛçÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛçÛÛçççççççÛçççççççççÛççÛÛÛÛÛçççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççÛçççÛççÛçÛççççççççççççççççççÛÛÛÛÛÛÛÛÛÛÛçÛçÛÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççÛÛÛçççÛÛççççççççÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛççÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛÛççççççççççççÛÛÛÛÛÛÛÛÛÛçÛçÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛÛçççççÛçÛÛÛÛÛçççÛÛÛÛÛÛÛÛÛÛÛççççççççççççÛÛÛÛÛÛÛÛÛÛççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛÛÛÛÛÛÛÛÛÛÛÛÛççÛÛÛÛçÛççççÛççççççççççççÛççççÛÛÛÛÛÛÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛççççççççççççççççççççççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛççççççççÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛçççççÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛçÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛççççÛçÛÛÛçÛÛÛçççççççççççççççççççççççÛççÛÛÛÛçÛÛçÛÛçÛÛÛÛçÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛççÛççççççççççççççççççççÛÛÛÛÛÛÛÛÛÛçÛççççÛÛÛÛÛÛççÛÛÛççÛÛÛÛÛÛççÛÛÛçççççÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççççÛÛççÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛçÛçÛÛçÛÛÛÛÛççÛÛççççÛÛçççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛçççÛÛçÛçÛÛÛçÛÛçççÛçÛççççççÛçççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛççççççççççççççççÛçççççÛççççÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççççççççççççççççÛçÛççççÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççççÛççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛççÛççÛççççççççççÛÛççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛçççÛÛÛÛÛÛÛÛÛÛçÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççÛççÛÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛçççÛÛÛÛÛÛÛÛÛÛÛççÛÛçççÛÛçÛÛÛçççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççççççççççççççÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççÛççÛÛçÛççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛçççççççççççççççççççççÛççÛÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛÛççççççÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛççççççÛÛÛÛÛÛÛÛÛÛçççççççÛÛÛÛÛÛÛçççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççççççççççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛçççÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛçÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛçççççççççççççççççççççÛÛÛçÛÛçççççÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççÛçççÛçççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛççççççÛÛççççççççççÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛççÛÛÛÛÛçççççççççççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççççççççÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛÛÛÛÛçççççççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççççççççÛçççÛÛÛÛÛçÛÛççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛçççççççççÛÛççççÛÛÛÛÛÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛççççççççççççççÛçÛÛÛÛÛÛÛÛÛççÛçÛçÛÛÛÛÛççÛççççççççççççççççççççççççççççççççççççççççççÛççÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççççççÛÛÛÛÛÛÛÛççççççççÛçÛÛçÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛçÛÛÛçÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççÛÛçççÛÛçççççççççççÛçÛÛÛçÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççÛÛÛÛçççççÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛÛçÛÛÛÛÛçççÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛÛçÛççÛÛççççççççççÛÛçÛççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛçççççÛÛçÛÛÛÛÛÛÛÛÛÛÛÛççççÛçççççççççççÛÛÛçÛÛçççççÛçççççççççççççÛÛÛÛÛççÛçççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççÛÛÛÛÛÛÛÛÛÛÛççÛÛççÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççççççççÛçççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççççÛçÛçÛçççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛçççÛÛÛÛçÛÛÛÛÛÛÛçÛçÛÛÛÛççççççççÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛçÛçççççÛÛÛÛÛÛÛÛÛÛÛççççççççççççÛÛÛÛççÛÛÛÛÛÛÛÛÛÛÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççÛçÛÛçÛçÛçççççççççççççççççççççççççççççççÛÛççÛÛÛÛÛÛçççççççççÛççÛÛÛÛÛççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛççççççççççççççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççççççççÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççççççççççççççççÛççççççÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛççççççççççççççççççççççÛÛÛÛÛÛÛÛÛÛÛççÛçÛÛÛÛÛçççççççççççççççççççççççççÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççççççççççççÛçççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççççççççÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛççÛçÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛçççÛçÛÛÛçççççççÛÛÛÛçççççççççççççÛÛÛÛÛÛÛççççççççÛÛÛÛÛççççççÛçÛÛçççççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççççççççççÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççççççÛççççÛççÛçÛçççÛÛÛÛÛÛçÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççççççççÛççççÛÛÛçÛçççççççççççÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççççççÛççççççççççççççççÛÛÛçççççççççççççççççççççççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççççççççççççççççççÛÛÛççÛççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççççççççÛÛÛÛÛÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛÛÛÛÛççÛÛÛÛÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛÛÛççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççÛçççÛçÛçÛÛÛÛÛÛÛÛÛÛçÛçççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛççÛÛÛÛÛÛçççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççÛÛÛÛÛÛÛÛÛÛÛÛççÛççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççççççççççççççççÛÛçççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççÛÛÛçÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛçççççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççççççççççççççÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççÛçÛçççççççççççççççççççççççÛÛçççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛçÛÛÛçÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççÛÛÛçççççççççççççççççççççÛççÛÛÛÛçÛÛÛçççÛÛÛÛçççÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛççççççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççÛçççççççççççççççççççççÛççÛÛÛÛÛÛÛçÛÛçççÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççççÛçççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççççççççÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛçççççççççççççççççççççççÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççÛççÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççççççççççççççÛçÛÛçÛççÛÛÛÛÛççÛççÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛçççççççççççççççççççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççççççççÛççççççççÛçÛçÛÛÛÛÛÛÛÛÛÛÛççÛÛÛÛÛÛÛÛÛçÛççÛÛÛÛçççççÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛççççççççççççççççççççÛçççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛçÛÛÛÛÛÛÛççççççççççççççççÛççççÛÛçÛççççÛÛÛÛÛÛÛÛÛÛÛÛççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççÛçççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛÛçÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛÛçççÛÛÛÛÛÛçççççççÛÛçÛÛÛÛÛÛÛÛÛççÛÛÛÛÛÛÛÛÛÛÛÛÛççÛççççççççççççÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛÛÛÛÛÛÛÛÛÛççççççççççççÛÛçÛÛÛÛÛÛÛÛÛÛçççççççççççççÛÛÛçÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛçÛÛççççÛÛÛÛÛÛççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççÛÛçççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççÛÛÛÛÛÛçççÛçÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççÛÛÛÛççççÛÛÛçÛÛÛÛçÛççççççççççççççççççççÛÛÛÛÛççççÛÛçççççÛÛÛÛÛçÛÛççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛççÛçççççççççççççççççççççççÛÛçÛÛçÛÛÛçÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççççççççççççççççççççççÛÛÛÛÛççççÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛçççÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççÛÛÛçÛÛççÛçççÛççççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççÛÛÛÛÛÛÛÛÛççççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛçççÛÛçççççççççÛçççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛççççççççççççççççççÛçççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççÛÛÛÛÛÛÛÛçççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛÛÛÛÛÛÛÛççÛÛÛÛÛçÛçççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛçççÛÛçÛçÛÛÛÛÛÛÛççççççççççççÛçççççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççççççççÛçÛÛÛÛÛÛÛÛççççççççÛÛçÛçÛççççÛÛÛÛÛÛÛççççççççççççççÛççÛççççççççççççççççççççÛççÛççççÛÛÛÛÛÛÛÛÛçççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççççççççççÛÛÛÛÛççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççççççççççççÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççççççççÛÛççççççççÛÛçÛÛççççççÛÛÛççÛÛÛÛÛÛÛççÛÛÛÛÛÛÛÛÛÛÛÛççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛÛÛççÛÛçççÛÛÛÛçÛÛççÛÛçççÛÛçÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛçÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççÛÛÛÛÛççççççççççççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛççÛÛÛÛÛÛÛÛÛÛÛÛççÛÛÛÛçççÛÛÛÛÛÛççççççÛÛÛÛÛÛçççççççççççÛçççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛççççÛÛçççççççççççççççççÛÛçççççççççççççççççççÛçççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÓçÛçÉ>!/g® ›™›¡¯g+/ç­Ÿš˜˜›¡®Ó:)"!'2MÁ¯¨¤¤§­¸ÓM82/04>Sçɾ¼¼¾ÁÍÓÛÛÛÛÓÓÓçgSE<::>IÿÁ¶­¨§¨¬¶ÍI0(# #*8ç´¦ž››¥´[- &>º¤š•”•š¤Á4*Û¦™’”›¬E#>®›’ŽŽ–¡Í*,¾Ÿ•ŽŽ“œ°8$Sªš’“š©g( 8º¡™”“–›¦Á6#"2Û­Ÿ›™šž§¸S0& "(4[Á°©£¦¬²Í[:/..>MESÁ²¸¸¶¶¸¼¾ÁÁÅÅÅÉÓÿSE:2006>gŶ¬§¦¨¬¶ÓA.&! $,>Í­¡œ™™œ¤´S,(I´ ™•“•›§Í--É£˜‘”°<"Mª™‘Ž—¤ç&0¸ž”Ž”ž¸2(禙’”›¬M&$A´Ÿ˜”“–œ¨É4"$8ͬ œš›ŸªºM/&!!$+:g¼®¨¦¦ª°¼ÛM<868>IgÛÍÉÅÅÅÉÍÍÍÉÅÁÁÉÍçSA8202:EÛ¼¯©¤£¦«¸Û<+#"*<ɬ ›™š¦ºA(*S®ž—“’•œ©ç+4ºŸ–•ž¶2'ç¦˜ŽŽ‘™©I":°œ“ŽŽ–¡Å,,É£˜‘–ž²>#'M¯ž˜••˜ž¬ç/ (>ÁªŸœ›¢­ÅE/'##'->ç¼®ª¨©­´ÁÛM>::4/.08EÓ¸­¦¢¡¥¬ºÿ8) #+E¾©žš˜™¨¾:%,竜•’’–¬S'<°”Ž–¡Á-*É¢–ŽŽ’›­< I¬š’ŽŽ˜¥ç)2ºŸ–‘‘—Ÿ¸8!+ÿ¬˜•–™ ¯[-+E¼©Ÿœž¥¯ÉA/(%&*0EÓº¯«ª«¯¸ÅçSA>>AI[gçÛÛÛÛÛÛÓÉżº¸º¾ÉÿI8/,+/6IÓ¶ª£Ÿ ¤«º[2&"-I¸¦™—™žªÉ4!/Í§š”‘’–ž¯A#"I¬›“Ž‘—£Ó).¼ž•Ž“¶4%g§˜‘ŽŽ‘™¨[%:¶ž–‘’™£Á0/ͪ˜–—›£¶M+".S¸¨Ÿž ¨´Û>.)&(,6MÓº°­­¯´¼ÍÿSIEIMSggÿÿÿggÿÛÓż¸´²¶ºÉgE4-*),4IͲ¨¡žŸ£«¼I.#"-[²¢›——™ž«Û/ 4¾£™“’—Ÿ´:&[©š’ŽŽ‘™§[%6´œ“Ž•ž¼.)Ó£—ŽŽ“›¬E""E¯•‘”š¦Ó.!6Á§œ—–˜œ¦¼A*%2g¶¨¡žŸ£«¸ç<.*(*/:S͸²®¯°¶ÁÍç[MMSSggggg[SS[çÓÁº²¯¯²ºÉg>/+((+4Mů¥Ÿž£¬ÁA+ "/ÿ¯ š––™ž­g+":¸Ÿ—’’— ¼2(Û¤˜‘ŽŽ’š«E!<®›’ŽŽ–¢Í*-Á –Ž”°:&S¬œ•‘‘•œ«ÿ+%>¼¦œ˜—™žªÅ<) (8Û²§ Ÿ ¥­¼ÿ[ɼ¶²²¶¼ÅÛÿ[[[[gggg[SIIISÿ;¶®¬¬¯¶É[:.)&&+4S¾¬£žž£­É<)#2Ó«ž˜••™Ÿ¯M($A°–‘’™¤Í,,Å¡–Ž“œ°:!M©™ŽŽ—¥ÿ'2¸ž•Ž–Ÿ¼2*ç©›•’’—ž¯S)(I¶£›˜˜šŸ¬Í8("*>Ͳ§¢ £¨°Á[:0-,/6Eÿͼ¸´¶ºÁÉÓççÿÿççÿÿ[SIAAEMÿɺ°¬©ª­¶ÉS6+%#%*4[ºª œœ£®Ó8%$8ɨœ—”•™¡´A%&S¬œ”“š§ç)0¸ž•Ž”ž¶2%ÿ¦˜ŽŽ‘šªI#<°œ”Ž—¢Å..ɦ𔒔˜ ´A&,S²¢œ™™œ£¯ç4'$-Eɰ¨££¥«´ÉS<0./2< !I­›“’™¦Û+4¾£™”“•š¤º:% /篡œ™š¦¶g4'  '0Mɰ©¥¥¨­¸ÍS<4228ASçÉÁ¾¾¾ÅÉÍÍÍÉÉÉÉÓç[M>:88! E¬š’ŽŽ–¢Ó).¼Ÿ•Ž”´6%[©š““›©[(!:¸¡™•”–œ§Å6##4Û®¡œšœŸ¨ºS2'! $*8[¾¯©¦¦©¯ºÓS>668>I[ÛÍÅÅÅÉÉÍÍÍÉÅÁÁÅÍç[I:4248E羯©¤£¥«¶Ó>-$#*<É­¡œ™™¥¶I*(M°Ÿ˜“’•›§Ó,/Á¡—•²8#[¨™‘ŽŽ™§[$4¶”Ž•Ÿ¾/*Ó¥™’•®I%%E²Ÿ™•”—ªÓ2#&:ɬ¡œ›¡«¾M0'#"&-<ÿ¼¯ª¨©¬´¾ÛS><:ŪŸš˜™¦º>'*[­–’’•œªÿ)6¶ž•Ž•Ÿ¼0'Û¤—ŽŽ‘š«E"<®›’ŽŽ—¢É+.Å¢˜’‘–Ÿ´<")S®Ÿ˜••™Ÿ®ÿ.!)AÁ« œž¤®ÅE.'$%)/AÛ¼¯¬ª«¯¶ÅçSE>>EI[ÿçÛÛÛÛÛÓÍÉÁ¼¸¶¶¼ÅçM<2-,.4EÓ¸«¤ Ÿ£ª¸ÿ6'!+E¾§™—™¨Å6#-Û©œ•’’–­M% <¯œ”Ž—¢É,+Å¡–ŽŽ’›¯<"M«š‘ŽŽ‘˜¦ç(4ºŸ—‘’˜¡¼6 -ÿ«ž˜•–š¡²[-  -M¼ª Ÿ§²ÍA/)&(+4EÛ¼²®­®²ºÉçSIEIIS[ÿççÿÿÿçÛÍž¸²²´¸ÅÿE6.**,4IÍ´©¢ŸŸ£«ºS/$!+M¶¥œ˜—˜©É2 /ť𔑒–ž²>!"I¬›“Ž‘˜¥ç(/ºž”ŽŽ”¶2%ÿ§˜‘ŽŽ’š«M$ <²ž–‘“™¥É02Í©˜–—›¤¸I, $0[¸©¡žŸ¡ª¶Û>/*().8SÓº²®®°¶¾Éç[SMS[[ÿÿggg[[[ÿÍÁº²¯¯°¶ÅÿE2+((+2Iɰ§Ÿž¢¬¾E,!!-[²¢›—–™ž¬ç- 6¼¢˜’‘—Ÿ¶6&g§™‘ŽŽ‘™¨S$8°œ“ŽŽ•Ÿ¾-)Ó£—Ž“œ¯A!#E¯–’‘•›©Û-#8Á§œ˜–™§¼A+ '6綨¡Ÿ ¤¬ºç<0+*-2>[ͼ´°²´ºÁÍÛÿgggÿÿÿg[[MIMSÿ;´®­¬®¶Ågº¥œ˜˜šŸªÅ<* !*<Û´¨¢ ¢§¯¾ÿ>2--/6Egɼ¶´´¸¼ÅÍÛçÿçççÿg[MIAAAIÿɼ²¬ªª­²Á[:-&$%)2S¼«¡œ¢­É:'#2Óª—••™Ÿ°I'#E¯•’˜¤Ó,-¾Ÿ–Ž“œ²8"S©™‘ŽŽ‘˜¦g&4¶ž•– ¼2,Û§›•’“—Ÿ¯M)*M¶¤œ™™›¡­Ó:)!$-AͲ¨£¢¤©°Å[>2//2:Iÿɾ¼ºº¾ÅÉÓÛÛÛÛÛÛçgSI><:>Iÿɸ®ª§¨«²ÅS4*$!#)2[º¨Ÿœ›£¯Û2##6Á¨œ–”•™¡¶<#'[«›”“š§ÿ'2¶ž”Ž”žº0&ç¥—ŽŽ‘š«I"<°”’™¤É-/ɥ𕓔™¡¶A'-[²£œšš¤°ç8)"!'0IŰ©¥¤§¬¶É[>6226>MÿÍÁ¼¼¾ÁÉÍÓÍÍÍÉÍÍç[MA:66:EÿÅ´¬¨¥¦ª²ÅI2(" ")4ÿ´¦›š¤°g. $:¼¤š•“•š£¾4)ÿ¨š’“›«M$:°œ“ŽŽ• Å,+É¡–ŽŽ“œ¯<"I¬›“’š§ç+6¼£š•“•š¥¼:%"0篡œš›ž§´g4(#!$*6[Á°ª¦¦©®ºÍS>846!E¬š’ŽŽ—¤Û'/¼Ÿ•Ž”¶4'g©š“”œ¬S'#<¶¡™•”—œ¨É6$%8Í­¡œ›œ ª¼S2)##%,8gÁ°«©©­²¾ÛSA:8:AM[çÛÍÍÍÍÍÍÍÉÁ¾º¼¾ÅÛ[A60./4A羯¨£¡£ª´Ó<+"!):ɬŸš˜™œ¥¶I))M®ž—“’”›§Ó+0¼ –•ž´6$[§˜ŽŽ˜§[$6´”Ž– ¾.*Ó¥™’•¯E%&M°Ÿ™••˜ž«Û2#(>Å«¡œ¢¬ÁM0)%$(/>ÿ¾°¬ª«®¶ÁÛ[E>>AISgçÛÛÛÛÛÛÓÉÁ¼¸¶¶¼ÅçM<0-,-2A纭¥ Ÿ¢©¶ç8( )>Á©žš—˜œ¦¾:%*g¬œ–’‘•œ«[(6¶ž•Ž–Ÿ¾/(Ó£—ŽŽ‘š«E!>­›’ŽŽ—£Í+0¾¢˜’‘—Ÿ¶<"*g­Ÿ˜•–™Ÿ®ÿ/" +E¾«¡žŸ¦¯ÉE0)&'*2Aç¼²®­®²ºÉçSIEEIM[gÿÿÿÿÿÿÛÓž¸´²´ºÅçI8.*)+0AÛ¶ª£ŸŸ¢ª¸g2% +Eº¦œ˜–˜œ¨Å4"-Ó¨›”‘‘•®I$ >¯œ”Ž—¢Í*,ÁŸ•Ž“œ°8#S©™’ŽŽ‘™§g'6¸Ÿ—‘“˜¢¼6!/Û«˜–—›¢²[.!#/S¼ª¡žž ¨²ÓA0*()-6MÛ¾´¯®°¶¼Íç[SMMS[gggg[SS[ÿÓź´°¯°¸ÁçE4,((+0EͲ§ žž¡ª¼M." ,M¶£›—–˜ªÓ/0É¥™“’–ž²< #M«š’ŽŽ˜¥ÿ'0¸””ž¸0'禘‘ŽŽ’š«M%!>°ž–’‘”š¥É0 4É©˜—˜œ¥¸I,!%2g¸ª¢ŸŸ¤«¸Û>2,*,0/)&%)/Eɯ¥Ÿ¡«¾E+ -[° š–•˜ž«ç,6¼¡˜’’—Ÿ¼2'ÿ¦™ŽŽ‘™©M#:¯›’ŽŽ–ŸÅ,+Å¢—Ž”œ¯>"%M­–’’•œªÛ.$:¾§™—šž©Á>+! )8ç¶©£ ¡¦­¼ÿ>2-,.4A[;¸´¶¸¼ÅÍÛçÿÿçÿÿÿ[SIAAEIgͼ²­ªª¬²¾ÿ<.'$%)0M¾¬¡œ¡«Å>)!/ç­ž˜••˜Ÿ®S(!<´ž–‘’—¡Á/+Í¢–ŽŽ’›®>E«š‘ŽŽ—¤Ó)0ºŸ•Ž•ž¶8)ÿªœ•’’—ž­[*'Eº¦™™›Ÿ¬É>*!#+>Ó´©¤¢¤©°Áÿ>4..08EgÍÁººº¾ÁÉÓÓÛÛÛÛÛçgSIA<<>Egɺ¯ª§¨«²Á[6+$!"(0Sºª œ›¢­Í8%!2Í©—””™Ÿ²E%$I®œ•’™¥Ó*.¾Ÿ•Ž“œ²6$g§˜ŽŽ˜¨[&6´ž•‘—¡Á0,Ó¨›•“”™ ²I)+M¶¤™šœ£¯Ó:*! %.EÍ´ª¥¤¦«´ÅgA6224>MÿÓž¾¾ÅÉÉÍÍÍÉÉÍÓçgMA866:A[ɸ­¨¥¦ª²ÅM2(" !(2g¶§ž›šœ¢®Û2""6Á¦›•“”™ ¶:"'[ª›“’š¨g&4´”Ž•ž¼/(Ó£—ŽŽ’›«E">¯œ”’™¥Í-0ť𕓕š£¸>' .g²¤š›ž¦²ç8)# #(2Mɲª§§©®ºÍ[>846:ESçÓÉÅÅÅÉÉÍÍÉÅÁÁÁÉÛgI<6228AgÁ´ª¥£¥©°ÉE.& '4ÿ²¤š™œ£°g-$<º¢™”“”™£¼4*Û¦™‘“›«I"<®›’ŽŽ–¡É+,ÅŸ•ŽŽ“œ¯:$Sª›”“›©g) 8¼¢š•”–›¦¾:&#4Û®£›œŸ¨¸[4)#"$+6SŰ«©¨«°¼Í[A<8:AI[çÛÓÍÍÓÓÓÍÉž¼¼¾ÅçSA6/..2,# (8Ó®¡›˜™œ¤²M*&A´Ÿ˜“’”š¦É--Å¢—Ž”œ¯< "M©™‘Ž—¤ç'0¸ž”Ž•ž¸2)ç§š“”œ¬S'%A´¡™••˜ªÍ6$&8Í­¢œ¢«¼[4*%%(.:g¾²¬ª«®´¾Û[I>ç¼­¥¡Ÿ¢¨´Û:* (:É«Ÿš—˜œ¤¸A'(S®–’‘”›¨Û+2ºŸ–Ž•ž¶4%ÿ¦˜ŽŽ‘™¨M#:°œ“Ž–¡Å.,ɤ™’‘–ž²A$(M° ™––™Ÿ­Û0#*>Ŭ¢žž¤­ÁM2*''*0Aç¾²­¬­°¸ÅÛ[IEEIS[gÿÿÿÿÿÿçÓÅÁº´²´¸ÁçI8.*)*0<ÿº«¤ŸŸ¢©¶ÿ4')>Á¨˜—˜œ¦¾8#+ÿ«œ•‘‘•œ«S'8²”Ž–Ÿ¾.)Í¢–ŽŽ’š­>  E¬›’ŽŽ˜¤Ó*0¾¢˜’’˜ ¸8#,ÿ­ž™–—š¡°g/"!-IÁ¬£žž §°ÍI4+()-4IÛ¾´¯®°¶¼Éç[MMMSSgggg[SS[gÛɼ¶°¯¯¶ÁçI4-('*/>Ó¶© ž ©¸g0$*E¸¥›—–—œ§Å4!-Í§š“‘•®E#!E­›’ŽŽ—¢Ó*,¾Ÿ•Ž“œ²6$[¨™‘ŽŽ’™¨g'8¸Ÿ—’‘“š¤Á4 /Ó«ž™—˜œ¤¶M."$0[¼«£ŸŸ£ª¶ÓE2,*+/:MÓ¾¶²²´¸¾ÍÛÿg[[gggg[SIIIMgÛź²­¬®´¾çA0*&&)/AͰ¦ŸŸ©ºM-!+S´¢š–•˜©Ó/0Á£˜’‘–ž´:$S©š’ŽŽ‘˜§g&2´”Ž”žº/(Û¥˜‘Ž“œ­E##A°ž—’‘”›§Í0"6Ũ™˜™§¼E,"'6g¸«£ ¡¥­ºçA2-,-2<[ÓÁº¶¶º¾ÅÓÛÿÿÿÿçÿg[SIE>AI[Ó¾´®ªª¬²¾ÿ>.($$(/IÅ­£œœŸª¼E* .g¯Ÿ™•”—ž¬ÿ+ 8¸Ÿ—‘‘—Ÿº2'ç¥˜ŽŽ‘š«I"<®›’Ž– Å,-Å¡—Ž”°4./06E[ÓÁ¼ºº¼ÁÉÓÛÛÛÛÛÛçgSMA<:Ó´«¦¤¦«²Ág>6204$$I­œ”‘™¥Û)0ºž•Ž“´4%ÿ§˜ŽŽ‘™©S%:²•‘˜¢Á/.ͧ›–“•™¡´E(-S¶¥š›¥°Û:+#!"'0IÍ´«§¦©­¸ÉgA846:ASÿÓÉÅÅÅÉÍÍÍÉÉÁÁÅÉÛgM>6226<[Å´«¦£¤¨°ÅM0' &2g´¥š™› ­Û0"#8¾¤š”’”˜ ¸8!(g©š’’š©S%6´“ŽŽ•Ÿ¾-)Í£–ŽŽ’›­A!"E®œ”“™¦Û,4Á¥›–”–›¤º>'!0ÿ²¤ž›œŸ¨¸g6*#"$*4MÉ´¬©¨«¯ºÍgE<8:AI[ÿÛÍÍÍÓÓÓÍÍÅÁ¾¼¾ÅÓ[E82..2<[Á°©£¡£¨°ÉE-$'4篢›™˜›¡°[,$<¸¡™”’”™£¾0+Ó¥˜‘Ž“›­E">­›’ŽŽ–¢Ó)-¾Ÿ–Ž”²8%[ª›“”›ªg*#:¸£š–•—¨Å8%$4Û¯¤žœ¡ªº[4*%$',:gÁ²¬ª«­´¼Ó[IA>AEMgçÛÛÛÛÛÛÓÉžº¶¶ºÁÓ[A4.,-0+"'6Ó­ š˜˜›£²M*&I²ž—’‘”š¥Í-.Á¡–Ž”°:"M©™‘ŽŽ—¥ÿ&4´”Ž•Ÿº0)ç§š“‘•®I'&E´¡š––™ž«Ó4$':Í®¤žž¤­ÁM4+'&*/>ÿÁ´®¬­¯¸ÁÓgMEEMS[ÿÿççÿÿÿçÓɾ¸´°²¶¾ÓS<0,*+/<ç¼­¤Ÿž¡¨´Û8((<Ūž™—˜›¤¸>&(S­–‘‘”›¨ÿ)4¸ž•Ž•ž¸0&ç¥—ŽŽ‘™ªI":¯œ“Ž—¢É,-Ť™“’—Ÿ´>%*[¯ š–—š ®ÿ0$ *AÅ­£Ÿž §°ÅI4,)),4Eç¾´¯®¯´ºÅÛgSMMS[gÿÿgg[[[ÿÓż´¯®¯´¾ÛM8-)().<Û¸ª¡žŸ¨´ÿ4%(>¾§œ˜–—œ¦¼8"+ç©›””œ«S%<°œ“Ž– Å,*Í¢–Ž’›¯<!I«š’ŽŽ‘™¥Û*2¼¡˜“‘“™¢¼6"-ÿ­Ÿš—˜›¢²g/$#.M¾¬£ŸŸ¢©²ÉE4-*+.8MçÁ¶²°´¸¾ÉÛg[[ggggggSMIIM[ÛŸ²®¬®²¾ÛI4+'%(/AÛ´§ŸŸ¨¶[."*I¸£›–•—œ§É0.Í¥™“•¯>!!E¬›’ŽŽ—£Û(.¼ž”ŽŽ”´4%[¨™’“šª[& :¶Ÿ—“‘”š¥Å4! 0Ó«Ÿš˜™¦¸M.#&2[¼¬¤  ¥¬¸ÓE4.-.2>[ÓÁ¸¶¶¸¼ÅÍÛççççççÿgSMAAEI[ÓÁ´­«ª«¯¼çA/(##'.Aͯ¤žœœŸ¨ºI,+M² ™–”—ªÛ.2¾¡˜’–ž´6%[¨™‘ŽŽ™§[%6²“ŽŽ•Ÿ¾.)Û¤˜‘”œ®E#$E¯ž—““–œ¨Ó/$8Å©žš˜šž¨¼E.#")8縫¤¢£§®¼çE60/06EgÓÁ¼¸¸¼¾ÉÍÓÛÛÓÓÛÛÿ[MA<:),g®ž˜””—«g*8¸Ÿ–—Ÿ¼/)Ó¤—ŽŽ’š«E!<­›’ŽŽ–¢Í*-Á¡–•ž´: ([¬–““—¬ÿ-'>¾§žššœ ¬Å>+#$,<Û¶¬¦¤¦ª²ÁÿE62246226::>I[ÿÛÓÍÍÓÓÓÓÉž¼¼¾ÁÓgI:0/.2<[É´ª¤¡¢§¯ÅI/$%0[´¤œ™˜› ®ÿ."8¾¤š”’“˜ ¸6(ÿ¨™’’š©S$8°œ“ŽŽ•ŸÁ,)Í¢—Ž“›¯>!#I­œ”“š§Û+ 8¾¤›–•–›¥¼>(#2ç²¥œŸ©¶ÿ8+&%',8SÅ´­ªª­²¼ÍgI><>EM[ÿçÛÛÛÛÛÍÉžº¶¶º¾Ó[A4.,-0:[Á°§¡Ÿ¡§¯ÉA,"%4篡›˜˜›¡°S+$>¶Ÿ˜“‘“™£Á0+Ó¤˜‘Ž“›­A A¬š‘ŽŽ—¢Ó).¾Ÿ•Ž”´6'g©›“”œ«[)$>º£š–•˜©Å:&'8Ó¯¤žž¢«ºg6,'&).É®¤ŸžŸ¥¯ÁS6,)),2AÿŶ°®¯²ºÉÛÿSMMS[gggg[SS[gÛɾ¸²¯¯´¾ÓS8.)').:ÿº«¢žžŸ¦²Û6&':Ũ˜–—›¤¸<$)[¬œ•‘”›©g(2¶ž•Ž•Ÿº/'Û¤—ŽŽ‘š«E">®œ“Ž—£É-/Á£™“‘’˜Ÿ¶>$+[¯ š——š¡¯ÿ2$",EÁ­¤ŸŸ¢©²ÉM6-*+.6EçÁ¶²²²¸¼ÉÛÿg[gggÿgg[MMISgÛÁº²­¬­°¼ÓI4,'&(-<Û´¨ŸŸ§´ÿ2$)Aº¥œ—•—›¥Á6!+ç©›”•œ­E$<¯œ“Ž– É++Å •ŽŽ’›¯:!I«š’‘™§ÿ)6¸ ˜“‘“™¢¼:#/Û­Ÿš˜˜œ¤´[/$%/M¾¬¥ ¡¥«¶ÓI6.,-2!!I«š’ŽŽ—¥Û(0¸ž”ŽŽ”´4&ç§™‘“›ªS&">´Ÿ—“’•›¦É2!!2Í«Ÿš™šž¨ºM.$ '4g¼¬¥¢£§­ºÓE60.06A[Ûżºº¼ÁÅÍÓÛÛÓÓÛÛÿ[SE<<>ASÓ¼²¬¨§©®¼Û>.'""%-AÉ­¢››ž¨ºE*+S°Ÿ™•”—œ©Û,2¼ —‘–ž¶4&g§˜‘ŽŽ‘™¨S$8°œ“ŽŽ•ŸÁ-*Í£˜‘”¯A#&M¯ž—“’–œ©Ó/%:Á©Ÿš™›Ÿª¾E-$#+:ÿ¸«¦¤¥ª°¾çE8224:IgÓž¾¾ÁÅÍÍÓÍÍÍÉÍÓÿSE<86:>SÓº¯©¥¥¨­¼ÿ:,$ %-AÅ«¡œš›Ÿª¾>',ÿ­ž˜””—­S(8¶Ÿ–‘— ¾.*Í£—ŽŽ’š¬A A¬š’ŽŽ—£Ó*/¼Ÿ––ž´: (g¬—””˜ž­g,)A¼¨ž›šœ¢­É>,%!"&-AÛ¸¬§¦§¬´ÁÿE:648>IgÛÍÉÅÅÉÍÍÍÍÉÁÁÁÉÓÿSA8426ESÿÛÍÍÍÍÓÓÍÍž¼¼¼ÁÍgI<2/.2:Sɶ«¥¡¢¦®ÁM0&%.[¶¦™˜šŸ¬Ó0! 4ť𕒓—Ÿ´<"%Sªš“‘™§ÿ&2¶“ŽŽ”žº/'ç¤—ŽŽ’š«I# >¯•’™¥Í.2ɨœ–•–›¤¸A)"/g´¥žœœŸ§´ç:,&$&+4MͶ®«ª­²¼ÍÿMA>>EM[ÿÛÛÛÛÛÛÓÉžº¶¶º¾ÓgE4.,+/8MŲ©£Ÿ ¦®ÁI-#%0ÿ°£›˜˜šŸ®ÿ-"8º¢™“‘“˜¡º4(ç§™‘Ž’šªM#<®›’Ž•ŸÅ,+Å¡–ŽŽ“œ°< $M¬œ””›©ç+!:¾¥›–•—œ§¾<'%4ÿ²¦Ÿž¢ªºg:,'&(-:[ɸ¯¬¬¯¶¾ÓgMEEIMSgÿÿÿÿÿgÿÛÍÁ¼¶²²¸¾Ó[>2,)*.8[Á®¦ ŸŸ¥¯Å>+ %4Û­Ÿš——š¢¯S*$>´Ÿ—’‘“™¤É.,É¢—Ž“›­> Iªš‘ŽŽ—¤Û(0¼ž•Ž•ž¸4(ÿ©›”‘•œ¬S)&A¸£›—–™žªÍ8&(:Ó¯¦ŸžŸ¥­¾[8-))+0AÿŶ°®¯²ºÅÓÿSMMM[[ggg[[SSgÛÉÁ¶°¯¯²ºÓS:.*'(,6[¼­£ŸžŸ¦°Ó:(&6ͪž˜–—š¡´E'&I®–‘“š§Û*/¼Ÿ–Ž”´6$g¦˜ŽŽ˜§[$8²”Ž– Á/,Í¦š“‘’—ž°E'*S²¡š——šŸ­Ó4&!+>ɯ¥ŸŸ¡§¯ÅS8.++.4EÿÁ¸²°²¸¼ÉÛÿ[[gggÿggSSIIISçɼ´¯­­²ºÓM6,'%',:ÿ¸©¡ž¥°ç4&&<Á§œ—•–›£º:#)[«œ””›©['8²”Ž•Ÿ¼.(Ó£—ŽŽ’š¬A!A­›“Ž‘˜¤Í,0Á£™“‘“˜¡¶<$,g¯ ›˜˜œ£°ÿ0%$.IÁ®¥  £ª´ÍM6.--0:Mçź¶´¶¼ÁÉÛçÿÿÿÿÿÿ[SIA>>EM矯¬ª«¯ºÓI2*%$&,:Û´§Ÿœœž¦´g/"'Aº¤›–”–›¥Á4 ,Û§š“”œ¬I#>®›“Ž–¢Í*,¾Ÿ•Ž“œ°8$Sªš’’š¨g(8º ˜“’”š¥Á6" 0ç­Ÿš˜™¥¶[0% '4[¾­¦¢£¦¬¸ÓI80./4>[Ûżºº¼¾ÅÍÓÛÛÛÓÛçÿ[ME>:ͯ¤››ž¦¶M,)M´¡™•”–œ§Í//Å£˜‘•°: #Mªš‘ŽŽ—¥ÿ'2¸”Ž”ž¸2'禙’”›¬M%"A²Ÿ˜”“–œ¨Í0!#4Í«Ÿ›š›Ÿ©¼I.%#)8g¼­§¤¥©¯¼ÛI:422:E[ÛÅÁ¾¾ÁÉÍÓÓÓÍÍÍÓÛÿSE<868-% $,>É­¡œš›ž¨ºE)+[®ž˜”“–œ©ç+2ºŸ—‘–Ÿº2&ÿ¦˜ŽŽ‘™ªI":°œ“ŽŽ– Å-,É¢—‘•°>"&M¯ž—””˜ž¬ç.&<ÁªŸ›šœ ¬ÁE.% !%,<纭¨¦§¬²ÁçI:648>IgÛÍÅÅÉÉÍÍÍÍÉÅÁÁÅÍçSE:426 E«š‘ŽŽ—¤Û*0¼Ÿ—‘‘–Ÿ¸8 +ÿ«—”•™Ÿ®[-*Eº¨žœ›¤®Í>-%"#(/AÛº­©¨ª­¸ÅÿI>8: !E­›“‘™¥Û*2¾£™”’”™¢º<$.ÿ¯¡›™™¤²g2&&/MÁ¯¦£¢¥«´ÍM:0/04>SÛżº¸º¼ÁÉÓÓÓÓÓÓÛçgSI><868IgÛÉÅÅÅÅÉÉÍÉÉÁÁÁÅÍç[E:424:IÛº¯©¤¤¦¬ºç8+"#+>ŬŸ›™š§º>(+g­—“’•œªÿ*6¸Ÿ––Ÿ¸2'Û¥—ŽŽ‘™«I!<®›“ŽŽ–¢Í+-É¢˜‘–ž²>"([­ž˜””˜ž¬ÿ/ (>ÁªŸœ›£­ÅE.'"#(.>Ûº®©§¨­²ÁçM>::4/.06IÓº¬¦¢¢¥¬ºg6) #,I¾©žš˜šž©Á:$-窜–’“–­M& <°”Ž—¡Å,+Å¡–ŽŽ’›®:!Iªš’ŽŽ‘˜¥ç(4º —‘’— º6 ,ÿ«—••š °S-,Iº¨Ÿœœž¥¯ÍA.(%%*2EÛº®«ª«¯¸ÉçMA<>AI[gçÛÛÛÛÛÓÍÅÁº¸¶¶¼ÉÿI:/-,.6IͶ«¤  ¤¬¼S0&"-M¸¦˜—™žªÍ2!/ɦ𔑒—ž°>"#I¬›“Ž‘˜¤Û)/ºž”Ž”¶2%g§˜‘ŽŽ’š©S$:²ž•‘’˜£Á20Í©—•—›£¶M+".S¸¨  ©´Û>.(&(-6M͸¯¬¬®²¼ÍÿMEEEISgÿÿÿÿÿÿÿÛÍž¸²²´¼ÉÿE6-**-4Mɲ¨¡ŸŸ£¬¼I.$#.[´¢›——™ž¬ç.4Á£™“‘’—Ÿ¸6&g¨™‘ŽŽ‘™¨[$6²“Ž•Ÿ¾-)Í£—Ž“›­A"#I®•‘”›§Ó-!6Á§œ˜–˜¦¼A*&4ç´§Ÿžž¢ª¸ç<.*)*.:[ͺ°¯®°¸¾ÓÿSMMMSggggg[SSgÿÍÁ¸²¯¯²ºÉg>0*'(+4MÅ®¥ŸžŸ¤®ÅA* "/ÿ¯Ÿš––™Ÿ®g+":¶Ÿ—’’˜¢¾/*Ó¥˜Ž’›¬A!>­›’ŽŽ—¢Í*-¾ –Ž•´8&[ªœ”‘‘•œªg+&>º¤œ˜—™ž©Å<)(8Û²§¡Ÿ ¥®¾g:/+*,2>gɼ´°²¶ºÅÓçÿ[[ggÿÿg[SMIM[çɼ´®¬¬¯¸É[:.)&'+4S¾¬¢žž£­É:)#2Í«ž˜•–™ °I($E°ž–‘’™¤Í,-Á –Ž“œ°8"S©™‘ŽŽ˜¥ÿ&4¶ž•Ž–Ÿº0*Û¨›”‘’—ž¯M((I¶£œ˜˜š ­Í8("+>Ͱ§¢ ¢¨¯Á[:0-,/6Eÿɼ¸¶¶º¾ÉÓçÿÿÿççÿÿ[SEAAEMÿɺ°¬ªª­´ÉS6,&#%+4gºª œž£¯Û4%$6Ũœ—”•š¡¶>$&S«œ”“š§ÿ(2¸ž•Ž•žº0&ç¥˜ŽŽ‘™«S !"%(,06>MgÓɾ¼¼ººº¾¾ÁÁÅÅÉÍÍÓÛÛçÿÿÿgggÿÿçÛÛÓÓÓÓÓÓÓÛÛççççççççÛÛÛÓÓÛÛÛçççÿÿççççÛÛÛÛÛÛÛÛÛççççççççÛÛÛÛÛÛÛÛççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççççÛÛÛÛÛÛÛÛÛÛÛçççççççÛÛÛÛÛÛÛÛÛÛçççççççÛÛÛÛÛÛÛÛÛÛçççççççÛÛÛÛÛÛÛÛÛÛÛççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççççççÛÛÛÛÛÛÛççççççççççÛÛÛÛÛÛÛÛçççççççççÛÛÛÛÛÛÛÛÛçÛÛçççççÛÛÛÛÛÛÛÛÛÛÛççççççÛÛÛÛÛÛÛÛÛÛÛÛÛçççççÛÛÛÛÛÛÛÛÛÛÛÛÛççççççÛÛÛÛÛÛÛÛÛÛçççççççççÛÛÛççççççççççççÛÛÛÛÛÛÛÛÛÛÛçççççççççÛçççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛççççÛÛÛÛÛççççççççççççççÛÛçççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÓÓÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛçÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççççÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççÛÛççççççÛÛÛççççççççççççççÛçççççÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛçççççççççççÛççççççççççççÛçççççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççççççççççççççççççççççççççççççÛçÛçÛççÛçÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛçÛÛÛÛÛÛÛÛÛÛÛçççççÛççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççççççççççÛÛÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛçÛÛÛÛÛÛçççççççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛççççççççççÛÛÛÛçççççççÛÛççççÛÛÛÛÛççÛççççÛÛÛÛÛÛÛÛÛÛÛÛÛÛçççççççççççÛçÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛbaresip-1.0.0/share/sound0.wav000066400000000000000000001047741372575704200162170ustar00rootroot00000000000000RIFFô‰WAVEfmt D¬ˆXdataЉ ô¦ ò_:w üEñ §Ö± PÏHÖý’ú’÷ëô®òèð¢ïßî îàî—ï¹ð7òÿóþõ!øRú~ü’þ}1£Ê¡'_Mûr¿ñ>uÊGöÿÛÿúÿR㤎“¨¾Ä«eâ ú…´‡-ÀþGü»ù0÷¾ôzòyðÐîíÈì…ìÍì¥í ïøðcó=ösùðüšW  íäihј¶(ñ¯Âi ¼ÖÓÓüñøJõ÷ñïªìÔê˜éýèé«éçê­ìëîŽñô¥÷æú*þVVy |  .Õ À 2 yªÖgëÿ¥þŸýÞüdü0ü=üƒüúü”ýEþÿþ²ÿQÑ%D)Ð:jÿdþ3ýãûúùÉ÷”öõÊôRô4ôxô"õ6ö¯÷Šùºû4þ亞{ 7 ¼òÆ%ÿJþŸ• §+EüiøµôEñ3î•ëéè1ççŠçµèêàì¿ï ó¤övúcþK¥ à ±Ïœâ?,¾ )2=bÿ´üGú,ønöõ(ô§óŽó×ówôdõöâ÷RùÌú?ü›ýÔþÞÿ¯D™°Œ5³bÿ­þþqýýÊüÉüýŒýUþ`ÿ¥¼r0âx ß  Ú Q_ü $ ×  õt§¢ÿzüFù ö óaðøíýë€ê’é<é†épêøëî¹ðÓóN÷ûÿöÀ Dh6½ŸÕ`C‰?xI Ì T‘þîú†÷oôÀñˆïÖí±ììì¥ì¯í/ïñFóµõJøíúŠý [m3¢´g ¼ ¸ b ÅîíЧƒq€¹&Ìÿ­ÿÈÿ˜?П^ÿt²¯cÊâ¯5€ÿ™ýûwù`÷_õˆóïñ¦ð½ïAï=ï¹ïµð1ò'ôŒöRùgüµÿ$ = 0Ää}âž´(T- ¤ ÔÖËýÍùúõoòFï”ìmêàèöçµçè'éËêùìŸï¨òúõ|ùý B' ¨ ·IUÛÜ^k_ i C ¸}avþÇüaûJú†ùùõøù‡ù%úëúÉû±ü”ýdþÿ›ÿîÿ ìÿ”ÿÿKþjýpüjûhúxùªø ø­÷—÷Ò÷døPù“ú*ü þ*zç^Ë  -ùggìë_F¥ è êšfýµùö°ò’ïÙìšêéèÓçcççè ê.ìÝîòõ\ùWý^W$ ¨ Ëx›(] ƒvù  ¼dìüùùT÷ õ1óÊñÞðlðsðëðÈñÿò~ô3ö ø÷ùÞû²ýcÿá#"ÙGnSÿ|×_¨‰ÿ7ÿÿ8ÿ“ÿ)÷÷b±þ7M . Í   § × ¡ ØW¨ýÞúøRõ¿òmðpîÝìÄë4ë3ëÉëõì³îùðºóãöaúþðÌ  ]3ŠOvôÅëkQ­‘ Wmyÿ”ûÜ÷lô\ñÁî«ì'ë=êðé>ê!ëìtîÂðdóBöDùQüRÿ.Ò-/ Ì þ Á   Á ­ ` ìaÒOç§œÿËþ:þéýÙýþ_þäþ†ÿ6éŽ|®¥\Ñ÷ÿ³þBý¯û úføÑö_õ!ô'óò<ò`òôòúópõQ÷“ù)üÿ$BH ¦Ð‡¹X^Ľ`„ <  ÈÒþÙúúöSóÿïí¯êÛè§çç?ç è|é…ëîñ{ôøçû»ÿ|^ M ÌË=j%VK0Ë 4 ÈþRüMúœøF÷RöÁõõ·õ0öîöã÷ÿø4úoû£ü¿ý¸þ„ÿs’w&¨ÿÿIþ‚ý¿ü ü|ûûìúû`û üþü:þ¸ÿlKFIC Ì 5Jû=Qr Q ÊêÇwþû¬÷gôZñžîJìrê(éxèjèé<êìîjñÂôpøXü^fQ `QÀœØlWš=K×ô¸ ?£ÿpý úðö-ô×ñúï¢îÒíŒíÌíŠî¹ïLñ/óQõ›÷ùùUüœþ»¤I¡¤R©°nì7^nxвürrü²‹ypa;ñt·²[¯¬U±È©þaüú¥÷Zõ6óPñ¼ï‰îÉí‡íÊí—îìïÆñôÜöøùZýéŽ+¦ ãÉ@5•VpߦÎbt h~vpü‡øØô~ñî#ìHê énèyè%élê@ì‘îKñVôš÷üúcþ³×·@ b Fý6÷I6Ï % I QNUvÂÿDþýühû ûóúûûüÃü†ýLþÿ«ÿ)z•v‡ÿ»þÂý¥üqû4úÿøá÷ëö+ö±õ‡õ¸õHö:÷Žø?úCüŽþ¹s' À &DU'o&IÙÝ` r &“Òÿþû4øô,ñ%î‘ë…éèAçç¢çÒè¢êíìï>óäöÁúºþ°ˆ& p N®»XVº‹Ø°(V R5ÿ;ü¤ùa÷õôþòhòBò†ò*ó!ô^õÏöbøúªû;ý¬þðÿüÊVŸ¨w‰ä2ÿßþZþýýÓýäý4þÅþ–ÿ¡áIÍ]é_ ­ à ‘   Ë Ù = =ã?cÿcüUùRöróÎð|î“ì#ë=êìé6êëì°îIñWôÆ÷|ûaÿU@ ~œCaäÂôzW•An2 ¥ ã0þwúùöÎó ñÂîíÓë:ë7ëÄëÚìjîdð´òFõøÏú™ýGÈ û”Ë  È + K 6þ³d"ûû,—ÿ<ÿÿ;ÿÿ ¬c"ÜYuNá+,êlÿ»ýçûþùø8öôóÈñèðnðeðÔð¾ñ"óüôB÷æùØüQ©ñ  ël|`1¨ˆÞ½ : owoýtù£õòïî=ìê‰è¡çdçÐçâèêËì‚ïòö ùPýú„ÕÕ p •:Uäèfiý4 Õ jó‡8þ7ü ú[ùnøÛ÷Ÿ÷´÷ø®ø{ùjúlûqüjýKþÿ”ÿëÿíÿšÿÿcþ’ý¯üÆûçú!ú‚ùùîø ù}ù@úVû¼üjþUq­÷: b Y j`áã`Uƹ 9 V#µ'ýù ö¹ò®ïíÔê-éè³çñç×è`ê„ì3ï[òäõµù³ý¾¼  Aóª˜ß‚ìÐ>M  °8Êÿ{üfùžö8ô@òÂðÃïEïFï¿ï¦ðíñ„óYõX÷nù†ûýuÿ+¤ØÀZ§«nùY›Íþ=–ÅÿªÿÊÿ$·~p‚§ÐîñÉg ¾ Å q ¿®@{i˜ýûúWøÀõOóñ4ï²í¤ììì¨ìÉíyï®ñ\ôp÷Øú{þ=¸ 6 g1~<\Ö£ÅB#zXÖ ÿ)ûe÷èóÌð%îì{êé@é’é}êöëïíTðóö4ùgüÿ•bä É  ò WL×  à { æ5yÃ%­hÿ]þ”ýýÏüÐü ývýþ²þgÿ¸9‘µŸIµäÿÚþ¡ýCüÏúTùã÷öbõtôÒó‡óžóô õ`öø7ú£üQÿ,"ý ² #8ÞŸ£ ÛÃô º ,c{þŽúºöóÑïïìŽê¾èçç.çèwéˆë"î2ñ¡ôSø.üè‘ò ô „‘öEþ'ËúÆC ‰ ®ÊôDþÊû™ù¾÷Bö-õô<ôXôÎô‘õ”öÈ÷ùúàû/ý`þeÿ5Ì%@ ÍM®ÿúþAþýôü}ü6ü)ü]üÖü—ýþãÿ_Ϥt. ¾  Ç Ý9 ‹ ‰ $hj=þùú¶÷ôœñ÷î¶ìíê­ééøèéÈê›ìÿîãñ4õÚø»ü»¾¥T ¯Ÿ ç!³šÖquóÿ± "n°ý‰ùQöuóñï°íÖìŠìËìíÍîsðrò´ô%÷®ù9ü²þõ{©{ò Ü`¨Â½¨”Ž¥äTüÿÜÿ÷ÿIÌw@õÃwTg0ªÔ®<ˆžþ‰ü\ú*øöô;òºð–ïÜîšîÖî–ïÛðžòÙô÷}úÁý3º=Ÿ ÆšêAü~En¼ !ü#øpôñ î¯ëÑé‘è÷çè·èêêëLîñ=ôœ÷û£þZ[ B SZhIÍ  踌yÿÚýhüAûiúáù©ù¹ù ú“úEûüìüÄýþ8ÿ»ÿ '¯ÿÿ]þsýmüWûAú:ùQø—÷÷âöýöq÷AølùñúÆüáþ2¬9Ä8 ~ -p:€;f° Ø £&}ÿ¿û øwô$ñ+î£ë¡é4èiçHçÒçéÙêAí+ð‚ó-÷ûÿ÷  õ ÞG!`þúW\ €‘ m,é½þ½ûù˜ö“ôýòÝñ4ññBñêñíò>ôËõ÷Où"ûèüþ RY•ɽwg¶ýJ«ÿ+ÿ×þ·þÒþ+ÿÁÿ’—É|á7m t ; ´ Ô ’ é × _†VÝ-ÿVüqù“öÕóNñï?íÝëë²êúêÛëSí[ïæñäôCøéû¾ÿ¤€6 ¨½]tóÌú{S‹/S r ¡µÌýúqö4óað î>ìëiêfêúêì»íÊï6òèôÈ÷¾ú²ý;¨Å… Þ Í Q l % … › t ±8Æj1'VÿÁþlþUþxþÐþQÿñÿ¢W”<>ÿ{²¨cÿêýKü”úÖø!÷Šõ"ôúò"ò©ñ™ñúñÐòôÖõú÷zúFýKt¨Ð Ñ “þý}nÇšüZB Éý!ùVõÐñ©îúëÕéKèeç+ççµèlê³ìxï¤òöÎù•ýXûe} .hEÛá[SÖöÄ V à …´ý¡ûÚùjøW÷¢öLöOö£ö?÷øù1úXû|üý~þDÿØÿ1Q6æÿeÿ¾þüý,ý^üžûüú†úGúIú•ú-ûüGýÀþu]f€˜› s ZFÄÊRWÝ ê † ®`ðüwùöÔòÞïGí$ëˆé‚èè\èCéËêíìšï¾òEöúþï | ¨]‡Jæß?pj  ™vÿüÒøìõióXñÄïµî,î)î¤î•ïíðœòô´öõø<ûwý“ÿ~-”¬pâÜsÖ4Mj›ëdöÿkø´–—š‹ZøYq7¦¼yããÿ”ý&û­ø?öòóÙñ ðšî˜ííí—í­îLðmòõøPûÚþ„6Ò > ^\*žh‡á5Š ¼ÂºþÁúóömóHð™írëâéòè¦èüèïéuëíúïÑòìõ2ùˆüÖÿô›ã Á *Œˆ7 † Ò ú*W§)ÿæýæü/üÁû™û³ûü‰ü-ýæý¥þ\ÿýÿzÌéÌqÛÿ ÿ þäü¡ûQúùÈ÷²öÎõ.õÝôåôOõöR÷èøÙúý™ÿHã¡ 6 ‹Š ;ÐÓ@]Z 2 ¶ÿ'þKú†öõò´ïÜì‚ê¹èç ç7çèŠé¡ëBî[ñÔô“ø{üoT ~ ‘.Gμ Áây•I© Í ÌÀÀäý?ûãøàöAõôHóñòówóAôSõžöø›ù*û¬üþSÿ^/À"ùœvÅÿÿmþâý~ýLýUýý)þöþF¸Kï–,   à Û ƒ Ë ©   ž ¿~é þîúÎ÷Çôññeï8í~ëIê¦éé3êgë3íŽïhò®õIù ýï˜ îÚDSáÃúˆúøš ø/\›üù·õÆòDðCîÎìêë›ëÝë©ìôí¯ïÇñ)ô¿öqù)üÑþS ¥W®£ 6 j C Ì  Í’_CJ€ëÿÿqÿŒÿÝÿ[ÿ»‚Fø‰î¨ ÐRžþ¾üÃú¿øÃöåô7óËñ´ðð½ïñï£ðÔñóžõ$øû%þuÝAˆ —V­‡Õ‰›Ïú“ªT ¨À»ÿ³ûÆ÷ô³ðÀíNëoé/è—ç¨çbè¼é©ëîüð5ô¬÷Hûëþ{ÞüÁ øS%n1vI¹Ø ¸ o·pQÿhýÃûkúfù¸ø_øWø˜øùÌù¥ú”ûŠüwýOþÿŽÿäÿãÿŽÿÿMþuý…üŽûúÁù ù‡øBøFøœøGùIúŸûCý+ÿJ’ðPž à «Bw:?u"Jø 8 ¼-ÿˆûé÷mô.ñEîËëÓéoèªççèOé$ëíyðÒó÷jûqÿwb n^έï‡ÞšÉ{Ä» y±aþ=û\øÒõ®óüñÅð ðÐï ð¹ðÉñ.ó×ô°ö¨ø©ú¢ü€þ4²ïåïÜyé9v°õRÔÿƒÿgÿ‡ÿâÿvB;YŽË! Ù U € R à ÒÐÌÿþVüœùæöKôãñÃïî­ì×ëŒëÒë¬ìîðòyõÄøVüë·] ÁËbqé½çd8j &× 3 W^hýùðõ¥òÄïaí‹ëMê­é¬éEêpë íEïËñ›ô÷¹úÖýÛ³Js í ÷ · v Ô Þ £ 4 ¢ÿ\Ë[ ÿ=þ±ýgý]ýŽýñý{þ!ÿÓÿƒ%«2"ÒApeÿ%þ½ü8û§ùø£öSõ;ôlóòòÚò+óëóõ´ö³ø û¯ý‹Œ›Ÿ '{gÚÃÒîq`ʾ Q›·Âü×øõ–ñuîËëªé#èBç ç‚ç¡è`ê°ì€ïºòEöúâý¹rñ ã.ò$ÀÆ;)œ¤V Ç @wÉÿHýûùy÷Aömõþôñô=õÙõ·öÊ÷ùLúšûÛüþÿÐÿeÀÞÁpòÿQÿ™þÚý ýzüöû¡û…ûªûüÌüËý ÿ‹<úæà | þ 9—£6Oì  Ð,;Ãüjù öó"ðŸíŒëüéþèèßèÅéKëhíð.ó¯öyúqþyuG Ó ÿ´ÞnZ›3$zBŽu  vÆÿ‘û@ø?õ¢òzðÓîµí#ííœí–îÿïÆñØó!ö‹øûlý»ÿÚ¼Tš‡ZFéN‚”“•µúmøÿgîŸoS=ãƒïû˵P¢·ÿ›ý^ûùÏö¦ô¬òöð—ïŸîîî–îžï+ñ6ó´õ•øÈû5ÿÄ[ß 5 Bî#ÎßN2¬‹ßº 3 cf[þ\ú‰öýòÒïíòê_énè#è~èzé ë%í´ï¢òØõ<ù³ü"q‡O · ± 23³µ?Z€ ­ ¯›ƒ|•àþfý2üIû®ú`ú[ú˜ú û«ûiü7ýþÆþmÿíÿ=X8ßÿKÿ„þ’ý€üZû0úù ø3÷”ö;ö3ö…ö6÷Fø³ùwûˆýÙÿY÷œ4 § ßÇL]ìïbC–d¸ ¥>œÚýú]öÝòªïÝìêËè§ç*çYç3è³éÎëuî”ñõÛøÎüο„ !Êí{l½n‡¸ý  Ý«ƒ~ý°ú-øöEôôòò±ñºñ-òþò ôƒõ÷Æøú6üÔýLÿ‘œeê**ð…ôJ•äÿDÿÂþjþFþ\þ±þFÿ!Z¸-©s Ÿ Ž 3 € k í  ® óÙnÁåýïúö÷õZòçïÏí&ìüê_êWêëêìÜí+ðøò0ö½ù…ýn[0 Ï f9l÷Ô“…îát Ãé/ü†ø#õòï}íüëë¿êë×ë0íþî0ñ±óiöCù&üûþ«&X4± Ç u ½ ¢ . l k 8æ„$Õ¥ŸÏÿ9ÿàþÅþäþ8ÿ·ÿV ÄuˆÐÞ«1qk&©þý8ûcù‘÷ÖõDôíòäñ5ñïðñ¼ñÖòfôföÊø…ûƒþ°ô8a VþBQþ yDt1â >]^ÿZûr÷Âódðríë#éåçOçeç%è‡éëþíðð<ôÉ÷|û9ÿãb› x çÚD"p3q7’– V ç_Õ\ ÿïüû‘ùbø÷÷øö*÷¥÷[øAùEúXûlüqýZþÿ«ÿ"¶ÿ2ÿ‡þ½ýäüü9û…úúù¥ù’ùÈùLú"ûHü¸ýlÿWl™Íò õ  Dk'l2u3q 8 •—TâþZû×÷sôJñtî ìêÂèèëçzè°é„ëìíÖð/ôÝ÷ÇûÏÿØÅz ÛÏC$hûLÿ!ÂöÕ wørþºú¹÷õÎòñ¹ïñî¬îçî™ï¶ð/òóóïõø>úiü|þfµŽP@ïh·ë9qÆCòÿ×ÿ÷ÿOࢌ“©ÀȲnî& ™Ë H-ÜþbüÔùH÷ÒôŠò…ðÖî‘íÄìzì½ìŽíîî×ð=óöHùÃüm+âv ÊÆQWÇ•»44Ðè“ éý ùvõò4ïÈìëê©ééé§éÜêœìÔîrñ_ô‚÷Áúþ00îW ] õ Ã÷º Ä 9 „·å xüÿ¶þ°ýîüsü=üIüŽüýžýNþÿ»ÿYÙ-M2ÚCsÿmþ;ýêû‡ú!ùÊ÷’öŠõÁôGô%ôeô õö“÷kùšûþÙ€^  §ã¼!S0»¶-0 Ô.Ztü–øßôkñTî°ë–éè7çç€ç¤èiêÁì›ïàòxöHú3þçy · ç¶ð‘—êL?Ö & HS_„ÿÖühúJø‰ö.õ=ô¸ó›óàó~ôfõŒöÞ÷LùÄú6ü’ýÊþÓÿ¤9¦ƒ,ª Zÿ¤þùýgýúü¾ü¼üúü~ýFþPÿ•®f%Ús Ý  á \n< ó 9 ˜ÌÈÿŸüiù@ö=óyð î ì‡ê’é5éxé\êÝëôí“ð©ó ÷âúÑþÑÇ” E÷­—ÕgRž[™o ö H¿þû°÷—ôãñ§ïðíÅì,ì#ì¦ì«í%ïñ2óžõ0øÒúmýíÿ>Q‰žT ¬ ª W ½éêϨ…u„¾+Ñÿ²ÿÌÿEצf €À¾tÜöÄK•ÿ®ý¤û‰ùp÷lõ‘óôñ¦ð¸ï7ï.ï¤ïœðòôgö+ù>üŒÿûuÞ  ­Ór|æªÇA#yW Ò üýýù(ö™òkï³ì†êòèè¸çèé¸êàìï…òÔõSùçüuä † ™/AÌÓZli w U Ï”yŽþßüwû_ú™ù&ùù+ù’ù.úòúÎûµü—ýgþÿÿðÿ îÿ–ÿÿLþjýoühûdúrù¢øø ÷‡÷À÷Pø9ù{úüñý_ÍG¶  ñdjôùs`ä  Å<’ýàùBöÔò²ïóì®êöèÙçaç”çpèóéì¹îÛñ`õ-ù&ý-'ö~ ¥W€W’‹> % á‹>ýúw÷-õNóãñòð|ð~ðñðÊñüòwô)öøçùÎû¡ýPÿÎÉ8`FôrÎW ‚ÿ0ÿÿ0ÿ‹ÿ!ðð\®ü8P 5 × * # » î »&7÷wÈýýú+ølõÕò~ð|îãìÅë-ë'ë¶ëÜì”îÕð’ó¸ö3úêýÁŸe ÷ :r?móÌùmϸA „©ÿÃû ø—ôƒñâîÇì=ëLêøé@êëìbî¬ðJó$ö#ù/ü.ÿ °  ± ç ®  ÷ … ½ ­ c ñiÛYò´©ÿ×þFþõýãý þhþíþÿ?ò˜#‡º²iÞÁþOý»ûúnø×öaõô"óxò.òNòÞòàóSõ1÷qùüÜþá!* ‘Á}µ\h֥܄¬ h Îøÿû'÷}ó$ð6íÉêîè³ç!ç;çèiékëöíöðRôò÷ºûÿNä4 ( «®' `!XXBâ N å>¼þoüiú¶ø^÷höÓõžõÃõ9öóöæ÷ù2úmûŸüºý³þ}ÿmŒq ¢ÿþþBþzý¶üüqû ûÞúóúOû÷ûëü'þ¤ÿX8496  Æ 4MIh:‘ t ïðŸþ7ûÑ÷‰ôxñ·î]ìê.éwèaèñè&êøë\îBñ–ôAø'ü-5"× 9/¤‡ÊfX¢LbóÞ hÎ+›ý7ú÷Rô÷ñð¹îäí˜íÒíŠîµïBñ"ó?õ†÷âù=üƒþ¢‹1Š?™¢bâ0Xjuˆ°ûrrü³Œ|tfBúÅÂmÃÃmÊâÃþzüúº÷kõDóZñÁï‰îÃí{í¹í€îÑï¦ñöó´öÎù/ý¾c€ Á¬*%ŒUvì»éƒ›C –®§¡ü¶øõ¦ñ³îAì_êéwèzè é`ê-ìyî-ñ4ôu÷Õú;þ‹°‘ C ö /ë)ïE8Õ . V ``hŠÖÿXþý$üyûûû*ûŒûüËüýSþÿ±ÿ/€œ}"ÿÁþÇý©ütû6úþøÞ÷åö#ö¥õxõ¥õ2ö"÷tø"ú%üoþñ›V ª 6üR*y6_õþ† œ RÀ,ü_ø¸ôQñEî«ë˜éèEçç—ç¿è‰êçìÇïó·ö’úŠþ€Zú G *h©MR¼•çÅBt sX<7ÿ^üÇù÷œõ ôózòPòò/ó#ô\õÉöZøüùžû.ýŸþâÿî¼I“l €Û)xÿÖþPþóýÈýØý(þ¸þ‰ÿ•Õ>ÃUã\ ­ Ç ˜  . ß ! ô [ ]b‡ÿ…üvùpöóäðŽîŸì)ë<êäé'êë‚ìî#ñ-ô˜÷Mû1ÿ&Ö Wy'KÕ»õ‚g¬^‘Y Ð 6^þ¥ú$÷öó/ñáîíæëGë=ëÅëÔì_îSðŸò-õå÷±úyý'©ëßz´ ‰ ù  ¾ $ G 5ÿ¶i(4ŸÿDÿ&ÿBÿ”ÿ³j+å‹f‚^ò<?ü~ÿÍýøû ú øCöˆôóÇñâðcðUðÀð¥ñóÜô÷Áù±üÜÿ*ƒÎ ñ ÑVlÿf'Eèç h Ÿ¨ ý£ùÐõBòï\ì.ê›è«çfçËçÕè|ê±ìbïyòÞõuù$ýÍY«® L w AÕßck@0 é  ¡R3þQü¸úrùƒøí÷®÷Á÷ø¶øùnúnûrükýKþÿ’ÿêÿìÿ˜ÿÿ`þý«üÁûàúúxù ùßøüøjù+ú@û¤üRþ=Y—â( S N hcêñsnäÛ _ MàRý¹ù4öÜòÍïíæê8é#è°çæçÅèHêeìï1ò·õ…ù‚ýŒ` î Ó—ŒÛƒ‹ýæZn : ×aóÿ¤üùÃöYô^òÛð×ïTïPïÄï¦ðèñ{óMõI÷\ùsûzý`ÿÄ®I˜žbïP“Æø7‘Àÿ¦ÿÅÿ³zl¥ÐñöÐq Ì Õ „ ÕÇ[—‡6¶ýûqøØõcó(ñ>ï¶í£ìì ì”ì°í[ï‹ñ4ôF÷¬úMþÚŽ  Eh-UÖ«ÔX@€ <JKÿYû’÷ôòðFî!ìê›éGé’évêéëÜí<ðõòïõùCüjÿo>Âë ­ Þ G@Ð  á  î?…Ñ4¼wÿlþ¢ýýÜüÜüý€ýþ»þpÿ ÁC›¿©TÀïÿåþ«ýLü×úZùç÷ö`õoôÈózóó ôñôDöþ÷úü.ÿ ûá š *Ö¤®ô3æ æ Z’ªþ¼úæöFóõïí¦êÐè™ç ç)çôçcémëî ñwô&øÿûåÿºdÈ Î buùç<û*Õ Ú\ ¤ Ìêeþêû·ùÚ÷\öDõ”ôKôdôÖô–õ–öÇ÷ùyúÙû'ýWþ\ÿ,Ã7ÄE¦ÿòþ8þ†ýêürü*üüNüÇü‡ýŒþÒÿNøÀ—j& º  ÏïO7 © « HŽdþûÙ÷¯ô¸ñïÇìøê±ééîèé°ê~ìÜî»ñõ«ø‹üŠŽw) ‰~ñÓ®œà‚Œ"× LšÝ3ý´ùzö›ó)ñ5ïÇíçì–ìÐìíÆîhðbò ô÷”ùü–þçÛb’gà ÐW¡½º§”§çWÿÿßÿûÿLÏ{EûË€ avA½èÃSŸ´þŸüqú<øöôCò¾ð•ïÖîŽîÅî€ï¿ðò¶ôX÷Tú—ý ‘{ ¦íÛ:û[Š%=ç :RI@üRøœô9ñBîÌëçé èþçè±èúéÕë1îúðôv÷ôúyþë14ß ! î<NfLÕ   úÌ¢¥ÿñý~üUû{úòù¸ùÇùúúMûüòüÉý‘þ;ÿ¾ÿ* ²ÿ!ÿ_þuýnüWû?ú6ùKøŽ÷ ÷Óöìö]÷*øTùÖúªüÄþ­# n u&n?‹L} :Õ ÎSªÿëû3øžôHñJî¼ë²é>èlçCçÆçòè¿ê íðWó÷ãúäþäÉt Ì º) Oô÷[)m7›± Qãþãû$ùºö²ôóóñFññKñîñíò:ôÃõw÷CùûØü€þüÿAH †¼±l÷^­õA¢ÿ#ÿÏþ¯þÉþ!ÿ¸ÿˆŽÀvÝ5o x C ¿ ã ¥ ÿ ñ {¤vþNÿwüù°öîócñ%ïIíáëýê©êëêÆë7í9ïÀñ»ôøºûŽÿuS ‚œB`åÆü…d£Nw4 ž Ïäüý0úö]ó…ð)îWìëuêlêùêì­í¸ïòÌô©÷úýkˆ§i Æ ¸ ? ^   ˜ t #·@Ïs;2aÿÌþvþ_þ‚þÙþZÿúÿ«a Ÿ IK ŠÂ¸rÿùýYü¡úàø*÷õ#ôøòòžñŠñçñ¸òÿó·õØ÷Vú!ý%O…¯ ´ zêïunή0€m ö6GGýPù‚õøñÍîììé[ènç,ç–ç§èWê˜ìWï~òõõ¢ùhý*Ï:U I1ÍÙYWà× m Ý<¡"Ñý½ûõùƒøm÷¶ö\ö\ö®öG÷øù1úXûzüŠýzþ@ÿÓÿ-L1áÿ`ÿ¹þöý&ýVü•ûòúzú9ú:ú„úûü2ý«þ`HRnˆŽ j ZJÎÙfpû « éÖ‰ýžù4öõòûï_í6ë“é†èèQè0é²êÍìtï”òöåùàýëë R ƒ=múFêêQ,ŽŒ ? Â. ÿ1üûøöŒóvñÞïÉî;î2î¨î“ïçð‘òô£öàø&û`ý{ÿf~—]ÑõÏiÎ /Ig˜èbôÿj÷´–‘™ž‘bfI»Ò‘ýþÿ®ý?ûÅøTöôæñðžî•íííƒí”î.ðKòÞôØ÷%û®þX ª  >H$ q˜ÿY9¶ ëòëþñú!÷˜ónðºíë÷éé¬èûèçégëjíàï²òÊõ ùbü®ÿÚÎwà ¤ |} 5 Œ Ü  ;h¹;ÿøý÷ü?üÐû§ûÀûü“ü6ýîý­þcÿ‚ÔñÔyãÿÿþëü¦ûTúùÈ÷®öÈõ$õÏôÔô;õö8÷Ìøºúùüyÿ(ôƇ y~;ÖßS0{<‚ ] ä-Vþxú±öó×ïúì™êÉè˜çç1çèué…ë!î4ñ©ôeøLü?%àT j +¹¬À焦_Ä ë íâãþaûùþö\õ%ô\óóóóEôTõœö ø”ù û¡üþFÿQ#µï“m¼ÿ ÿcþØýsýAýHýýþèþõÿ8«?åŽ& ž á à Œ Ø » - - » ß  61þûð÷æô òzïGíˆëLê¢é’é!êOëíkï@ò‚õùðüæàÂn ɺ* GÝÇ ¡ $]ŠÉü2ùáõëòfð`îåìûë¥ëáë§ììí¢ïµñô¦öUù ü³þ5‚ˆ=•Ž $ Z 7 à ÿΕcHP†ñÿ–ÿwÿ’ÿãÿa‰N”û)¹ãf²þÑüÕúÎøÑöïô=óÍñ²ðùï°ïàïð¹ñ`ó{õþ÷ÛúüýMµf y=™zÏŠ£å¶Ò€ ×ñìÿãûõ÷>ôÛðâíjë„é=èžç¨çZè¬é“ëÿíÛðô„÷ûÀþO´Õœ ø Û<b*uNÂå É „)ωkÿýÛûú{ùÊøoøeø¤ø"ùÔù«ú˜ûŒüyýPþÿŽÿäÿãÿÿÿLþsýƒüŠû—úºùù{ø4ø6ø‰ø2ù2ú‡û)ýÿ1zÙ;Œ ´ ¡=w?ŠP‹=j ` GçXÿ³ûø“ôPñbîâëäéxè¬çˆç è;é ëlíRð§óS÷:û@ÿG2æ F;°•Þ„…ã¦Ü”âÝ ž?Ú‰þdûøôõÍóòÜððÝïð¼ðÈñ(óÍô¤ö˜ø˜úümþ žÜÓßøÏnß0o©îKÍÿ|ÿaÿ€ÿÛÿp<6UŠÊ# â a d Ø êšìê ÿtü¸ùÿöbôõñÑï î¯ìÔë‚ëÂë–ìýíñïgòPõ˜ø)üéÿ½‹4 «H^ݹêoJƒ)K ` †Ž˜ý¾ùöÍòèï€í¤ë`ê¹é°éBêgëí1ï±ñ}ô}÷–ú²ý·(oV Ó á } © l Î Ý ¥ 9 ª hØh%ÿJþ¾ýsýiý™ýûý…þ*ÿÜÿŒ/µ=.ÞN}rÿ1þÈüBû¯ù ø¦öSõ8ôdóçòËòóÔóÿô–ö’øéúŒýhiz f i[ÔÄ àŒðè ~Ëçòüù@õ½ñ˜îçëÀé2èIç çzç‘èIê“ì^ï“òöÙù³ýŠDÆö ¿Ø²¿;/§µk à )^–éÿgý$û/ù“÷Xö‚õõÿôGõàõ»öË÷ùIú•ûÕüûýúþÈÿ^¸ÖºhëÿIÿ’þÑýýpüëû”ûwû›ûü»ü¸ýúþx*ëÙ¸ t û :!¢²Jg 4 óRb8êüùCöó=ð´í›ëêé˜èÒè±é0ëHíéïóöIú@þHE ª Ú•Å]P™81[­™ 6  òIÿ½ûjøfõÅò™ðíîÉí2í%íží“î÷ï¹ñÇó ötøçúRý ÿ¿¢<ƒs J9ÞE|•¶ûnúÿið¡rWB#ìŽû( ŸßËgºÐÿ³ýuû)ùâöµô·òýð™ï›îîîƒî…ï ñóŽõmøžû ÿ™2¹  $ÕÁÛQDĪã ` ’—ŒþŒú·ö(óøï>í ësézè(è|èpéûêí˜ï‚ò´õù‹üúÿH`* – “ ¤«9Z‰ ¹ ¾¬—ªõþ{ýEü[û¿úpúiú¤úû´ûqü=ý þËþrÿòÿB]=äÿPÿˆþ–ý‚ü[û/úùø,÷Šö.ö#örö ÷-ø˜ùZûký¼ÿ<Û‚ “ нG]óüu\µ‡ß ÏkÊþ<ú‡öóÌïùì£êÚè¯ç*çRç$èé±ëRîlñèô­øžüWØ û©Ñf^µn.Ð ! Ш£ýÔúOø$öaô ó,òÀñÅñ4òóô~õ÷¼øuú(üÅý<ÿŒVÜåzê@ŒÛÿ;ÿ¹þaþ<þRþ¦þ;ÿ P¯%£r ¡ ” = |   Ê ùãþûø-õròûïÝí.ìþêZêLêÙêì¾íðÐòöŽùVý>- ¦ ùâM'bôÙ¦ ž ð3^ü³øNõEò®ï™íì"ëÉêëÔë'íïîñ˜óNö%ùüÚþ‹9— ± b ­ – & g i 9é‰+Ý­©ÙÿBÿéþÍþìþ@ÿ¿ÿ^Í”Üë¹A‚|7ºþýGûpùœ÷ÞõHôîòàñ-ñâðñ¦ñ¼òHôEö§ø_û]þ‰ÏA :æ0L‰[‘6Y mŽŽÿ‹û ÷ìóŠð“íë7éòçUçcçèvéhëáíÍðôŸ÷Pû ÿ·6r S ƽ-e-q=¦ i ýxïx'ÿ ý2ûªùyø£÷(÷÷6÷®÷bøEùGúYûlüpýWþÿ¨ÿ²ÿ/ÿƒþ¹ýßüü1û{úïù˜ùƒù·ù9úû2ü¢ýUÿ@V…ºã é ¹ @l-xD‹N‘ \ »À~ ÿ„ûþ÷—ôjñîì,êÊèèäçlèšéhëÊí¯ðô®÷–ûžÿ§—N ³¬&XýûS 5Üø ž!œ*þãúß÷3õïò ñÐïï¹îîî›ï³ð(òèóàõý÷*úSüfþOx¡{A3ä^¯ä 4mÃ@ïÿÔÿóÿLÝŸŠ’ªÂ͸wù4  ­á¹7dJøþ}üîù_÷çô›ò‘ðÝî’í¿ìpì¬ìxíÒî¶ðóëõù—ü?ÿ¸N §§8E¼’¿@Nð¾  554ýOù¢õHòXïçìëºéé é£éÒê‹ì¾îWñ?ô_÷œúÞý  Ê6 ? Û ±é± È @ ŽÃó0‰ ÇþÀýýüüKüUüšüý§ýWþÿÃÿbá6V<ãM}ÿvþDýñûŒú%ùË÷ö…õºô;ôôRôöôöw÷Mùzûòý¢yaB  ’Ó²[EÖ×SZ ]‰£üÃø õ‘ñuîÌë«é"è=ççwç”èRê£ìwï¸òLöúþì¹M iǜ݄‘ñYQí A fs€¦ÿ÷üˆúhø¥öGõSôÊó©óêó„ôiõŒöÛ÷Gù½ú-üˆý¿þÉÿš/…œy#¢Qÿ›þïý\ýîü±ü¯üìüoý7þAÿ†ÿ YÒn Ü ç g~#T  Y 9¼òîÿÄüùaö[ó’ðîìê’é/ékéHêÂëÓímð~óóö²ú þ¡˜h ô !ÙŽÔm`³vº•  t®íþHûÛ÷¾ôòÆï îÙì:ì+ì¨ì§íïôð óˆõø¶úPýÐÿ!5þqˆA › M ¶äçΩ‡xˆÂ/Öÿ¶ÿÑÿ!¢J Ý®oŒÎÎ…ï Ø`«ÿÃý¸û›ù€÷yõ›óùñ§ð³ï.ï ï‘ïƒð÷ñäóCöùübÿÒN¹ ú ÷–ÂhyêµÙ[Bž€ ÿ 39-þ-úUöÃòïÓìŸêé è¼çèé§êÈìdïcò®õ*ù½üJºñÛ c z-½ÉVmt † f *嬑¦þöüûsú¬ù7ùù7ùœù7úùúÔûºü›ýjþÿŸÿòÿ ïÿ—ÿ ÿMþjýnüfû`úlùšøø÷“÷x÷®÷;ø"ùbúöûÖýõÿD´/¡ ô è`lü†yáÇ 5 =ñi¾ý újöùòÒïíÃêéßç`ç‹ç`èÛéòë–î³ñ4õþøõüü÷ÈS 6eÿúQ¡ -] G ²e:ýEú›÷NõkóüññŒð‰ð÷ðËñùòqôöó÷Ùù½ûý>ÿ¼¹)R:èhÅ O™ùÿzÿ(ÿ ÿ(ÿƒÿèéWªû9T < á 7 4 Ï  ÕCU—èýûHø…õëòðˆîêìÅë(ëë¤ëÃìvî²ðjóöú»ý“q: Ï ø[.dñÒ–‰ðßl ²ÌÙÿòû7øÁô©ñïãìRë[êêAêëvìRî–ð/óöù ü ÿçŽìó– Ï š ÷ ë ~ ¹ ¬ e öpådþÀµÿãþQþþîýþrþöþ˜ÿHû¡-’žwìÏþ\ýÈû úwøÜödõôóoò!ò=òÈòÇó6õ÷Oùáû·þ½Ý ç {±s²`sç½ú§Ô ” ý(3ÿ7ûT÷§óJðWíãêé¿ç%ç7çõçWéSë×íÒð*ôÇ÷û_ÿ ¸  ‰’üUZeSø g ¸\Úþü†úÑøw÷}öåõ­õÏõBöúöé÷ù1újû›üµý­þxÿ g†kœÿøþ;þsý®üúûfûÿúÐúãú>ûåû×üþÿD%"*) À 2O V)~U° – 9Èþ^û÷÷«ô–ñÐîqìŒê4évèYèâèêÛë9îñjôø÷ûüÿô¬  ˆq»_Yª[w6 øVÆýaú?÷vôò3ðÐîöí¤íÙí‹î°ï9ñó.õr÷Ëù%üjþ‰rt{,‰”VÙ(Rfr†¯úqsý´Ž~xkJ‹ÓÒ€ØÙ†ãûÜþ“ü3úÏ÷}õSódñÆï‰î¾ípí¨íjîµï…ñÒóŒö¤ùý’8ÙZ ŸƒS{ùÏ¥Án ÄÞØÒüåø0õÎñ×î_ìvê*éè|èéTêì`îñôP÷®úþcˆlú # Û ÙçB9Ú 7 b oqzêÿkþ-ý6üŠû(ûû7û—û%üÔü•ýZþÿ¸ÿ6‡¢ƒ(“ÿÇþÍý®üwû7úþøÛ÷ßööšõjõ“õö ÷YøúüPþÓ}:ô“ (óO.‚Fu« Å ~î.Yü‹øáôvñeîÅë¬é)èJççŒç­èpêÈì£ïëòŠöcúYþP+Î  qO—BM¿öÚ[‘ ”{`[ÿ‚üéù¡÷¹õ:ô*óŒò^ò™ò4ó$ôZõÄöSøóù’û"ý‘þÔÿà¯<‡‘bvÒoÿÌþFþèý½ýÍýþ¬þ}ÿˆÈ2¹MÝX ­ Ê Ÿ  = ò 8  y ~(†ªÿ¨ü—ùö¨óûð î«ì/ë<êÝéêòêfìnîýðôk÷ûÿöä« /W 5ƳõŠvÂ{³€ û =dþÒúP÷ôSñï5íúëTëDëÅëÏìSîCðŠòõÉ÷“úZý‰ÌÂ_œ t è û ³  B 4¹m.  <¦ÿKÿ-ÿJÿ›ÿºr3î•rmNQ‘ÿßý üú-øMöôóÆñÝðYðFð¬ðñéò¼ôûö›ùŠüµÿ^« Ñ ¶A]öÿk4XÜÈ) • ÏÙÑýÓùýõkò8ï{ìGê¬èµçhçÆçÉèiê˜ìCïUò¶õKùøü¡-‚‡ ) X,ÇÖ`n MA ý ˜%»mNþküÐúˆù—øÿ÷¾÷Î÷'ø¿ø‡ùrúqûtükýJþÿ‘ÿèÿêÿ–ÿÿ^þŒý§ü¼ûÚúúmùÿøÐøìøWùú)ûü:þ$A€Í C C ÿffòÿ‡‡ý … §w |ýãù[öÿòëï7íùêEé(è®çÜç´è0êGìêîòŠõVùQý\\2 à õ²æƒÕ…• ývŽ ^ þŠÌü´ùèö{ô|òôðìïdïZïÉï¦ðäñsóAõ:÷Kù`ûeýKÿ{±›8‰VåG‹¿ò2Œ »ÿ¡ÿÀÿ®ui|¤ÑóúØ{ Ù å — ëßu´¤SÓý3û‹øïõwó8ñHï¼í¢ì ìýëì—í<ïhñ ô÷úþâ­d ê #øRMÕ²ãn]¿¨- jz{ÿˆûÀ÷=ôñhî=ì¥êªéNé’épêÜëÉí$ðÙòÏõïøüEÿJ Ì ‘ ç Ê 85É þ â „ õI‘ÞBˆÿ{þ±ý+ýéüèü!ý‹ýþÄþyÿ)ÊL¤É´_ËúÿïþµýVüßú`ùê÷Žö^õiô¿óló|óôóØô)öà÷öù`ü ÿèàÜÅ ‚ üΨº0 Q D  ‰ÂÚþëú÷oóð-í¿êâè¤çç%çççPéSëâíçðMôú÷Ñû¶ÿ‹7 § AXâÖ2ø-Þît À ê 6†þ üÖùö÷vöZõ§ô[ôpôßô›õ˜öÇ÷ùtúÒû ýNþSÿ#¹.¼=žÿêþ/þ|ýàügüüü?ü·üvý{þÀÿ=豊_ µ  "×$eQ Ç Ì k´·ŠþDûý÷ÏôÕñ&ïÙìë¶éÿèåèné™ê`ì¹î“ñÜô|øZüY]Iþ b\Ö¾¨žê’¤.Dþ vÆ `ýßù£öÀóKñQïÞíøì¡ìÖìŽíÀî]ðRòô÷ö{ùüzþËèÀJ|SÏòÄMš¹·¦”‘©éZâÿþÿOÓI$ÓŠn…RÐýÙi¶Ëþµü†úOø%öôKòÂð“ïÏî‚î´îjï¤ð_ò’ô1÷,úmýÞhîW †d×Ì2û›p¦Ge i‚{qüøÈôañeîéëþé°èèèªèíéÁëîÛðöóO÷ËúPþÁ »  Ò%ôAdNÜ  ' à·¥¼ÿþ“üiûŽúúÇùÔù"ú§úUû üøüÎý•þ?ÿÂÿ.¶ÿ%ÿbþwýnüVû=ú1ùDø…÷÷ÅöÚöI÷ø;ù¼úŽü¨þúu• ] imC•\“;Zú ) ù€×ÿü^øÆôkñhîÔëÄéIèpç?çºçßè¥êíßï-óÒö³ú³þ³™H ¤ – ð=éó_3}M·Ð ²v5 ÿüHùÛöÐô3ó òYññTñòñîò6ô¼õm÷7ùûÉüoþìÿ18ûw¯¤aìT¥ì9šÿÿÆþ¥þÀþÿ®ÿ…¸ qÙ4p } J Ë ò ·  —Öoÿ—ü¯ùÌöôxñ5ïTíæëüê êÜê°ëíïšñ‘ôé÷Œû_ÿF&á [z&K×ÀýŽuºlš\ É ý+þ^úÉö…ó©ðHîpì,ë‚êrêøê ì í¥ïò±ô‹÷}úoýIøhˆM ­ £ - P  y • t &¼G×}F=lÿÖþ€þhþ‹þâþcÿ´j©UX™ÑÇ‚ÿþgü­úëø2÷”õ%ôõòò”ñ{ñÓñ òãó˜õ¶÷2úüü*bŽ – aÖánmÔœÂK=¦— $ fxwýù®õ!òñî6ìêkèwç-ççšèCê}ì6ïYòÌõvù;ýý¢. ç *ê¿ÑW[éê ƒ öW¾?îýÙûú›øƒ÷Éömöjö¹öN÷øù2úWûxü‡ývþ<ÿÏÿ(H-Ýÿ[ÿ´þñýýNüŒûèúnú,ú+úrúûìûý•þJ3>\x a YO×èy‰, Ð ÿ²BýÆùYöóðvíGëžé‰èèFèé™ê®ìOïkòêõµù¯ýº»” ( ]TòîBíõbD«® e êXËÿ\ü#ù8ö®ó•ñøïÞîJî<î­î“ïáð‡òsô‘öÌøûIýcÿNþh‚KÀæÂ^Å)Dc•æ` òÿhö³–’›¢—j s[Ïéª8ÉýYûÝøiöôôñð¡î“ííóìpí{îð(ò¸ô®÷ùúþ,à‚ ô å3õ¡z¨0|aã #ÿ!ûO÷Âó”ðÛí¨ë ê é²èúèàéXëVíÆï”ò¨õèø;ü‡ÿ³©S¢ ‡ ø ïlr4 “ å /KzËMÿ þ ýOüßûµûÌûüü@ý÷ýµþkÿ ‰ÜùÜìÿÿþñü«ûXúùÇ÷ªöÁõõÂôÄô'õïõ÷¯øœúÙüYÿÕªn hq:ÛëeI™`ª ˆ \…þ¦úÜöEóûïí±êÚè¡çç+çòç`éiëÿíñô7øüö²) Cë¢û¾ì·uÞ *þƒû$ù÷wõ=ôpóóó†óIôTõ™öøŒùû—üüý:ÿE©ú ä‰c³ÿÿZþÎýhý5ý<ýƒý þÚþæÿ*2Ú…! › â å • å Ì B F Ø þÂ1[Uþ4ûøõ&òïXí’ëPêŸéˆéê7ëøìGïòVõìøÀüµ±•D £™õ;Ùʲº8@ê OЏöü^ù öóˆð|îüì ì°ëæë¥ìåí•ï¤ñþóö:ùîû•þdl"}x  K + º  þÏ—gMV‹÷ÿœÿ}ÿ˜ÿéÿg È‘V Ÿ6$Ê$2÷zÆþäüçúÞøÞöùôCóÐñ¯ðòï¤ïÏïwðžñAóYõÙ÷³úÔý$Ž÷D [#…mÈŠ«%ü3Øú¬ "ü$øjôñî†ëšéLè¥ç§çRèé~ëãíºðêó\÷óú”þ$Š­w × ¿$U$tRÌó Ú ˜@碄ÿšýóû˜úùÝø€øsø°ø,ùÜù±úœûü{ýRþÿÿäÿäÿŽÿÿLþqý€ü†û’ú³ùøøpø&ø&øwøùúnûýøþaÂ&y ¦ –7vE•`¢Y‹@ ‡ q„ÿÞû;ø¹ôrñîùëôé‚è®ç‚çè'éîêKí,ð|ó%÷ ûÿ¹ ’~Î{‚è²î¬ÿþ Âe±þ‹û§øöìó3òóð0ðêïðÀðÇñ#óÄô—ö‰ø‡ú}üYþ ‹ÉÁnÐêÃcÖ(g¢èEÇÿvÿ[ÿyÿÕÿi61P‡È&# ê l ž v í  ´ ¿=ÿ’üÔù÷yôòßïî³ìÑëyë²ëìâíÑïBò'õløûû»ÿ_ x‹.Jдíy\œHp) Œ µ¿ÈýìùHööò ðŸí½ërêÄéµé@ê^ëíï˜ñ`ô\÷túŽý“lO9 ¹ Ë k › b É Û § > ±såu2'ÿXþÊýýtý¤ýþþ3ÿåÿ–8¿H9ëZŠ~ÿ>þÓüLû¸ù&ø©öSõ4ô]óÜò»òó½óäôxörøÇúiýDFXb J ùWOÎÄ'î§¢ «ú"ý4ùkõåñºîì×éAèQç çrç‚è3êwì<ïlòðõ¬ù…ý\›Î ›ð¾ü¥¸:4²Å€ ø E|¶†ýCûLù®÷pö–õ!õ õRõçõÀöÍ÷ÿøFúûÏüôýóþÁÿV±Ï³aäÿBÿŠþÉý ýfüàûˆûiûŒûöû©ü¦ýèþfïÛÌ­ m ÷ :&¬Á^% U  x‰_ýµùfö?óXðÊí«ëêé“èÆèžéë(íÄïÚòTöúþí € ¶v­KE–== u̽ ^ Êuÿéû“øõéò¸ðïÞíAí.í¢í‘îðï­ñ·óùõ]øÏú8ý†ÿ¥‰#l^ø:+Ó=v‹ŽŒ•¶üoûÿkò£u[G*ô˜7²ôâÓèÿËýŒû>ùôöÄôÃòñ›ï˜î îúíoîlïïðòòhõEøsûßþn ’ ï ¼ýµÕS)UÜÉ( Œ ÂȽþ¼úåöRóð^í'ë†é‡è-èzègéëêøì|ïaòõîøbüÑÿ8 t u ÿ ” 4Y‘ Š;ª¥¿ ÿýYünûÐúúwú°ú!û¾ûyüDýþÑþwÿ÷ÿGbBéÿUÿþ™ý…ü]û/ú ùø%÷€ö!öö_ö ÷ø}ù>ûMýžÿ¿h € À²B^ù ˆuÓª ù—÷5þiú±ö*óîïí¹êêè·ç+çJçè‡é•ë0îEñ½ôønüm`)­ Ô‡µPO®m“*@è6 A #ôÎÈýøúqøDö}ô%óAòÐñÑñ;òóôzõ÷²øiúü¶ý-ÿr}HÎÚpà7ƒÒÿ2ÿ°þWþ2þGþ›þ/ÿ F¦q £ š F š  4 å /±*þ1û4øIõŠòðìí7ìëVêAêÇêèë íäï¨òÙõ`ù&ýþ×} ÔÃ4Wñݺº.+Ç FbŒüàøxõlòÐï¶í)ì2ëÓê ëÑëíàîñ€ó2öùæûºþjæü~ š O Š  b f :ìŽ1ä¶±âÿKÿòþÖþõþHÿÇÿfÕˆ%ŸéùÈQ’ŽHËþ ýVû}ù§÷æõMôïòÜñ%ñÕð÷ðñ¢ò*ô$öƒø:û6þbªñ ÎöGšr®Y: ›¾¿ÿ»ûÎ÷ô±ðµí8ëLéè[çaçèeéQëÄí«ðîóu÷%ûàþŠ I - ¥¡ÿY(rB¨µ }  ‘ ”Cÿ&ýMûÃùø·÷:÷÷B÷·÷iøJùJú[ûlünýVþÿ¥ÿþÿ¯ÿ,ÿþµýÙüûû)ûrúäù‹ùtù¦ù'úùúü‹ý>ÿ)@p¨Ó Ý ± <m4„U¢j±  âé¨7ÿ­û%ø¼ôŠñªî4ì;êÒèèÞç^è…éLë¨íˆðØó€÷fûmÿwh" Љ÷HõúYIö4 ÄIÅTþ ûøWõó<ñçïïÆîöîï°ð!òÝóÒõì÷ú>üOþ9îbhô1%ØU§Ý/i¿<ëÿÐÿðÿIÚˆ‘ªÄÑ¿ B . ÁøÑQfÿ™üúw÷ûô¬òðåî”í»ìfìœìbí·î•ðóòÃõòøjüÒ& ƒ‰2±ÃL+h4è D efeý~ùÏõqò|ïíëÌééé éÈê{ì¨î<ñ ô<÷wú¸ýãå¦ ! À ë žÜ¨  Ë G ˜Ð?™ØþÐý ýüXübü¥üý±ý`þÿËÿjê?_EíW†ÿþLýùû’ú)ùÍ÷öõ²ô0ôô?ôàôéõ[÷.ùZûÐý€XB% ì }çd,Zòøy„ -‹¹Ñüñø4õ¸ñ–îçëÀé0èCççnçƒè:ê†ìTïò!öìùÕý½‹! f D¨ƒÊx‹øfd\ „“¢Èÿý¨ú‡øÁö`õhôÛó·óõó‹ôlõŒöÙ÷Bù¶ú%ü~ýµþ¾ÿ${“p™úÿHÿ’þæýRýãü¥ü¡üÞü`ý'þ1ÿvð‘LÊi Ú í q7k * x [àéü°ù‚öxó¬ð4î&ì–ê”é)é^é4ê¨ë³íGðTóÆö‚úpþqi< Ë þ»ð…Òtmȑں H ŸÜÿtûøæô+òæï#îîìHì3ìªì£íïæð óqõþ÷›ú4ý²ÿãXr- ‹ B ®ßäÍ©‰{‹Æ3Úÿ»ÿÕÿ&§Oäµx˜ÛÝ–ívÁÿØýÌû®ù÷†õ¤óþñ§ð¯ï$ïï}ïkðÙñÃóöÝøìû9ÿ©&” Ù Ù~°]uíÀëtbê , cj^þ]úƒöíòµïóì¹êéèÀçèé•ê±ìFïAòˆõù“ü ɵ @ \ü®¿Qn"~ ” x >ûé¾þ ý¤ûˆú¿ùHù!ùDù§ù@úûÚû¾üžýlþÿ¡ÿôÿñÿ™ÿ ÿNþkýmüdû\úgù’øî÷‡÷h÷œ÷'ø ùJúÜû»ýÚÿ*šŒ ã ß]mš’ÿé \ f•êý5ú“öóóï)íØêéæç_ç‚çPèÄéÔërî‹ñõÏøÅüËÇš( XJêìJ$¯´G{ i *ØŒaýjú¾÷nõˆóòñœð”ðýðÍñ÷òjôöç÷Êù­û}ý,ÿªîï©D-Ý^¼G‘òÿsÿ!ÿÿ ÿ{ÿàâ R¦ù9W B ë E E ã  ï_s7·þ:ûeøŸõó¡ð•îñìÆë"ëë‘ë«ìXîðCóböØùýdD § óÙCZïØª¤— ßû"üeøìôÐñ&ïÿìiëkê êDêëlìAî€ðóèõâøêûèþÄlÌÕ{ ¸ † ç ß u µ « h ûxîo ÌÁÿïþ]þ þùý!þ|þÿ¡ÿQ«8ÑË„ú-!ÝþjýÔû+úøâögõôógòò,ò³ò­óõòö-ù½û“þ˜ºÞí Í e i®c}øÔÊü À +Xcÿgû‚÷ÑópðwíýêéËç*ç4çêçEé:ë¹í®ðôœ÷_û1ÿó‹á Û guùëJ[re € Ô {ùþ«ü¢úëø÷“öøõ½õÛõKö÷í÷ù1úgû—ü±ý¨þrÿa€e–ÿòþ4þlý¥üñû[ûóúÃúÔú-ûÓûÄüÿý|ÿ0  ¹ /Rb:”oÎ ¹ 9`@ðþ†ûøÎô´ñêî…ìšê;éuèQèÓèùé¾ëîóð?ôã÷ÆûËÿÔÅ€ êêk[­XY²j*V( ¸"òý‹úg÷›ô9òOðçîî±íàíŒî¬ï0ñóõ^÷µù üQþoZ]fx†JÏ!Lao„®ùqrýµ|qQ –áâ’íðžüöþ¬üJúä÷õbóoñÌïŠî¹íeí—íSîšïeñ­óeözùØüf °4 }rûyP€ãÆç™ ò ýù]õ÷ñûî}ìŽê;éŠèèéHê ìHîóðñó+÷‡úëý;aF×  ¿ Çß>:ß @ o ~‚°ýÿþ@ýHü›û8ûûCû¢û/üÝüýaþÿ¾ÿ<©Š/šÿÎþÒý²ü{û9úþøÙ÷ÚööŽõ[õõöòö?øéùéû2þ´_Ù| î êL0‹UŠ,@Ñ î ª\‡ü·ø õ›ñ…îàëÀé6èOçç‚çœèXê©ì~ïÂò]ö4ú)þ ü¡ ö âR6„6HÀ¦ît® ´„€ÿ¦ü úÁ÷ÖõTô@óžòlò£ò:ó&ôXõÀöKøéù‡ûý„þÇÿÒ¢/{†WömÈfÿÃþ<þÞý²ýÁýþŸþpÿ{¼'¯D×U ­ Í ¦ * L  O ) — žJ©ÎÿËü¸ù®öÄóñ²î·ì5ë<êÖé êÞêLìNîØðÙó>÷ïúÑþƵ 4í·«õ’…Ø—Õ§ % j’¼þû{÷Fôwñ ïOíìbëKëÆëÉìHî3ðuòûô®÷uú;ýéÿj®¦E„ ` × í ©  > 2¼r4C®ÿSÿ5ÿQÿ¢ÿ Áz;÷Ÿ&ž|_c"¤ÿòýü-ú;øXö—ô óÅñØðOð8ð˜ðuñÍò›ôØöuùcüÿÜ8ˆ ± š+Míüo@köèO; à þ þú*ö•ò]ïšì`ê¾èÀçkçÁç½èVê~ì$ï2òŽõ!ùÌüuX`  9ì¸Í]pYQ  ®>Õ‡hþ„üéúŸù¬øøÎ÷Û÷2øÇøŽùwútûuülýJþÿÿçÿéÿ•ÿÿ\þ‰ý£ü¶ûÓúúcùòøÂøÛøDùúûuü!þ )i¸ 4 7 ødiû ›   ª Т6§ý ú‚ö#ó ðQí ëQé-è¬çÓç£èê(ìÆîßñ]õ'ù ý++ ™ Ï‘ÌosЇž‘¯ ‚ %²DõüÛù ÷ôšòñðtïeïÏï§ðàñkó5õ+÷:ùMûQý6ÿëg‰'y‚JÚ>ƒ¸ì,†¶ÿ›ÿ»ÿ©qez£Ñõÿß… æ õ ª  øÐÁqðýPû¥øö‹óHñSïÁí¢ììðënìíïEñæóñöRúòý´: à Ü<EÕ¹ò„zâÏY ™ª¬ÿ¸ûî÷hô?ñ‰îYì»ê¸éVé“éjêÐë·í ð¼ò¯õÌøúû ÿ%ö~¬ u Ï µ ()Á û â ˆ ýSìQÚ•ÿŠþ¿ý9ýöüôü,ý•ý%þÍþ‚ÿ2ÓU®Ó¾jÖûþÀý_üçúfùî÷ö\õcô¶ó_ókóßóÀô öÂ÷Öù>üéþž½© i è Åÿ­ÅB$o-l = ·ñ ÿû?÷˜ó?ðMíØêôè¯çç çÜç=é9ëÂíÂð$ôÍ÷¢û‡ÿ\ s <ËÆ(ô0ç'Œ Û *W¦þ*üôùøöqõ»ôkô|ôçô¡õ›öÆ÷ùoúÌûýFþJÿ° &´5–ÿáþ&þsýÖü\üüü1ü§üeýjþ¯ÿ,×¢|T ±  %ß1{k å í Ùݱþiû øðôññ=ïëìë¼éýèÜè_éƒêCì–îkñ°ôNø*ü(-Ó ;:º©ú¢Ÿó£»Kf% Ÿñ7Œý úÌöæólñnïöí í­ìÛìŽí»îRðCòzôáöbùèû^þ¯Í¦1e?½ã¸D“´´¥”’«ì\åÿRÖƒN)Û“"{”cãï€ÍâþËüšúbø5ö*ôSòÆð“ïÉîvî£îSï‰ð?òoô ÷úCý´>Ç2 fHÁ½)ú%©…ÁiŒ> —²¬¢ü°øôôŠñ‰îìêÀèèè¤èßé­ëþí½ðÓó)÷¢ú&þ—àæ— á ¶ â4aQã ) 5 óͼÒÿþ©ü~û¡úúÖùáù.ú°ú]û'üýüÓý™þCÿÆÿ1¹ÿ(ÿeþyýoüVû;ú-ù>ø|÷öö·öÉö5÷ý÷#ù¡úsüŒþÝYë}ú L ]kGŸl©W{ Q $¬Düˆøíôñ‡îíë×éUèsç;ç¯çÌè‹êàìºïó¥öƒú‚þƒj { rëØ+Þðb=cÒï Õ›[0ÿ.ülùýöïôNó!òkñ+ñ]ñ÷ñîò3ô¶õd÷*ù÷ú¹ü_þÛÿ (ìi¡˜UâJœä1’ÿÿ½þœþ¶þÿ¤ÿu|¯kÕ2q R Ö  Ê + # ³á¶@ÿ¸üÎùéö!ôñFï^íëëúê˜êÍê›ëíøîuñgô½÷]û0ÿù· 5Y 6ɹÿ—…щ¾„ õ +C[þúõö®óÎðhîŠì@ëêxêøêì”í“ïññ–ôm÷]úMý'ÖGj1 ”  B  r ’ t )ÁNà‡PGvÿáþŠþrþ”þëþkÿ ¼s³"ae)§á×’ÿþvüºúöø:÷šõ'ôôòò‰ñlñÀñ‰òÈóyõ”÷úÖüÛÿ>m y HÂÓflÚ©Öe]ÌÀ Q •¨¨ý®ùÛõIòïTìê|è€ç/ç‰çŒè.êbìï3ò£õKùýÏuå à ϱÉU_ó!ü š sÛ\ þõû*ú´ø™÷Üö}öxöÃöV÷$øù4úVûvü„ýsþ8ÿÊÿ$C)ØÿWÿ¯þëýýGü„ûÝúbúúúaúõúØûýþ5*Iht W ÿ XSàö¡5M ô 7(Ükýîù~ö8ó5ðŽíYë©éèè;è é€êì+ïAò½õ…ù~ý‰‹f þ 8ý:ßâ>ðÿs[ÈÐ ‹ ‚öÿ†üLù^öÑó³ñðóîZîFî±î’ïÛð}òeô€ö¸øúú1ýKÿ7çQn8¯×¶S¼ý#?`’ã^ ðÿfô²•“¦œr€ŸmäÂ1R4äýsûôø~ö&ôò&ð¥î’íùìåì]íbîòïò‘ô…÷ÎúUþÿµY Ï ýÉç¡‚·G:Ÿ‰ ITMÿQû}÷íó»ðüíÄë êé¹èúèØéJëBí­ïvò†õÃøü`ÿŒƒ0 j ß Û\fÿ2 ™ ï =[‹Ý_ÿþý_üîûÃûÙû)ü§üIýÿý½þsÿ‘ãäŠôÿ$ÿ"þøü±û\úùÆ÷§ö»õõµô³ôõØõ÷“ø}úºü9ÿè·T ô Vd 9á÷xa·ƒÑ ³ >‹´þÓú÷móð6íÉêëè«çç%çåçLéNëÞíèðTô øíûáÿÇ…ÿ ÉóŒò»ðšÇŠø & .')Mþ¥ûDù:÷’õTô„ó!ó'óóMôUõ—öø…ùûŒüñý.ÿ9 ïÚ€üZªÿ÷þPþÃý]ý)ý/ýuýÿýÌþØÿ&Ð| ˜ â é ž ò Ý X _ õ  äUzþXû3ø"õAò¦ïhíœëTêœé~éê ëÚì$ïðñ+õ¾øü…g }xõá/ÔÍÃÒVd z·æ$ý‹ù4ö8óªð™îíì»ëêë¤ìÝíˆï’ñèótöùÑûvþøFPec ÿ <  ± ýýКkR[‘ýÿ¢ÿƒÿžÿîÿmϘ_ªD4Û6E ŽÚþøüùúîøëöõJóÒñ­ðëï˜ï¾ïaðƒñ"ó6õ´÷Œú«ýüfÑ! < q_Á‹²4Pú!× 4RMDüSø–ô*ñ'î£ë°é[è¬ç§çJèéhëÈí™ðÆó4÷Éúiþù`…R ¶ ¢ ïIsVÔ ë ¬Vÿ»ÿ³ý ü®ú¤ùðøøø¼ø6ùãù·ú¡û“ü}ýSþÿÿåÿäÿŽÿÿKþpý~üƒûú¬ùïødøøødø ùúVû÷üÞþýHªg — Œ2vJ q¸t«e ¯ ›>°ÿ üeøßô”ñœîìêŒè±ç}çôçéÔê*íðRó÷öÚúÞþåÔ õ ótf½q€ì¾Ä çŒ)Ùþ³ûÌø:ö ôOò ñCðøï&ðÃðÆñó»ô‹ö{øvújüFþúÿx·¯]ÁÜ·XÌ_›á>ÁÿoÿTÿsÿÎÿc/+K„Æ)( ò w ¬ ˆ   Î%&Þ\ÿ±üñù4÷ôòîïî¶ìÎëpë£ëkìÇí°ïòþô@øÍûÿb3á Rk6Ä®ïƒmµg”R ¹ äïøýúuöó1ð¾íÖë…êÐéºé?êVëôìïñCô<÷QújýnIä/ Ÿ µ Y Y à ٠© C ¸ñƒ@4ÿeþ×ýŒý€ý¯ýþ˜þ<ÿîÿŸBÉ'SE÷g—‹ÿJþßüVûÀù,ø­öSõ1ôVóÑò­òòò¦óÊô[öRø¥úEý #7C . áEBÇÄ.ü-ÂÃ;< Ø)GQýbù—õ òÝî!ìíéQèYç çkçtèê[ìïFòÆõùVý-éo¥ wФ藱99½Õ•  `šÕ'¦ýaûiùÈ÷‡ö«õ2õõ\õïõÄöÏ÷ÿøCúŒûÊüîýëþ¹ÿOªÈ¬ZÝÿ;ÿƒþÁýý\üÔû{û[û|ûåû˜ü”ýÕþSÝ˾£ e ô ;+¶Ðq—A u : ±‡8ýÛùŠö_ósðàí¼ëêéè»è‹éýêíŸï°ò'öêùÞýææÀ W ‘V”9;“AI³Žëà … õJ¡ÿü½ø´õ ó×ð!ïóíPí8í¥íîèï¡ñ§óåõGø¶úýkÿ‹o VJå*È4o‡‹Š”¶üpüÿló¦x_L0ý¢E-Å ø—ëãý£ûSù÷ÔôÏò ñžï•îîìí\îTïÒðÐòCõøIû´þCßk Ë æ¢é¨ÐU2fôçL5¹ ñùîþíú÷}óDðíBë›é”è3èxè^éÜêãìaïAòlõÈø:ü¨ÿ÷àR W åõ„•.X!™ Ñ ÜϽ¹Ôÿ¤ýmü€ûáúú…ú¼ú+ûÇûüKýþ×þ|ÿýÿLgHîÿZÿ‘þýˆü^û/ú ùÿ÷÷vöööLöôöü÷cù"û0ý€ÿ¢Nî k °§<^›ŽñÍ. $ Ä%bþ•úÛöQóð3íÐêúèÀç,çDçèqéxë îñ’ôPø>ü<0û‚ ­f™:@¦l™6RÿR a Eóíýû“øcö™ô=óUòáñÝñBòóôvõ÷¨ø]úü¨ýÿco9ÀÏf×.zÊÿ)ÿ¦þMþ(þ<þþ$ÿöÿ;œ–p ¥ Ÿ O § ž + L  M:Ó(LþRûSøfõ£ò"ðûí?ìëQê6ê¶êÐë‚íÁï€ò­õ3ù÷üßϪS ¯£Líâ*ÍÔNPñ Iu‘»ü ù¢õ’òòïÓí@ìCëÝêëÎëíÒîõðióöéøÇû™þIÆüßd „ < Ž ~  ] d :ï“7쾺ëÿTÿúþÞþýþPÿÏÿn#Þ’0ªõ×a£ŸZÝþ1ýfû‹ù²÷îõRôðòÙññÉðæðzñˆò ôö_øûþ<„Î ¶ êA(©‰Ë|©f Êîðÿëûý÷CôØðÖíSëaé èaç`ç èUé:ë§í‰ðÈóL÷ùú³þ^à  ƒ„ÿíM"rH³Ä * ª%¯^ÿAýgûÛù¦øË÷L÷$÷N÷Á÷pøOùMú\ûlümýTþÿ£ÿûÿÿÿ¬ÿ(ÿ{þ°ýÔüõû!ûhúØù~ùeù•ùúåúüuý'ÿ)[•à Р¨ 8n:e¸…Ð £  ÒaÿÖûMøàô«ñÆîJìKêÛèèØçPèpé1ë†íað­óR÷5û<ÿF8ö bfëà8ìø_'\S> ërï~þ5û-ø{õ/óXñÿï'ïÓîþî ï®ðòÒóÃõÛ÷ú)ü9þ#ØMxVã"ÍKžÖ*d»8èÿÍÿìÿEך†ªÆÔň Q ? Õêl›ƒ1ÿµü"ú÷õ½òªðìî–í·ì\ìŒìLíœîuðÏò›õÇø=üæÿ¦bÿ _j ¦‹ÇW=‚0Y r ”–•ý­ùûõšò¡ï$í5ëÞé'ééé¾êjì’î!ñô÷Sú’ý½¿‚ó ¥ Ô ŒÎž Î N ¡ÜO©-èþàýýžüfünü°ü#ýºýiþ!ÿÔÿròGhO÷aÿ‰þUýü˜ú-ùÎ÷Žö}õªô%ôøó-ôÊôÐõ?÷ù:û¯ý_7" Ò h²œl:o ž­ Zºèýù_õßñ¸îìÕé>èJççeçsè#êhì1ïhòõõ¾ù¥ýŽ\õ= ‰i¶j…þsvw ¢³Ãêÿ:ýÉú¥øÝöxõ~ôíóÅóÿó‘ôpõŒöÖ÷=ù¯úüuý«þ´ÿ„q‰gñÿ?ÿ‰þÜýGýØü™ü”üÐüQýþ!ÿfàƒ?Ác Ø ó |›Jƒ F – }<8ýÔù¤ö–óÅðHî5ìŸê•é#éQé êŽë’í"ð+ó˜öSú?þ@: ¢ ÙØ|{ÐyzÜ«ûß q Ë Gÿ¡û0øõOòð>îíWì<ì¬ì í ïØðûò[õå÷€úý•ÿçýÉ@\ z ‚ 7 ¦Ùá̪‹~Ê8Þÿ¿ÿÚÿ*«Tê½(¤éì§2‹ÖÿíýàûÀù ÷“õ®óò¨ð«ïïïiïRð¼ñ¢óúõµøÄûÿ€þo · ¼fžQqðÊýŒ€èÓ Y “›þú°öóÛïíÓê*é$èÅçèüè„ê™ì)ïòbõÙøiüöÿe   =ážµLn'ˆ ¢ ‰ QÚÀÕþ$ýºûúÒùYù0ùQù²ùHúûàûÃü¢ýpþÿ£ÿöÿóÿ›ÿ ÿOþkýmübûYúaùŠøä÷z÷Y÷Š÷øõø1úÂû ý¿ÿw Ñ ÷ ÖXo !­ª ‚ HÂþaú¼öDóðDííê éíç_çzçAè®é·ëOîcñÛô ø”üš—lý 2ó.ÕÞC+½È`™ ‹ Oÿ´ˆýúâ÷õ¥ó.ò0ñ¬ðŸðñÐñõòeô öÛ÷¼ùûlýÿ˜ÜÞ™ 7!ÒT²ü?‰êÿkÿÿûþÿrÿØÚL¢÷:Z H ô Q U ÷ 3 |’V×(þYû‚øºõó³ð¢îøìÇëëëë“ì:îlðó7ö«ù^ý5ã л+ PíÝ!¾¿2+Á +7Qü’øõ÷ñHïíë{êêFêëaì1îkðûòËõÂøÈûÅþ¡J¬·`   r × Ó m ± ª j ÷yØÍÿûþiþþþ+þ…þ ÿªÿZµB¨Ýב;/ëþwýàû6úˆøéöjõôó^òòòžò”óýôÒö ùšûnþt–½Î ² O^ªe† ì5í$ë Yˆ“ÿ–û°÷üó–ð˜íë)éØç/ç2çàç4é"ëšíŠðÚóq÷2ûÿÅ_· µ EXáÚ?]&~v# ™ ï=™ÿÉü¿úù§÷¨ö öÌõçõTö÷ð÷ù0úeû“ü¬ý¢þlÿ[z`ÿëþ.þdýüçûQûçúµúÅúûÁû±üëýgÿþþ  ÷ ³ -TnKªŠí Û _ˆiÿ®ûBøñôÓñï™ì¨êBéuèJèÄèäé¢ëôíËðôµ÷–ûšÿ£–T ÂÈNEPY¹y¢FwM àM­þ¶ú÷ÀôZòlðÿîî½íçíŽî¨ï'ñúò õJ÷Ÿùõû8þVAêGQhx>ÅF]l¬øpÿÿrýµ‘ƒvX¢ïò¥¶/ÿÅübúú÷¢õpózñÑïŠî´í[í‡í=î~ïEñ‰ó=öPù¬ü:⇠[UäòoN…÷:æ à >;3ýDùŠõ òï›ì¦êLé”è‚èé=ê÷ë1îÖðÐó÷aúÃý:!´ ä ¤ ê´Ö;;ä I { ’ŸÃ’þSýZü«ûGû+ûPû­û9üæü¥ýiþ#ÿÅÿC”¯‘6¡ÿÔþØý·ü~û;úýøÖ÷Õö öƒõLõpõóõÚö$øÌùËûþ•@¿e Û àH3”d G`ö  ÖJ‹µüäø3õÁñ¦îúëÔéCèTççxçŠè?êŠìZïšò1öúùýðÍu Ì ½2q)CÂ®Ë ÔÀ§¤ÿÉü-úá÷óõnôWó±òzò¬ò@ó(ôWõ»öDøßù|û ýwþ¹ÿÅ”#n{Lëc¿ ]ÿºþ2þÔý§ýµýþ“þcÿn°¤<ÐQ ¬ Ð ­ 4 [  f D ´ ¾lÌòÿîüÚùÍöàó*ñÅîÄì<ë<êÏéýéÉê1ì-î²ð°ó÷Àú þ—‡S à Ч£ô™”í³÷Í O —Áêþ.û§÷oôœñ?ïií"ìpëSëÇëÅì>î#ðaòãô’÷WúýÉÿK‰+m K Å ß ž  : 0¾v9JµÿZÿ<ÿXÿ©ÿ'ÉC©1‹¬‹#qv5·ÿþ,ü=úIøcöžôóÅñÓðFð)ð…ð]ñ°ò{ôµöPù<üeÿ´e ‘ <ãùtK~te ð .:2þ2úWö¾ò‚ï¹ìyêÐèËçnç½ç±èCêeìïògõ÷ø¡üIÖ.9 â Ò¨ÃYrea % ÄVþžüû¶ùÁø$øÞ÷é÷=øÐø”ù|úwûwülýJþÿÿæÿèÿ“ÿ ÿYþ†ýŸü±ûÍúÿùYùæø³øÊø2ùíùýú^ü þôÿR¢ð$ + ñal®¹=A Ð øÌaÒý6ú©öGó*ðkí!ë^é3èªçÉç’èê ì¢î·ñ1õ÷øïüùûÖn ©p±[eʉ¦,(­Ï ¦ KÚmýú2÷¿ô¸ò(ñð„ïpïÕï¨ðÝñcó*õ÷)ù:û=ý!ÿ×R‰vju>Ï5{±æ&±ÿ–ÿ¶ÿ¤law¡Ñ÷æ ó  ½  ªìßþlûÀøöŸóXñ_ïÇí¢ìýëäë\ìfíï"ñ¿óÇö&úÄý‡T œ ß¿%þ<ÔÀ™–ö„ ÇÚÜÿèûø“ôfñ«îuìÑêÈé_é•édêÄë¥íõï òõ©øÖûûþÒ\ Y ¶ ¡ º ÷ ã Œ  ]¨ù_é¤ÿ™þÎýFýýý7ýŸý.þ×þ‹ÿ;Ü^¸ÞÉuâÿÊýiüïúmùò÷‘öZõ^ô­óRóZóËó¨ôòõ¤÷¶ùüÇþ£Œ Q Óþ¼ü°ÏS;P“ h ä!9ÿHûl÷ÁódðlíòêéºçççÐç*é ë¢íðûó¡÷tûXÿ.ÝI Z ü´µñ3ð5£ ö &IwÇþJüú/ø©öˆõÎôzô‰ôðô¦õöÆ÷ùkúÅûý>þAÿ¨ÿ¬-ŽÿÙþþjýËüPüüóû"ü—üUýXþžÿÇ“nH ¬  (ç=#‘…   ³ÿØþûDøõòVïþìëÁéüèÔèOélê&ìsîDñ„ôøúûøÿýì¨ Ÿ”뜠û³ÑgˆK Éc¹ý6úõö ôŽñ‹ï îí¹ìáìí¶îHð4ògôÊöIùÎûCþ”±ŒO+¬Ô«:Œ¯±£”“­î_èÿUÙ†R.âœ-ˆ£tö&—äùþâü¯úuøEö6ô\òÊð’ïÃîkî’î>ïnð òLôäöÚùýŠŸ E,«­!ø+¶šÝвi ÆãÝÓüßø!õ²ñ¬î$ì,êÐèè èžèÓéšëäížð°ó÷zúüýn·¿s À šöÏ&þ_Sé 3 D .âÒèÿ3þ¾ü’û´ú&úæùïù9úºúfû.üýØýžþGÿÊÿ5½ÿ+ÿhþ{ýqüVû9ú*ù8øt÷êö¨ö¸ö!÷ç÷ ù‡úWüoþÁ=Ðeå ; PiK©|¿r›D z OÙ1qü³øõ³ñ¦îìêé`èxç8ç¤ç¹èrêÀì”ïÚòxöTúQþR;î R MÌ¿ÓëeGyì ÷¿VÿSüù÷ õhó7ò}ñ9ñgñüñïò0ô¯õZ÷ùêúªüOþÊÿÜ[”ŒJØA“Û(‰ÿ ÿ´þ“þ­þÿšÿkr§üeÑ1r … Y á  Ü A < ÏÿÖb²ÿÙüíù÷;ô£ñVïjíðëùê‘ê¿ê†ëæì×îOñ>ô÷/ûÿèËŒ 7î »²ÿŸ•è¦á¬ YrŠþ»ú!÷×óóð‡î¤ìTëœêêøêþë‡íïÚñ|ôO÷=ú,ýµ'L { x 4 ü k t +ÆTèZRÿëþ”þ|þžþóþtÿÅ|)¾.mr7¶ðç¢ÿ'þ„üÈúùC÷ õ)ôòò òñ]ñ­ñqò¬óZõr÷êù±üµÿßL [ .®Ä]jßµê}ñê ~ ÅÙØýÝùörò9ïrì4êèŠç1ç„çèêGìõîò{õùáü¢IºÞ Ÿ ëµô¢ÀRbû/ ° (Ž÷y'þüEúÌø¯÷ðöŽö…öÎö_÷*ø!ù5úVûtüýoþ4ÿÆÿ ?$ÔÿRÿªþåýý@ü{ûÓúVúú úPúãúÄûóüjþ6Xf M ù WVé ºRn  ^Q•ýú¤öZóSð¦íkë´é’èè1èúèhêpìïòõVùMýX[9 Ó Ý ÌÖ9ó „råò ± ;¬°ütù…öôóÒñ,ðïjîPî¶î’ïÖðsòXôoö¥øåúý4ÿÐ;Y%žÈ©I³õ;\á\ îÿ d󱕔Ÿ©¢y!Œ¯øÛKmOÿýŒû ù”ö8ôò/ðªî‘íòìØìJíIîÔïãñkô\÷¢ú(þÓŠ0 ª ܮ٢ŠÇ^WÂbaresip-1.0.0/share/sound1.wav000066400000000000000000001047741372575704200162200ustar00rootroot00000000000000RIFFô‰WAVEfmt D¬ˆXdataЉa°Ø È pÀ®/=ÓòšÒ¢2¸ > ³'¬O!þ,üzúùþ÷<÷Ìö¬ö×öD÷ì÷ÂøºùÈúÜûëüçýÄþxÿúÿBM§ÿ÷þþùü¼ûdúýø–÷=öÿôëó órò$ò+òŒòKóiôäõµ÷×ù>üÞþ¨|b . Ì.AùJ)zèÜYjr† f#Ò†þPûCøpõæò³ðàîwí{ìïëÒë!ìÔìäíEïéðÃòÃôÙöõøûýÙþ}èóŒÝç±B¢Þ-Rÿ’þ÷ýŒýYýeýµýHþÿ5† ³yM! å ‰ ;,É åXa>  ©ïüâÿ±ü{ùTöPóðóí»ëåé}è‹çççŸçèêêë#î¬ðuómöùžü³ÿ¬zY P ì %ùht"{ˆT í b Àvê@6iÿÛþþ…þ¹þ%ÿÃÿ‡i[P<ÁC‹“RÆíÉ]¯Êþ·üƒú<øóõ·ó™ñ©ï÷í‘ìƒëØê˜êÉêmë„ì îûïLòñôÞ÷ûJþ¤ÿFf Nì2…‚ ˜°[¤—B¶  <r¶ÿ¬üxú‹øíö¥õ¶ô!ôäóûó_ôõèõöö#øcù¦úßûýþÖþvÿÜÿìÿ–ÿÿCþSýBüûéù¼ø ÷¤öÕõ=õéôàô*õÉõÀöø®ù›ûÊý0Àl"Ò i × õ†´s¾æÄ/-Ë  è–5Úü–ù|öó ñÐîúì‘ë™êê ênê>ëpìùíÍïÝñôpöÒø.ûuý™ÿ‹BµÞ¹E„y,¤ì$8iÂÿKÿ ÿ ÿHÿÇÿ…~«z— ’ ß ù Ò`™uñ ¿   Ä.bpþfûXøYõyòÍïdíMë˜éNèyççBçãçþèê†ìßî‰ñsô÷Äúþ=[Kþ g x)rPÂÊm±¡H´ ó  (<`¢ ­ÿ‰þ¦ýý°üœüÈü-ýÄýþYÿ>&Çg×½*Q3Öÿ@þ|ü•ú˜ø”ö™ô¶òúðvï6îGí´ì†ìÂìkíƒîðíñ2ôÉö¥ù·üìÿ3z­ º IqV¿«š½†H d hiw¥ýûšø|ö²ôCó2òƒñ5ñBñ¦ñWòKówôËõ;÷¸ø4ú ûðüþÿÓÿU˜›aíÿGÿwþˆý‡üû~ú’ùÇø*øÆ÷£÷Ê÷?øùú~û+ýÿ:‡ñgÙ 6 nq.˜£Ev3xI¨ž5y yEñþ1ûì÷Òôôñdï.í_ëÿéé¤è­è+éêqë$í(ïlñáóuöù¸ûEþ­æá–ü Í 5 L  œ èþâ¿¡—«èWæÿ l áæU§ú> g f . µ ð Ø f ™ p îô÷ÿ7ýaú…÷¶ôò…ïEíUëÄé›èåç¨çæç èÔézë‹íûï»ò½õïø>ü—ÿå å ^}8†eÑÍ\†TÒ ù È”k]wÅþOýü4û–úCú7úmúÝúûFü(ýþÿåÿ«M¿ú÷³+b[ÿþªüûcù§÷ìõCôºò`ñBðnïíîÉîï®ï»ð.òô/ö«øjû\þq™ÀÓ À vã÷¨è²ÿÎø``]z lFÿþü3ù¥öcôxòíðÇï ï²îÀî,ïïïþðMòÏótõ/÷ðø§úIüÇýÿ0 ¨ëˆó6]ÿrþƒýžüÎû"û¤ú]úWú—ú!ûõûývþîð@p _ð4¦Ãq­xÖÎj ´ ½“Iòü ùgöYóˆðîÞëêÑèüç¢çÄç`èpéìêÈìùînñôãöÀùœüeÿ µ 9 y ] å  ë u º Æ ¤ cºn9'A‘äÿìÿ1±eEG^œ¨”T Ý $ ! Î & )Ù8O'ÌþIü¯ù÷xôýñ®ïœí×ëkêeéÍèªèéÎéëÊìêîgñ4ôB÷úÙý;•Òà ­ +LO%ƒlâí—éôÄ k ù¶…ÿ‡ýÈûPú$ùIøÀ÷…÷–÷ê÷zø;ù!úû(ü/ý%þÿ´ÿ7„“côÿFÿ^þCýþû›ú%ùª÷8öÞôªó©òçñqñOñ‡ñòóoô#ö,øúýÝÿÆÂ¾§ lúB4ÃäÀs©g³—Z X +æ›_ýCúX÷®ôTòUðºî‰íÆìqìˆìíàíïˆð:òôöøú üÞýƒÿò#·0¦W€š²ÿÕþþmýùü¼ü½üýŒý[þmÿ¼AóÅ«– v = ÛAa0£³Z•eÌÑ } Üùæµþuû;øõ$òlïíðêIéèWççWçèBéáêãì<ïÝñ³ô¯÷½úÌýÇ E©À € â á~·“OB þ ‘ uäcÿùéÿWÿÿôþ"ÿŠÿ#çË¿¶˜YîKh=ÅÿëŒçðý´û^ùÿö§ôfòMðlîÒìŒë§ê*êê…êbë±ìoî“ðóàõíø)üÿá7p z A¸Ñ€¼€Ê›ôÞa‰cÿ m ¾S¸DþüúOøëöÞõ(õÊô¿ôõŠõNöA÷Xø„ù¸úæûýüýÏþoÿ×ÿíÿšÿ ÿFþSý:üûÉùŠøY÷DöXõ¢ô.ôô+ôªô‚õ´ö<øú6ü–þ%Øže  ¯-øccñŸ¾eœlà ò²Yýþ®ûø„õÌòfð_î¿ìëÏê„ê«ê?ë9ìí1ïñ-ógõ±÷ýù:üZþOÆ´T¨´{a”¬·ÂÚ aÿåþ¡þ˜þÑþKÿþ-‹ §Lî } ë *-æLVÿC"ž ½ †DTGý,ú÷ôEñ­îaìpêçèÏç/ç çgç?èŽéLëoíëï®òªõÌøü7ÿYY#ª à »3Cé%üs“gû ] œ Èð!lÚyQÿgþÀý]ý>ý_ý»ýIþÿÕÿ»¥‡Tþ{ÂÉŒ9$Ì8ÿqýûvù^÷HõDóbñ³ïCî!íXìòëöëiìKí›îUðròèô«÷«úØýp·à Ø õû—¾lQŒT±°]É  !0DpÿÂüKúø/öžôhó’òòþñ9òÃò“óœôÓõ*÷’øüù\û¤üÉýÀþÿNU®ÿÿ7þDý;ü(ûúù=øŠ÷ ÷ÑöÞö9÷æ÷æø7úÔû¸ý×ÿ&™© % ƒ±¡B‡gØÔYfÿ)îZ y \¶SýÿùÌöÎóñ®î©ìëæé4éûè8éèéëìPîgð¶ò,õ·÷GúÌü4ÿqw=¸ã¼A u \ þc–¤™„pl„Â0×ÿ¸ÿÚÿ9×®¶è7˜þY » ¥ P ± ¿ t Ì Å b ¦˜C±òþü(ùAöpóÇðXî3ìfêÿèè„ç}çôçæèNê&ìcîøðÖóíö*ú{ýÊ " ¡ êÔWmItw&޽  ¬ smŠÖÿYþý'üyûû÷úû~ûüÍü¦ýþzÿZ#ÊD‡QÒ ÊþVý¸ûûù,øZö”ôéòiñ!ðïnîî%îšîxï¾ðjòuôÕöùeüvÿ¡Ö ê†Ñ½?Lßô‹§O‰cé, < + òïýûoøöôPòÿðð‹ïiï¥ï:ðñFò£ó*õÊövøú´û,ýzþ•ÿtt‘oƒÉÿïþþ ýüCûˆúúù¡ùˆùµù-úðúüYýôþÉÐú; ¿ â Ü›5öO8®±Dk0ž Á©hÿµûhø>õIò™ï>íEë¹é¡èèáç:èéFêéëæí.ð±ò^õ%øóú¶ý]Ú !Ô2 8 ä 6 2 à G q l C¿SFc²:GÆz]d…³à Þ ƒ è  Ï F e -¢Ê¬TÐý,ûyøÉõ-ó¶ðvî|ì×ê“éºèUèièöèýéyëcí±ïVòDõjø¶ûÿs¿åÓ yÉ·:LéÅ ïv°«u ¼Y Ø×þ ý†ûHúXù·øeø]øšøùÁù–ú†û„ü‚ýtþMÿˆÙíÂV«ÿÃþ¦ý[üíúiùÚ÷QöÚô…ó`òxñØð‹ð˜ðñÕñó™ô…öÃøGûþïòÿ è  A o^ÔÍHGÒïª2 ìªnÿGüJù†ö ôâñð·î¿í4íí[íîïLðÖñ‘ómõ[÷Kù0ûúüþE;íYe…Ñ4ÿSþ‡ýÝü^üü üCüÁü‡ý’þÝÿbõêêæ Í ‘"qr`<¬¯EuE Á õïÂý7úÿöéóñmî'ìCêÍèÍçHçAç¶ç¤èêÍëóífðóöõðøóûìþÉ{ô&  Œ ´ {àè˜÷  ï ¡ 4 ¶6Áf/&T¿ÿhÿRÿ{ÿßÿv: "%ê“:&ÆÆ-R>ÿýüœú+ø¹õXóñ ï>íÂë¡êèééÆéeêzëíôîHñòóäö ú[ý»h z iPÊÏ[n 2ñP\#µ $ €ÛEÐÿˆý{û²ù6ø ÷:ö¼õ‘õµõöÇö¡÷¢ø»ùàúüý þÝþ~ÿèÿ³ÿ%ÿ`þiýJüûÀùoø)÷úõñôô…ó7ó;ó–óLô^õËöŒøœúïü{ÿ0Ú« b í;<ã#óL)‹råëß ê ÁvÊýŽú{÷¤ôòâïî¦ì®ë(ëëlë,ìKí½îvðfòô¯öçøû1ý%ÿçp¶³fÍìÇdÎ3FVo ÿòþrþ&þþHþ¼þrÿg—ù„,㜠H × <gMáófqZ B Ù*D7ÿüíøÕõßòðŸívë¯éUèqççç°ç¼è=ê'ìpîñáóèö ú9ý\eAá7 8 Ûñ_iaa¤  I †Ç0ÿhþýýÕýíý@þÇþzÿL3! à–!wcî.$ÕD}þ‡üpúFøööóðñðxî#í$ì†ëPë‰ë3ìMíÖîÇðóºõ£øÂûÿY®î æ{¸÷è^WÖßy°(‡ ¿ â0~þúû²ù²÷ö­ô±óóÐòäòHóôóÝô÷õ4÷†øßù2ûqüý„þFÿÎÿ#ðÿÿÜþ þýüãúÅù¶øÂ÷÷ö`ööøõ7öÉö°÷êøvúLücþ±)»Yñ q Éè¿>\ J\1”‹#f f 2Ý{ÿü×ø½õßòNðîDìàêðévétéäéÂêì¡íŠï°ñôtöðøhûËý év¶§F”–RÏ:@7-/J‰öÿ™ÿwÿ”ÿñÿŒcn¦oçZ ¹ ö  Ó [’oï  Î 0 <úu»Ûýäúé÷üô/ò”ï=í7ë’éXè’çFçwç%èMééêïìTï òõ%øhû´þöÑ ? U S0žŸ9qSè@h p h`fˆÔTÿþýTüáû´ûÊûü¥üWý(þ ÿõÿÖ£QÒ0ÿ‰ÍΑÿþwü¯úÐøèöõ;ó•ñ#ðóîî‰íbí£íNîeïåðÉòõ˜÷kúsýÚ= = ‚¦fµèÅ&‡™Q¾ð úìÚ×ÿóü>úÇ÷œõÅóLò4ñ€ð/ð>ð¦ð_ñ_ò˜óÿô…öø°ù:û©üóýÿðÿ•ú«gÿŒþšýŸü¦û¾úôùSùçø¹øÑø4ùåùäú/üÁý’ÿ™ÊsË  1Ç °Ö‰Ç’íàu ¸ ¹‡4Õý{ú:÷$ôLñÂî“ìËêté•è/èDèÑèÏé7ëýìïnñùó¥ö`ùü½þ>Ž¡jä Ô H g 7 ¾   á¬yUNm¼CHÅz`m—ÑC^ T  œ Ù Å ] › € J;ëiÿ¿üÿù:÷ôåñyïMípëïé×è0èèKèéOêÿëî’ðZódöœùñüO¤Üå ® )GL%Š|ÿÙEk\ & ÛŠEGþ´ügûdú¯ùGù)ùPù¶ùQúûøûìüãýÑþªÿ_ê?Z4Í%@ÿ!þÑüZûÈù'ø‡öôôó6ò&ñ[ðâïÂïð¥ð®ñóåô÷wù(ü ÿ)@C Æ#(Éû¶õ¶ùĦð þ â®uLþAûgøÎõƒó‘ñðØîîÄí×íKîï6ð–ñ,óèô¼ö˜ønú.üÍý>ÿxu0¦ØÉ}üO‚ ÿ¶þÐýýüIü¿ûiûPûyûêû¤ü¥ýêþm&  4 : "Ý[Žkèü£Û¥ü › êøÕ“ÿCüùøÉõÅòþï…íhë´érè©ç\çŒç7èWéãêÑìïñZô;÷,úýûÿµ=… ( u c ò $ü „ Â Ä • B Ûm´‚|©·ÿÿÁÿ!·|ehw‡ˆo-¸ Å-C~­ž]þôûtùíönô òÒïÕí#ìÈêÒéHé1é‘éiê¶ësí˜ïòêôú÷9û”þ÷Q™ dÞû¯ò¾ïXTì+!Û j ßKÀMÿêüû‚ùAøR÷¸öpövöÄöQ÷øþøúû3ü>ý1þÿ¡ÿ =/âÿVÿþ—ýrü,ûÑùnø÷Èõ¢ô¬óòòò\ò’ò#óô^õ÷þøAûÄývM4 ñ £T5´Åb„*SE›Ë ¿ ˆ9çÿ¢ü~ùŒöÝóñ}ïáí²ìòë£ëÁëIì2írîüïÄñºóÍõï÷úüþÓÿ`°»}õ%À8†³Íáüÿ*ÿxþñýžý†ý®ýþÊþ¼ÿêOà”\+ ò ¢ ,€’VÁËoª|è ô ¨ 81 þÙú¬÷™ô°ñï§ì¥ê éäç6ççQçèZé ëí„ï5òõ*øIûhþs\ ¤ n ØÝ{µŽ 9Ê J « þQ².Ѧ´ÿÿþ]þmþºþ;ÿêÿ»¤—‡h,Ç.X>Û,1ìcŸÿ¦ý†ûMù ÷Ìô¤ò¡ðÕîNíìAëÑêÎê>ë ìtí4ïYñØó¤ö¯ùçü:–è  ÞN^5î,ï:…š`ç @ {ªá.¤ýNû9ùq÷üõßôôµó¥óåónô7õ4öW÷”øÛù!ûVüný`þ!ÿ«ÿøÿÖÿiÿÄþïýóüÚû°ú„ùbøX÷söÁõLõõ=õ±õ|ö÷ù×úãü+ÿ£?ìœ ; ºÈ"‘™';ÙÐ=^ Cþ¡Aþîú¾÷Áô ò¤ïžíìÕêêÜéê¯ê·ëíÕîÏðþòPõµ÷úvü³þß9Œ‘G®Éœ1Ã×ÛÚáÿ>©ÿHÿ!ÿ9ÿ’ÿ+K®+µ> ¸  D ;ëLUÿG- ² Ü ³?±ÿ´üªù¦ö¹ó÷ðpî5ìTêÚèÑç?ç+ç”çyèÖé¡ëÒíZð+ó4öcù¥üæÿò ¾ ž+Ï×EXžë  $ /Cn½;óþéý#ý¤üjüsüºü6ýßýªþŠÿqV(ÝiÁݸNœ¥løþOý~û‘ù–÷›õ°óæñJðìîÙííÀìËìBí&îwï/ñHó¹õuømû’þÐTr _ e`ï ªÎt X¤’-‡ ¯ ·³´Íþ üƒù>÷Hõ«ókòññòð/ñ¾ñ—ò¬óóô]öÛ÷_ùÚú@ü…ýþÿ)’»¥RÊÿÿ6þ@ý=ü9ûCúhù´ø2øî÷î÷:øÕøÀùûú€üIþM‚ÙEµ  _wRàæJ<·½Ou6Ÿ ½ ŸXûÿ™üGùöófðîìsêSé¬è~èÈè‡é²ê?ì$îPðµòCõç÷ú-ý¯ÿ%’Ѻ N | " ˆ ¸¾¨ƒ\B@b²7øÿöÿ3®cL^‘Ù(p¤ µ — = ­ h È Í x ÌÐŽfþûÇøõõ9ó¤ðIî6ì{ê#é:èÇçÎçQèNéÂê¥ìëîŠñqô‘÷Öú.þ…ÉèÏ o º¥'9Úǰ Ú ŸhEDqÿ×ý}ükû¤ú(ú÷ù ú]úçúûsü^ýOþ;ÿËZ¶×¹XµÓÿ´þ`ýâûDú’øÛö.õ™ó+òóðýïVïïïïið«ñPóRõ¨÷Fúý"@f‚  NÛõhgëò{‰!M  ¢tJ9ýPúŸ÷5õócñ ðï•îuî·îTïDðzñêò…ô>öøÈù|ûýƒþÀÿÀ‚=7ôzÓ (ÿ;þPýtüµûû¸úú©ú ûµûªüæýeÿ5` ƒ Ž q‚•I—wèçwžd Ô úç¬[þûÀ÷ô°ñ ï·ìÈêGé;è©ç”çúçØè&êÛëêíEðÝò õ|ø`û9þöˆâöº ( : ð I I ö Z } m 5 ä‰0齺èNñÿÓÿôÿQ欙¢¼Ùëæ»` Ç ê ¿ C rM×ÐÿcýØú?ø§õ"óÂð–î°ìëéé éÈèèè€éêìîYðóõõùnüÐÿ0}£ ‘ 5ƒmëöЧP‰[Ñ÷ÛŽ ¢$¸lOþküÊúuùoø»÷W÷B÷v÷ê÷•økùaúiûvüzýiþ6ÿÙÿFzp&žÿØþÜý²ücûûù†ø÷±õmôUówòÝñ“ñ ñ òÒòûó‚õ`÷ùü°þ‡xqa 4 ÚAYgG®™ùv‡6‘§ ‰Kþ·þ‡ûøµõ3óñ;ï×íáìYì?ììBíNîªïHñó õ÷#ù%ûýÑþa¸Íœ#c^¡ú0Pf‚ÿ­þõýfý ýèüýhýþüþ'Œ#à·›| K ù vµ©F„[ÉËc— m ð-1ÖüšùnödóðîÈëñéˆè•çç%ç©ç¦èêïë%îªðmó^öjùüŠÿx;à ð ±}åì˜ðÿ Ð p î X¾-²[0<…ÿ ÿÖþßþ%ÿ£ÿN ýê¼hâ!Í1G’ÒÛþ¶üqúøÄõ|óSñ[ï£í8ì'ë|ê<êoêë1ì½í²ïò³ô¤÷ÌúþuÒ; "ÀäUPÑ×e-yr$  ø <ÑDÿäüÀúáøR÷ö5õ«ôxô–ôþô¨õˆö’÷¹øïù'ûRüdýSþÿžÿîÿÿÿÑÿfÿÂþëýéüÈû“úWù"ø÷ö3õŸôPôOô¢ôNõRö®÷]ùYû˜ý ¬e(ã „ û5$¹éªôÅ÷`]ùA D Äe ýÌù¶öÜóNñïGíâëîêoêcêÇê•ëÄìIîðòNô˜öìø9ûoýÿ`g~HÅöàŠû@cry…¥äÿLÿæþ¹þÌþÿµÿˆ–×BËf š  h …_ì!øm|( t g i’•þûkøcõ}òËï]íDëŒéAèkçç4çÕçïè~êvìÍîtñ[ôp÷¢úÝý " µ  ÅßMQó8+×J “ À á<Äÿ´þæý\ýýýPýÃýdþ)ÿï×°mi“|zZêÿ@þiüpúcøQöIô[ò–ð ïÇíÖìDììWìí"î«ïšñçó†öiùü½ÿ VŒ œ qü.ûW;¤ù„©wûF j x„×ý@ûæøÕöõ³ó®òòÀñÓñ:òìòÞóõRö¸÷)ù–úñû/ýDþ(ÿÓÿ?lZ …ÿÎþïýôüèûÙúÕùçøø†÷)÷÷B÷Å÷™øÀù5ûòüñþ$‚ûþ f ¨²uãð“ÄÂëÝp° ­x!¿þaûøõ(òšïgí›ë>êVéæèïèméZê®ë]íZï–ñôŠö ù²û/þˆ°›?–šJ § ´ w øA^[F,B’ÓÿÎÿ6 8tÈ'„Ñ ÿ É M ƒ c é  Ü L h7ÄQýnú‡÷®ôõñnï(í4ë éuè¾çç¿çzè¯éVëgí×ï—ò˜õÇøühÿ²àà  ,à*lfõ!òv¹Ê ¹ –qY]‰ëþˆýjü“ûûÃúÅúûû*üõüØýÄþ­ÿ…BÖ9cMõXz^ÿþ„üÛúùO÷‡õÓóBòâðÀïëîkîJîŽî:ïOðËñ©óàõfø/û+þIx§À ³ lÜ󤿝ýÌøac h‰ ‚cA.ÿ9üvùòöºôÚòXñ;ðƒï2ïCï±ïtð€ñÊòCôßõ÷?ùæúuüßýÿæl¯²v`™ÿ¶þÆýÔüïû#û|úúÌùÓù"ú½ú£ûÔüJþÿÿèü-lª Ö ß·M•‚ &ÐÏ'® ó öÇyýÊùŽö€ó¯ð,îìGêûè&èÍçïçŠè˜éëéìï‚ñ#ôåö·ù‡üCÿÚAhEÐ  Ü Z € R Ù  +  ÔŒBááuõÿmȹÉí<L9 ø } ½ ± S ž “3ƒŠRæþUü­ùÿö]ôØñïiížë/ê'éŽèkèÂè“éÚê“ìµî4ñô÷Pú©ý b§ q ë½Ö2‘žK£µŽ @ ÛoƧÿ»ý ü¦ú‹ùÀøEøø1øŽø#ùçùÌúÇûÊüÇý²þ~ÿ!“ËÆ€ûÿ7ÿ:þ ý´û?úºø2÷¶õTôóòUñâðÄðñ£ñ¥òôÈõÝ÷>úàü³ÿ§®³¤ pQFØú§×ŠÀ}É®8u v M È“ý~úš÷ùô§ò¯ðïñí3íâìûìxíRî~ïðð›ònô\öTøGú&üäývÿÐíÇZ§±z n¬Ðêÿÿ*þlýÔümü?üRü¨üFý)þPÿ³Lõëä Ñ ¢ H³×§'ÉÿÈ(% È 3àþšû[ø6õ<òïíë[é&èjç*çiç"èRéîêîìBïÝñ­ô¡÷¦úªýšhYd  p fú.‰À ¶ w  •ŒÌ¤¯õÿxÿ<ÿ@ÿ‚ÿûÿ¥wfehbD’æøÀ:d?Î#üý¯ûJùÝöxô,ò ð"î‚ì9ëQêÔéÉé3êëfì(îPðÔò¦õ·øöûPÿ² B K ‡J„G`»§-Z;ß W ´bÖrþAüRú¬øW÷Wö®õZõWõ õ,öñöã÷õøúCûdüpý[þÿ¦ÿùÿ âÿyÿÕþüýöüÍûŒúAùø÷Àö¦õ¹ôô”ópó ó)ô õLöâ÷ÊùúûhþÇ™k + È0S"’ 5Íë‘Ç• 1  ݇-ÿâû¹øÃõó°ð­îíæë+ëãê ëžë–ìæí„ïañnó›õØ÷úBüPþ2ÞKqMÝ" Ýaµåþ >{ÿßþtþAþLþ™þ)ÿúÿJ»Pû®\ ö l °µnÒØ{¸Ž  ÓF{jýFú)÷$ôKñ¯î`ìmêâèÈç(çç`ç8è†éCëdíÝïò”õ°øßû ÿ&ÝZ ‡ YÉÑq©}óì‡ ò < u«îKÎmÿ˜þþ·ý«ýÝýGþâþ¤ÿjV6þ¡NGúc‚ZîGÿlýjûNù'÷õôò ñRïÝí¸ìîëˆëŽëìëìAîð&ò£ôl÷rú¥ýòG‘¼ · oÕÛvJz/k5•˜K¾  'AašÿùüúhøŽö õàóó¤òòÏò[ó+ô1õcö±÷ùkú»ûòüþåþ‘ÿ1#ØÿSÿœþºý¹ü¥û‰úuùtø•÷åömö9öPö·ör÷øâù‘û…ýµÿ–+ J ±èÞ„Í®ž¨>f' ¬ ŽEæ„ý1ú÷ôMñêîèìQë+ê|éDé‚é1êIëÁìŒîœðâòLõË÷MúÂüÿF<ð[v@¸à¿Z»íý÷èßè^àÿšÿ‘ÿÈÿ>òÝú>ž ä . P < æ DLù H 6 Ç þã€áÿ+ü5ùDöjóºðEîìKêáèççdç^çÕçÇè0êìEîÙðµóÊöúPýšÓåÁ V ˜|ø ªÝ¥ À/g v n ]S_îÿ…þ]ýyüÞû‹û}û°ûü¹ü{ýVþ?ÿ&Â]Éüð¡5Èþ@ýŽûÀùá÷ö0ô{òóð¦ï¢îðíí­í'î ïZðò"ôŒö?ù-üGÿz¶æø Ùxų4BÕꂟG„aì3 J @*!þPû·øcöaô¹òqñð ðïï/ðÅð§ñÊò"ôŸõ4÷ÒøjúïûSýþ“ÿ]è2;˜úÿ3ÿOþYý`üpû–úàùXù ùüø7ù¾ù“úµû ýÎþµÎ Y® ø ')ïl‘S«““¶uÝ üà›@ÿâû”øiõsòÄïjísëèéÒè5èèlè9étêì îLðÇòkõ'øèúžý7¥ÛÍrà ¼ \ ¥ š B § Ò Ï¬v; íò"†$sÏÄÛ CyŸ¥ € # ƒ — Y Ä Ö ‘÷ázçý5ûuøºõó”ðLîMì£ê]éƒèè1èÀèÉéGë2í‚ï(òõ<øˆûæþAЬ– 7‚lëù“¸mµš'gj> õ ŸL íýþFýÑû¥úÆù4ùïøôø:ù»ùmúCû1ü+ý"þ ÿÖÿ{ñ//ïm¬ÿ¯þ}ýüŸú ùn÷ÙõYôýòÔñêðKððð‡ð_ñ›ò8ô0öyø ûÔýÈÖëö ã ¡K}mãÜWWáÿ¼%J < Òœÿ~ü‰ùÍöZô;ò{ð ï.î¨íŒíÕí|îxï¾ðAòòóÃõ£÷„ùXûýŸþüÿÿö à|ç*Rlÿƒþ¥ýßü=üÊûû“ûÝûnüGýfþÆÿ^(, 5 ' ôŒàãŒÐ©¡Ê’  3&ò©ý\ú ÷ô$ñ‡î@ì\êæèæçbçZçÏç¼èêàëîoðóñõâøÚûÈþ™?«Ï£  ; ù WYc ~ a  µCÑm$ PÐÿÿÿÌÿB쿲¹ÇÎÁ“8¥Ð±C„ti|Wÿý•úø–õ*óàðÊîøìvëSê™éNéxéê2ë½ì³î ñ¹ó®öÚù*ý‹ì8\ G è1,Èò´)ø” vßXóÿ»ý¾ûú™ø÷¹öHö'öRöÂöm÷GøEùXúuûŒü‘ýxþ7ÿÄÿ0¢ÿÿþ%þýêûžúCùæ÷—öbõVô€óìò£ò­òóÒóðôiö8øVú¸üRÿðÕ± q W^JtQ²˜ ´ é¡KüýÅú¸÷çô`ò1ðdîíì‹ëxëÒë‘ì­íïÌð³òÀôãö ù-û4ýÿÅ:mXùP`/Â%aƒ—«Íÿÿfþôý¹ý¼ýþŠþVÿ`¥¹r9ÿ ¶ O ºéÐd›oÛß|µ ” gwaÿ6üùéõíò'ð¦ízë²éWèrç çç°ç¼è;ê$ìiîþðÒóÔöðùý/.–â Ù r¨xáæŒÜß¡ / — é4†ìt)9ÿ þIþ4þ^þÂþXÿñÞйŒ=À ÛUƒga‡þüWúøáõ²ó¢ñÀïîÁìÀë!ëìê(ëÕëõì„îzðÐòyõhøŒûÔþ,„Æà ÀV’hÏ¿4-­·Tty » éO¬þ6üüù øiöõ0ô›óaó{óãó‘ôxõŽöÄ÷ ùZúžûÌüÙý¹þfÿØÿ ¹ÿ5ÿ}þ™ý’ütûLú&ùø÷Rö¿õmõfõ¯õNöB÷Œø(úü6þ“»f • ö÷{›MŠN™lÌÁV˜ – a «ÿOü ùôõóŒðYî‹ì*ë=êÆéÄé5êëPìèíÉïçñ0ô”öùkû¾ýìÿç¨#S3Äý°(n˜”“ É—ÿMÿ@ÿrÿæÿ—ƒ£îYØ]Û B … • fìömƒ 8 Ž@®çûýúúõ÷ÿô+òŠï-í$ë|éAèzç.ç_ç è6éÑê×ì:ïîñâôøBûˆþÄãÕˆ ï ý©íÄ.-ÆäÞ  % *2I~ÝqÿBþTý­üLü0üVüµüGýþ×þ¼ÿ£HëaŸŸ\Òïžÿþ\ü‚ú’øœö®ôØò)ñ±ï}î™ííìì1íâíïˆðtò»ôT÷/ú?ýq´õ! % ïo•T¤|×´zK½ö  ú(ýúøõõ*ô»ò­ññ·ðÊð5ñîñëò ôõúöƒø úƒûàüþÿéÿxÇÖ¦<¡ÿÚþóýøüöûúúúJù®øJø&øKø¼ø}ùúéûýqÿ‰Ì)“ø H shtr,Ýß6$µ ó ðºeþ©úg÷Rô{ñòîÅìë«éÍèhè~è éêkë,í=ïñô²ö`ù ü¢þTW|’ Q » Ñ ™  c zmJ÷ãì÷ÿd÷À¹×X Üü ó ¶ 7 n S à  ë k˜z‹ÿÓüú5÷rôÍñZï'íEëÂé§èÿçÏçèâè"êÓëïíhð1ó:öqùÄüp¤¨ l áú®õÊ,¡¿€ñ ï ±p; /sþóü¸ûÈú#úÊù¹ùìùZúûúÃû¦ü—ýŠþoÿ;ä_£ªpô6;ÿþ¤üûwùÇ÷ö}ôÿò°ñðÒïZï>ïƒï.ð@ñµò‹ô¸ö3ùïûÝþì ,6 Ä%-оý¾Í'´ ýО}þ{û«øöÚóññiðGïî?îTîÊî—ï°ð ò˜óJõ÷ßø¤úRüÝý:ÿ`HîPoNóe®Ùÿòþþ!ýRü¤û#ûÙúÎúû‹ûWükýÅþ['1Sv ˆ {=Áø×Sf =XKâ * 2Áÿmüùìõæòð¤íˆëÔé“èÊç}ç­çWèuéÿêéì'ï©ñ^ô6÷úýÔÿû6$ ¿ ä i ” h ì + /  º]û¤cDR•ÏÿÊÿx öíü+0ÔZ Ÿ œ J ¤«_ÅäÃrþùûjùÖöKôÝñœï˜íáëƒêŠéÿèéèKé%êuë5í]ïâñµôÇ÷ûdþÇ Zd ,£½m­xʦªïë® H ÉCÇc)ÿ"ý[ûÛùªøË÷>÷÷÷f÷ø÷¼ø¦ù©ú¹ûÆüÅý©þhÿöÿMhDâÿ@ÿeþWýüÈú^ùï÷ˆö8õ ôó[òëñÎñ ò¥òžó÷ô©ö°øû‘ýQ3& ö ¯2lQÒ僥Js$d<ºì â ®cÖü¸ùÎö&ôÎñÔï>îíYì ì-ìµìœíØî]ðòôö"ø2ú0üþ¿ÿ9tl‚¢#“Ù3TÿŠþãýiý%ýýZýÚýŸþ¥ÿèa̤‚ U  ¡ûÔ>EäãFI ô Rqa4þúúÇ÷®ôÁñï³ì¯êéíç>ç çZç"èaé ëí‚ï.òõø,ûBþC!Ê1 I  hdü0ƒ°™ K Ó ? Ÿsº£Çÿ(ÿËþ¯þÓþ0ÿÂÿ}ZKC6ÖjÈçÀM€)޶ÿ«ýzû1ùßö”ô`òUð‚îõì¼ëãêsêrêäêÊë#íèîñ–óhöxù´ü i¼ñ ô ´"1Õ¾û¾ æ[tAÐ 1 w³öQÖýû‰ùÏ÷höYõ¢ôDô;ôôõ×õÑöï÷$ùaú™û¿üÆý¤þQÿÅÿüÿõÿ®ÿ,ÿsþŒýüWû"úìøÃ÷¶öÐõ õ¯ôˆô±ô0õö6÷»øúªüÿŠ3î© T Û/?ûXKÊÒ^q :lŒ q,Ðrþ"ûõ÷ýôIòèïçíOì'ërê2êeêë ìmíïñ6ó|õÔ÷-úvü¢þ¡iò2'Í&4þ‹ä+28JsÂÿ=ÿîþÛþ ÿwÿ%3„ù‡µ 8 œ Ð ÉzØÜ¿›  4 ÿÃÚÿÓü¿ù²ö¾óöðjî+ìGêËèÁç/çç„çièÅéë¿íEðóöBù~ü¹ÿßá­3 h @³¾]’_Ìâª2ˆ º ÙôV¸Jÿ!þoýýÛüõüJýÒý„þVÿ9"ÒÿKX"¥àÕ‡ÿþDý`ûbùW÷NõXó„ñáï}îhíªìOì]ìØìÂíïØðùòrõ5ø5û`þ¥ñ2T DòMH×ñ’µ[ˆB’ƒ#ƒ ³ ÄÊÖúþGüÊù‘÷¨õôáò ò˜ñ€ñÁñQò)ó;ô|õÝöPøÆù2û†ü·ý»þ‰ÿo‚WòÿWÿþ¦ý¥ü™û‘ú˜ù¾ø ø‘÷V÷a÷º÷cø_ùªú@üþ1vÞYÖ E –·˜,d6š‹•·tÙ ô ÓŠ*ÉüvùGöNóšð<î@ì¯ê‘éëè¾è éÆéïêxìWî|ðØò[õó÷úýÿÖå±2b> Å ù à € ã ìÐÃÑgØÿìÿ?К–»ÿU¯ ; P 3 Ø 3 = ï E > Ü "È<…þ¯ûÍøñõ+óð-îìVêüèèžç¥ç(è'éœêìÆîeñKôi÷¬úþT“¬ ' lQÍÛx¤b¹°S®Ï Ç ¤ wP>OÿþÂüÃû û¢úú úýúûJü#ý þûþßÿ­ZÚ&5ŽÕÞÿªþBý±ûú?øzöÁô"ó®ñqðyïÒî…îšîïøïCñòòþô^÷úêü÷ÿKm q DÕóggëó|Š$Q™Ñ Ö ½–umýŽúç÷‡õzóÉñ{ð“ïïöî:ïØïÅð÷ñaóóô öXø ú¯û4ýþ¶ÿ¢O¹áÈuí9fÿ}þŒý üÇû û|ú!úú-úŸú[ûcü³ýDÿ (\– Æ Ü Èzäù¯üÚFAÌí­  7Þˆþ0ûè÷ÃôÕñ.ïÜìîêmébèÑç½ç#èÿèKêüëî[ðëò¥õwøOûþËP› W ¸ ¿ i º ³ ] ¾ â Õ ¤\ ŠqÄ?ùÿñÿ'™B-QwŒa  d  J Á ã®(V?ðÿtýÛú3øõó–ðcîwìàêªéßè‡è§èAéTêÚëÎí$ðÐòÄõïø?ü ÿÿJm W øA(¢ª<X;ж£` þ ‡{þ©üûÕùßø9øã÷Ú÷øø?ùú û üý þíþ«ÿ:–µ–6—ÿ¼þ¬ýnü û•ùø”ö)õÞóÃòãñKñññˆñ[òŽó!õ ÷GùÈû‚þd`c\ 8 äPl*~`Dz P¬Å ªp)èþ¾ûÀøüõó\ñ˜ï;îJíÇì°ìí³í½îðªñqó[õV÷TùEûýËþHŠ‹G»êÖ†Q‚Ÿ·ÿÕþþXýÕü‡üuü¥üýÖýÖþ: òåÓ ­ dè,!¿úÎ62Ãï ½ 7 kg<ýü»ùŠö|ó¥ðîÙëê˜è¥ç.ç5ç¸çµè#êùë+î«ðióRöVùaüaÿEüy­ Ž  :þ_a br H ï w íaàx4?žÿ;ÿÿ7ÿÿض¬¬©—g‚¶¥I¢ZÉ÷îþ·übúý÷˜õDóñïSíäëÑê$êåéêÄêãësímïÇñwôl÷—úæýF¤í ô Ó± ™Ÿ-HùJH‡ é :‰êkÿýû8ù·÷‹öµõ6õ õ1õŸõJö*÷1øRùú«ûÈüÊý¦þRÿÈÿýÿ¹ÿ8ÿþ•ý‚üQûúÈøŠ÷döcõ“ôô¹ó¿óôÓôäõN÷ ùûdýéÿ•\+ñ › [NçÛ&öK&‰#k o @ñ”?ýúñöô“ñcï—í7ìGëËêÁê%ëòëíîcð`ò†ôÄö ùFûkýkÿ8ËØEiGçR“µÅÑæ\ÿÓþ~þeþŒþõþŸÿˆ«Äp  ” í éu§yæí Ñ ¹ Q¥Â»þžûøpõ„òÍï[í?ë…é9èbçç+çËçæèsêjì¿îcñFôV÷‚úµýÞêÉj À À `škÔÕuº°bÝ / h ˜Ì|ÙÿÝþ$þ®ý|ý‹ýÖýWþÿÑÿ³Ÿ‡\¡ûñƒËÊ„CþYüNú1øöüóò7ð¥î]íjì×ë¬ëïë¢ìÄíTïJñžóCö.ùLüŽÿß/i { RÞÜ8„pàÛh‘dîA n †œ þû2ù/÷~õ&ô+óŽòNòfòÐòƒósô•õÜö8øœùúúEüqýrþ@ÿÕÿ+C¹ÿ ÿWþiýbüLû6ú-ù>øw÷ãöö}ö»öK÷.ødùêú¹üÈþ z” ’ Ýî·)9Ü ÆÑ*©æ á©Rïþ’ûOø8õ_òÔï¤íÛë€ê›é-é7éµé êðëšíïÄñ%ô¢ö+ù®ûþd{Ué/%Ç  ÖR™¶·§–¢×9Ñÿ£ÿ´ÿ“]\‡Õ8¤ a ” ˜ a â í j ‡ F ª ¸zúEmý~ú÷«ôéñ[ïíëéUèç_çžçYèŽé6ëGí·ïvòtõ¡øéû:ÿ§ Z Æ ×†ÉžûŠ·Œ`{ v aKDZšÿÀýµüñûvûCûSû¡û%üÕü¤ýˆþsÿV(ÚaµÎ¥9ˆ”cÿúýbü¦úÕøúö&õgóÎñgðCïlîííÏíîÊîæïkñQó’õ"øôúùýV‹ª ¡ ^ÑéœÞ¨õÅò]a n– •~e[ÿrü¹ù@÷õ=óÅñ°ððµïÊï:ðüðòJó¼ôMöî÷‘ù'û¤üûý"ÿÂ2aPÐÿüþþý&ü@ûxú×ùjù:ùNù­ùXúPû“üþãÿßF•à  + ¦òáiƒ,`"ubñ 1 /û©Lýõù¸ö©óØðVî1ìtê)éUèýçè¹èÆé;ëí4ï›ñ3ôëö±ùtü"ÿ«êg Z Î ë ¸ ; ~ Ž uCÇ™†™ÜW 5¦O(*Iz¯ÚîÝ š  U @ ×  ýŽÏÆ~ÿcü­ùóöFô·ñXï:íjëøéíèTè1è‰è[é¥ê`ì„îñÕóäö"úzýÚ/fm 2 ¨Àq´ƒÝÄ;JûYrU  º] ÔÆÿìýQüüúòù7ùÊø¨øÎø2ùÍù“úxûpülýaþ@ÿÿÿ‘ðû +ÿþÖülûæùRø¾ö7õÍóŽòˆñÆðUð;ðð)ñ4ò¢ómõŽ÷üù©üˆÿ‡—¥Ÿ q [Tç ¸é›ÑÜÁM ‘ m2ôÆý¹úÞ÷Eõûò ñ€ï\î¤íWíríðíÈîñï]ñÿòÈô©ö“øuúBüîýkÿ±ºÿ:2írË!9ÿTþýÉü;üàûÁûäûMüþüöý0ÿ¨U,"(/ ( ±"I—6f(v  _mL ÿÁû}øTõWòšï,íëré=èçBç€ç9ègéëýìMïáñªô–÷‘ú‹ýo0½  ° ü é u¢uö - & î ‘ ¥2Ó•‚£þÿ˜ÿqÿŠÿßÿj$ÿ ï«4ˆD¯Ê”HB þ­û9ù¾öLôöñËïÛí7ìêêêƒéyéåéÇêìäíð˜ònõ‚øÄû ÿ‚Ú  ÞQeH Q!|jô&» = ¥oòžþ~üžúùÃ÷Ñö4öëõñõAöÑö—÷‡ø•ù²úÑûæüâý¼þiÿàÿÚÿ[ÿ¢þµýœübûú»øh÷)ö õôióüòÞòó©ó™ôäõˆ÷~ù½û9þ岑n 8 ÝLuH¸¼J_÷¹í»/W D ´^ÿüóøöVóüðÿîjíBì‹ëEëoëì÷ìDîÛï°ñ³óÔõø0úLüHþ° çgŽ?º 6O`w¢ÿêþ[þþßýþý`þÿêÿ déK Ç k é 29óUWõ*øa k  ‡²¯ýcú>÷3ôUñµîcìnêáèÇç'çç_ç6èƒé?ë^íÓïòõ—ø¾ûãþôà— - õ \]ö*ûp“n ƒ Ø d¸'¾†ˆÿÈþJþþþYþÒþzÿE(å¨D­ÛÆhÀÍ‘XÿjýWû*ùôöÃô¨ò´ðõî{íRì‡ë"ë+ë¤ëìëí±ïÜñ_ô.÷:úrýÃi— ’ K±¶Pv"SEt|4¯ û *P|Âÿ/ýÓúºøîövõYô—ó1ó#ógóöóÅôÉõõö;øùÝúüBý@þ ÿ¤ÿþÿõÿ”ÿûþ1þ@ý1üûìùÒøÎ÷ïöAöÏõ¢õÃõ6öþöøùLûQý‘ÿ‘4× j ÜÁ ða\Þæzž]Ã Þ ¾uµýdú5÷<ô‰ñ*ï,í˜ëvêÉé’éÑé~ê”ëíÍîÕðópõâ÷Vú»üÿ¥þ Ä/L!µCTRKKa—ùÿÿ[ÿgÿ´ÿ@  :ük ½ ã Ñ zÔ×| ¦ + U .¾;ÿEüDùIögó±ð6îì4êÈèÍçJçDç»ç­èêîë*î½ð—ó©öÞù&ýk¨| E!—¡>n4–žVÌ & + )0N¯þšýËüBüüüCü»ü`ý(þÿïÿÔ©añOrUóL_1Èþ,ýhûˆùš÷¬õÏóò‚ð0ï(îwí$í8í·í¢îøï´ñÑóCöÿøöûÿR”Éà Äfµ£&3ÆÛs‘;{[ê7 T SF?RþŒûÿø·öÀô#óåñ ñ‘ðxð¼ðRñ3òSó¤ôö¢÷2ùºú-ü~ý£þ”ÿH¾óçŸ rÿžþ¯ý²ü´ûÂúêù7ù·øqøpø¸øOù4úhûåü¥þŸÉuØ . gr?Àè¬éZVßý¸ 5 ÍpÿüÁø–õ òòïší¤ëêélèKè£èoé¨êCì5îoðâò|õ,øàúˆýr˜{S ? Ó  £  0 0嵑„›ßX þÿ.E!(PŒÑ; E Á  ) â B G ôKT¢þAûuø®õýòvð'î"ìuê+éPèëçÿçè™éëíVïýñìôø[û·þTrW ó 9˜¢8\YAÒ% Ç < ÿ"ÿ}ýüû2ú±ùzùŠùÛùcúûñûÞüÓýÃþ¡ÿ`÷\‡s†°ÿžþWýæûTú¯ø÷dõÛóyòKñ_ðÁïzï‘ï ðìð2òÙóÛõ0øÌú¡ýŸ·Õè Ü Ÿ!P!†wîæaaí Ê6_ V -øÊÿ´üÈù÷«ô–òÞð‹ï î îîRîùîóï4ñ°òXôöï÷Áùƒû'ý£þìÿøÅO”—]êI„§ÿ¼þÓýøü7üû5ûûûvûüý8þ¬ÿX55Lj € } SñJPù<zqûÞ K p]#ÔýƒúC÷(ôCñ¥î]ìzêéèçyçîçÚè6êøëî}ð!óïõÖøÄû¦þjay@ ¯ Á u Ë Ç p Ì è Ï 4ÍjÞÏðIàÿµÿÊÿ¤_BBTiuj<ÝC e ; ÁóÓb¦¨sÿýúøwõÿò¬ðŽî¶ì0ë êNéé0éÓéïê|ìvîÒð‚ózö§ùùü[»)  °ö×LLÕæ®rÚòÉo ó iàhìýüXúüøñ÷:÷Ôö¾öñög÷øïøêùøú üýþçþ“ÿ LN•ÿÜþíýÏüŒû0úÈø`÷öÍô¾óèòUòò!òŽòYóƒôöå÷ú€ü'ÿöÞγ | oz'l>—tÔº+0Ô&3 Êx.þýúö÷,õ¬òƒð½î`íqìòëâë<ìúìî{ï%ñóõ÷6ùEû:ý ÿ¥&þÔÕ— {³Óè)ÿmþØýuýKýaý¹ýWþ7ÿV°:ê´‹_ !  4gPãçNKß ä g¤«ÿYü$ùÿõÿò4ð°íƒë¹é]èxçç$ç¶çÁè?ê%ìgîøðÇóÁöÖùóüøÀJ‹ x 5ý``TY µ ( †ßAºUZÿÕþ“þ’þÏþCÿçÿ°•‰~h9ä_ žT¾Ú¬6€“þyü@ú÷÷­õróWñmïÂídì`ëÁêêËê|ë ì4î0ð‹ò:õ.øWû£þÿXœ· —,h=¢‘þ~Š*iTùh ´ í%mØþpüFúcøÐö“õ¯ô%ôóóô€ô/õö'÷Wø–ù×ú ü+ý%þñþ‰ÿåÿâÿ„ÿëþ þ*ýüéú¶ùŠøp÷yö¯õõÓôÔô(õÓõÕö.øÙùÏûþs ¹p ´ J+³ÕˆÅ‰Ò£ô‡Ç Ä ;ÛÿüAù-öWóÎðŸîÕìxëŽêêêŠêdë ì2î ð!ò`ô¸öùqû³ýÐÿºhÑðÀBvc Âãîð÷F¦ÿ6ÿÿþÿOÿØÿž Ô2¯=ÐX È  $öz©zêö   ì à…çþûøõ+ò„ï#íëlé/ègççLçûç#é¾êÃì%ïÖñÆôä÷û^þ’ª”> £G„V»¸OŠqy µ Õ é)qäÿqþ˜ýý¶ü«üàüMýéýªþ…ÿlS-í‡ð »;­ÿþEüXúYøSöYôxòÁðBï î%íì{ìÃìzížî,ð òpô÷ôù ýCŒÓ ÖW~>ŽeÀžëh€@¸ø  )]ýÀúbøOöô,ó(ò…ñAñYñÆñòzóªôös÷ïøhúÐûý<þ,ÿäÿ]–MÑÿ$ÿOþ\ýWüOûOúfù ø ø­÷”÷Ä÷Døù4ú£ûXýNÿwÊ8°" } ±®cÃÃY},e({eò - &í–4þØú–÷‚ô­ñ&ïûì8ëæé é¦è¼èGéBê£ë`íkï´ñ,ôÂödùü‰þë¸ Î , 9 ú y ¾ÖͱŽtm‡ÌDöÿäÿ~&?‡Ü.q — R Ð  ß c Š U ÈçºN¯ÿêüú4÷fô¹ñ>ïí ë™é}èÔç¤çðç¸èùé¬ëÈíAð óöGù˜üðÿ<kj ( —«Y›l˺>]#™ÏÓ ´ „R-%Fþ0ýü*û–úLúIúˆúÿú¦ûrüUýDþ1ÿ ÐkÖü®J:ÿñýzüÞú*ùk÷°õ ôƒò/ñðLïÖî½îïºïÓðRò1ôiöïøµû­þÆï' ¾",ÑÀÀÑ,"¾' ïÆ­þµûïøiö1ôRòÓðºïï½îÖîLïð/ñƒò ô°õk÷*ùÞúzüñý:ÿJ®üÖkÐ 1ÿDþUýrü¦ûÿúˆúIúLú–ú*ûü0ýþF%-R„´ Ó Ï™#]>ºËl›Y«—( j k<ðÿ˜üGùö óAðÈí¬ëùé¸èðç¤çÔç}è™é ëí>ï¹ñfô4÷úêü¯ÿNºçÈU Š c ß  Ð R — q .܇?&~äÿöÿḊmtޱÍÖ¾y ú 9 , Î  ¸ë‰þüdùÂö,ô´ñkï`í£ëBêGé¼è¦è éæé8ëûì&ï­ñ‚ô–÷Øú4þ–í&- ò e{(e,}YÃÃc®±} " °8ÊwNÿXý£û4úùDøÄ÷”÷­÷ ø øfùOúOûWü\ýOþ$ÿÑÿM–]äÿ,ÿ<þýÐûhúïøs÷öªôzóòÆñYñAñ…ñ(ò,óôOöbøÀú]ý) ø ¸@€hëžÀeŽ>~WÖ  ÓŒC ýôù÷pô ò,ðžîzíÃì{ìì%í îBïÁðxòYôSöYøXúEüþ­ÿ;» ð‡í-Sl…ÿªþéýMýàü«ü¶üý˜ýqþÿäq)éÕ µ y qŠO¸»V„G£ > ”ª’^þûä÷ÆôÖñ%ïÃì¾ê#éûçLççgç/èléë#í„ï+òõøûþç…àì   ö êz©zö$ È X Ð=¯2Ô žØÿOÿÿÿþ6ÿ¦ÿF÷ðîã cvBÀðÑhºÐÿ³ýqûù¸ö`ô!ò ð2î ìdëŠêêêŽêxëÕìŸîÎðWó-öAùüÛÿ;Ä Ç ‡ô£Ò‰ÅˆÕ³+J´  p¹ sþÏûÙù.øÕöÓõ(õÔôÓôõ¯õyöp÷Šø¶ùéúü*ý þëþ„ÿâÿåÿ‰ÿñþ%þ+ý ü×ú–ùWø'÷ö/õ€ôôóó%ô¯ô“õÐöcøFúpüØþm%í´ h ùTi*Š~þ‘¢=h,—· œXÿ£þWû.ø:õ‹ò0ð4î ì|ëËêêÁê`ëdìÂímïWñró­õ÷÷@úyü“þ€6¬Ú¾Tž _ä9h~‰•°çÿCÿÏþ’þ“þÕþZÿUºA߆( µ YT``ý5x ‹ JÀøóüÖùÁöÇóøðgî%ì?êÁè¶ç$ççxç]è¹éƒë°í4ðÿòÿõ$ùYüÿ«¤gä  ßKNçãPg4 ! _ ‹´ê:°V7ÿWþ¹ýaýKýuýØýmþ)ÿèÓ³{ —ÕÔþ&¥ ÿ:ýEû6ù÷õó%ñ{ïîúì<ìâëòëqì`í½îƒð¬ò,õö÷ýú.þxÊ3 &Ô0+ºÔt—>l'zo| ³ ÎÞö'ÿ€üúå÷öƒôYóŽò!òòUòèò¾óÍôö`÷Èø0úŒûÏüíýÜþ•ÿNL “ÿçþþý üøúêùïøøg÷ñö¾öÔö:÷ñ÷üøXúüìýhàió o ÉòÚr®æÕLL×ö° ) »[ùü§ùzö‚óÒðvî|ìïêÓé0ééNé ê0ë¶ìŽî¬ðÿòwõøúýsÿ¨¦bÓóÁ; e C Ý<juiTBB_¤ÊÿµÿàÿIðÏÞjÍ4 Ï è Ì p Ç Ë u Á ¯ @ yaj¦þÄûÖøïõ!ó}ðîøë6êÚèîçyççèézê]ì¥îCñ(ôC÷ƒúÔý#]pK Þ ûqz<ùPJñS} € j L55X¬ÿ8þýüvûûû5ûû7üøüÓý¼þ§ÿ„Iê]—”OÅøìÿ£þ'ýƒûÁùï÷öXô°ò4ñóïùîRîî î î‹ïÞð–ò«ô÷Èù´üÊÿø-V _ 6Ê íaaæîw†!P!ŸÜ è Õ·Ÿ¡ýÌú0øÛõÙó2òìð ð‘ïzïÁï_ðKñyòÛódõ÷¯øTúæûWýžþ°ÿ†s‡\÷`¡ÿÃþÓýÞüñûûcúÛùŠùzù±ù2úûü}ý"ÿÿ <Ç  %ÒAY\8¢˜9ó W rT·þ[ûøìôýñVïíë™éèÿçëçPè+éuê"ì'îvðýò®õuøAûþ¢TKôG B â )  Á E ; ÑŒP(!E.þÿ Xß›„‘µå00  £  Ó ? S {˜rˆýàú,ø|õâòoð5îCì¨êoé£èKèlèéê¤ëšíòï ò–õÁøüpÿÍ5  ¸ýßVZé¬èÀ?rg. Ø uÉŸ¥þåühû4úOù¸øpøqø·ø7ùêùÂú´û²ü¯ýžþrÿ Ÿçó¾H”ÿ£þ~ý-üºú2ù¢÷ö¤ôSó3òRñ¼ðxð‘ð ñåñ#óÀô·öÿøŒûRþ?FST 7 ê[{;‘sÛÆ3&£µfÄà É”RÿöûÿøCöÑó´ñøï¢î·í8í$íwí(î0ï‚ðòÏó¬õš÷ˆùhû,ýÈþ1_LóUrOña©Ôïÿÿ(þ`ý»üCüüüBüËüšý¯þN0)+ & ÌVž–4n>¡—!E | ¨k&ýÞù©ö—ó½ð*îîëê­è»çDçJçÍçÈè4êì6î±ðgóIöDùEü;ÿ¾.U + ¦  |×ÔzÑ ã ½ k ü:  @´ÿgÿ[ÿÿùÿ—aKKRTCµ!L/Ä þ¥ÿ»üVúâ÷põóÕðÍîí”ë~êÑé’éÉévê˜ë,í*ï‰ñ<ô5÷dúµýu¾Þ à ]žzæÞ\að ÁÜj × 4‘‘ÿQýLûùøþö6öÃõ¢õÏõAöïöÎ÷Òøìùû1ü@ý1þûþ”ÿõÿþÿ¤ÿ ÿ@þBýüÝúù;øõöÉõÅôöógó#ó1ó—óYôvõîöºøÓú/ýÂÿ|P*û ¯ 4|tES"vP¶±K’ — iÃrý:ú.÷_ôÜñ±ïëíì¤ë+ë"ë‡ëRì{íõî´ð¨òÃôôö*ùWûjýXÿ‘ÍÀhÆÛ­D¨å(EzÿÒþYþþþJþÈþˆÿ†¾'¸dØ ƒ  n“pû*ö]\õ - —àôãþ¾û—øõòÓï^í?ëƒé6è_çç'çÇçáènêcìµîUñ3ô>÷cúý¯²‡ k a ø*õWUó92é k Ç Kéd êÿÿ`þþýßýþ[þêþ¢ÿw`O6 º?Žgç °HþLü0úøÔõ³ó°ñÛïDî÷ììoëEë‹ëBìjíÿîüðVóöóøü^ÿ´D W /»í¹÷_J¼¸HuLÝ8 n ‘²å9þ½û~ùˆ÷äõ™ô©óóÞòüòióô õ)öh÷»øúbûœüµý¢þ[ÿÚÿàÿiÿ¼þâýæüÑû²ú•ù‡ø—÷ÑöAöñõëõ4öÑöÃ÷ùžú~üžþòo¥= » &ôj|!Q HeQÞ  Ú‚ ÿÄû‚ønõ˜òðäíìÇêåéyéƒéêêê7ìÛíËïöñLô¾ö9ù­û þBH”ʯDˆ4«ï ÿ$jßÿŠÿqÿ˜ÿþÿ£‚•Ó2¥‘ î & - ö u¢ué ü °  ½0o‹ý‘ú–÷ªôáñMïýìëgé9è€çBçç=èréë,íšïWòTõ}øÁû ÿLm_ v (f6—I"±( / (",U¨0ÿöýþüMüäûÁûàû;üÉüýTþ9ÿ!Ërí2:ÿº±kÿîýBüuú“ø©öÈôÿò]ññïÈîðíríWí¤í\î€ï ñûòEõÞ÷¹úÆýô2m‘ MÁÜÑ›é¸ çT[ qŸ ¥—‡ˆÿ©üüùŽ÷mõ¢ó4ò)ñð;ðUðÆðˆñŽòÍó7õ¾öRøæùlûÖüþ+ÿ ûð‘ÿÿ@ÿaþlýpüxû“úÍù2ùÎø¨øÊø7ùòùüúQüìýÆÿÔ ]º U rYûJ;Ä݃´qÀ¨2 m f/Úzý"úäöÕóñ„î`ì¥ê[é‰è1èTèíèøéjë:íXï·ñFôóö­ùcüÿ~ÆÏŽý × @ U  š Ý îÚ¯zI*(O¦5 WÜ™†™ÇCuŽ ~ ; ¸ ë Î Z g ê«"ÿtü±ùëö3ô›ñ4ïí;ëÆé¹èèýçUè)étê1ìVîØð©ó¸öõùLý©û/1 ñ bu"`,ƒiáò¦ + à •Fßãÿþ“üPûXú­ùNù:ùjù×ùxú@û&üýþüþÐÿPa2Â"ÿûý¤ü'û‘ùî÷Mö¼ôJóòüð:ðÊïµïð°ðÅñ=óõ@÷¹ùrü[ÿe~•– n a]òÅõ¨ÞœéÑ^¡ ª ‹Vùýôú"ø’õQókñæïÊîîÏííílîCïgðÎñgó&õúöÕø¦úbüúýcÿ”ˆ9¥ÎµaÚ(Vsÿˆþ¤ýÕü%ü¡ûSûCûvûñûµüÀýÿšZDKav { `Œ·ŠûžÉ†×Æ Z  §:ÿéû¡øtõvò·ïGí6ëŽéYèžç_ççUèéëí[ïéñ«ô÷~úmýEúz¸ª F ‡ j í â a ˜ ” a ¤8Õ‡\]“´ÿ£ÿÑÿ9×¢–§·¶™RÖ  Ç%/éU{dþ®û+ù¢ö%ôÄñïšíðë êµé7é-é›é€êÛë¤íÔï_ò8õOø’ûïþR©áæ ©*ÑÆ Ü9)·îÝ’  ”z Èþ¹üêúdù.øK÷»ö}ööãöw÷>ø-ù6úLûbüiýWþ ÿ¹ÿC+Õÿ@ÿrþqýEüúúœù8øÜö•õsôƒóÐòfòNòŽò+ó&ô~õ/÷2ùû þœ†n A îd‘hÛàp„8ÜÞR{ i /ߎÿLü.ùCöžóJñTïÄí¢ìïë¬ë×ëjì]í¥î7ðòüóö1øNúYüCþ„Ê˃ñû¡\‡Ÿ³ÑÿÿWþÖý‹ý|ý®ý$þÝþÙÿ|̘h / Ý b°ºuÕÔkš`À À j ÉêÞµý‚úV÷Fôcñ¿îjìsêæèËç+ççbç9è…é?ë[íÍï„òpõøžû»þÂ¥Q¹ Ñ íæy§uéí ”  p Ä«ˆŸÿõþŒþeþ~þÓþ\ÿæÑŵ“RçGiEØË8kÿkýFû ùÄö†ô`òcðîíòë%ëÁêËêGë7ì—ícï“ñôñöú?ý”ñ@o k #‰&Kö&ÛçN[› ñ +\•éÿdýû ùN÷äõÓôô¿ó¹óô“ôcõdöŠ÷ÈøúQû‚ü•ýþ8ÿ¹ÿýÿÈÿRÿ¦þÊýÈü«ûúRù1ø*÷JöŸõ1õ õ6õµõ‹ö·÷8ùûýkÿê‰:é ‡ HJùH-Ÿ™ ±Óô  í¤Fæý—úl÷wôÇñmïsíãëÄêêåé$êÑêäëSíïñDó˜õý÷bú·üîþ÷ÉZ¢I¥¶‚g—©¬¬¶Øÿ7ÿÿ;ÿžÿ?4xàaíw ï H r b a_þ: Ž ­ yüEaÿaüVùRöió«ð+îùë#êµè¸ç5ç.ç¥ç˜èêÙëî¥ð|óŠö»ùýü<gk7 ½ ï Ã26Îú¿!,èd­ Ó åò :ÖþÖýý¥üuü‡üÕüXýþÕþ·ÿŸ‚Q†Öê»G‹ŠHËþýEûTùV÷[õqóªñð½î³íí°ìÇìJí;î˜ï\ñóüõÀø¾ûèþ)pªÅ ¬P ²Ç`~*lPä8 \ c`d‚þÈûGù ÷!õŽó[òˆñññKñãñÃòÞó)õ”öø•ù ûnü¬ý¼þ—ÿ6–µ–:«ÿíþ þý ü ûú?ùøøÚ÷ã÷9øßøÕùû©ü{þ‡Âþ ` £¶Š;X<ª¢(AøW m Jÿ ÿ?üïøÄõÐò$ðÎíÚëTêAé§è‡èßèªéàêwìcî–ðóõ3øÛútýðÿ?V(®ãÁ J  d  a ŒwQ-B™'ñÿùÿ?ÄqŠÂ \¤Õ â ¾ ] ³ º i ¿ ¸ W  ›PËþOûwø¥õëò[ðîüëKêÿè#è½çÑçbèméîêÜì.ïÕñÃôè÷0ûˆþÞ7 ­ íÌAFÚü¯ùäzÈÜ Æ – \( Dÿ³ýcü[ûŸú-úú!ú|ú ûÇû üŒý}þfÿ9íuÈá¹O¢¶ÿþ4ý¯û úXø öóôaó÷ñÅðØï:ïöîï“ï{ðÉñzó‡õç÷Žúmýu–½Ö Ñ ™Q$Š|óëggóÕDq m K÷ÿêüú^÷þôòòCñøïïšî…îÒîyïqð®ñ"óÁôzö?øú±ûBýªþÞÿÕŽ5&ÚZ­ßÿûþ þ#ýJüûýú úú¢ú ûÃûÂüþÿO>Pw¤ Ç Ï ®S°¹b¤xÛÍQl' ¬“Tþ¬úi÷KôeñÆîìœê'é(è¥çžçèüèVêì-îð+óñõÍø¯û…þ<È"Ü > E ï = 3 Ø 3 P ;  ¯Uÿ»–šÐ?ìÿØÿgÑÃÐì 〠à ù Å > b2±åÖÿýúó÷[õØò|ðWîxìïêÆé é¾èëè‘é¯ê@ì<îšðNóGövùÉü*ŠÓô Ù t·•‹š6d,˜·–E Ö YÞv1þ@üªú_ùcøº÷a÷V÷‘÷ ø¾ø˜ù‘ú™û¥ü¦ýþWÿòÿW‚o‰ÿ»þ·ý†ü2ûÆùPøÝö|õ;ô)óQòÁñ€ñ˜ñ òáòô¨õ‘÷ÊùGüúþÖÊij ƒ #ƒ’Bˆ[µ’ñ×HMòDT 2ñ¥`þ5û5ørõùòØðïÂíØì]ìOìªìhí}îáï„ñXóNõW÷bù`ûDýÿþ‡Õà¥"XKÿÒ"9Vÿ„þÒýJýõüÛüýoý!þÿJ¸VôÙº ˆ 2ªâÌ_’]¾³@h 3 ­áß¹ÿ~üBùöóEð¿íëÅéiè„çç/çÁçËèGê+ìjîöð¾ó²ö¿ùÓüÚÿÃÿ4  › ¿ÜØzÉÐ œ 8 µ ‡ù„3%wÿ ÿÛþîþ=ÿÂÿsJ82+ä‹þ4&Í'2òi¡¢þvü-úÔ÷|õ6óñïmí ìëeê2êrê'ëOìçíèïIòýôõ÷"ûrþÐ,qŒ l: q^ÒÊKXû?/ÛT © î3Šÿªüú»ø6÷ö0õ±ôˆô¯ô õÐõ¶öÃ÷ìø"úWûüŒýsþ,ÿ®ÿõÿüÿÅÿQÿ¤þÆý¿ü™ûaú$ùï÷Ñö×õõô;ôDô¢ôYõhöÏ÷‰ùûÖýQö³w1 Ð At[æ ¾û¾Õ1"´ô ñ ¼i ´üxùhö–óñèî#íÊëäêrêsêãê¼ëõì‚îUð`ò”ôßö1ùzû«ý¶ÿŽ)€MÀçÈjÖ6CKZ}Âÿ0ÿÓþ¯þËþ(ÿÇÿ£ºsŸ? Ó K ™ °ƒ0üdh I 1 Ê!CBþ,ûøõ.ò‚ïí ëaé"èZç ç>çíçé¯ê³ìïÁñ®ôÇ÷úú4þaqRô I FãäE>Ôû¡ U ‚ ¤Ìaè¥ÿŸþÚýZýý%ýiýãýŠþTÿ3Ù“#¢‚lt9¿ÿþ0ü2ú"øöôò]ðØîœíµì-ì ìYìí>îÔïÎñ&ôÎö¸ùÖüc®â ì º<d$sJ¥ƒåÒQl2¯ö  &3Q‘ýû°ø©ö÷ôžó¥ò òÎñëñ[òó ô8õˆöï÷^ùÈúüWýeþ@ÿâÿDhMöÿhÿ©þÅýÆü¹û©ú¦ù¼øø÷f÷÷÷>÷Ë÷ªøÛù[û"ý)ÿcÇCÉH ® ë益Êx­m½£,d Z ÇdþûÇ÷µôâñ]ï5íuë%êKééèÿèŠéƒêáë˜íœïÝñKôÖöjùùûrþÃäÅ_«¤J œ Ÿ Z Ô0+üíö xÊÿÏÿ•RDc¤û]º / + ì h ” i ä ¿ $ 6ûÔÿýú6÷^ô©ñ'ïéìÿêuéWè­ç}çÊç“èÔéˆë¤íðæòìõùmüÁÿ2* â KX= fS×øÁ={ˆ v S1'[ÅþkýWü‹ûûÎúÙú#û¤ûRü!ýþòþÙÿ®eóNoPîH`:ÿÝýRü¤úßø÷Jõ˜ó ò°ð—ïÊîTî?îîGïiðññÚóö«ø{û}þžÐý ´';ý¾Ð-%Ä6 , ìÝþïû3ù¸ö‹ôµò@ñ.ðƒï>ïZïÒïð°ñÿò}ôöÇ÷wùû¤üþ;ÿ6ôpª£_ä;oÿŠþ—ý¦üÃûûúZúìù¹ùÊù#úÈú¸ûóüsþ/ ;p±ï  ñ€¿¡,Êõ®úál ¨ ¤pÄüqù:ö1óhðïíÓë"êâèèÏçÿç§èÂéEë'íZïÍñrô5÷úÓü‹ÿz˜kë  à S n 7 ¶ ó ü Ü X×¹À÷d÷ÿìã÷Jmzc  ™ Ñ » Q ’ |WT¢þ ü`ù²öôñ=ï,íkëê é~èhèÍè«éëÅìòî{ñRôg÷©úþeºðó µ $6ßÝ,rthsH ø “)̉qÿýéûú}ù¼øKø&øJø®øJùúúúöûøüóýÚþ¡ÿ<¦ÖÇxéÿÿþàüƒû úƒøúöõ ôëòîñ5ñÊð·ðñ­ñ»ò*ôõõøú(ýú ö ½Kz´×|¤T•oï% ! õ´q?ý/úT÷»ôtòˆðïâí1íììí™í}î±ï)ñØò®ôœö’ø‚ú\üþžÿïÒ\ŸŸaëH£¼ÿ×þþGýµüVü0üLü­üTýBþqÿÝ~I2*%  Þ äÆ-.Äí©ýï ˆ ÕãĈþBûøâôîñ:ï×ìÑê6é è_ç.çzçAè|é$ë-íŠï+òÿôõ÷úúûýç®?Ž 8 ƒ möìf• … B Û ]ØY—æÿrÿ@ÿMÿ—ÿÉ “”˜n(°ýÄ3S#¨çìÿ¾ýkûù”ö0ôçñÉïèíPìë5êÄéÆé=ê*ë‹ìYîŒðóôõ ùOü«ÿ a– ˜ VÁÌl™NŠM›{÷ö• f»“6þü(úŒøB÷Nö¯õfõmõ¿õRö÷ø&ùLútû’ü™ý}þ5ÿ¹ÿ Øÿfÿ¹þÙýÌüžûZú ùÄ÷Žöxõ‘ôãó{óaó›ó0ôõiö øüù6ü¬þOé» y tT·­-4¿Ïh’VÀà Æ„,ÔþŒûhøyõÐòzð„îõìÕë(ëìê!ëÀëÁìîÀï¢ñ²óáõøWúü‡þagƒUÛ À=Œ¹ÐÞñXÿÂþ^þ4þIþ þ9ÿ)tì†4é— / ¡ ßÜŒæáx¨rÙ â –./ýðùÔöÒóþðiî$ì;ê¼è°çç çrçWè²ézë¦í'ðíòéõù6üaÿwg ” µ |ßÛo›dÐéºO ¶ ÿ 9r¹¥`VÿŠþþ¼ý¹ýôýfþÿÍÿ«—ƒa%Â/`PùXm:Åÿ4ý-û ùãöÀô³òÌðï­í‘ìÒëxë‹ëìídî1ð`òçô¸÷ÅúüýK¡é ´ ˜²QtJ^Wq ± ÕðRÿ¸üVú8øiöðôÒóó­ò£òìò€óVôbõ—öæ÷Cùžúêûý%þÿþ¢ÿ0Äÿ7ÿxþ‘ýŒüuûXúEùGøm÷ÂöRö'öHö¹ö÷™øú¾û»ýóÿXßv ” ø)´òÈ,1èG \ 8ì‹*ýÚù®ö¹ó ñ³î½ì2ëêxéNé™éSêvëøìÊîàð*ó–õø•úýWÿ|it„C±Ð¥8“ÁÎǹ²¿ìBÌÿÿÿÐÿP $mÑCµ a ~ c YWù ;  £ Ï«?™ÈþÚûâøñõóoðîàëê¼èÏçZçbçæçæè\ê@ì‡î$ñô ÷\ú©ýò&3 ’ Ê¡©ÐŒãàŒô' 5 , (^ÆÿfþGýnüÝû“ûûÊû=üßü¥ýƒþlÿR*ç|à öÿüÿŸþýXû„ù£÷ÃõòóAò¾ðxï|îÕíŒí¨í.î ï{ð;òZôÍö‰ù~üœÿÒ< J %¼ÿáWWÜãm}K¡ã ö ëÖÈÔý ûyø0ö8ô›ò_ñ‡ðððKðêðÔñýòYôÙõn÷ ùŸúü}ý¯þ¬ÿmï//ñ{Öÿ ÿ"þ+ý1üCûmú»ù:ùôøïø4ùÆù¥úÑûFýýþí LŸõ > jg'šµm¸“ùël‚7– ¬ŠAæþˆû<øõ(ò‚ï2íGëÉéÀè1èèƒè]é£êMìLî”ðóºõuø5ûçýzá÷‘Ö Ä Y — ƒ # € ¥ ŸyC ÛÄÏs$†"òí ;v¬ÏÒ § B š ¥ \ ¼ à rÍÛ¥7žýèú'økõÇòLð îìtê9élèè5èÒèèésëjíÄïsòiõ”øâû@ÿ›àüÝ u¶““«S‘lï)'ø ® Y εÎþ ýµû“ú¾ù7ùüø ùXùàù–úpû`üYýOþ3ÿúÿ˜;2è]“ÿþSýïûjúÒø4÷Ÿõ"ôÊò§ñÅð/ðïï ððqñ¹òaôcö·øPû!þ*@J 3 ìa„GŸ‚êÕB4³ÅxÙø æ¶zGÿ-ü?ùŒö"ôòZð ï'î­ííðí¢î¦ïóð{ò0ôöá÷ÀùŽû@ýÈþ5¡ðüÉ]Â&?ÿVþ{ý¹üü°û}û‹ûÞûyü]ý…þîÿ_S]n v g /À ¥Ýª ø|˜V Á åÓšPýúÊöµóÙðEîì0êÇèÕç^çdçççáèKêìEîºðjóDö5ù+üÿá€ãþÇ 6 H ù LDæ < P . ä  ž>úÝò>Èÿ‘ÿšÿàÿ^èßè÷ýí»Z¿à¸@v[ð<FÿÂüMúË÷LõâòœðŒîÁìIë1ê‚éDé|é+êQëèìêîMñô÷1ú„ýæEެ 'f>¨ž®Í„Þè±J  +–µÿ…ý‘ûâùør÷·öPö9ömöåö•÷tøuù‰ú¥û¹üºýœþSÿØÿ#1‘ÿåþþòü»ûkúù±÷cö1õ+ô[óÏòò¤òóàó õŽöhøúùüšÿaA' ¾ K˜•5k/zJvÛÕo· ¼ ‘Gò¥ýrúl÷£ô&òðAîëììŽëˆëîë¸ìÝíRï ñôòõ'÷NùjûlýGÿîZ‚cúGN¡þ6Vj¤ÿâþGþÝý«ý·ýþ˜þmÿÎKî«u< ò ‡ ìó}©qÑÉY‡ Z Ý& ÿßû°ø”õòÝïdíCë†é8è`çç(çÈçâèmê`ì¯îKñ$ô)÷Fújý{FÓ Ž¸{ØÒnµ°l ö \ ®ûP»Júÿ)ÿ™þLþAþtþßþ{ÿ> þåµaÝ "ÝMqKÞ2PþBüúØ÷›õnóañ„ïæí–ìžë ëãê+ëæëí­î°ðóÃõ¹øâû-ÿ‡Ý 1 •Ç‘ëÍ5 ’"S0È+ k ™ÇhþúûÊùâ÷Lö õ)ô ópó”óô¹ô¦õÀöø÷AùŒúÍûöüüýÕþyÿâÿ ùÿ¦ÿÿ[þpýdüCûúõøã÷ñö,ö õWõZõ®õWöW÷¬øRúAürþÖb´W ß ;Z-§»`G„J‡K B ²Pÿöû·ø¦õÔòPð(îfìë3êÉéÔéQê9ë‚ì"î ð,òxôÝöJù¯ûüý#Î?d:Àøæ’Dbhefw¥ûÿ‚ÿ@ÿ<ÿxÿõÿ¯¤ÌŒ• w ¶ À ‰.úfp  d Yhšªý¦ú¡÷­ôÝñBïîìîêRé"èiç*çjç&è[éëíï<ò6õ[øšûàþ3È % (ÈÿÉ'§×³H¢ Ñ ä ëõL³Pÿ)þFý¨üRü?ümüÔülý*þÿêÿЬn z±§ZÇíÐvÿäý&üGúTø\önô›òðð~ïRîxíûìâì3íñíï¯ð§òùôš÷~ú“ýÈ Mv u 8®É}ÀŠ×§úØFQp¤ ³®§³ÿàü>úÝ÷Èõô¥ò£ññÄðâðUñòóTô¶õ2÷ºø?ú´û ý:þ7ÿûÿ€ÆË“!~ÿ²þÇýÊüÇûÌúçù#ùŽø1øøEøÀø‹ù¦ú ü»ý§ÿÆoÛ@ Ž µ£Kž‘2Ö½ëq § b ©ýPú÷ô4ñµî“ìÚê“éÂèkèŽè'é/êžëiíïØñ]ôÿö­ùUüæþRŠƒ3“ž S ± ½ } ø 9 L<íɹÈmõÿuááBŒÔ +  Ù R € Z Ü  Ð EhAÚCÿ‡ü·ùåö#ô‚ñïéìë˜éŠèïçÍç&èûèGêì,î¯ð€óŽöÊùýyÇöó ® 'ÏÐ& ‚•M·ßÖ ª l-üèÿÿJþÔü£û½ú"úÓùÌùú|ú#ûïûÔüÆý¶þ™ÿ`v²¯læÿßýuüæú?ù÷ßõCôÊò€ñtð±ïCï2ïƒï;ðXñÚòºôòövù9ü.ÿAc‚‰ h caøÌý¯æ¤óÜl³ À §xI+þ/ûføàõ©óËñOð:ïŽîJîkîëîÀïâðBòÓó‡õO÷ùÛú„üþ^ÿzXõMc9ÖB…­ÿÄþØýõü*üûûÅúÃúû“ûjüˆýëþ‰]Yq–¹ Ê ¹vò!õfl*à,  àà²hÿüÇø˜õ—ò×ïgíVë¯ézè¿çç¾çuè é4ë(ínïõñ®ô‡÷núQýÄ7hL Ü  é c ƒ M É ÿ Ñ „'Èt8 6ÎÿÓÿ’B,F[^Aøw ´ § J š–?›°ˆ/þ²û ùŠöô–ñZï]í®ëZêméïèæèVé>ê›ëgíšï(òõøaû¿þ!x­° pÝëÂÄ“ðãu²¨f þ û‚$ñþòü5ûÀù™øÅ÷B÷÷)÷†÷øçøÕùÙúèûôüïýÎþ…ÿ Zl?Óÿ(ÿDþ/ýñû–ú)ù¸÷RöõÞóìò:òÓñÀñò®ò³óõÕöæø@û×ý„xj F ûw©„ù¤;Wû.üqœ Œ V ½ÿüiù†öçóšñ«ï"îíWììDìÖìÇí ï–ð[òIôQöcøpúiü@þêÿZz|“im°×ï)ÿdþÃýPýýý\ýæý´þÄÿ<áÀ “ J ×+8óQMßÅ µ " Ýý¢úp÷[ôtñÍîvì~êïèÕç4ççkçAèŒéDë]íËï}òcõkøû•þ’i g t ( |mø!ì_…h  š  fËB×–ˆµÿÿÌþ¹þæþLÿäÿ¥…yrc@ûŠàöÅH~g`ÿoý9ûìø˜öNôòðIîbaresip-1.0.0/share/sound2.wav000066400000000000000000001047741372575704200162210ustar00rootroot00000000000000RIFFô‰WAVEfmt D¬ˆXdataЉšl u "b'gIì¿ý² < ²*¸qgÿ¦ý:ü+û}ú-ú:ú™ú@û ü*ýKþpÿ†}BÈévª†ÿVýbûEù÷Þô¾òÈðï§í¡ì ìñëXìDí³î ðóÆõàø9ü»ÿMØB t VÕákkܾèD9Ø8 o ’ºünÿý!û~ù>øf÷ööéö7÷Ö÷¸øËùÿú?üzýœþ•ÿSÎûÓV…ÿeþýcûùÀ÷àõôgò÷ðÓï ï®îÄîUïdðîñíóWöù2ü}ÿç\ ÿ ý¦æ­ï£ÅUX×ßÏß É¤ˆÿÅüDúøTöøô ô’óƒóØó†ô€õ³öø€ùòúRüŽý—þ`ÿÞÿ äÿjÿ¡þ“ýKüØúKù¶÷-öÄôóŸòòÊñþñ£ò¾óLõF÷£ùUüLÿq±ó Ù:.¦—øÆ³à™îô À k ¿ÿ–ü©ù ÷Ëôøò˜ñ°ðAðGð¹ðñ³òô²õd÷ùÉúUü²ýÐþ¥ÿ)Y6Ãÿÿ þáü—û?úíø´÷¦öÖõRõ(õaõö÷Žømú§ü.ÿñßáà Å xãó”¸UcàÍ0‰Ÿ k þÿüPùTö°órñ¨ï[îŽíAíqíî!ï†ð2òôöøúü³ý)ÿT.±Ü³<’ÿzþNýüûú=ù¹ø‡ø¯ø9ù'úxû&ý)ÿró™O ÿ ‘ñÃâ/ð#Ëî˜Ø À dÝC°ü:ùúõórðMî¤ì~ëàêÊê6ëìoí ïñOó£õø[ú”üœþdàÑ>Q‚¸¾§†ÿkþjý•üûû©û«ûü¾üÓý?ÿù÷)}ß 9 vD­¬4:¹°"˜ · †‰ïübùûõÓòþïí˜ë#ê7éÚèé¾éòê–ìšîëðsóöÓø|ûþZk+‘.jJÖ)㵘 ÿÚþUþþ7þ©þrÿŽ÷¡}z… Š t /¥ÆË™èµß N c/ÉHýÂùSöóðsí>ë…éTè±çŸçè&é­ê¥ìþî¢ñ}ôx÷yúlý9Í ˜¾ w Æ ° > | zIû¤W%!XÖÿ£ÿÃÿ7þaçHþ ž  H/¸Õ±j ­ ƒ øú±ýTúúö¼ó³ðõí–ë©é<èYççIçèvéQë›íCð5óYö—ùÙüÆ6F ê  Û &{ œ t  “qø§Ž¸.øÿ„?=rÍ>± R Z  ‚ ‰ $ P [DÓ%þ ûæ÷ÊôÏñ ï›ì‹êîèÔçEçGçÛçÿèªêÑìeïRòƒõáøTüÃÿ6 £ FoJSBá C { žÁöPà²ÒÿEÿ ÿ*ÿ–ÿI8T‹Í!½ $ ÈÚK]šþâû ù.ö]ó±ðAî!ìeêéUèèkèLé¹êªìïàñõbøèû{ÿe f Ýãmvùú~<”ª ’ b . IÇÿ“þµý1ýý1ý©ýdþRÿc‡«»¥YÇå¨ ·ÿËü_úØ÷KõÎòwð\îì'ë0ê¸éÅé^êë*íPïçñÞô!ø›û2ÿÎW´ Î èÈ%ùCB gm/ < ³<ìÖÿþ‰ügû¥úCú>úú'ûýûýþCÿ][+¿ŸãÐjÿ»ýÐû¸ù‡÷Põ)ó&ñ]ïâíÅììàë,ìüìOî"ðkòõ'øtûðþ„ Ä ¹Ou:ËË?.£­_Ë 1W“ûÿŸýûÙù…ø˜÷÷òö/÷¿÷“øžùÌú üGýoþpÿ;Äè{ºÿ¨þOý»ûúùø<ögô²ò4ñþï!ï«î¨îïð„ñkóÀõvø{û½þ#™ M [qS³†Èw˜3T i† w U62_ýÏú“ø¸öFõDô±óŒóÍójôTõ}öÑ÷>ù°úüXýlþAÿÎÿ óÿˆÿÎþÌýŽü!û–ùøröõ½ó½òò¿ñÛñiòkóáôÆöù³ûþ»ø=q }H¿Ì`oðÞ:Q!‹  x )ËxGýLú÷Iõ^óæñåð]ðJð¦ðfñ|ò×ódõ÷Éøwú üpý›þÿS?Úÿ+ÿ:þýÒûzú%ùä÷ËöìõWõõ>õËõÄö)øõùü—þP89< ) êgŒGˆCp ™˜#L& ÈJÄQýúûöBôîñ ð£î»íSíiíôíëî>ðÜñ²ó«õ´÷¶ùŸû\ýÞþ–Ò¸P¡ºÿ©þ~ýNü*û%úRù¿ø{ø‘øùáùû»ü®þëcºo x¡rÙÇ1b'f)~w )©zýüù¯öªóñÂîþì¼ëëÍêëêë&íÄî°ðØò&õ…÷Þùü0þǤ#G—ØæÓ³ÿ•þý®üü¦û—ûàû†ü‰ýåþ‘„®þ` ¿ óq‰+MêþŒš3e CáW¼ý*ú¹öó™ðîìoêeééèúè“é¬ê9ì)îjðçò‹õ>øëú{ýÛÿúÊAVWIå8P>åÄÃÿòþ`þþ"þƒþ<ÿI¤C %  ßgœnÑ»$ wh í ìŽþ‰ú÷Åó·ðî²ëÝéŽèÌç›çúçåèQê2ìwî ñÝóÑöÒùÈüžÿ>˜@{ K ¯ ­ M › ¦}5ßWJtåÿ¢ÿ²ÿÎÒ—;ó­ T Ô ±æ©ôÆ " ”űoþûµ÷nôWñ‡îì ê€èç ç/çâç éàêí©ï‹ò¦õàø"üSÿ]-®Ò Ø ® ‘ Ä ª V ÛKº=ä¿ÜCþÿ j 6ŒûpÙ! 6  ƒ Ÿ Q ” g ËÈiºÐþ½û—øuõpò ïíòê;éèUç7ç¬ç±è@êNìËî¦ñÊô øûÿ[‡o / ë-ó=uw&• Õ üP¢'íþÿ`ÿÿ$ÿ‚ÿ( "V˜Õùñ® 9 òD.²Ö¥-ÿ~ü¬ùÌöõó>ñ¾îŠì¶êTépèèGè éZê/ì~î8ñIôž÷û¯þ:§ÝÈ Ut=Ýú˜Áƒì Õ ¢}x¦ÓþäýOýý.ý—ýFþ+ÿ7Y~”‡HÅôÊAXoÿMýèúcøÔõPóîðÃîäìdëSê¾é®é)ê.ë»ìÈîHñ,ôa÷Ñúdþø" øhcÝÏ6nNÂÚªF Å <ÁiFhþÚü§ûÒú]úFú…úûÛûÖüðýÿ38² ÄÀÿþ<ü+úü÷Ãõ•óˆñ°ï"îïì'ìÖëì¹ìñíªïÛñxôq÷²ú'þµHÃ ÄÆ²Òdoýá\£ Ïô,‰!þü9úÑøÏ÷5÷÷*÷ª÷qørù™úÖûý@þJÿ ¶úìÿéþœýüWú~øšö¿ôótñ,ð;ï®î’îïîÈïñîò-õÐ÷Çúþý_ÕE˜ µ†õópbÃ’Ò‰Ã+ $ äÚýý^ûù ÷˜õôÕóšóÆóQô,õHö”÷ýønúÖû ý>þ ÿ»ÿ¤ÿùþþÏüiûáùKø¸ö>õïóÞòò¹ñ¾ñ3òó|ôJöøûñý@†À Ø ³>dAáïjV»¥$J- åŠ3úýòú2øËõÉó9òñ}ðRð˜ðCñGò•óõ¿öuø&ú¾û.ýdþVÿùÿIEðÿMÿhþMý ü¶ú]ùøóöö`õõõ–õyöÉ÷€ù—ûþ°’– ‹ Xæ!õQ*w2]û¸ôÞ ŠŒþ¿ú¥÷ÚôoòtðñîííkífíÙíºîùïˆñSóFõK÷Où=ûý‘þÚÿÓwÄ»a¾âÿÖþ¯ý~üUûIúiùÈøtøvøÙøžùÉúSü6þeÔp%Ý ü6œ¥-*š~Ùµ!, êtßFþÁúh÷Qô“ñ=ï^íÿë'ë×ê ë¾ëãìlîIðdò«ô÷aù¥ûÁý£ÿ=…s;©õ ÿàÿ¿þ²ýÊüü§û†û¾ûRüCýŽþ+3~àC ’ ·0_[FðÉ þ§#Šþôúy÷3ô8ñœîpìÁêšéÿèñènélêàë¼íìï^òúôª÷XúïüYÿ†fïÞADñRujDðèÿ ÿmþþþ`þ ÿSç²§²¿ º $mVÒÖ[_ãí ‡ À§SÙþQûÔ÷{ô^ñ’î,ì<êÏèîççÞç«èüéÄëõízð>ó,ö+ù$üÿ¬,ä4  ” § Y ¸ ϰmÇ‹t“öÿ¤ÿ¤ÿùÿ¡—ÓHçž[  “ ç ó¦òÍ2‘ “ .ng,ÿÒûrø#õòï’ìrêËè«ççç°çÑèvê‘ìïåñõô)øjû þ´"Z , Ž | ÷ £ è Þ • ! •‚"ò[SóÙüK¸/œî  ð  ± y Ô ½ 8 Iû[{ÿmüHù"öó5ðí_ëŽé9èlç/ç„çkèÜéÏë6îþðô`÷Ìú?þžÕÍs ¶ ŠæÇ+‘¨hä - Y |ªöq)+~ÿ%ÿ"ÿqÿ äò"c£ÎÑœ K  ~L+ÀÿýKúj÷ŽôÍñ?ïøìë‘éèè*èÎèêºëðí”ð”óÜöTúãýqæ*& È ÿ¿ÿ»ó¬îÅ@qm G íâhÿþoý"ý-ýˆý*þÿ +Rlh4ÀÿçrœfÖôÿÍýoûîø^öÕóhñ/ï=í¦ë|êËéžéúéâêSìEî®ð~ó£öú–ý3Ç:s \äøž#”C"È M ÅGè¹Îþ0ýêûûzúQúúüú¼û®üÃýçþ÷£ $åM[þ§üúqø7öôíñðfîí>ìÒëæë}ì™í7ïOñ×ó¾öòù^ýé}Z r3‹jœѩR‰`é; l ’Ŧþwüœú!ù ø[÷÷)÷˜÷RøHùhú¡ûàüþ"ÿ¦ ½'ÿçýfü³úÞøùöõRó¸ñ_ðYï¶îîÄîƒï¿ðvòŸô.÷úAýœ„à îu&7¸§Ù-”Ì Ï ´“„œþðûùŒ÷ïõ¿ôþó­óÄó;ôõöY÷¼ø-ú–ûçüþüþ¥ÿ¾ÿ!ÿ8þý°û,ú–ø÷~õ$ôó0ò·ñ¥ñòÔòôÓõõ÷vúFýR‡Î / ¹÷ Ëù”Ÿ #¸ðá ¡Hï¯þœûÌøQö9ô‘ò^ñ£ð`ðŽð%ñòUóÎônö!øÓùqûéü+þ*ÿÝÿ<Hmÿ”þ‚ýFüòú—ùJø÷#ömõ õõfõ3öm÷ùûpýìçîê Ãa°œ vQ›WŒH™“ K ÙTØþzûRøuõõòâðEï&îˆíiíÃíî¹ï8ñöòáôãöçøÚú¨üBþ˜ÿ¡V³ºoÚÿàý®ü‚ûnú„ùÕøoø`ø®ø`ùvúîûÁýãÿGÝJ õ |ÇÁY}">ÌÎE<¾Ü ª <¬ÿ‡û#øýô*ò½ïÃíIìTëçêÿê—ë¤ìîäïóñ1ôˆöãø,ûQý?ÿç??ã+¹2* ëþØýçü(üªûyûŸû üÿü:þÉÿ¢ºÿ_Å  LCê1b9‡N‘Z¶ µ kïXÿ¿û<øéôÜñ)ïäìëÕééðèOé1êëSírïÖñjô÷ÆùbüÖþÿšÖ°&=úi˜•sE*ÿ~þþþAþØþÆÿŒO>GW Y 7Þ99Í쌬Jm i `¢ÿü˜ø5õò)ï«ì êéè§çÈçwè¬é\ëwíêï¢ò‡õƒøûbþ¸ƒéå t œ b Ñ öá¥T¿ µ ©ÿ™ÿÞÿv_û“H » O ² Ï–ùíkoû  Ãèÿ‘ü0ùÛõ«ò¸ïíßêéßç.çç…çˆèêìîBñFôs÷³úìýñ“߯ ? F Ø ú ±   Ñ f ÞNÉa(+vþÿ>Ъà uì^¸ æ Ö x ½     ÆŠù#ýùùÐöºóÏð$îÑëæévè‹ç.çcç*èéWë¥íZð`ó£ö ú|ýà!'ß 8 $š”ªÕ§0 ƒ µ ÚK¼h[Ÿÿ6ÿ#ÿbÿïÿ½Âí-o¡®† X 9 µÉv¿®O³ýêú ø*õ`òÄïkíjëÔé·è èè™è­éJëfíôïâòö‹ùý§$s€ 6 …_»“ç»Ñ× ¸ ˆ^Mg½\ÿLþ”ý5ý/ý{ýþâþâÿý$CF·ŸÜ¹9fKþöûyùéö[ôåñžïšíîëªêÞé”éÒéœêðëÈíðÔòéõBùÉüdýyÀ ¼ Zˆ:g "´Èi¨—H Ô NÎh/6ÿˆý0ü6û›ú_ú}úëúŸûˆü—ý¹þÝÿìÙ’1}œdÝþýûçø¬ötôTòað¯îRíZìÔëÌëFìFíÉîÉð:óö4ù–ü²;  È ž€mʙݡðÚtÐ  /_­-ÿïüûtùIø…÷(÷,÷Š÷5øù8úmû«üàýøþäÿ“üÙGbÿ0þºüû=ùY÷tõ¥óÿñ–ð}ïÃîuîžîCïeðòôögù†üÚÿKÂ% ] Rï Ö¦´1#’$kx cB.>ÿ„üúý÷Jöõ,ôÄóÆó*ôäôçõ ÷}øëùWû­üÝýÖþÿ÷ÿÔÿFÿkþLýöûwúâøI÷Àõ[ô-óGòºñ‘ñ×ñò¿ó`õn÷Üùžü¡ÿÏY „ ~/„iѯý·àœH“‘ Z ¬eÿHüiùÛö®ôîò¢ñÎðrð‰ð ñêñó†ôöÎ÷ù#û¢üïýüþ½ÿ-I‹ÿ¾þµýü.ûÒù€øJ÷Dö~õõîô:õñõ÷£ø•úàüwÿG>FG +Ø;>ÑåoiÒ¬þÓ:E Ÿÿ7üùö€óUñžïeî«íqí²íeî}ïëðœò~ô|ö€øvúLüðýTÿk1Ÿ·{ó*/ÿþßü°û•ú¡ùäøoøMøˆø&ù(úûOýcÿ»Iùµ g ùSbOJø¬½W‰ f yàÿOüáø¬õÆòBð/î™ì‡ëýêùêvëjìÉíƒï„ñ¹ó öeø³úßüØþŽ÷¾Å+UT9ÿþý=ü±ûpû„ûóûÀüèýhÿ4BÞF £ ßäŸüícV¦æX i -¹%‹üù¡õ„ò¼ï^íyëê?éôè6éýé?ëïìüîRñÜó„ö3ùÓûPþ•”A~1~¸¿¢uK6Hÿþþöý$þ«þ‰ÿ¸3ìÕÜî ö Þ ”Ãü·ò¬è¯  ×hãü]ùñõ·òÅï0í ëdéFè·ç¹çIèbéøêýì^ïòåôÝ÷ÙúÂý‚@š« P f æ  Û:ôÎØ±ÿ‘ÿÆÿN)L®Aó²k x ¦úž¼a ‘ U ¸Ë¡Qýîù”öZóWð£íRëuéèIç ç`çEè±é›ëñí¢ð™ó¿öüù7ýZN^[ ë µ í º % ; © &—¢_V“üÿ-°}‹Ì2©€ ¹ ¸ l Æ » D \  >”ÊËý«ú€÷côlñ±îHìEê¸è¯ç3çIçñç'éäêí¹ï°òçõGù¸ü!k~H µ ¹ H]õ½ýáy ×  7a¡ ªÃÿJÿ&ÿVÿÕÿ˜”¹÷;r‰n a V èÒ..ÝKþˆûªøÇõõòLðâíÌëêåè0èèkè`éàêâìYï4ò_õÅøMüÞÿ_ºÖ   ùpeÕÄ8;Ý-? ' ûйʥÿ„þ»ýKý4ýqýùýÀþ¸ÿÏö#¬ ÈšÖÇþ{üúu÷ãôeòðüí:ìßê÷éé±é]ê”ëPíˆï.ò1õ~øýû—ÿ1µ  Êß)êÎü¶ Æ Y ×Ué§¡ÿäý{ümûÀúqú~úÝúƒûcülýŒþ°ÿź~;ªÚ²:ÿyýû\ù"÷æô¾ò¾ðüî‹í{ìÜë¸ëìúìaîGð¢òcõyøÑûSÿætã  ‹ 5@¼ª êRQûd ¢ ÍúA·ÿkýnûÌùŒø³÷A÷2÷÷øùø ú:ûwü®ýÍþÂÿ~õòq›ÿvþ ýiûœù¹÷ÑõûóIòÑð¥ïÕîoî~îïð•ñóöõ»øÎûÿ†þi ­ ²d®€Í»Wfñ¯  òÚâÿýœúrøªöMõ^ôßóÌóôÆôºõèö?øªùûrü©ý®þrÿëÿèÿiÿ›þˆý;üÂú/ù”÷ö–ôZócòÁñƒñ°ñQòhóòôêöFùøûðþ[£Ö Ý¡  ‹ùÓ×Ó1?  Ãiöü úi÷(õPóìñÿðŠð‰ðôðÁñàòAôÑõ|÷.ùÔú[ü²ýËþ›ÿF§ÿæþçý¸üiû ú·øy÷gö’õ õÜôõ³õÁö:øúSüÝþ£–£ LÁÛˆ¸a{üjYÖó Æ cåböü¶ù¸öôÍñýï©îÔíí§íBîEï¡ðEòôöøúîûœý ÿ3 ˆ°„ LZÿ@þýßû¾úÀù÷ørø>øføïøÝù/ûßüåþ1·c × sÜýÂùPZ 9ë2 ÉE¬ý¡ù_öfóÌð îïìÀëëøêZë6ìí&ïñCóõè÷8úküoþ2«Í–ÏBw}fDÿ)þ(ýSüºûiûlûÉûƒüšý ÿÈË]Æ ) o‚PÃÌ^n÷÷rnö  í‚óXýÈù]ö0óTðÞíÝë^êiéé#éÎéöêì‰îÐðPóòõ øDûÈý'äFHæ"×çÐ¥y_iÿ¥þ#þíý þþNÿoÜ‹mq„ ‘ ƒ FÅï³Ý3^= ° È–/­ý$ú°öhóeðºí|ë¹é|èÎç°ç#èéšêˆìÖîrñDô7÷3ú!ýêÿ|ĶFl ( z g ù ; =Çt+þý8»ÿŒÿ±ÿ)õ cî\ À < yh÷ÌÁ â Xz[þ®úO÷ ôúð3îËëÓéZèkç çBçèXé'ëgíðïò öEù‚ü«ÿ©jÚì “ É Œ Ü ¿ = d C ê náW䙄³.ýÿ’RUŽïeÞF Š — \ Ê Õ u ¤ b ³,oyþ]û1øõ òAïÄì©êéÛç@ç6ç¾çÖèvê“ìïò-õ†øõûaÿ²Ò¬. I ñÒ Ë!À ) i “¼øXîÅêÿ`ÿ-ÿMÿ¾ÿtg†ÁBbR g p  T*š«hâþ&üKùeöóØð^î3ìlêéFèýçDèé}êdìÂî‰ñ¥ôø‚ûÿ™þ)  ‚Ž 0½ÇTp%†¥ • m A&/nðÿÀþæýeý=ýjýäýŸþÿ¢Èìýé *íQS÷CBÿýŽúømõçò‡ðbîŒìëê“é–é$ê=ëÝìüîŒñ}ô¼÷2ûÈþdïP n 6–~åÃâ+ýfvAÝ ^ Ül!BþÈü©ûèú‡ú‚úÑújû@üBý^þƒÿœ™hùA6Óý”ÿßýîûÑù™÷Zõ*óñMïÈí¢ìéëªëìë³ìÿíËïò»ôÁ÷ ûˆþ¬# i e2ã ¨´4.®Ã~ô ; i–×BêýÜû'úÓøæ÷_÷=÷w÷øÖøÝùûCü|ý¡þŸÿfë$—Òÿ»þ\ýÂûûùø0öSô—òñÑïìîoîdîÔîÁï,ñó`õøûYþÁ:ªù Ô6#Žm»v£Jv7ŸÅ ½ ¡‡‡¶ý'ûëø÷›õ•ôôÖóôªôõ³öøjùÖú5ütýƒþTÿÜÿøÿ‰ÿÊþÃýü û|ùß÷KöÓôŠó‚òÍñyññòóˆôjö³øUûAþa¢ì& 9ަFaîèP*~YÌê É &Ö§ý¬úü÷¦õ¸ó;ò5ñ§ðŽðãðœñªòþó…õ+÷Üø„úürý—þvÿA(Àÿ ÿþðü¥ûJúïøª÷ö©õõÏôðôzõröÕ÷ ùÊûEþíóý ò »Br8…L…-DÐÙmž '¬)·ýlú^÷£ôJòaðóîî“í¡í$îï[ðññ¾ó°õ±÷­ùûGýÄþùÿÞn§ŠmƒÿoþBýüéúâù ùxø3øGø½ø—ùÕúsüiþ©&͉E ê `”oáÚP:—f¯{×Ö Œzäýdú÷ ô[ñïKíì;ëþêDëì9íÌî°ðÏòõk÷½ùöûþÕÿ[iç ×W—¥’qÿSþLýmüÆûfûXû¢ûJüPý¯þ_V†ÜE ¬ û ü„¦S&CÚðÇ ©JÀ%þ‘ú÷ßóððcîHì­ê™ééé¥é³ê5ìîRðÆòbõø´ú?ý›ÿ¶„ù¿Ÿó ýÕ¨‰‹ÿ½þ-þèýõýZþÿ(ˆ, * % ô„Þ ün^ÎÅ N wSõvþìúq÷ô ñJîòëê¹èëç¯çèáèBêìRîÞð¥ó’öù~üPÿíFIí* û b d  Y hDÿ­b/%TÈÿŠÿŸÿÄÍGÆ u ü IJï+ôF} l õ&Îþnû ø¿ô¡ñÈîIì7ê¡è”çç,çÒçéºêâìnïHò[õøÌûúþÐRx 6 „ ^ Æ ¿ R Š w ) ´*Ÿ'Ô´ÖBw)!Q¬!œ X r H É ê ¡ è ½ # !Â&ÿüãø»õ¯òÕïEíëQé èSç)ç’çŒèêì†îYñuôÆ÷1û þ÷# £ Ó ”Ü©úÕAKy Á ïP©3þzÿ6ÿGÿ©ÿR;S‹Ñ84ôh … ? “~%ñwÿÃüëù÷&ôgñÝîŸìÁêSécèüç#èÛè êëë1îãðîó=÷¸úHþÒ?xg ø ÊöŸÄlŸjÜ Þ ³”–É=ÿþþýHýeýÑýþhÿu™À×ËŒ 9†›Q­ºÿƒýûŽø÷õkóñÌîãìXë<êœééñéíêqìuîîðÌóüöiúúý—(“Á ž›–ðU@¾àº_ å dï~¤þýèûû ú‰úÉúTûüý1þVÿrvOîEKùLEëÿDþ]üEúøÏõ™óƒñ¢ï îÎìüë¢ëÈërì¢íTïñô ÷Kú¾ýMâa´ Áu½‹ÒŒ·Ul1þƒÓ  2nÐkþNü†úùø÷K÷s÷ï÷´ø²ùÖúüJýsþyÿLß&»ýþ«ýüZú{øö­ôçòRñðïsîOî¥îxïÈð’òÎôn÷cúšýüuéB f?¸ÀHF´Úãº4g h O4.Sþ¶ûhùw÷íõÑô%ôåó ô’ôhõ€öÆ÷*ù–úøû>ýWþ4ÿËÿ¦ÿõþûýÁüVûÈù,ø“öõ½ó¦òÞñtñsñãñÈò#ôïõ$øµú”ý«è3t ’ w <÷0Üö~væÚc’} ;äYþSû’ø(ö$ôòpñÉð˜ðÖð{ñxò¾ó;õÛöŠø4úÇû1ýbþNÿíÿ80Öÿ/ÿFþ'ýáû†ú)ùÝ÷¶öÄõõÅôÑôFõ'öu÷+ùCû¯ý`EIU Q '¿ãK0‰P†/TE6 èsñzþ%û ø;õÌòËðBï7î­í í îâîðŸñaóLõJ÷Gù/ûïüxþ¼ÿ°Qš0‹«ÿžþtý@üûú%ù‚ø+ø-øŽøTùú üðý#–7ò± ^ â&¡¶IRͺx‰ M ÚG¯þ)ûÍ÷³ôïñ“ï¬íEìdë ë5ëÝëøìwîJð]ò›ôîöBù€û–ýtÿ N:ÉþÛiµÌ¾žÿ~þpýˆüÕûfûGûûüýWþùÿã [Ã. … ´£AzAŠN‰<l$p c ôþ[ûÝ÷“ô‘ñîî¹ìëÐé*ééƒévêßë°í×ï?òÓô|÷#ú´üÿC!¨Ð•øý« 2)ص°ÿ×þ:þæýâý6þâþäÿ5Π›­Á Ä  @’„ £®9Iè $ ¹?ÿµû4øÖô²ñÞîoìtêüèè´çèç©èïé¬ëÒíMð óïõçøÛû´þ\ÄÙ‘ãÊ G \  u u7ç™aNrÙÿ‹ÿÿéÿ•‘ÒMñ¯r ' ¹ (â5‚së ñ ŽÐÈ‹ÿ/üÊøvõKò`ïÌì¡êïèÄç&çç£ç¸èRêbìÙî¤ñ¬ôÙ÷ûHþY4Æ Ó 9 , « º b ­ © f ørçkæûY ^îjÜXÌ# J 0 Å û È &  ¢T³ÑÿÀü•ùjöUómðËíƒë§éFènç$çmçHè®é–ëóí²ðÁó÷núÞý;rk Y 2”{æÙ\zCÆ  J t©û{9?—ÿBÿCÿ–ÿ3"UšÞ áf • e ÎÍe›x _ýŒú¥÷Âôùñaïíë“é‡èè è¢èÉéxë¥í@ð:ó|öïù}ý ÄÄ j §n¶z¼~É©.hl N $þ'ŽAÿEþ¡ýWýdýÁýeþBÿIk“®«xE-·ß¨/þ¡ûùƒöòó}ñ:ï>íëgê«éséÅé£ê ìôíUðó@ö¡ù-ýÉ^Ô Ž«Jcòøx}G/ß k ëtñ ÿný*üDû½ú”úÃú@ûÿûñüþ(ÿGQ4ßE\€Š?¦þÉü¹ú‡øEö ôêñûïQîÿìì ëªë8ìLíâîôðvóYö‹ùõüû ãD,‘j´p£Wš{h ¡ Î`ïþÃüéúnùWø§÷]÷r÷Þ÷•øˆù¦úÜûýDþRÿ0Ð&,Û5<ÿ÷ýqü¸úÜøðö õ:ó˜ñ7ð)ï}î@î{î4ïjðò@ôÌö±ùÝü8¯'ˆ º ¥5Wü¥  êJ8Æ ýâÖòþGüèùä÷DöõNôøó ô~ôDõOöŒ÷ëøVú»ûý(þÿ¶ÿ Áÿÿ1þýžûúyøÝöTõóóÍòóñsñ[ñ³ñ€òÃóxõ˜÷úéü÷ÿ/z¿ è ܄̢øÃþ¥»HVõ6. õ¡Lÿüû+ù¯ö•ôèò°ñðð§ðÎð^ñIò€óòô‹ö8øäù{ûíü*þ$ÿÒÿ-4êÿQÿsþ\ýüÃúdùøáöãõ(õÀô·ôõáõ÷»øÀúýÂÿžŸ¬¯ 8‘ˆ …l‰Ɏèé § :¸>ÿàû¶ø×õSó:ñ˜ïrîÌí¥íöí·îÛïQñóêôäöáøÎú–ü*þ{ÿ0ŠŽ?§ÒÿËþ¥ýqüBû,ú@ùŽø'øødøù,ú¥ûzý ÿ¢Z Ð _´¹[‹;bü‰‰9 ¢|ÿðû‰ø`õˆòðî‘ì“ëë+ë¸ë»ì&îèïîñ#ôröÆø û(ýÿ´ ¨îÜyÑñéËÿ©þ—ý¥üçûiû9û`ûãûÄüþ”ÿrÚA® GGøI*pȘ㴠 ÓXÂÿ'ü¡øJõ7ò~ï0í\ë êJééfé>êëJí_ïºñEôêö’ù(ü—þͺSŽgÞõ´$TS4áÖÿóþIþæýÓýþ°þ£ÿår;0@W a H÷\d)ÒùŸÈ} Ì Å|~üùø‘õ^òwïðìÜêGé;èÀçÕçxè¢éFëVíÀïoòLõBø7ûþÉ>e0—” ' Q  ¶¥m Ñ”y’ëÿŽÿƒÿÌÿiWŒýœX × t Ý Ð:5¹ÄU q # v|Gïü‰ù/öøòýïTíëCéúç=çç{çrèïéçëIîñþó%÷_ú•ý­•7ƒm é ô ‹ ² n Ì × ¡ < º/°N"rIß¾Û)˜Œì   ¼  ê ` d ÷ ãQzpýHú÷ýó ñUî÷ëê†èç&çOç èSé ëeíðóKö¬ùý}¾Å Û Ë FGÌØr¥ k ¥ ÐNÅwo·ÿRÿCÿ†ÿéñ dªßðË` ¢ †  Æüšúý,ûGø_õŽòèï…ízëÙé°è èöçoèxé ëí£ï‰ò½õ(ù±ü@¼  × , oP­Šîå|ÅÔ ½ –rg‡â…ÿyþÄýiýeý³ýJþÿ<e…‰aüLGä ûy£„þ*ü§ù÷zôüñ«ïíçë˜êÁélé é`êªëyíÁïvò†õÛø`üûÿ”] ^ 9ó)Öù–´aª¢] ð rù™epÿÅýpüwûÞú£úÁú/ûâûËüÙýûþ+ÎCj:±Í‘ÿ5ý,ûþø¼ö|ôTòWðœî5í3ì¤ë’ëìûìvîoðÛò«õÍø.ü¶ÿK×@ n KÄÈJAª…Õ¤þó–ü ; jŸòvÿ:ýPûÂù–øÒ÷s÷u÷Ð÷yøaùwú¨ûãüþ*ÿ¾#9ùbyÿBþÆüû=ùR÷fõóáñpðNïŒî7îXîõîð©ñ¶ó/öù"üvÿédÌ ­è©ä«41¬²S£¹ ª€“ÿÛülúTø öWõ|ôôônô#õ!öT÷­øú|ûÎüøýíþŸÿÙÿFÿfþBýæûbúÇø'÷˜õ,ôøò òxñIñ‰ñ=òhóõ÷ù@üDÿu¿ ; =÷VGº¤þÅú¤Í‚ÖÝ ­ ^Äÿ§üÈù9÷ õFóöññ»ðËðEñòFó¬ô>öç÷“ù/û©üðý÷þ´ÿ6ûÿpÿžþ‘ýWüû ùIø÷ö:õ¿ô¢ôëôŸõÁöNø@úŒü%ÿøô õ ¬'Åå{‚öÜ8‡™ d ÿ€ügùwößó¯ñòï²îñí¯íçí‘î¡ïñ¯ò‰ôö|økú;üÙý8ÿK w‹LÁ÷ÿøþÖý£üqûTú]ùžø'øø>øÛøÝùCûýÿz Æ @ Ú>WZ'l%Oî«ä Ç iáH¸üHùö%ó›ðîãìÈë4ë'ëšë„ìÙí‰ïñ­ó÷õJø‘ú·ü«þ]ÂЄÛÚ‡ëøÿÖþ¾ýÅüûûoû/ûDûµû„ü¯ý2ÿZ¾- ’ ׿« Ž‹íU>¶ Í ”"óügùöàòð¬í½ëQêoééPé êCëéìëî8ñ¹óYöù›ûþTPúI6Àé¹9u}b7ýÿÿ[þêýÆýøý‚þdÿ˜×ÆÓì ü í «"@õ7û>ÿA q {=ÏHý¿ùNöóðwíIë—énèÓçÉçNè[éåêßì7ï×ñ¬ô÷“úwý3¶îÌHZ  A  ¢ ÙÓ£Y Ȧ´•ÿzÿ³ÿ@H¯HƆ + ¢ ×¹:Në¹ í ´ -¯ýIúêö©óŸðâí†ëžé7è[ççYç2è“éqë½íeðTósöªùáüó¤ • · f ¤ v ç  Ú } xöPLŽ6½¢éSÐK² ñ õ ¯   • ° [ —oí" þüúË÷¨ô¨ñäîqìcêËè¶ç.ç8çÓçþè°êÛìrï`òõëøXü¿ÿçW _ ó­Ò„̸X ¾ ý +\£·¡ÙÿdÿEÿyÿüÿÂÂë-u¯Ê²W « £ 6 `"~|)”þÌûéøþõ%ósðÿíßë%êáè èêçDè.é£ê›ì ïÝñõbøçûwÿ÷Sr @ «¥# ™‘Æ : +  âÒé8Íÿ°þëý~ýiý¨ý2þûþõÿ6ZfHñQ] ]KÛÿ±ü4úž÷õ~ò ðî6ìÏêÝékéé#êPëí2ïÒñÐôø”û-ÿÈN¥ ¸ rÀ–é´ô­æªØ t ù~ÜÚÿ þ¹ü®ûûµúÁú ûÇû¦ü®ýÍþðÿø»=tVÞ àcÿžýžûuù4÷ñôÀò·ðìîqíWì®ë€ëÖë°ìîïïCòõøhûêþ‚ ¿ ¯?]üš“ë]g Ó 9…þÿµýºûúÙøø÷|÷Æ÷`ø;ùIúvû°üäýÿñÿªC´ÿŠþýqûžù´÷Åõçó-ò­ðyï î3î:î¼î¾ï<ñ2ó•õXøiûµþ#Ÿ X e tP©t¯Wr&Ü=^ V =+5rýóúÉø÷¡õ°ô-ôôaôõõõ÷pøÖù=û”üÆýÆþ…ÿúÿîÿjÿ˜þý,ü®úùt÷Þõhô&ó(òñ<ñdñÿñó˜ôŽöèøšû“þ½RŒ šgÛåu}÷Þ2ú> s‰ c ÄzUýiúÈ÷„õ©ó@òNñÔðÌð1ñ÷ñóiôòõ–÷Bùâúbü´ýÈþ“ÿ5ÿÇþÄý‘ü>ûÝù‚ø?÷(öOõÃô‘ôÄôbõmöå÷ÃùÿûŠþTJWd X œÁyµj$(¡š!F ÂGÇ\ýú÷oô(òSðøîî¿íÞípîkï¾ðZò*ôöø úßû‡ýóþæa†VÙ$ÿþÕü¡û}ú}ù±ø*øõ÷ø¤ø“ùåú—üŸþïz+î­ QÄïÀ# pGL‚=‹ -¬‚ý úÃöÇó'ñôî;íìSë)ëëRì‘í.ïñ9ó}õÏ÷úEüCþw–\ÅÕ‘7<$ÿçýæüüxû(û,ûŠûGü`ýÓþ•Ú;«  d‚YÖꆡ4=ÀÄS| Së]Áý/úÁöŽó¬ð.î%ìœêœé(éAéàéýêŒì{î¸ð/óÉõpø ûŒýÚÿäžÿžÚ»J“¤g=%1ÿpþðý½ýÞýWþ(ÿM¿t\f€ • [ãä?}Y¶š  -ü–þ‡ú÷Áó¶ðî¼ëîé§èíçÃç*èéŠêmì±îCñ ôùöîù×üÿ+sdô Ù .  ³ ùÿÖ‘BýÕØžÿsÿœÿêcô¨o3 à d ©ž5aUe A ¹Ü¼oþ û¦÷\ôCñtîìÿé{è€çç?çøç=éë6íËï¬òÁõôø,üRÿN’ < v < ‘ z þ +  ½ F¿<Έx¬,%žck©Š w À Ó  ! Å ø ¹ ÷†ÈÏþ¯û~øTõJòwïðìÊêéåç>ç'ç¤ç°èEêWìØîµñØô+ø–ûÿþOoKÏ î ›ÏˆÇîíœ  U †¶ø^ùÕÿÿzÿJÿoÿãÿ”·ö?~¡–J ° ¼ d £zêúµ+ÿlü‹ùŸö¾óñ}îIìvêé9èäçèêèBêìuî4ñIôž÷û¬þ1—Ä¥ &8Ñê’)M vž — v R=Lëþþ–ýqý ýþÚþÌÿà.@-âRp3–—9‚}ÿ7ýÀú,øõó™ðjîŠì ëÿépéhéìéûê’ì¨î1ñôW÷Êú_þû‡ë ÜC3£‹é¿ïb|Qõ  šTF~þýéû*ûÊúÅúû®ûƒü„ý þÄÿÜ×¥5{oG,¿ÿþüìù¬÷fõ/óñ?ï±í€ì¾ëuë­ëlì°ítï±ñYô[÷¥úþ²F µí¨Üƒš&+·×œj  Óˆ3þ(ütú!ù3ø«÷‡÷¿÷IøùúDû}ü³ýÔþÏÿ“I+µëÿÐþlýÌûÿùø&öAô}òîð§ï¹î4î!î‰îpïÔð²òÿô°÷²úôý^ÚN£ ¿ŽùñgR«s¬_–aÓ  ëÖÚ þ~ûBùe÷ïõçôNô!ôYôëôÌõêö4ø—ùþúYü“ýþiÿíÿ‹ÿÇþ»ýrüúúcùÁ÷&ö§ôWóIòŽñ3ñCñÇñÀò/ôöUø÷úãýJ™Ú ô Ñ[~)PéðdI© 2 Õ€3þ û[øöôò…ñòðÓð!ñÓñÛò'ô§õF÷ñø“úüvý–þpÿúÿ1§ÿîþõýÊü{ûú»øq÷OögõÊô„ô¢ô)õö€÷Kùuûòý°¡¬¼ ¸ ŠV'R—Kn¶ï× „ŽþÑúÂ÷õ¦ò¸ðCïLîÕíÚíTî9ïzðòÍó·õ±÷¥ùû3ý«þÜÿ¼H}]î:Nÿ7þýÑû¨úŸùÇø1øê÷ý÷røLù‹ú*ü"þfç“V Æ FƒjçëlbʤöÊ/4 ïwãMþÌúz÷lô¸ñmï™íEìxë1ëmë%ìNí×î±ðÇòõS÷žùÑûÙý¦ÿ)Y1¬Í™WdQ/ÿþ ý*ü„û%ûûcû üýwþ+'\¸( — ï •Áx°`‡&Dë(  ²*þøú€÷?ôJñµî’ìíêÏé=é7éºé½ê4ìî<ð¨ò;õß÷úý\ÿt?²ÆxǺY¯Ê¼–kNSÿ†þùý¶ýÇý/þïþióù , /  çÌA<¶®%"¯ ܹ\ÜþPûÑ÷xô]ñ•î5ìKêæè èÅç èßè4êÿë/î±ðpóVöJù6üÿžô÷›Ù¬   Á  ) É{3ÿ2ªÿpÿ‰ÿ÷ÿ·Æ¡QÞ “ " w+n?–s× Ê Uˆt.ÿËûdøõìñ ï‚ìeêÅè¬ç"ç+çÅçìè•ê³ì5ïòõ?øwû¢þ§u÷ Þ /  z y  P B û ‹‚Á§Í?‚95kËEÅ9 ­ ˆ  5 ð ;  | {k}ÿaü1ùöïò ðtí7ëjéèTççzçhèàéÙëCî ñ"ôm÷Ôú?þ•À«C x =‹^¶˜ Ý [ « àN­= &’ÿSÿhÿÍÿ{gƒ¿Lwv: ± Ð âÎRt?Áÿ ý-ú@÷Zô’ñÿî·ìÎêTéYèæçè­èèé©ëåíð“óÜöTúáýjØ › Æy­^>zNÊÿ  å Áª±êc)ÿAþ²ý|ý›ý þ»þ¤ÿ³ÙÑPUËà”í÷ÿ»ýKûºøö‰óñÖîãìNë'ê|éWé¼é­ê(ì$î•ðmó˜öú‘ý-¿-` BÀËW\×Ê:/¸äÇu  ŠÎ´ÞþVý'üUûãúÌú û—ûaü[ýsþ—ÿ²µ*€„/€vkþübú%øÝõŸóñ—ïõí¯ìÓëoëŒë-ìUíÿî#ñ¶ó¦öãùUýå{ÿV j%vMŸe›Df B§ : m¯´þ™üÓúlùiøÍ÷•÷»÷5øøøòùûJüý§þ«ÿz M?Úÿ¼ý&ü_úyø‡öôÏò2ñÚï×î:îî\î(ïrð7ònô ÷þù5ý™Œê ÷y‹(¡‰à¯âf¢ ª ˜‚€¨þ ü¿ùÍ÷Bö$õtô0ôTôÕô¦õ¸öú÷Xù¿úü^ýrþJÿÜÿªÿõþõý¶üEû²ùøpöèôŒónò ñ/ñ(ñ“ñtòËó”õÆ÷Wú6ýOß& K 8ÖØÕû“ ØÊ Ž=í¸þ²ûñø…ö~ôåòÂññÞðñ´ñªòéó_õøö¡øEúÒû6ýbþIÿãÿ*¿ÿÿ%þý·ûXúöø¦÷yöƒõÕô|ô„ôõôÔõ ÷Öøîú[ýø  ô–åÏC3˜l­b‘G”Œ D ÔUßþŠûmøœõ*ó#ñ”ïƒîðíÛí=î ï:ð¸ñróUõL÷Bù#ûÝü`þ ÿ,rbYwÿfþ9ýüÕúÄùàø;øã÷ã÷Cø ù4úÁû¨ýßÿVü½ƒ 8 ŤÄbwýõdRÍæ ¯ @°ÿ‘û4øõMòêïüíì£ë?ë`ëþëí„îNðWòôÙö%ù]ûnýFÿØÁ+u‹|]ÿ<þ.ýFü“û$ûû@û×ûÍüþÃÿ²Þ5¥ w ®¨O“e¸†Ê†¿~Ð Ç wö]ÿÃûCøóôìñBïíDëêXé4éšé‚êàë§íÄï"ò®ôO÷ðù{üÝþÝb‰N±¶eÈîçÅšyvÿ þþ³ý³ý þ¹þÀÿ³‹Œ¥Á Ì °Y´°>SéüޤH ˆ t!¦ÿü•ø1õò+ï³ì¯ê,é5èÍçõçªèäé—ë²í#ðÖò´õ¥ø”ûhþ s‡?’{ ù  Ì 1 P:ÿ³j5'N¹ÿoÿxÿÖÿ‡ˆÏOú¾ˆ D Ý A[w`ÒÈE N î1*ìÿŒü#ùÊõ˜ò¥ïíÒêéÞç5çç™ç¢è0ê6ì£îdñdôŒ÷ÂúñýÿÙk¥{ ä Ú ^ s q s 6 ÎNÉRü×ñTh.ˆÿúV „ o D  y i è ü® (ýåù´ö—ó¨ðüí©ëÂéVèqççXç'è‚é_ë²íiðoó°öú}ýÙ ³ ý Ú A. š%K¦ ÿ : j¥þ„GR®ÿ^ÿcÿºÿZ<QˆÑJU& ® à ²  ¶ëÆU§ýÏúâ÷øô&ò…ï*í*ë—éèîçêçwè“é8ë[íïïáòöŒùý¢^a Nk8‚N¢Œ]i T 1G³iÿqþÑýŠý™ýøýžþ~ÿ‡ªÓðï½J‹sý$ëVm>þÖûIù«öô“ñGïAí•ëUêŽéKé’éfêÄë¥íþïÂòÝõ:ùÄü_öm® £ 8\&¿ÏZj I:ó ˆ žJ&Bÿªýiü…ûÿú×úûƒûBü3ýGþiÿ‡‘r•Sµ¼lÏþíü×úžøVöôêñòï>îâìïëpëpëõëíîšðóõõ$ùü°9œ Á ‘úí\@•]›[¨“0“ Ô F¤7ÿ ý6û»ù¤øó÷§÷»÷%øÙøÉùäúüOýyþ„ÿ^ûNPüQTÿ þ~ü¿úÝøêöûô$ózñðúîFîî4îåîðÁñáójöMùxüÕÿMÉ/ h [ô Ð÷—ùe]õ?R D/'Fÿü?ú:øšöeõžôEôTôÂôƒõ‰öÁ÷ù€úàû'ýEþ)ÿÉÿÆÿÿ-þøüûú]ø»ö,õÄó—ò¶ñ0ññeñ-òkóõ;÷ºùŠü›ÿÕ$p Ÿ ›Lž€â¹ÿ³Õn‡0zz G ù§lÿ[ü‹ù ÷ðô?óò>ñîðñ˜ñ}ò­óõ«öPøöùˆûôü+þ ÿÊÿ #Ôÿ6ÿTþ9ýôû–ú3ùÜ÷¦ö£õäôxôkôÆôŽõÄöeøjúÈüpÿOTgq Z oq’…æ¸Ò5>  ™£ÿEüù9ö²ó”ñëï¿îîâí+îäîþïlñóôôçöÞøÃú…üþaÿ` ccvžÿ”þký5üûêùûøHøß÷Ì÷øÊøáù[û2ýZÿÆe$ì ¨ @Ÿ®\—R…*@ÌÕh” l |åÿXüðøÃõçòmðfîÛìÔëTëXëÜëÕì6îîïêñô_ö«øçúýäþ„ÕÐo³Ÿ;’±¨ŠÿgþUýcü¤û'ûøú û¤ûˆüÇý^ÿ?b³ • ü ?I_Kº¥à4 t } :Á*üù«õ“òÓï}í¡ëHêzé8é€éMê’ëCíNï ñ"ô¿öaùñû[þŒw G –®mßóÉ¥›ÿ»þþ³ý¢ýèý‡þ}ÿÄV$ 7U g V|Ž5eEò"Ü 0 +ãnãü[ùîõµòÆï7íëyécèÜçåç|èšé3ë9í˜ï>òõøñúÌý{îßFE Ù  Ò H ui5ì¡gQmËÿrÿkÿ¹ÿZM‡þ£e1 ò – 3 {}® Î ƒ ØÞ¨Nýäù„öGóDð’íEëléèOççtç_èÐé½ëîÅð¹óÙö ú>ýT:Ü) ” ¢ = i + Ž   p  ”–9 lQëÏòE¹;¹ W R ÿ O 8 ² ¹ O x>«ÒÆý™úe÷AôEñ‰î ì ê˜è•ç ç=çìç)éìê&íÈï¿òõõQù¼ü[b } r òù„˜9tVï Q ’ ÄýÕ€Ìÿlÿaÿ©ÿ<R™ã0 ¨ í Ó S i_KçCþqû…ø—õ½òð¢íëàé¬èýçÚçHèEéÍêÖìSï2ò`õÆøLüÙÿT§¹ x Ò¸# rXÅÅe¸Ï Á  „€¥­ÿ¤þóý›ýšýêýƒþYÿ[{¥ÆÍ¦B“*f?»á¿þ`ü×ù9÷œôò»ï£íâë‰ê§éFéoé%êeë+ílïò$õuø÷û’ÿ+«ù ªè«ê¡ÎvŸU©«o ”"Ç™¨ÿþ®ü·ûûåúûrû%ü ýþ<ÿ\kV ¤ræÿÀ0ÿZýLûùÏö‡ôVòPðŒîíìvëZëÃë±ì%îð|òGõgøÆûMÿärà  øy†‰nʤ  ¶% l ¢Þ5¼ÿ„ýœûúãøø½÷¾÷ø¾ø¢ùµúäûýKþ]ÿAêL^€’ÿVþÕüû@ùM÷Zõ{óÅñLð"ïWîùíî¨î¾ïPñXóÍõŸø½ûÿ†r · »i®zÀxŸ4=ÄÔ€Ú÷ ðÛÐæÿ1ýÃú«øööªõÍô]ôWô²ôcõ[öŠ÷ÝøBú£ûðüþÿ´ÿ#ßÿHÿbþ9ýØûNú­ø÷qõÿóÃòÑñ6ññ<ñëñó«ô´ö ùâûçþi¸ð ú¾&" –ýÐÇû»' þ ´b ý(ú—÷fõžóJòlññññSòtóÔô_öø§ù=û±üóýõþ­ÿ&æÿVÿ€þný0üÕúpùøÕöÅõöôxôVô›ôMõlöø÷êù7üÒþ¨©¼Ë ¾ ~õ·â…— pYÒì ¾ ]ãfýÌùÚö>ô òGðï8îîíîÀîÆï#ñÄò–ô„özøcú,üÅýÿ-êQb‘ÄÿÂþýgü3ûúùXøß÷º÷ó÷ø’ùùú¾üØþ7ÏŠT  ¹&Ic;ŒP….Rý>& ÍH±!ý¯ùtö…óöðÕî/í ìnëWëÀë ìëí’ï€ñ£óåõ1øqú‘ü€þ-ŽšK¡I¬ÕÒ·ÿ”þ|ýƒü¸û-ûîúûvûFütýûþÏç1œ € Íæ´&+¶¿>4¤•/ ú‹ø\ýÎùfö>óiðüíìŽê¢éBéméêJëäìÝî ñ˜ó0öÑøeûØý¶îx¢só1:!øÒÂÿØþ%þ¶ý•ýÊýWþ=ÿuú¾´Èè ù À@g&q>ˆQšl Ô à¤6®ý"ú­öfófðÀíˆëÌé˜èñçÜçUèVéÕêÄìï©ñuô^÷Nú.ýçÿgœzö ´ ö Õ \ —–i#Ø›}Žßÿwÿ`ÿžÿ/A®M ØŸ L Ê ñy“8bJ  {dþ¥úA÷ùóèð"î½ëÊéWèoççUç!èwéJëŒí*ðó(öYùŒü¨ÿ˜I¨¨ > d  Z 2 ¨ Ê § P ÙVÚw?@†<È ·sõvã ( 2 ð U T æ  ² ñÉG{vþNûøîôçñïì„êáèÀç+ç(ç¸ç×è~êŸì,ïò<õ‘øúû^ÿ¥¹†ù  ž¾dI™4 ¢ é U¢Á°îÿ}ÿbÿšÿ ëîa­ë õž õ ï … ±sÎÌvÞþü)ù8öWóœðîôë/êßèèÐçèþèhêVì»î‡ñ¥ôø‚ûÿí à PPÕÚ[\ãù­3 ,  òèYóÿÛþþ¯ýýßýkþ6ÿ1Lv›©6—¤T£S>ÿèüeúÉ÷(õ™ò2ð î4ìÂêÅéHéSéêé ë·ìßîwñoô³÷,ûÃþ^æA X nL¨|Ç‹Îè Œ  ¥FZþ÷üîûCû÷úûcû üèüðýÿ0D7ùz¯?ÿÅýÀûùH÷ýôÄò³ðÞîYí5ì‚ëKë—ëiìÀí˜ïæñô­÷ûþª! c ZòÂâuzóèf{8´  ;vÇCþýüeú&ùLøØ÷Å÷ ø¥ø~ùˆú³ûêüþ3ÿ!×Hi6¬ÎÿŸþ*ý{û¢ù±÷»õÕóò‹ðNïmî÷íöíqîlïäðÕò4õô÷ûPþÀ?² Ú7‚Z T{Fq› š ‡zˆÇýJû ùV÷õõõ{ô_ô§ôGõ1öU÷¢øúfû·üåýàþ›ÿ *öÿmÿ–þxý üœúýøU÷¹õ=ôóòïñAñõðñ®ñ»ò>ô1öŠø<û5þa­ÿ? U*©¾YmóæGiA²Ñ ³ o×´ýÈú&øàõô•òžñññoñ.ò?ó’ôö²÷Xùñúlü¸ýÇþÿ&öÿtÿªþ£ýküû®ùMø÷êõ õ|ôFôuôõö÷mù©û6þý"  ìu¥h°q£CS×Új—w ©,Âý€ú~÷Ïô„ò©ðHïeîîî¡î’ïÞðqò9ô!öøúÒûtýÛþùÿÅ<]*ªèÿîþÏýšücû=ú:ùløã÷«÷Ð÷YøGùšúMüWþ«:ñ» .ªßº)oÊÊãÝ ~ëýqú(÷(ôƒñIïˆíIìë[ë©ëpì¦í9ïñ1ómõ·÷úù!üþÕÿEa$‹™SÄ÷üäÿÁþ¥ý¤üÏû6ûæúëúJû ü%ýšþam°Ž  X`è¬Ñn‚ ¯Þ ¸SÆ*þ–ú%÷íóñîmìÛêÑéRé`éôéëŠìoî£ðó£õBøÙúSýœÿ¢Zº¹V“uObN'ÿêÿ÷þ9þ»ý‹ý¯ý+þÿ) ZHYz — ™ nÿ;v_Æ© ÷ t ’cþyþëún÷ô ñOîþë&êÓèèÙç3èé|êTìŽîñØó¼ö«ùüQÿÜ"¢Ë‹ â Õ m ·ÁœZϪ±õÿÿXÿ†ÿÝþ`÷²J ÿ Š ×Ôr¥c§oÀ   >Ïþgûþ÷®ôŽñ¶î:ì-êè—ç!ç=çëç#éÜêí’ïjòxõ¥øØûúþô³$8 å " í F 4 ¾ ð Û Ž ¶uk£(+¨rÂ-®2¦ õ  Þ W l  L  e Qá!&ÿüÌøõ‹ò¯ïíîê0éñç>çç‹çŒèêì•îiñ…ôÒ÷8ûŸþí êp ’ D~=ƒT¹Àw ð ? w®öbä‘ÿfÿÿÅ¿æ)v¹àØ ù  ² ôË;Jwÿ³üÍùÚöòó,ñŸî`ìƒêé.èÎçýç½è êÜë)îàðîó>÷¹úEþÊ0_C É á¡?[û)ñd• – } `Rg°;ÿAþÆý¤ýÖýTþÿGoƒq'˜·zÜÜ|úÿoýóúYø¶õ ó­ðuî‹ìëêéPé=é¶é»êIìVîØð½óòöbúõý‘†­ îç`Q¹šøß]_ )Å…{·þCý(üjû ûûWûðûÅüÆýáþãr·¨@|]ìÿ.þ3ü úÃ÷uõ5óñ3ï›íaì•ëBëqë&ìaíïUñ÷óöö=ú¶ýJà_® ¸e¦k©[~'½è·@˜ ÕZÍ{þrüÀúmùøö÷Ð÷øø[ù]ú‚û·üëý ÿÁ@qOÕæþ~ýØûúøö1ôeòÎð~ïˆîúíßí@î ï~ðVòŸôL÷MúýúxñK oEº¼>4šn³q³‰< C 4$+`þÔû™ùº÷Cö9õôkôŸô.õ ö"÷gøÅù(û}ü³ý¹þ€ÿÿÿ-ÿÇþ¶ýgüéúMù¤÷ö}ô'óòPñîðùðvñkòÖó²õ÷÷˜ú…ý©ñD‹ ­ “&T =âõvgÒÂIxe (Ùdþkû¹ø_ökôæò×ñ>ññañ ò óRôËõd÷ù¥ú&ü{ý–þkÿñÿ#ÿÓþÖý¥üQûìùˆø:÷ö&õ„ô:ôTôØôËõ+÷õøûý^Rcy } Wò7wV§g–8Vý>. áoò‚þ6û&ødõóñ•ï—îîî‡îcïœð òÞóÀõ²÷ ùvû"ý”þÀÿœ$V2À ÿÿýÍü”ûiú]ù‚øê÷¡÷²÷&øù?úàûÚý!¦X!ë   *qbêú‡ˆúß;…‘ Q ÝK¶þ4ûà÷ÏôòÃïèíŒì¶ëfë˜ëFìdíäîµðÂò÷ô>÷‚ù¯û±ýyÿø%ùr‘\Ú$îþÏýÇüèûBûãúÖú#ûÎûØü=þöÿõ/’ € à ¤ÛœÞ˜Éq—Eˆ s “øþ`ûå÷Ÿô¤ñïÝì.ëêjéYéÑéÉê5ìî)ð‹òõ³÷LúÌüÿ3üm€1€tj‡{V-ÿOþÄý„ý—ýþÆþàÿI÷Ýê , 7 º ùwzýüz} @ ÄCÿ´û2øÓô²ñâîyì†êé1èÝçèàè)êéëî‡ð=óöùïû¸þO¤¦Jˆ] É Ð z ÓêÍ‘GØ× ŠÿTÿqÿäÿ©¼£Y%ó ° F ¢³g±ˆæÉ2 ( ¶êÖÿ)ü¾øfõ9òOï½ì–êêèÆç0ç,ç»çÖètê‡ìþîÇñËôò÷$ûKþNœÄ† Û ½ . 2 Ð  Ë aãcö­˜Ã9ŠFH‚ègíg À æ Ç T  ? Ž j Õ ÖwÅÔÿ¶üùMö2óGð¤í]ë…é)èWççeçGè³é¡ëîÃðÑó÷wúßý3^Jä  å 9qZÕï¶ < “ ÏJ¯E8©ÿmÿ†ÿðÿ¡’²ñ>†µ¸ ú  Û 2 £ÅŽ Rýpú}÷ôÀñ$ïÑìÝêXéQèÒçâç‚è±éhëœí=ð:ó}öñù{ýq­£ = n(cTT1¶ó þ ë Î½Ë ‡Qÿmþáý®ýÐý@þõþàÿðB[S–Æœ%Ø/4õý€ûéøDö¨ó+ñäîæìFëê^é.éˆépêáëÔí>ðó5öšù(ýÄWÇþ å j| ¥¢°æÒ‰ ­Fþéÿ’ýeü•û$ûûNûÚû¤üýµþØÿòôËg¼¾gµ¨E•þ¤ü€ú=øîõ¨ó€ñïâí’ì¬ë>ëQëêë í«îÈðUóBö|ùíü|›÷ Ô-j;|1_P2Ê+ m §îYûþãüû¸ùµøøß÷ø{ø;ù3úRû…üºýÝþÝÿ©5vdû<+ÿÏý3ügúzøöô¹òñ³ï¨îîÏíîÙîðÜñô¨öšùÐü4±.‘ à ¬8Tò€ä¾•Ú ë ßÏÑüþbüú#ø—övõÃô|ôœôõäõòö.øˆùêúCüýþcÿðÿ.°ÿöþñý¬ü6ûùô÷NöÀô]ó8òcñìðßðDñ òró8õh÷øù×üóÿ5‰Õ  ÷Ÿä¶Ëþ­4?Û á”HÿüOùãöÙô<óòbñ%ñWñîñÝòô„õ÷¹øXúßû=ýdþFÿÜÿ ©ÿùþþÞüû+úÅøo÷>öCõô3ô7ô¥ôõËö€ø—úý½ÿ¨¶ÍØ ¿jø84¥…Ò’Ì‹âá Ÿ 4¸DÿïûÑøþõ‡ó|ñçïÏî5îîqî8ï^ðÓñ…ó`õO÷>ùûÍüKþ…ÿq K8Ô)Cÿ/þýÆû–ú‚ù›øô÷š÷˜÷ø÷½øèùvû_ý™ÿ¿†S  ¦þ¤Ðzš+.§Ÿ"A  ¥ÿúûšøyõ«òCðMîÖìãëvëë!ì(í”îTðTòôÅö ù<ûGýÿ¨æËV‡aí6K<ÿúýìüüPûâúÄúÿú˜ûüãýŒÿ° „þ f ¦ª[ª†ä¼ Ï×/ + Þ_Çÿ,ü¨øUõHò–ïRí‡ëBê‡éYé´éêäë í³ïò‹ô%÷¿ùDü¡þšCjo„«¦…\=<ÿgþÏýý‚ýÜýþ™ÿô–t{›¿ Ò ¿qÕÚq.Iâÿ¨ ë Úˆ ü÷øŽõ]òzïùììê^é[èèçè®èÜéƒë”íûï¥ò{õføNûþÀ#6îA+ ¬ È „ íýÆ9þ)˜ÿRÿ_ÿÂÿw}ÉOÊ› _ kV¸¨ ž ¬ N ”ŒLëü~ùöçòìïEíë>éûçFç"ç’çèê ìoî'ñô?÷qú›ý¦~K# ‰  + Ý 4 ;  £(¨7çÇåMoD£ §& ‰ ¼ ­ M d Ë ¾ @ V g€iý6úÿöÜóäð/îÒëàéhèwççFçèXé*ësí!ð óYö¶ùýw­§S   îáY[íò … å ' ^ þŠRbÃÿwÿ€ÿÛÿ€e~¹Q‡–k ö + l o<¢ñýû!ø0õVò¬ïGí<ëžézèÝçÍçOè`éúêížï‰ò¿õ*ù±ü:°øþ ­ õÉôGylOd W <(0dÕÿœþÿý»ýÍý/þ×þ¹ÿÃè22ѺDk0˜¬yþ üyùÔö3ô­ñVïFíëEêsé%éaé*ê~ëVí¨ïeòzõÔø[üöÿK E à ¼è‹¥;TþHC ¢ 1ÇxYyÿåý¦üÄû@ûûHûÆû„üvýˆþ«ÿÈѱZ½Ð‹ëïœúþýøú¸øhöôìñëï.îÈìÊëAë8ë³ë¶ì=îAð·ò‘õ½ø$ü°ÿHÕ< f >¯«$tG‘\´ªP¼  ?„ç}ÿVý€ûúðø?øñ÷økøù ú#ûSüˆý°þ¸ÿ(xvonÿþüÈúßøåöïôó^ñìïÍîîÃíîí˜îÁïgñ‚óöéøüpÿêjÕ  ±æ¡ÔyŒ}€"u Šzw™ÿòü•úøîö·õîô‘ôœôõÃõÃö÷÷Kù­úüJýcþCÿÞÿ+&Îÿ"ÿ*þðüûíùDø›öõ—ócò{ñïðÊðñÚñóÂôÞö[ù+ü=ÿzÍ T Xo[ɬÿ¾í‘µh¼Ä ˜ OÉÿºüéùj÷Kõ—óVòŒñ7ñRñÔñ²òÛó@õËökø ú–ûýü/þÿÃÿ¿ÿÿ6þýÍûkúù§÷lödõ ô/ôôvô;õoöøúrüÿÿ!2 #ÞKXò œ›æ<€‘ \ ø~ªüù›öôîñ?ð ïXî îaîï$ð‰ñ/óõíöÜø»úwüþHÿCë>:åGkÿ_þ3ýùûÅú©ù·øø–÷‚÷Í÷~ø•ùûèüÿ‚&ëº ~ ‡¡Y g¥Uw ºí Ì kãMÁüWù'öFóÇð¸î&íìëˆëìñìGîöïêñôMö’øÈúÛüºþU£š7xcþSqgIÿ&þý!übûåú¶úÞúdûJüŒý%ÿ 2‰ýz é 5HsjäÙE'„cÒ à ¡*”øünùöðò*ðÌíçë„ê¬é_éé^ê™ë?í@ïˆñô—ö1ù»û!þN5ÉÚPg(šÍϳŠh`ÿ‚þÝý~ýpý¹ý[þUÿ¡7  +Q k c$›¶fŸY‘E{; ’ ‘KÕIý¾ùLö óð€íXë®éŒèùç÷çƒè•é"ëísïòÝôÄ÷­úƒý/ŸÃŽõõ‹ » Š  4+û¶o9'G¨ÿSÿPÿ£ÿI@€ü§pB ¶ /cAºÃUk+ ã :@ ­ý@úÛö˜óðÒízë—é7èbççoçNè´é–ëãíŠðvóŽö½ùêüýÿàϼ > O ï ç P g = ãmîy"ø c Vöß_Ø`äO Ž A — …   § Ó™+þìú²÷ˆô„ñ¾îLìAê­èžçç-çÐçé¹êéìƒïqò õ÷ø]ü¼ÿù¾  ª<VÿB+Ë 6 } ·öNÑàÿ„ÿ}ÿÉÿ`;K‚ÍXpS ï 7 ¢ ºh°›5Žþ·ûÆøÑõïò8ðÂí¡ëééªèïçÀç"èé‘ê‘ìïÜñõdøçûrÿíAV  wdÕÆ5#š£M¨È  ©”–Á&ÒÿÎþ þËýÍý þ»þ“ÿ—¹åëˆÙÕq¬„þ"ûþ—ü úe÷Àô0òÍï«íàë|êŽé#éAéìé"ëßìï¿ñÃôøû(ÿÁC•   Q–aªj¡S‡H¦±~ # ´HôËÞÿ:þëüöû`û&ûEû´ûgüOý]þ}ÿ«•J¼ß¬3ð]ÿ‚ýnû3ùãö”ôZòLð}îííëJë$ëƒëiìÔí¿ïòåôø]ûäþ| ~ ¸ £,BØåeV½£ÔK › ØvÌýæûYú/ùiøøø^øùåùõú!üVý‚þ‘ÿrw†> ­ÿlþæü(ûDùK÷Põjó«ñ)ð÷î$î½íÎí]îkï÷ðûòkõ;øWû­þ#¤ a m$rIš^‘2GÙõ«4 4 %8…ýûùJ÷ýõõ«ô¡ô÷ô¤õ—öÁ÷ùoúÌûý5þ!ÿÊÿ&1èÿLÿaþ3ýÌû<ú•øéöLõÓó‘ò—ñöð»ðïð™ñºòQôWöÁø‚û‰þ¿e¤ µ‚ôú„‡ùÙ&è'ñXo M ¼}eý†úõ÷Áõ÷óžò»ñMñQñ¿ñŠò¤óýôöø½ùMû»üøýõþ¨ÿ Óÿ?ÿdþNý ü«úAùà÷œö‡õ³ô0ô ôLôúôö¢÷“ùáû~þW[tŠ … MÎò¦ÝŒ«74¦™> »DËhý1ú<÷žôdòðPï€î/îWîðîîïBñÛò¥ô‹özø\ú ü³ýÿÊ-:ôc’ÿþeý,üõúÒùÖøø—÷p÷§÷CøEù­úsüþóP ê • 9 iMªy¹lšN–… 0¯ŠýúÙöæóQñ)ï|íPìªëˆëèë¾ìîœï‚ñœóÖõøSúnüWþ]egb n•’vÿRþ:ý@üvûêú«úÂú5ûü8ýÁþ™¶wõ j Áã»8GÝðyyñêp‘ `ôbÆý5úÊöóÂðLîLìÍêÖéléŒé1êSëãìÑî ñzó ö¤ø2ûŸýØÿÍr½¨2\-®íøà¹”†ÿžþíý€ýbýšý+þÿQÚ¤Ÿºâ  Ó\U©Ò¢òÊ 6 F žþ†ú ÷Àó¹ð îÊëêÄèèðç^èSéÇê«ìîî|ñ@ô"÷ úæüœÿL)¦»f ª  UW.ì¥kQg»ÿWÿEÿ†ÿ9«Oè¶ j ð 5'¶Ø„´h¦ s ÜòÆoþû™÷Lô2ñdîõë÷éyè†ç#çSçè]é%ë\íñïÏòßõ ù8üQÿ?ïNP è  È  ì h r " ±3¼^+1|AҮˑ  ] m 2 œ   6 Y K $£ÕÎþ¡ûgø6õ'òQïËì§êøèÌç+ççŸç³èNêeìéîÆñèô8øœûþþCW%› ª HnM e` „ Ò LŸÊ¾”ÿ}ÿºÿCK”ä&H8 ä ? < Ô  Ä Å*ÿZükùtö‹óÇð@î ì;êàèè¹çüçÏè/êìoî3ñJô¡÷û©þ)†ª ô ù†’&µÕ“þ* +  ý yÿDþÞýÏýþ¢þoÿlжÜìÑ|Þë›êÕa•{ÿ!ý™úö÷Nõ·òGðî4ì¸ê¯é'é'é´éÌêmìŒîñôN÷ÅúZþõ~Üø ½eC˜f´ÿõ ¢ 7 Êq?E“þ2ý,üƒû8ûFû¥ûLü+ý2þPÿq„w7·ëÉMtB½ÿîýäû­ù_÷ õÊò°ðÒîCíìYëëYë"ìqíBï‰ñ<ôG÷˜úþ®D¾ £Ó…°O^ãämŒTØ / p°‡FþOü°úqù—ø"øøTøêøÁùÉúðû%ýSþhÿSs’[Íêÿ·þ=ýˆû©ù±÷³õÅóüñkð%ï<î½í´í'îïðxòÓô÷Ÿúêý\ÝU« Ç’ùêY<O‚0d/£Õ Ü ÐÇÙþŸûvù«÷HöRõÉô©ôíôˆõnöŽ÷Õø2úûÜüþýþ³ÿ9sÿ–þtýüŒúæø8÷–õôÂò·ññ°ðÌð]ñfòäóÔõ+øÜúÖýSªñ ìt”:ZììY8’uð Âv3þ&û„ø<ö\ôëòïñiñVñ®ñfòpó½ô8öÐ÷oùûxü¿ýÈþŠÿüÿäÿ^ÿþƒýGüêú€ùøÎö®õËô5ôûó'ô¾ôÅõ:÷ùSûáý°¯Æß ã ºL†U¨u³`{ ±çÎ | &þåúá÷/õàòñ˜ï®îBîQîÓî¼ïÿð‰òJô+öøýùÇûdýÅþÞÿ¦6|·ÿºþ—ý`ü&ûýù÷ø&ø›÷b÷…÷ øúøNúüþeùµ…S ͳ--§•ôÆÜ:: óyæTþÙúŽ÷ŠôßñŸï×íìÌëëÓë‘ì¼íFïñ,ó`õ¢÷Þùÿûòý©ÿ.íR^†¸¼£ÿþcýaüŒûóú¤ú©ú ûÉûçü`þ*;ƒðo é Jzd÷ѧÄYm >  »0”þþú‰÷Mô^ñÒî¸ìëêéé êë‹ìfîðôò~õø§úý_ÿbusM/À  èÁ®ÿ½þþ…ýWý~ýýýÖþ>2Jr – ¢ _?¬ž ùcTÕ ÷ÊeßþOûÏ÷wô^ñœîAì_êé1èñç?èéqê>ìmîìð¥ó‚öjùIüÿÒÁR|= – ‹ ' t‚`#ÜŸ}‰Ñÿ^ÿ<ÿmÿõÿÍô\øº_  ® ®è­÷Æ ÿ |¡€0ÿÅûXøõÛñûîuì]êÃè±ç.ç>çàç éºêÚì\ï+ò1õWø…û¤þ›YÊߎ Î û í } µ ¥ ^ óxÿœ`[˜"ÿÿ.°ÙJÐZÔ ) H  œ · d Ÿ g ¿ ¬<|~ÿWüùæõÍòèïNíëJéè@ççuçjèèéæëSîñ3ôz÷Üú?þ‹«‰ 7 í -ò>ƒ‘P Ð & f£ñc ð"§ÿ€ÿ­ÿ(ëé[¬ó Ö B T  D ›SÄÿüüú÷(ôZñÃîzì’êé&èºçÝç‘èÓéœëßíð•óßöUúßýcÉúá l Š0Xþ"ÌÔP‰ “ ‚ le€Î^;ÿlþõýÕý þ‹þMÿB[†°ÅµmßþÁ$#Áùÿªý(ûˆøÞõ?óÄð‚îìúê×é2éé‚é}êìî€ð^óöûùŒý(· K %™™ˆrÛÍT‚j ¹ Lï´¯ïþ~ýeüªûLûIû™û2üýþ#ÿE\W"°ôãy²YþXü(úÛ÷†õ=óñ*ïˆíDìmëë6ëâëíÊîúð—ó‘öÕùMýáyûP _^,u2`ÁöÐb  G™Âþ»ü û¸ùÊøAøøNøÔøŸùžúÀûóü#þ?ÿ2ñm›u÷$ÿ‘ýæû úøö#ôOò¯ðXïYîÂíŸíøíÐî(ðúñ?ôéöèù)ý•“ó üz††f·Î¯5t ƒ zp|´þ)üîùø—öŠõëô·ôæôpõGö\÷œøõùSû¤üÕýÖþ™ÿ=—ÿÉþ²ý^üÛú8ù‰÷áõUô÷òÜññ«ð¯ð'ñò}óVõ™÷9ú&ýL—î; d Rï'é'Ùø…‚øô„¼± {0êÁþÉûù¼öÅô<ó(òŠñ_ñ¡ñFò@óôñõƒ÷"ù¸ú3üƒý™þiÿêÿòÿ{ÿºþ¸ý‚ü*ûÀùWø÷×õæô?ôðóô‡ôwõÕöžøÈúGý 4 ? "ÆýlWµ»h‘BŒƒ < ÏUçþ›û‰øÅõ`óhñçïâî\îQî»îï¿ð;òñóËõ¶÷ùmûý€þ§ÿ0 “ÚÿæþÉý”üXû)úù=ø¢÷W÷g÷Ú÷³øòù”ûýÛÿcé» y \X럫)eÚí ³ B³ÿûFø1õròð9îÕìöëœëÅëiì}íôî»ð¿òëô+÷hùŽû‹ýNÿÉòÄ:W œÙäÐÿ¬þý…ü¥ûÿú ú“úáúŽûšüþ¾ÿÂjèg Ï  °ò¾ Ï »éžè × übÿÉûKøõò]ï)íqë@ê™é}éêé×ê8ìþíðqòóô‰÷ú–üäþôº):ë:.Î&D9ï×ÿÞþþýOýeýÓý›þ¹ÿ&ÚÆÙ ) = 'Ò,#ª·BJÏÙp ¤ ‡+ªÿü“ø0õò1ï¿ìÂêGéWè÷ç'èãè!êÕëðí_ð óâõÉøªûoþUVú9 } † 3 ©‘XÒ«­éÿhÿ6ÿWÿÎÿ˜± ¢_1 Ë i Íå óÑ5Œ †  M9ðÿˆüù»õˆò•ïúìÉêéâç@ç0ç³çÂèTê\ìÊîŠñ…ô¦÷ÓúöýöÀBk/ † l â ê × Õ ™ 5¼CÛ—†·1ÿÿ‘RX˜ˆ“ ó   ˜ É á À . 1Ò - ýÒù™övóƒð×í†ë¢é;è\ççRç(è‰élëÂí{ðó¿öú€ýÒüé„ ¿ æÅ*¿  y ¼úD¯J$H½ÿ†ÿ£ÿƺß"s¿òùÄ B g ) ‚ põß[œý¶ú½÷ÈôðñJïîìïê^éKèÁçÄçYè}é*ëTíìïâò öŽùýœ H@ ß ÕÙÜ+Ÿæ ù í ØÎâ&¨wÿ—þþÞýþvþ-ÿ-V‚ž–[Ü äZlrt1þ·ûùnöÊóEñóîììAëêCééWé4ê›ë…íçï²òÒõ4ù¿üZîa› ‡ -Êâqyý¥æÛ› : În,MÿÌý¢üÔûdûPûûüæüßýöþ35 ¦ùù¡ìÜuÁþËü¡úXøö³ó‚ñ†ïÑíwì‡ëëë§ë¾ìXîoðöòÞõù„ü­6— · ãÍ3\U\IêT ž Þ,›Aÿ+ýhûúùcø(øKøÁøùtú‘ûÁüóýÿÚc¡‹[FÿäýCüqú}ø}öƒô¥òøðï{îÍííÎí‹îÈï‚ñ¯óFö5ùjüÐÿNÏ7 o `õÄåvuåË3*Ã) $ Nÿ¶üjúxøëöÈõõÈôäô\õ$ö,÷dø¹ùûkü£ý­þ}ÿ?%¸ÿùþïý¥ü)ûŠùÚ÷.ö™ô/óò(ñªð–ðõðÌñóÜô ÷™ùxü•ÿÚ2„ · µeµ’î¾ýªÆXm^` 2 ê¢sÿoü®ù?÷3õ“ógò°ñmñ™ñ)òóDô¬õ8÷ÔølúîûGýhþFÿÖÿþÿ–ÿáþêý½üiûú•ø:÷öõLôêóêóTô-õuö)ø@ú°üiÿWi‡™ ˆ<ŸŸ*3°œõÀÎ-4 ù “¨ÿTü5ù_öæóÖñ;ðï{îVî§îeïƒððñšómõU÷=ùûÀü8þnÿTé'¨ûÿÿúýÇü‹ûWú@ùWø­÷Q÷M÷«÷pø›ù*ûýQÿЀM! æ …ç÷£Ú»Weèéu› p êÿbüùÝõ óœð î í%ì¯ë¼ëFìCí¥î\ðTòxô´öòøû#ýñþz´—M%°ø üÿÚþ¸ý©üÀû ûŸúú½úWûPü§ýSÿJä`â S œ©e¾¥ðH`. Ž EÈ/”üù·õ¥òíï íÍë~ê¹é€éÏé¡êêë›í¤ïðñjôüöùügþ„YÚþÁ$*Ú?hdDÿ-þ—ýJýOý¬ýcþqÿÐwZh» Ö Ë†ô£Êr•6X O @ðtåüZùíõ¶òËïBí*ë’é„èèè´èÖérëxíÖïvòDõ(ø ûÖýtÕæñÝ` } = ©ÏÀIÚÓuÿ3ÿDÿ«ÿepÁMÕ­ x “½Žøïnpø ¯ öï¯KýÛùvö7ó5ð…í;ëhéèYç)çŒç}èôéäë=îìðÛóõö!úFýN%¶òË 9 7 Ä â š õ  Ò u†Ï´ØDt'!X½?ÌQ º ó ê Ö ²   ™ ±eÂÚÀý‰úL÷"ô"ñdîýëê|èçç6çìç0éøê6íÛïÑòö\ùÀüKEóC ( š’³èÈ b É  P˜üŽ[pÖÿŽÿœÿûÿ£ªé:‰ÃÖ¯ > v N ¼ ÀZŽgð<þ[ûbøjõˆòÕïfíQë§éwèÎç³ç)è.é¾êÎìPï3òcõÈøLüÕÿI“› M štÒ¯ èOKë@] W D7EõµÿÅþ+þêýÿýdþÿòÿÿ&StvG׌²vÜí¶þEü¬ù÷WôÈñhïNíŽë7êZéé2éñé;ë íSï òõnøóûÿ#Ÿç æ ‡ºs¨Ty=ñEJ º Pí¥Š¯ÿþâüü€ûYûŠûüÆü¸ýÊþìÿ ñ™û Æ#$Í(ÿ<ýûÔø}ö*ôðñæïî¯ì§ëëësëmììíéïYò.õVø»ûGÿàoÛ échëåP/„Z½¾nã 3 u¿'ÂÿžýÊûQú;ù‰ø;øKø²øbùMúbûüÂýçþìÿÀW¤žCŠÿ5þŸüÔúäøãöåôþòDñÊï¢îÝí‡íªíLînïñ$ó¦õ„ø­û ÿ† y ¾ Ák«p¯_~ ’¡M©Í ÍÃÅëÿFýêúåøC÷ ö>õÞôåôKõöÿö.ø~ùÚú1üoýƒþ_ÿöÿ>4×ÿ'ÿ*þëübaresip-1.0.0/share/sound3.wav000066400000000000000000001047741372575704200162220ustar00rootroot00000000000000RIFFô‰WAVEfmt D¬ˆXdataЉÙ’ (ÏírV˜;KÖó¹E ´ #®o}ëþÃýýÎüýü’ý|þ§ÿýeÃþü¨ðÅýaVìþ5üKùJöOózðçí³ëöéÇè3èFèédêbìïîóñWõûøÃüŠ4¡µ W vøTZ!†  Œ fIP”(}ÿJÿ…ÿ&!dÚjùlª š ' @ Ù ë wJ1þäú‚÷)ôúðî‘ë‹éèDçççÉè“êëì»ïëò\öïù„ýû8 œ ›  ÷ P"y g  a ¡Ü-®t‘ZB·g= ï ” ò ò‰ñ K  q`þiý¾ùö©ò~ï¹ìsêÀè®çFçŠçvèýéì™î}ñ¡ôä÷(ûOþ;Ö Æ » ñ ¯  û²?½G÷äÿ"ÿÀþÉþBÿ)y%Dˆ Ë ð ÜsF`àÄÇ ÿ ËC…²üçøGõðñþî‹ì¨êdéÆèÐè{é½ê…ì»îGñ ôìöÉù†ü ÿ9bE¯¤-[A÷–8ÿøýíü/üÐûÜû]üUý¿þ“Á6Ù < ÀÿßF"düUT –Óùÿ&ü|øõòï–í5ìsëQëÈëÌìLî1ðaòÁô4÷ùàûæý™ÿèË;;Ðõÿ©þ?ýÏûvúMùkøæ÷Ï÷0øùpúIüþ0*K ] @Ö³ÎIBë ÷ Œ ç)rÿàû“ø¤õ+ó7ñÕï ïÒî)ïðFñäòÁôÀöÇøºú~üÿý)ÿîÿG2´ÿÔþ¢ý1ü˜úñøW÷äõ³ôÛópóóô:õåöù­ûªþì[Ö> uZÓÉ'âðS1Êò [ Ù^ ÿõû;ùñö&õãó+óýòNóô5õ ö9øçùûý^þ\ÿüÿ4ÿÿ]ÿTþñüEûeùk÷põ’óëñ–ðªï9ïSïðBñósõHø€ûÿ®j † ©_* l sVËì Ù ¯‘Öþqüxúöøó÷q÷k÷×÷¤øÀùû‚üôýNÿvXá¶÷Ëÿ8þNü"úË÷bõóÒðãîSí:ì©ë®ëQì”íqïÜñÆôø´ûÿ[#º Û3÷šu²_YØ ' f±%Ûèþ[ý@üœûnû°ûUüLý€þØÿ9Œµœ-WNiXÿïüHúz÷£ôßñNï í4ëÛééïèoé•ê\ì·î“ñÛôqø8üÕlµ – úÎ ¨ª{—s ) ØœÄRHÿ«þþÀþeÿ_œ‚÷I_# € g 扵þ¡ûjø,õ òï‡ìaêÂè¼ç\ç¦ç›è3êbìï2ò õ@ùðü‘.ô A =ßñ}? ¡ Ð ç>¯m†÷ÿR1˜5ï«N ¾ à Ÿ è ­ æ ‘ ³ U‡`ùýnúÞöjó1ðQíåêé»çç'çÞç9é)ë›íwð¡óüöfúÂýñØ_u  ¡ ¤ 0 R ! ³"Ь–Öÿxÿ‡ÿì8غÆã ô Ý ƒÍ¥øºåwv ð ôšþ=ýwùÌõ\òFï£ìŠê é2èèzè‘é9ë^íéï¼ò»õÈøÃû‘þBÿD W,˜¬}#¹Yÿþnýý=ýÎýÒþC:š ¦ XGÎÕM(bûúmf ýNyžüÜøSõ#òcï*í†ëƒê$êeê>ë ìvî¨ðó´õRøÛú3ýCÿöA|mõ# ¾ÿZþùü´û¤úáù~ùŠùú û‡üqþ¾]3(  óϞ攟¼Øcr ~¸ëÿ5ü·øŒõÏò’ðæîÒíXíuíîFïÕðµòÊôùö%ù3û ý”þÂÿ†ÝÄCeÿ9þÔüOûÃùKø÷ö\õ'õpõ<ö÷dù¯ûbþe¡ùN €p©˜Þyi¹v¶’ & ‘ómÿüùöcôÍòÆñNñañóñóòNôêõ­÷{ù:ûÐü&þ)ÿÊÿËÿ)ÿ%þÌü1ûkù“÷Åõô°òžñúðÔð9ñ.ò´óÄõQøKû™þ Ãb Ý ëGBÇ Ðabè ë £Sÿaüú1øÓöùõ¤õÊõaöW÷–øúŠû ýmþ˜ÿvø½úÿÌþ?ýcûNù÷Ýô¸òÆð#ïæí%íðìQíNîæïò½ôÛ÷RûÿÔ I ¯ ´@> [oÞ³þÔOŠ £ ¸èLþþý’û‹úúìùGúû üLý«þ YvLÈÜ~ªb¯ÿžýBû±øöaóÜð•î§ì,ë8êÛéêëì²î^ñ~ôú÷µûÿf ¨ I`àÀ£¶GnBà d ë’r /ÿ(þ”ýrý½ýjþiÿ¤sÑû™ÍŒÍÙ±,ÿ[üYùBö4óNð®ípë­éxèâçóç¯èêì›îñýôœø\ü»$ º ÌO:R[Ç î ë ÙÖú]*­ÿžÿûÿ»Ò.¸Wði § “  " ª © ”±‚þ"û¯÷Gô ñîë„é è5ç çŠç²èyêËì•ï¼ò!ö§ù-ý“¾“üç L # p 8 Š w  ~̃Açÿøÿu\¡4ÿìà ¿ m ÐÐY[Ϋö ¸ þÜlÊýújöîò¼ïóìªêõèâçxçºç¢è$ê/ì®î…ñ™ôÊ÷úú þÞ`zBå ¸ôª<Ä] &ÿþ<þeþÿ |H\¡ý U Š‚ NøŠf¨X‡ J»÷ýQù°õYòhï÷ìëÔé7é@ééé&ëåìïŽñAô ÷ÐùrüØþê˜ÖìÉ>\7ç†ÿ,þöüúûPûû/ûÍûãümþ_¬=úÇ ‡ hQ¾à~uËŠÄŽ Biœü÷øšõ¡ò"ð/îÔììùëpìqíêîÅðæò4õ÷ßùüìý}ÿªk»œ4 ÿ°ý:üÅúkùGøo÷øöóöj÷bøÛùÎû/þééH j [ý5ê ‡Z‚ïPAÜ ?ŠÞÿZüù:öÏóéñ“ðÒï£ïþï×ðò¯óõm÷^ù7ûßü?þGÿéÿçÿFÿGþøüoûÂù øgöïô¾óêòˆò¥òLó€ô>ö}ø/û@þ•Ÿ UCý ÜîS9Ù å ‹ ¯mÿnüÉù”÷Ýõ­ôôåó@ô õ-ö”÷%ùÄúWüÅýõþÔÿShJÿþœüÒúØøÇöºôÎòñÄïØîkîŒîBïðqòÜô¾÷û‘þI ¼ 6 ]HãÚ'ËÍ:&¦Ö Ô ¾²Ï.ÿåüûžù´øIøVøÑø©ùËúü‰ýòþ<Q‰ ?ñÿ=þ4üëùy÷ùôŠòFðLîµì˜ëëëµëþìáîTñEôœ÷?ûÿê´I d¹z›ó3åô‚ æ ; 00ÿÃýÇüAü0üŠüDýKþŠÿçJ˜· !¾â‹Á’ÿ ýKúe÷xô¢ñï´ìÓêué¬è…èé-êõëQî.ñuô øÍûŸÿ^í-  ^)]õôbOÍõ à ª qO^µf~ÿÿùþZÿ.ú‚üOa  j @ • d°„îÿØûŒø<õ òïpìCêžè”ç1çyçlèê.ìÜîôñZõïø”ü'Œ¥Z — N v œ® ` Ê  0a¶F$`–z¶: 4 © Ì ‡Ç¬ G V æÍVþ»ú÷ ó^ðwíë éÖç4ç=çòçHé2ëœínð‹óÖö/úxýaÒÐP K Á ¶ 7 T !·/¥3òøÿVÿÿKÿëÿöd$#I{ ž ”C’jºv˜  zo§ýÙù*ö·òŸïüìãêeé‹è[èÐèãé„ëŸíðáòÍõÃø§ûZþÄÒsJ~@œ¤o®Yÿ+þ>ý¦üsü®ü_ý„þKÇc  †ÔÎ\gß¹ð„~ëß sÁëýPùÌõŸòåï±íìë·êøêÏë*í÷îñóö‰øöú1ý!ÿ´Ý–Ú¯7 ¶þLýéû©ú£ùïøžøÀø]ùwú üþ}6&1 : !Éí9ë÷Y0»Ëx ßX­ü9ùöhó8ñ–ï‹îî:îäîðñdójõ„÷˜ùŠûBý«þ·ÿW‹Q°ÿµþoýöûaúÉøL÷öõjôBô›ô{õãöÎø0ûùýcÍ2 qm)º¬ö’…ØšàÄ b ÙJÔÿ”ü¥ù÷õŽó–ò+òGòÞòàó7õÊö€ø=úåû`ý˜þzÿùÿ ±ÿíþÇýOü™ú»øÐöóô?óÐñ½ððþïmðoñó$õÂ÷Ìú)þ¾n › Ùµä›vª?G×ô ½_sÿÖüœú×ø÷Ëöˆö¾ö`÷\øœùûƒüöýDÿWxÊþý!ûðø¢öQôòðqî0ínì;ì¢ì§íGïzñ1ôY÷Øú’þg8ã I NÙÖ5ðvO¢ƒ X … ²û|Lÿ|ýü1ûÀúÄú4ûüý\þ¼ÿ\j-’Œ¶äÿ´ý;ûøÎõó}ð(î1ì¯ê·éYéžéˆêì;îêð ô‹÷Eûÿñ£ " ¼ÌF!]­Ý¿ o ªmkºjÿ…þþþwþ=ÿP ~Ýú‰¬U(UtÿŠüpùDö$ó/ðƒí;ëqé7èžç®çhèÉéÇëPîOñªôCøûû°ÿC˜‘  ”u¾‹ÿ 2 ? CX™ó.ÕÿéÿfG{ðŽ=âa Ÿ ‡   z g Ê ªÚþhûä÷oô(ñ-î›ëŠéè4çç„ç©èkê¸ìzï–òðõgùÝü0H\4 … M ‹ J – ‚ # ”ðPφ‰éÿ±ÿåÿ†ö§‘˜ … =¥¥+'bŸ S Š[Ý0þpú¾ö:óð8ííê7é#è¸ç÷çÛèWê[ìÏî™ñô»÷ÕúÍýˆïîx„"ÁýêŸ4ÆmEÿaþÕý°ýúý·þãÿvb”ôh Ó Ãõ µ+<ä Ç2jýÀùöÉòÛïlíŽëOê³é¼écê›ëRírïàñô5÷áùgü°þ£2Qú-ñR_.Øÿtþýòûûmú<ú}ú7ûküþ#:ô Ç kĶ) Píä7õ-÷ m®Ùýtùö/ó¹ðÏî|íÆìªì#í!î”ïdñwó²õø÷,ú5üûýkÿvC`fÿ(þ»ü:û¿ùdøC÷tö öö¢ö±÷CùOûÉýœ³ñ9 m kX8¸·;'ƒ% ‘çGÑü¡ùÑövôŸòWñ¡ð{ðÛðµñõòƒôGö$øú¿ûIý‰þoÿíÿÿÿ¤ÿáþÂýXüµúôø.÷õôÏòÿñ¤ñÍñ‚òÇó—õé÷®úÑý8Ç`á ,!§¥ ÊÝE 5Üþ ± PúÌÿâüTú6ø”öxõâôÐô6õö+÷øú¨û)ýþ”ÿU³¦)AÿôýPüiúTø-öôò[ðüîî¥íËíŠîãïÐñGô5÷†úþà¬a ß Áô†Ô{õéu´ Ä ÃÏÿRýûCúsùù@ùËù°úØû-ý”þôÿ/2å8‘Lþ$ü¾ù2÷œôòÇïÁí#ìënêwê#ëpìYîÒðÈó$÷ÊúœþyAÔ  ç6ò‹e§_¡ƒ" ˜ …2$qÿ$þHýáüëü_ý.þFÿõZ¤º…ðîrz Ôÿ4ýXúZ÷XôqñÂîiìêéPè'è§èÏé˜ëôíÑðô§÷eû1ÿèm¢ o ½~¨94¡‘H B þ÷%p«ÿTÿkÿëÿÉ÷_é|ýQ _  S  Z  IXUÿü¶øVõòïfì1êˆèzççZçKèÞéì®î¿ñõ¦ø=üÂÿÀë ‘ ª 44´ Å z ì 4o·&ÓÑ0úÿ/Ñ×2ÒŸ€[  ±i¢Qoú ù x‡>·þûg÷ßó–ð©í3ëJéþçZçaçèdéHë©ípðóºöú4ý6ïG.—} ß Å ; Q¶7º[1RÿÎþ³þÿÉÿ÷†fÀ = AùL%s)Dí ÿ‘âþAúŽöóð^íGëÊéñèÀè3éAêÜëíí]ðóéõÉø“û+þyiíú¨U œ`¢ÿUþ5ý[üÚûÀûüéü.þàÿñRé Q èDIÞíf?súcS ä2\„ýÇùHö"ónð@î¨ì®ëTë—ëkìÁí„ïœñîó\öÊøû8ý ÿz‚?÷LOÿ±ý@üÜúŸù¢øû÷¼÷ó÷¨øÝùû°ý40 L DùP.€5C¦a} Í :Ä#ý¼ùªöôáñLðKïàîï³ïÔðUòôöøúëû„ýÌþµÿ2Bçÿ&ÿ þ®üûyùÖ÷Röõ ôzó_óÇó¹ô5ö5ø­úŒýº™ X^(¾³ÿž”ë²ÿì – š5 ý.ú»÷ÃõPôhó ó2óÏóÓô'ö³÷\ùû™üúýÿÕÿ0¢ÿºþsýÝû úøö*ôlò÷ðãïEï-ï¦ï´ðWò†ô3÷Lú·ýYÇQ •tרÙa?v ¹öó ΧœÉÿEý%ûyùKø÷m÷³÷aødù¦úüýæþ!Æ åLCÑþýêúø6öÑóŠñïËí…ìÁë‘ëüëí¯îêðªóÚö`úþøËw Ý àhbÀyß9%¼ \ ¡£‘ÿàýžüÑû|û™ûüüüþlÿÍ(bbaA©˜ Óý>ûyø õÑò*ðÈíÇë?êCéãè(éê¤ëÌí}ð¢ó÷Øú®þ}( — )1£x°RiA1 ó £]=[ÊÿÚþˆþ¥þ*ÿ 3‘ …ç÷z ‹ 3Ã×{ÂÿÀü‘ùQöóðdíëBéèhçuç.èŽé‰ëî ñ_ôð÷žûHÿÍþw m Õ«î¨ã³ . l Š¢Ð.ÐÊ(òÿ)ÊÊ©]Ì Q ’ v ê Þ H $ u A˜Œ8ÿµû"ø ôNñKî³ëéèAçç‹ç­èjê°ìjï{òÇõ/ù’üÓÿÕ½€ ¾ t ¤ W † +¤ ~å‡ÿqÿÉÿŽºA, F A qsöìLEë  ÚQ™þÐú÷óVðˆí<ë…épèèBè"é˜ê“ìüî¸ñ«ôµ÷¸ú˜ý8ƒgÖÉ>:ÉùÞ‘*Ãyÿbþ•ý$ýý‡ýdþ²ÿfrÁ<Ç F œ«Z‘=PÔÈj‹ B ¨Üþ1ú‘ö>óTðêíìÔê;êEêêêìÌíàï?òÌôj÷üùgüþdÓÓ]tid'Éþdýüíú úˆùlùÆùœúìû²ýáÿf- û ¯ˆn´QG™VŽX ÑG‡ýòù§öÁóVñvï,î|ífíßíÜîHðòô;öjøƒúoüþcÿKÇÓt³ÿŸþJýÌû?ú¼ø`÷Bö{õõ:õÙõþö§øËú]ýGtÇ! d p'o0XÛ²ÞeT¾»e Û>¬Fý'úh÷õWóòuñXñ¿ñ›òØó`õ÷äøªúPü½ýÝþ ÿûÿéÿkÿ†þGýÀûú/øYöžôóæññÅðùð»ñóðôT÷+ú_ýÖt¥ øô~€è©¿*ò$Ó Ï €=%SýÜúÕøJ÷CöÀõ½õ/ö÷.øŽùû“üþAÿ;ÞíMBÿÓýü úÜ÷žõlóeñ¢ï>îOíçìíÙí;ï3ñ´ó®ö ú«ýtEÿ ªc–0&u(¢Ÿ8‡ © ¾â2Éÿ¹ýüãú.úòù(úÅú¶ûæü>þ¢ÿø'´ìµ èWdþü›ùööJô´ñSïBíœëvêâéìéšêëëÙíWðQó°öXú+þËZ • b¬b{òÌ͵ @ Ä_);©ÿ}þÂýzý¡ý/þÿ=•i°½{Õ½*‰†dýnúZ÷DôLñî+ì9êÐèèÕçUè}éEë¡í|ð¾óJ÷ûÅþsí Õ Íívk×ÈS š ‹•âzpÏÿ›ÿÔÿtp¸6ÑpøN Y  : ñ  Ä åŠÆ¯ÿ[üêøzõ*òïhì-ê~èmççHç6èÆééë‹î”ñæôdøìûaÿ¢—&? Ó Û W M Æ Ô Œ  Z¥ŒVu÷ÿäÿ=)¤`F; % è iDw.« › ±ÿiû·÷&ôÖðåílëé3èç“çAèŽéjëÃí}ð~ó¨öÚùøüãÿ‚ÁŽß®þÓ=K°9Ê|jÿ¥þ?þCþ¸þžÿîžÕ- ‹ Ñ â£üÖ"Õé`A› V‚þ¬ú÷öƒókðÊíµë:êbé1é£é­ê@ìGîªðLóöÚø‰ûþ5l\ÓÕl¦•Qóÿ“þNý<ütû û û~ûlüÐý¡ÿÑNÍ – >¨·SfâºìzmÓ R  Ì÷ý@úÇö©óýð×îFíRìüë@ìícîð(òhôÁöùMûJýúþI0¥«Enÿ þ°ü8ûÑù—ø¢÷÷Úö%÷ñ÷>ù ûFýæÿÐð% S Z}b¹qå¢ÀOe ß,˜ý>ú:÷¤ôòñð¯ïÜïŠð©ñ$óâôÈöºøúWüÑý÷þ¼ÿ…ÿ£þmýõûPú™øêö_õôóò~òõòøó‡õ›÷(úý[Ñ\Ý 5Dî´¬ûœ•ñ¾ À Tå’zý´úWøsöõ>ôïó!ôÆôÌõ÷¢ø?úØûUý›þ˜ÿ8q=œÿ‘þ)ýtû‡ùy÷gõkó¢ñ'ðïvîdîåîþï­ñêó¥öËùCýï´oÿ G)_‘ú4ÕìÙç ÕÄЮý©ûúùmøQø¨øcùnú³ûý„þÛÿêy¢[¡vãþôü½úUøÕõ\óñíî/íäëëðê_ëoìî`ð'ó]öèù¬ý‡[ j jïå@÷ bÄ»`Ð ( †ÁÎÿ=þýlü4üjüýõý#ÿyÞ6h[ú3úGufüýKûmø}õ›òäïuíjëÛéÛèzè¿è¬é<ëfíð=ó¹öoú@þ¬ ŽøÆúš³Vš˜ k 1@ÑÆÿ&ÿöþ4ÿ×ÿЀ‰í ó i k í éb^éÿüºùgö&óðQíøê éÞç?çJçè_éWëÚíÏðô¤÷FûãþZjÒ ¸ ÛÇÒ S Ëø?¹{–`$D³Z#ó¯ ; ~ _Í¶à  ÙšÿühøÚôñtîÖë¼é:è[ç(ç¡ç¿èvêµìeïjò¨õÿøOü{ÿfú!Íö ™ º b Ÿ †,­!¥Q<|ÿÿ(ÿ£ÿ‹Ún‹½ ê ô À37¹ªÀæ   YÆÿ5ûw÷ëó°ðáí•ëßéÊè^èšèvéçêÙì6ïãñÄô¹÷¥úkýðÿæ8mUÑôÒ¿ÿþ|ýÅünüƒü ý þyÿLwãx ­ .å!ÏáRMê ¸ Nrþ¥ú÷ºóÕðpîœìdëÎêÙê|ëªìQîYð©ò#õª÷"úpü{þ.|[ÆÀP„m#ÿ½ýTüûèùù øšø ùüùhûJý•ÿ6+ #åVZÙà ©žñ­æ³ 0 z³ûýpú1÷Wô÷ñ#ðãî;î)î¥î ïñÃò¹ôÎöæøåú³ü8þdÿ)kíÿ ÿÞýsüäúIù¿÷`öEõ†ô4ô_ôõJö øDúìüîÿ/” Q h)x>jðÊø‚våé  ¸ý«úþ÷ÇõôéòMò<òªòˆóÄôDöñ÷­ù^ûëü;þ;ÿÜÿÝÿ;ÿ4þÖü2û]ùs÷ŒõÆó;òñ:ðìï)ðøðZòKôÀö§ùêüpË` º¼JO¸|”ξ  ã ¦yw¾ý`ûrùÿ÷÷Ÿö¬ö+÷ ø4ù“ú ü„ýáþ êpŽ<zMÿ¼ýØû¶ùn÷õÖòÀðóî‰í˜ì2ìbì/í™îšð&ó)öù6ýÛ— Dü-Å» ³ÁBIîM ƒ ®ìX þ‘üûåúÂúû½û¼üôýOÿ°ÿ!‡¦S‰H—…þ"ü„ùÅöô\ñìîÐì"ë÷éaékéêpëaíâïßò@öéùºý“TÝ ×ÉÜP(m/‚}= Ü y.IØÿÎþ4þ þQþùþõÿ1– uºÀq»ä¹òo›ýŽúd÷;ô2ñhîùëê‘è¾ç‘çè6éþêXí0ðnóôö¤ú]þÿlˆ: n ,¬›÷ˆ Ï ç ìù)”NgéÿØÿ3õq²^î F O ò  Æ ä v ‚9 ¨ü&ù§õKò1ïwì5ê‚ènççDç/è»éÙëtîsñºô)ø¢ûÿ3Ž’  w a Ó Þ — wÔGéÑ´ÿÄÿA)r äâí ç µ <dEâèY; › '‡ÿÈû øuô!ñ,î±ëÄéuèÎçÒç|èÄéšëèí—ðˆó ö½ùÃü–ÿ?ò*âá=C ¦7Ô™ÿ›þðý§ýËýbþiÿÛ¬É  YxC¡~Éw†öÐ"  „Êòþûf÷òóÝð?î-ì´êßé®éê%ë±ì®îñ”óDöôø‰ûéýûÿ¬òÇ®Cáþ„ýFüAûŠú4úMúÞúéûjýZÿ¨A ñ Î ˆÿ¼ÔQ*Zæ×<* º :kþ»úJ÷4ô‘ñuïìíÿì­ìóìÄíïÁð¿òîô2÷nù‡ûfýôþ"å9›¼ÿ’þ2ý´û3úÉø‘÷¤öö÷õUö7÷ø€ú×üÿ’Ç O e3œ‰å ²Öö‰¤` Ü7‘ þ¿úË÷Fõ@óÅñÜð…ð¸ðiñ‡òüó¯õ†÷dù/ûÍü'þ,ÿÎÿÍÿ,ÿ*þÖüDû‰ùÁ÷ösô#ó.ò¨ñ¢ñ&ò9óÙô÷ ù¦üùÿ~¥ ϘéŠê¾á …(éçý7ûðø#÷ØõõÖôõÀõÊöø˜ù)û²üþFÿ#¤¼e ÿsþêüû ùèöÁô¶òãðaïIî¯í¡í*îMïñPóöJùÍüƒO¦ ðÔ9 =Ǩ拫Y±Ï Ò×ý]þ)ü³ú¹ù:ù5ùùeúyûÁü%þŠÿÔí½2=Øý±ýþïüšúø€õòòŠðfî ìOëˆêYêËêàë”íÜï©òäõsù9ýé’ò în_µi|òÙBDø { é`üÕ’þýýåü7ýéýëþ&†îDoVä·ê ß³-þaûkøfõpò©ï.íë„éèèaèNéàê í¼ïßòXö úÔý•/ƒv ó æF ;Ùò›è ó Ù µ¤¾Îæÿjÿ\ÿºÿzçiýˆï ì W J ¹ ¡ ç[rEýìùˆö6óðKíéê éÅç#ç,çáç<é1ë¯íðâó_÷õúƒþéÖ,  K 6á  ê q ÅD¤:YÿÿŽtµAàÂ Š  cCªŠÛ™ È q ¤vaü´øõ¹ñ¨îìéécèƒçNçÃçÝèêÆìlïdò’õ×øü)ÿýx‡/ ¾ Î i ž)°0Ňÿéþ©þÖþuÿð·ÂùC ‚ ›rìòs_±fƒ ( ×;tÿžûÝ÷OôñDîùëDê0éÄèþè×éBë+í|ïòèôÈ÷›úFý°ÿÀj \ qÛðÅp ·þ…ý‘üïû±ûãûŠü¨ý7ÿ*sûªc }¥d¥UgÖŸÊb{ * Œ¿äþû‚÷:ô\ñýî0íþëlëxëìDíãîßðó…õõ÷Súƒünþ-ë6‡¤{ÿ"þ³üGûùùãøø¸÷Å÷NøXùßúÜüCÿý÷6 ?Œ˜ Uõê=û6 ˆ Ùmþîú¼÷ïôòÕð ïïõîtïnðÐñ‚ójõm÷mùRûýfþoÿF mÿpþ&ý¤ûúZøÈöeõLô“óLó†óHô•õi÷¹ùxüŽÿâZÔ 3 Vt@oøÔ“‹ Ì ZÙh&þ,û”øpöÎô¶ó*ó#ó™ó|ô¶õ1÷Òø~úüŽýÁþ¢ÿ 4Ûÿÿíýnü­úÀøÀöÉô÷òdñ+ðbïï_ï9ð¨ñ¨ó+ö!ùsü¼v sy |A[̜ۜ÷ ì Ä­Ã#þàû ú±ø×÷}÷œ÷(øù>úœûýzþÆÿÙ  •±aÿ¯ý¬ûmù ÷ ôKò'ðPîàììë‡ëºëìÿíðœò§õùÁü•n+­ ÖŒºPC‘=NÕæ˜ R ”ìtDrþ ýü—ûûòû³üÀýÿ_Àì^eö¯à°þ/üvù öÉóñ‘îjì´ê„éìèöè§éþêòìuïtòÕõ}ùLý Û^Š G€(5¤yÀ†áé ¹ m "óúMþÿÿžþ—þúþ½ÿГ~ÁÁf   a ¡]›cÇÛý·úx÷=ô%ñNîÕëÔé`è‰çZçÖçüèÂêíîï&ó¤öKúùýŽíúœ Á \eÚÃ)²  + Ch³=Súÿ Šm¥"Ì‹E Ü 8 ? Ý ÿ š § ' °qúüiùÝõuòSï‘ìKê”è}ççMç5è½éÕëhî\ñ—ô÷÷_û®þÇ’÷æR 7 ” r Û â "Žú‚>B¢ÿhÿ›ÿ;G±j_u” ž x1ã ¡žØ + žóÿ,üiøÌôtñ}îìêÄèèèÆèê×ëî¼ðžó¢öªù˜üPÿºÂZw<î=:ûš1Ûÿ°þÇý6ý ýLýþ,ÿ¿°ì\æ n Ö×;d„X¤ | û>dÿŒûØ÷gôUñ¼î®ì:ëgê8ê§ê©ë.í!ïhñçó‚öù“ûÕýÈÿY1o<¦º7ÿÑýuü>ûDúžù\ùù8ú_ûÿü ÿv+ û ÅJn4´½H8œ‹  q¦Ýþ5ûÎ÷Ãô+òð™î´íhí°í€îÇïpñaóõ­÷ÐùÍû‹ýøþ¤Õ™ùÿþþ¼ýIü½ú3ùÆ÷ö¨õ$õõ†õ|öø÷ôùbü2ÿK•ñA d=°£ÂÖ>þ!¸Ù # ‰ñyþ?û\øèõóóˆò­ñ`ñšñOòlóÜô…öMøúÊûLý‡þkÿéÿüÿ¡ÿÝþ»ýIüœúËøñö)õŽó;òGñÇðÊðZñ|ò-ôeöù.ü’ÿ%Ìe Ð ï¤ÙyvÉppÖ±&ø ­c:Nþ¶û‡ùÑ÷œöìõ¾õ ö¿öÍ÷ù”úü’ýäþ÷ÿ¹•®ÿ^þ´üÂúžøaö&ô ò-ð¤î‰íðìçìwí£îgðºòõÉøVüç­F ’vÚ«ÜgIŠ5]}­ Äá œmþ¢üIûjúúú‘úhû…üÒý4ÿ‘ÑÙ”ðà\aõ!ÿôü‚úå÷6õ”òðëíìÆêýéÎéBêZëí_ï0òoõùÈü£tu kåÐ!ÑâYDµÂ…  Ÿ0èá-ßþýýý‘ýþýÇþÝÿ'üQvQÏàx‘,OfþûsøYõQò{ïôì×ê;é3èÍçèýèŽê¸ìhï‰òþõªùlý$³ûâ Q 9ŽKs(Õ+ E < /7oìÂýÿ¤ÿ¹ÿ7H¶Kíì  â B ' … Y ¦tÒÓ‘ý&ú±öRó'ðPíèêé»çççÎç&éëívð±ó"÷©ú(þ}C† I ‚ . R õ & ú † æ2ˆ²³Üÿ³»Å ”‡ [ ÷ @YžOo  ,ïk¿üùgõýñçî@ì!êšè¸ççôç éµêäìïiò‡õ¹øàûÞþ™ûðmhãâošy!®:ß·ÿÕþNþ-þ|þ=ÿjüã ]½  8š£# X¡ ­ T±äÿ üGø¸ô}ñ¯îgì´ê¢é6éoéEêªëŠíÏï]òõá÷œú+ýwÿjõ ¬Öçí¸_þþ­ý‡ü£ûûðú=ûü?ýìþþe Ñ  XÜ×ÏâO>Óé ˜ ú.Wÿ’ûø¿ôèñ’ïÌí ìì!ìÃìéí€ïqñ óóõLøŽú ükþÝÿ烮kÅÊÿŽþ&ý¬û<úðøà÷$÷Ïöïö÷°øQúiüéþ½Ï6 P.µÉUF’3*~>|Q Ù 3ÝþkûGø‰õFó‹ñbðÍïÉïKðEñ¢òKô%öøÿùÈûZýþ„ÿ¹ÿ÷þÛývüÜú(ùr÷×õqôYó¥òhò¯òóàôÇö-ùÿû)ÿ  8 d4gòÑ–”'ñ ޾þ«û(ù÷‹õ†ô ôôŽôtõ®ö$øºùWûßü:þQÿn_âÿúþ¯ýü3ú,øöô1ò—ðZï’îNî›îïúðó˜õœøúû™ÿY¿ $-ÀÈ3ùˆ]£mÕõ ì ØØ‚þZü¡úaùŸøZøŒø&ùúKû¨üþuÿ°¯]©‰õð~ÿ¬ýŠû/ù³ö3ôËñ™ï¸íBìKëæêëôëkí{ïò(õ™øMü#þ»; a>ÐÁºÏ\w6·  oá†uÃþzý¤üDüWüÑü¦ýÂþ pÐÛ9'žš0ãþFüsù…öšóÏðBîìSêé„èè?é—êìïòpõùàü®bÜþ ± စîÁÒ6J * óÀ®ÔGVÿÿÿœÿz¥Š„Æ¿ [ † 5 _ *Ú%!þèú•÷Iô"ñ?î½ëµé<èbç0ç«çÏè’êæìµïæò\öøùšý plý  ™äF: Õ 0 eÌ3ÛØ66ØÛ2É‹\# Ä # *ÂÛih × ¾ )*ÙSý³ùöªòï·ìlê²è˜ç(çdçIèÌéÝëgîQñ}ôÎ÷#û^þac;‘ b ¯  à â(ž¶‹­ÿ+ÿÿhÿ,Zå¾Îý0 K 1Çõ¦ËZM¨q ¹ “b”üËø*õÏñ×îZìmêéwèwèéZê ìZîíð¾ó®ö ùtüÿ_KÆÈO]ý</ì‹'ÝþÂýîüuüeüÆüýçþšª1 Î G_É«õŸ¥ Ù ô p°ÖÿÿûNøáôÔñ@ï8íÈëúêÌê;ë:ì¸í ïÙñFôËöJù¨ûËýžÿ¦ÅwÉÉŽÿ-þÂügû6úGù°ø‚øÊøŽùÑúŒü¶þ<    öˆµg‡ äŸôä z ÒNÿ°ûTøTõÈòÂðMïpî+îvîFï‰ð)ò ôö3ø<úü»ýÿïÿl{]ÿGþíüfûÌù8øÇö‘õ¯ô5ô4ô¶ôÀõR÷dùêûÐþþ\É( X<¶¯ÕìW@ÜÑ b ÕKåþ¼ûìøŠö§ôMóò@òƒò<óYôÄõc÷ùÓúnüÕýñþ³ÿýÿÿ˜þUýÅûþùø*öUô±òZñgðìï÷ï’ðÂñ‚óËõŒø³û&ÿÇz ´n¦HGœEJ´— $ Ì—„°þ1üú}ø_÷Äö¨ö÷À÷Óø"ú•ûýxþ¶ÿ°U—lÏÅÿTþ‰üyú9øäõ—ólñ‚ïòíÔì;ì5ìËìþíÌï)òõJøÞû¤ÿ{Eß +qApúÝ!ÒÇ= ¬á;ÔÂþýÚûûÍúõúƒûiüýâþDœÑÉp³ˆæÍANÿýuú½÷øôBòºï}í¥ëIê}éNéÃéÞê™ìêî¾ñÿô’øXü1ÿŸô ã U9„/=µ¤3 ® JõËâP#ÿcþþ6þ¿þ¡ÿÉ#—]{L»¹;;¼Åb§þ©û…øWõ>òZïÇì¡êþèòçŠçËç·èHêpìï;òªõOùýµ7rK ¬ ‡Ðƒ¤;Ue Œ •žÀ´« Ôÿ ¬«÷~&Öt ã Ó +  P  K M:åýhúãöwóBðbíóê é½çççÉçé ë{íYð‰óíöeúÒý²á ¶ S i  0  •þZÃS"BÄÿ¯ÿÍ÷y?4> B $ ÈóQ"] Ÿ ´iÙ"ýaù¹õIò/ï†ìeêÝèúçÁç2èCééêíïzò†õ¤ø´û›þ<ƒ^À¤ õs”n©?õÿàþþ«ýªýþüþKþJ¶- ’ ɵ<Iɰöª*/ Ï'Uzüµø'õîñ#ïÞì.ëêµéíéÀêìöí.ð¬òSõø¦úýGÿ†²öì¬Oÿíý¢ü†û²ú9ú+ú“útûÎüšþÊM ìÑ ›.l<ˆ=Q½‚¨<Qÿ c›Èÿ üøGõzò-ðoîKíÃìÕìví˜î(ð ò-ôlö­øÔúÈürþÂÿª#-Ë öþ¥ý.üªú5ùé÷ßö-öæõöÍöø¿ùðûŠþvžå, U@Ñí~sÂe]´v¹” $ ‡ÞJÿçûÓø%öñóEò*ñ ð¤ð*ñ$ò}óõéöÇøšúIü¼ýßþ£ÿþÿëÿmÿ‰þOýÎûúVø’öíô‚ókò¼ñˆñÛñ¼ò,ô&öžøƒû¿þ6Îd Ú çHQÞ¿÷Œ5 ¸Yôþ&ü¹ùÁ÷IöVõêôþô‡õrö¬÷ù©ú7ü¬ýîþéÿŠÅ“óÿèþ{ý¾ûÃù£÷yõ`óuñÓï“îÊíŠíÝíËîQðiòõøû*ÿò»d Ì ×ksÞ¤Á7^2¦Ö à ãûEÛþÏü2û údù6ù{ù$ú ûYü¶ýÿsŸŠP^7¥ÿ³ýsûûøföÑóWñï,í¯ëµêOêˆêcëàìöî–ñ®ô#øÙû²ÿŒGÄ æ ”¹F4+C×ûÈZ Í ?Íž ÿãý.ýìüý­ý–þÁÿßËîK+‘ˆÿfüzùvövóšðîÄëÿéÆè(è0èâè;ê1ìµî³ñõ²øwü>éYp  <ÑÍ0ÿF  nT^£8,ŒÿYÿ”ÿ40tê|…Ç » M j   ®¼Uˆoþ!û¼÷`ô+ñ=î²ë£é&èHççŒç®ènê¾ì‡ï°òö¬ù?ý¶ôÞ^ a Ü È (ÿ \ P ï S –Ô(ªqŽýÿW@µh@% ú £ ¡²5&† \ ¶¦F±ýúaöçòµïéìšêÝèÂçPç‰çjèèéòësîPñnô®÷ïúþœÒ’ÒŽ É ‹ áÞ˜(¨4äÑÿÿ«þ´þ,ÿc3{  í ß}¯`‚ öGD Óÿü2ùŽõ2ò:ï¾ìÒê…éÞèÝèé¸êwì¦î+ñêóÆöŸùZüÜþ Ú8Š =%ÛzÿÜýÐüü¯ûºû9ü/ý™þl›·q " ­óÚK0{#'ˆR•g á!FtüÇø_õYòÌïÊíaì–ëkëÚëÖìMî+ðUò°ô÷…ùÆûÊý}ÿ̯!"¸ñÝÿ‘þ&ýµûZú.ùIøÁ÷¦÷øáø>úüYþúâ÷ 3 ¹ð¨ÎR._ëÛB5Ð /r¼ÿ*üÚøèõiópñð3ïõîEïðUñíòÄôÀöÃø³úvüõýÿäÿ=)«ÿÊþ˜ý&ü‹úáøD÷Íõ—ôºóJóUóçóõ«öÒømûhþª™ A.°®Ûõb(Sõ$û ˜  Lÿ6üzù-÷]õôXó$óqó/ôMõ³öJøôù˜ûýfþdÿ<fÿ]þùüKûiùk÷mõ‰óÝñ‚ðïï*ïÏï ñÚò1õø7û·þe"Í G p-g  a †qî âÂÇ ÿ§ü«ú'ù!ø›÷‘÷ù÷ÄøÜù,ûšü þdÿpùÐæÿSþhü:úà÷sõóØðâîKí)ìëŒë'ìaí7ïœñ€ôÍ÷gû3ÿ Ør ¾ ŸÿÌùe¬bšlñ E ˆ×Lÿ‚ýeüÀûûÐûsüiý›þóÿU¨Ò¼O{5w?•ƒÿýqú¡÷Åôüñeïí:ëÙé éÙèOélê*ì}îSñ”ô&øëûÁÿˆ"o U ¾šÞ„øwš{ 6 鯢Úi_ÿÁþ”þÔþyÿs±™eF § “ ÿéQ?ÃïþÚû ø_õ6òDï¦ìxêÏè¿çTç”çè ê3ìÞîõñ^õúø¨üI¾é²  Ð µÎ`z. – É ä?²q‹ ûÿV6ž=ù¸` Ô ü À Ú  É ï •Ë¥>þ±ú÷¦ógðí ëéÍç#ç%çÑç"é ëríGðkóÁö)úƒý±™#<Ö é u ~  5  žzöžˆÈÿjÿxÿõÿÝ*˯¾Þ ô ã à¿ä¯µ 3 <åI‰ýÀùöòïÖìµê,éIèè}èŠé)ëFíÈï–òõ™ø’û_þåÏá0wŽa  @ÿþRýýý¯ý²þ"ö~ ‘ NEÔäeIŒ-4®¬ HœÇëü'ù›õeòŸï^í³ë§ê>êvêFëŸìmî™ðóšõ4øºúý ÿÓø\OÙî¤ÿ@þÝü–û…ú¿ùZùbùãùàúXüAþŽ-ýö Ót½•æŸ³ä œ±a È7üùÒõóÍðïþí|í’í3îSïÛðµòÅôðöù$ûùüƒþ±ÿuÌ´3Uÿ(þÃü<û­ù2øæöàõ8õþôBõ öY÷*ùsû$þ'e¿ OFàš“ä‰„Ý£ëÍ f Õ9³ÿaü]ùÁöžôóöñxñ„ñò ó`ô÷õ¶÷‚ù?ûÓü(þ*ÿÌÿÌÿ*ÿ&þÌü0ûgùŒ÷ºõ ô›òƒñÙð¬ð ñùñyó…õøûRþØ} Ÿ ܺö.½¡Ûv€9 ÚVSÿœüHúgø÷'öÍõðõ‚öt÷¯øúŸûýþªÿˆ &Ñ àþRýuû^ù%÷åô»òÃðïÔí íÎì(íî­ïÐñxô’÷û¸þ‡V l x ~C`Ù¸ êl­ Ê ãz-ÿ>ý½ûµú&úúhú"û)ühýÆþ(t’içý Î‡ÕÿÃýeûÒø%özóïð¡î¬ì(ë+êÄéþéÝê^ìxîñ8ô°÷hû@ÿÐI e +³œå‘¬EsNñ z ®¾LÿEþ°ýý×ýƒþÿ¼í%½õ·ûÁ æaÿü‹ùpö^órðËí…ë¸ézèÙçàç’èêéàëcî^ñ¹ôUøüÑÿqÕà { “j5{L¾ ë ì ÞÝh6¹ÿ©ÿÆÞ;Æg à ³ < M Ú Þ Y QÓñÃþbûì÷€ô?ñGî´ëŸéè<çç{çšèVê¡ìcïƒòäõfùêüP|S¿¯  õ G  m _  o¿zü;àÿñÿnV›/ýìä Ç z ãêz„ýá2 ù C$¶þ\ú¯ö-óöï%íÔêéøç„ç»ç™èêìŠî[ñjô—÷ÄúÒý¦)Dëºâ•à×#­G ÿhþ$þMþèþòÿc0Fí I „‚(^0³˜á˜Ì ”Emýùøõœò¥ï+íBë÷éQéPéïé#ëÚìþîtñ"ôèö©ùJü®þÀp¯xɨ?ËjÿþÙüÜû/ûåú û¦ûºüCþ5‚Ô¦ k YJÀ©õžüÄÔ N·éüBùáõãò^ðdîí=ìì„ì}íîîÂðÞò&õ÷ÊùïûÓýeÿ’T¤…ÿöþšý#ü¬úPù(øM÷ÒöÉö<÷1ø§ù—ûöý±±Ý = 5ÞÜŽlž+†~ …Ò'¢ü`ù}ö ô!òÅðýïÇïðíð*òºó…õp÷^ù4ûÚü9þAÿãÿáÿ@ÿ@þñüfû·ùþ÷VöÙô£óÊòbòyòóIôö>øíúüýQÒ_Ù   Ôï_)Y9 Å Wï®ÿ­üúÎ÷öÞô2ô ôcô'õFö©÷7ùÔúeüÑýÿàÿ_tWÿ+þ§üÛúßøÊö¹ôÈòñ²ï¾îJîcîïYð4ò™ôw÷ºúFþþÄv õ "âÁÂÈÔK>Æý îåbÿý7ûÍùàøqø{øóøÉùèú9ü£ý ÿTj6¤©=][þRüú‘÷õ™òPðNî¯ì‰ëïêîêŒëÌì¨îñÿóR÷òúÀþœh J 'ƒLwýá*æ&˜  ZÂT(UÿçýêübüOü§ü`ýfþ¤ÿfµÖ°1Gç ¸ðÁÿ<ýxú÷ôÂñïÆìÜêué¢èqèçèêÅëîïð0ôÀ÷ûRÿ£æ à "õ0Ð×MBÇõ å ´ ~_pÈy‘ÿÿ ÿkÿ,@“—j€ > ’ m Å ˜é¿*>ÿüÅørõ9ò:ï’ì\ê®èšç,çjçRèßéì¨î¹ñõ«øNüáÿFa [  Eáñ~– N ½ ý*^µE$a—{¸=óÄ’ D ¾ æ §î®ß € ” (Kœþûa÷Þó–ð¨í.ë?éëç>ç=ççç3éëví@ðXóžöôù;ýS%—™  –  6  “"áèÿEÿÿ9ÿÙÿäR=t › —M£‚ÚžÈWRÅ Âa¼óý$úqöúòÜï1íëˆé¤èjèÕèÞévëŠíð½ò¥õ˜øxû+þ•£Fr"Y{†Rù”>ÿþ"ý‰üSüŽü=ýaþòÿå)§F é tÈÊ_tõص·+% ½9^ýœùöãò"ðçíAì9ëÓê ëÙë,íñîñmóëõnøÙúýÿ”¿x½”ôÿþ2ýÎû‹úƒùËøxø–ø0ùHúÛûáýJõ  þ­á7ó v:_ó ¼ 'j¤øü‚ù_ö©órñÊï¸î>îWîûîð™ñgóhõ~÷ùû5ýžþ©ÿJ~D¤ÿ¨þbýçûOú¶ø5÷çõåôEôôlôGõ«ö’øòúºýÒ$‘ù >Aã ¨¥ù úÅý   Ž×üçù]÷MõÃóÅòTòkòüòùóKõÚöŒøFúíûfýþÿþÿ·ÿòþÌýSü›úºøÌöêô1ó¼ñ£ðüïÖï?ð;ñÉòäô~÷…úáýv'Ó[ Ÿ‚ëÃýŽt²Qbú1$ ò¹˜­ÿýÓú ùÀ÷øö±öãö÷yø¶ùûšü þYÿk0”Ž1áþ2ý7ûù±ö\ô!òðiî íVììzìvíï;ñíó÷ŒúEþìš  £¨ÖóoR­–%w © Ú%§wÿ¦ýDüXûåúçúTûü2ýxþ×ÿ5yˆM´¯6EÞ Üýbû´øïõ/ó“ð7î8ì­ê­éEéé`êäëîªðÈóA÷ùúÏþ¤WÉ ß –û@ì ¨àÈ }  À……Ô„ÿŸþ+þ'þŽþTÿg³"—ù-®Õ‚¯[‹J«ÿÀü¥ùvöQóVð¢íRëé<è˜ççMè¥é™ëîñhôý÷²ûgÿúQN Ú å aIb§{ô , > D\Ÿ#û6ÜÿðÿnO„úšLôv º § ( - «  èV_ÿªû$øªô]ñ\îÂë¨é!è>ççxç“èKêìJï`ò´õ(ùœüðÿÉ ü R  c ' x h  ƒáCÄ|ßÿ¦ÿÚÿ|†ìž‡™ ‹ H·¿LO¿—Ü ” Ф({þ¹ú÷|ó@ðlíëYé;èÆçûçÕèHêBì®îrñpôŠ÷¡ú˜ýRº»HWçûžÝÍ„­U-ÿHþ»ý•ýÞýšþÆÿYFzÝT Ä È¶ÔS2t#P  ¸Üý úgö óð¢í¼ëtêÏéÏélê›ëJíbïÊñeô÷¾ùBüŠþ} -Ø Ò4C½ÿYþýÔûåúKúúUú û?üæý÷ÿ`çÏ § R²¬)c  g,l; ¶ú'^ý¾ùgöróöðïªíììÈì8í/îšïdñqó§õé÷ú"üçýVÿa/ñMTÿþ§ü$û¦ùIø$÷Röäõëõrö~÷ ùûŽý`x¹ = Bö?2¼œÐ^SÁ¾e Õ-Žýæù÷³ô×ò‰ñÌð ðúðÍñóôOö)øú¿ûHý‡þlÿëÿýÿ¢ÿßþ¿ýSü°úìø"÷oõìóµòßñ~ñ¡ñPòóZõ©÷kúŒýòƒ£ ôð~†õ¾ÝORC1 ê Œ7 ýúnøÉö¨õõ÷ôYõ$öE÷¥ø*úºû9ýþ¤ÿdö:Rÿþ_üvú_ø3öôòQðìî÷í…í£í[î¬ï“ñôîö<úÓý”a œ ËŒÇklÅu…þ’Ø í ðþ6°ÿ‚ý¾ûoúùEùdùìùÎúõûHý¯þ JMV=±±AnþEüÝùN÷³ô+òÓïÆíìõêYêYêûê@ì!î“ðƒóÚö}úNþ+ô‹ Ð ©ÄênQœ]¦4 ° !£RE’ÿDþhýÿüýzýHþ`ÿªvÁÚ§¨7Rfýˆú‡÷ô”ñßî~ì‹êéHèè‹è©éië¾í“ðÒó_÷ûåþœ#\ - I{Š E D ' 3¬»ÿcÿyÿúÿØoûl ~ 4 | F Œ J ƒB–”ÿTüòøŽõGò<ï‹ìMêšè‚ççMç3è½éÜë|î†ñÞôdøùû}ÿÑÚ° [ y • « f Ü )f°!ÏÎ-öÿ,ÎÔ0Ñ¡…d   ʈÉ~¢4 8 »Í…ÿþVû«÷ôÐðÜí^ëléègçdç èRé-ë†íEðOó…öÈùúüüÿµøeN µ    3ž!¦G?ÿºþžþðþ³ÿáqRo²þ 7 A[<’QtúëT G Ü0`þúÖö]ó?ð•íuëîé éÑè;é?êÑëÚíCððòÄõ¡øhûÿýL=ÂÑf…3Dè‡ÿ9þý=üºûŸûöûÄüþ¹ÿÊ,Æ} 6 Ò5Bß÷z]š31¢˜ . ªÑýú‘öfó¬ðwî×ìÕërë¬ëwìÅíï“ñßóIö³øûýíþ^gÿ%Þ58ýþ™ý'üÁúùø×÷•÷È÷yø«ùYû{ýÿÿÒÜ Ú8 {:RÀ…ª@Y €ËmýúîöEôò€ðxïï&ïËïåð`ò$ôöøúäû{ýÃþ«ÿ(8Ýÿÿþ£üûjùÄ÷=öíôîóVó5ó˜ó„ôüõø÷núKýxÜZÑ #/Ú ©©©© Ú/#Ñ ZÜxKýnúø÷üõ„ô˜ó5óVóîóíô=öÄ÷jùû£üþÿÝÿ8(«ÿÃþ{ýäûúøö$ô`òåðËï&ïïxï€ðòEôîöúmýË€ Y@ª…ÀR:{ 8Ú ÜÒÿÿ{ýYû«ùyøÈ÷•÷×÷øùÁú'ü™ýýþ85Þ%ÿg^íþýû³øIößó“ñïÅíwì¬ërëÕë×ìwî¬ðfó‘öúÑýª. ˜ ¢13š]z÷ßB5Ò6 } Æ,ʹÿþÄüöûŸûºû=üý9þ‡ÿèD3…fÑÂ=Lÿýhû¡øÄõðòCðÚíÑë?ê;éÑè éîéuë•í?ð]óÖöú`þ0ÜG T ëútQ’<[A7 þ ²oRqá³ÿðþžþºþ?ÿG¦!ž3   µ N eøµüÿúüÈù…öOóEð†í-ëRé èdçgçèlé^ëÜíÐðô«÷Vûÿþ…Í»8 4 ¢~Ɉʠ d …¡Ñ0ÔÎ,öÿ-ÎÏ!°f)Ü f « •  y [ ° ÚÑ}ÿùûdøÞô†ñ|îÜë½é3èMçç‚çšèMê‹ì<ïGòŽõòøTü”ÿ–BƒJ Œ F | 4 ~ l ûoØúÿyÿcÿ»ÿ¬3' D E Š{I- \ #œåþû_÷Òó“ð¾íië©é‹èèHèé‹ê~ìßî”ñô‡÷ˆúfýR7¨§ÚÁvª`ÿHþzýýÿühýDþ’ÿER£!° 4 ¦]œQnêĩР‹ ô+Nþ}úÚöƒó“ð!î@ìûêYêYêõêìÆíÓï+ò³ôN÷ÝùEünþA±±=VMJ ¯þHýõûÎúìùdùEùùoú¾û‚ý°ÿ6þðí Ø ’þ…uÅlknj˜  a”Óý<úîöô“ñ¬ï[î£í…í÷íìîQðòô3ö_øvú_üþRÿ:¶Ãd¤ÿþ9ýºû*ú¥øE÷$öYõ÷ôõ¨õÉönøú ý 7Œê 1 CROݾõ†~ðô£ ƒòŒýkú©÷ZõóPò¡ñ~ñßñµòìóoõ"÷ìø°úSü¿ýßþ¢ÿýÿëÿlÿ‡þHý¿ûú)øOöôóÍñúð ðÌð‰ñ×ò³ô÷æùýŽ-Õe ¾ÁS^М¼2?öB=  ¹x`Žýû ù~÷röëõäõRö$÷Iø¦ù$û§üþTÿMñ/aVÿçý"üúé÷§õqódñšï/î8íÈìììªíïöðrógö¾ù^ý'ú¶; l,g  c)¬²R§ Ï ç`÷ÿæý?ü ûUúúKúåúÔûýYþ½ÿC4Ò Ø- }ŠþBü¾ù÷eôÊñbïJí›ëlêÏéÏétê¼ë¢íð ógö úÜý¸ P #t2SÔ¶ÈÄ T ÝzFYÆÿšþÞý•ý»ýHþ-ÿU­„ÍÝžûçWH»ºR˜ý¡úŠ÷pôrñ®îBìHêÕèûçÆç;èYéëlí@ð|ó÷¹ú{þ(¤Ð” Ü —¿OL¿·H‹ ™ ‡žì†|Úÿ¦ÿßÿ|ÄCრh x ' c  R ü Éðÿœü(ù´õ`òJïìKê“èxçç>ç!è¨éÂë\î]ñªô$øªûÿ_Vè « - ( § º v ôLšú„OnðÿÜÿ6û#Ÿ\D> , ô {§bIaå Ú N Qúgÿ²ûý÷hôñî™ë¥éMèç˜ç<èéRë¢íVðQóvö¥ùÀü«ÿJ‹[¯‚Õ®-ù—"³gTÿŽþ'þ+þŸþ„ÿÔ……À } È à¨ ì@û–ß É W¤ÏþùúA÷Èóªðîäë`êéEé­é­ê8ì7î“ð/óïõ´øbûÜý ÞE6¯´Mˆy5×ÿxþ2ýüTûçúåúXûDü¦ýwÿ§%Ú© w %–­RoóÖ¨£ š ìEþŒú÷íó;ñïvízììVì íiîð!ò\ô±öù7û2ýáþ1Ž”0kYÿ þšüû¶ùyø÷ãö±öøöÀ÷ ùÓúý­ÿ˜¹ò$ 1úbQ²tŽýÃ낟[ Ó'váý…ú~÷äôÉò;ñ?ðÖïüï£ð¼ñ1óêôÌöºø›úSüÌýòþ·ÿþÿÿþfýíûFúŒøÚöKõùóüòkòTòÅòÃóMõ]÷çù×üŽ  ý Åú ù¥¨ ãA>ù ‘$Òºýòú’ø«öGõlôôEôåôçõ5÷¶øOúçûbý¨þ¤ÿD~J©ÿžþ5ýûù~÷hõgó™ñðûîWî>î¸îÊïrñ©ó_ö‚ùøü¤j'¼ ó_:v ó7á­þ  õJáýÛûHú0ù–øxøËøƒù‹úÎû2ýþôÿ”½x¿”ÿýÙúnøëõmóññî,íÙë ëÓê9ëAìçí"ðãòöœù^ý9½% +·µØõt_ÊÈté F §)åòÿaþ=ýŽüSü‰ü"ýþ>ÿ”ùR†{Y"rF£•+þxû˜ø¥õ½òðŠívëÞéÕèjè¤èˆéë1íÜïúòqö$úóý¼aÂÅ RWÈžÚ‚£M—› t =RäÙÿ9ÿÿEÿèÿá"“ 6  –   ™—%S;ýôùžöXó@ðvíë3éçç=ç>çëç?é.ë¨í–ðÞóa÷ûœþK(” € ß ®î§æ ¾ D ’ Äó=¸{—a$Eµ^*ý½ N – ~ñáE [  aFáÿNü«øõ¹ñ¨îìßéRèjç,çšç®è\ê’ì:ï9òrõÅøü>ÿ*¿é˜Å m ’ > € j—“@,kÿ ÿÿ‘ÿyÈp_~´ å õ ÇBM×Ð0õ"Ã æ £RÿûÀ÷0ôïðîÅëêçèqè¢èuéÜêÆìïÂñô÷xú<ýÁÿð¸ çG1°Öµf¤ÿfþ`ý§üOübüêüçýUÿ(TÂZ ˜ &æ*áýwLƒ'J  hœÀþòúR÷ÿóñ¨îÌìŒëîêïê‰ë¯ìNîPð™òõ‘÷úRü[þ]=©¤6jT ÿ£ý9üèúÉùóø{øqøàøÍù7ûýbÿåî ý Æ>KÔÈÂÁâ"õ v ÄþFþºúw÷™ô4òYðïcîJî¾î²ïñÈò¹ôÊößøÛú§ü+þWÿt_àÿÿÑýeüÔú7ù©÷Fö'õcô ô2ôÞôöÎ÷ú­ü®ÿïWÅ  9Y)_ïÔ   Ù _ÒQüýíú>øöIôóyòbòÊò£óÙôVöþ÷·ùfûñü@þ@ÿáÿãÿAÿ9þÚü4û^ùp÷…õºó*òíððÇïýïÅð!ò ô}ö`ù¢ü'Ò… ~†+žlŽÜÞ5=  ݱ±öý—û§ù1ø<÷ÉöÒöM÷(øPù¬ú#üšýöþÿ…¤T’eÿÓýïûÊù÷&õÞòÂðîî}í„ìì=ìídî^ðãòáõBùéü·NÔ Äüžõ©ÀJYk ¦ Ô‚5Cþºü¦û ûåú/ûÜûÙüþjÿË?¨Éx¯pÀ®þJü©ùèö"ôtñþîÚì#ëïéPéQé÷éBë+í¥ïœòøõùmýE”Ì ˜á˜³0^(‚„I í F0còÿèþMþ$þhþÿ G­#×à•âºëD)¦ÒýÄú—÷jô[ñŠîìê™è»ç„çøçéÔê%íöï-ó¯ö\úþ¶$Cù 2 áý„zêãz Ç ä ìý/›Vnñÿàÿ;üz¿o _ m  G õ  ¯ ¿S|Pêüfùäõƒòcï¡ìVêšè{çç<çèŸé´ëGî?ñ€ôì÷bûÃþñÓQY Þ Ú M < ³ à gÆ;ÞÆ©ÿ¹ÿ6hÝÞì ë ¾ L{5j“{ à ÕqÑÿüUø¹ô^ñcîàëêé’èàçÙçzè¸é…ëËírð^ópö‹ùüaÿæ Áû·õ½%í¼ÿƒþ×ýý°ýEþLÿ¾®z ñ NsE¬‘圳+ e I Ð@ÿhû°÷8ôñxî^ìÝêþéÄé+ê(ë¬ì¡îïðzó%öÒøeûÃýÕÿ‡Î ýçi’t(Æþhý)ü"ûhúú&úµú½û>ý-ÿzãÊ ­ lê ¸Ù`C~ xl  V‡¸þû’÷xôÐñ­ïî(íÎì íÔíïÃð»òåô%÷^ùuûRýàþ Ñ& ˆªÿþýŸûú¯øt÷‚öðõÍõ'ö÷gøHúœüSÿVÚ 9€vÛ¡½.öºÜŸ  }ØRþûø…õyóùñ ñ¬ðÙðƒñ›ò ôºõŒ÷gù0ûÌü&þ*ÿÌÿÌÿ*ÿ(þÓü?û‚ù¶÷÷õ`ô óò„ñxñöñóžôÁö]ùaü³ÿ9Õf Í ë£Ý„‰ä“šàFO ¿e'$þsû*ùY÷ öBõþô8õàõæö2ø­ù<ûÃü(þUÿ3´Ìu±ÿƒþùü$ûùðöÅôµòÛðSï3î’í|íþíïÍðóÒõùü7Èa ±œ 䳟敽tÓö ý-ŽAþXüàúãùbùZù¿ù…ú–ûÝü@þ¤ÿîÙO\øÓ ÿýºú4øšõó™ðmîŸìFëvê>ê§ê³ë^íŸïeò›õ'ùëüÇœH¬ ®4-ŒIeäÔEN ‘  ~ö"²þ¯ýýýRýþÿ@  aŽw0áÏå_þ’û™øõ–òÈïFí)ëŠé}èèIè,éµêÖìïòöÀù‰ýIå<3 µ ¯ä¿àã ô Þ ¾¯Ë*ÝõÿxÿjÿÈÿˆžözž 5  ~ u é Ö <#™±ƒý)úÁökóGðrí ë"éÑç%ç#çÍçé ëígð¦ó÷±ú>þ¥Ë•ï É  Ú À ü Ô ` ¸ù=ž6Vûÿ ‹q²?äÉ – . z`ε Ð  ² é¾I¨üúø^õõñÞî3ì êè”çTç¿çÏèxê¦ìDï6ò_õ øÚûïþÃ?Qéÿ“ § F e™±syÿÔþ”þÁþ_ÿiÚ¢¯é6 { šwø„Þš¾U o "ˆÁÿëû&ø”ôSñ}î*ìlêOéÙè éÙé:ëíeïüñÅô¡÷qúýƒÿ•?w5{O¼Ò¨Uóÿ›þiýsüÐûûÀûeü‚ýÿL׈E ñ lšb¬eùÌÿŸ¾ r Ø 3ÿgûÍ÷€ôœñ7ïaí'ìŒëë)ìKíâîØðósõà÷:úhüSþæÿÐùpdÿ þšü,ûÜùÄøù÷‘÷›÷!ø'ù«ú§ü ÿÇÂâ îq† a  g-pG Í "e·þ7ûø1õÚò ñÏï*ïïï‚ðÝñ‰ómõk÷iùKûùü]þfÿ<dÿfþý˜ûôùJø³öMõ/ôqó$óXóô]õ-÷zù6üLÿ ˜ û $õS(bõÛ®°.A ™ªhþmûÒø«öõçóUóJóºó—ôÍõD÷áø‹ú&ü˜ýÊþ«ÿ)=äÿÿõývü³úÃøÀöÄôíòUñðEïõî3ïðpñióèõÚø*ü¼ÿr/Ð 5BÛë_.RΨð¹3  ÷âúYþü>úáøø¦÷Á÷Iø.ùZúµû&ý‘þÝÿñ¸"!¯Ì}ÿÊýÆû…ù÷°ôUò+ðMîÖìÚëkë–ëaìÊíÌïYò_õÇøtüF!ág •Rˆ'#{0KÚó­" q ·›l™þ/ý9üºû¯ûüÐüÜýÿzÛ%= Š8Ú ÜþZüŸùÆöêó+ñ¦îwì¸êéÝèÞè…éÒê¾ì:ï2òŽõ2ùÿüÓD Gö ‚`¯}ßí  { 3c,ÿ´þ«þÿÑÿä4¨(˜Þá‹ É Ž Ò’Òœþïú®÷nôPñsîòëèéjè‰çPçÂçÝèšêéìµïçòaöú±ýF¦¶\ † &5²¡£ ú % @hµ@WýÿŽqª(Ô–S ï P \ ÿ (È Ü a ^ Þô¶?ý¬ùö°ò‡ï¾ìnê®èŒççHç&è£é²ë=î+ñ`ô¼÷!ûoþˆU¼®  j M » Ç …|êt04”ÿYÿŒÿ,8£^Tn   Fÿ0ÍÑ< p Yé>wü²øõ³ñµî1ì;êâè0è(èÆèÿéÄëîšðvóvözùfüÿˆ‘+KîËßÁÿ–þ­ýýìü.ýãý ÿžÍ?Í Z Èû×C+4F¹”æ Ä GŒ²ÿÙû#ø®ô–ñöîàìcëˆêOêµê¯ë,íïWñÑóföûøsû³ý¥ÿ7^PŠŸsÿ¶ýYü û$ú{ù6ùdù ú2ûÏüÛþEûãà Ö ¦2^7Á¤Þsk×Ì d »ò*ÿûøõiòQðËîÝíŠíÊí“îÓïuñ`óyõ£÷Ãù¾û{ýèþóÿ“ÅŠéÿîþ¬ý7ü©úù¬÷rö‡õþôêôVõIöÁ÷¹ù&üôþY¸ 5Œ÷¿ÞQHçÚ d Î6¿þƒûžø&ö,ô¼òÛñˆñ¼ñkò‚óíô’öVøúÎûOý‰þmÿëÿþÿ£ÿßþ¼ýIüšúÇøéöõ}ó$ò*ñ¤ð ð*ñEòñó%öÓøçûJÿÞ‡$ ” ¹v´]eÂs~íÑ@U, åžvŠþðû¿ùøÍööæõ-ößöé÷5ùªú.ü¥ýöþ Ë-#ªÂÿrþÈüÔú­ølö-ô ò(ð˜îvíÕìÃìKíoî-ðzòGõø üÈÿ›cÿ Q<¨‚½Q=ˆ<l.›Ñ ì MÊšþÎütû“ú+ú9ú²ú†û¢üíýOÿ¬ìö²†Gÿý¦úøSõ¬ò.ðöíìÀêíéµéê.ëÞì#ïîñ'õµøzüU'Ï/ *ªö°ÉI<µÉ’ - ¶JþKüþþªý«ýþàþõÿ?©n”sõ ¤À^ƒ<›þ´û¤ø†õzòïíéêCé2èÁçúçÝèeê†ì/ïIò¹õaù"ýÙi´Ÿ  ]"QóÈ$ B > 4?y÷ͯÿÄÿB"SÃZþ• 0  i S ¶ á²Òýeúíö‰óYð{í ëéÉççç½ç éóêbíBðwóãöhúåý:MK  P  + Ó ã t Ö&~÷«¬ Ôÿ «´Àž•Œ e U;¤ƒÐ‡¬ K r7µýOùªõ;òïpìHê·èËçŠçòçþè¡êÇìZï>òWõ…ø©û§þbż;;¹»L{]—#É¡ÿ¿þ6þþcþ#ÿPâËõJ®  3¤µ=/„9Uã ô Ÿÿ1Xü’øÿô¾ñêî™ìÞêÃéNé}éIê¥ë}íºïBòøô½÷uúýNÿAÍæˆ³pÉÑœDâþýiüƒûõúÍúûÚûýÂþÔ;ᬠ=ÇÒ!ÝúpAq+ß E{¤ÿÞûJøõ)òÌïþíËì5ì;ìÔìòí‚ïlñ—óäõ9øyú‰üTþÅÿÏl—U°¶ÿxþý•û"úÓøÀ÷÷¨öÄö_÷}øú1ü°þ„—Ì $ —´JEœGH¦n´  zÇ&ÿ³ûŒøËõ‚óÂñ’ð÷ïìïgðZñ±òUô*öøþùÅûUý˜þÿýÿ³ÿñþÕýnüÓúùc÷ÄõYô<óƒò@òòMó§ôŠöìø¼ûåþKÕb Ñ Ü@WìÕ¯¶<X( É\þÐþêûdùR÷Àõ¶ô4ô5ô¯ô‘õÇö8øÌùfûíüGþ]ÿ{lïÿÿ»ýü<ú3øö ô)ò‰ðFïvî+îpîMïÂðÈòTõTø°ûNÿÒz ä ôŸä ‡gµˆö   <¶þŒüÑúŽùÊø‚ø°øGù6úgûÂü-þŽÿÉÉwŦžÿËý¨ûJùËöFôÙñ ï¸í:ì;ëÌêúêÈë8í@ïÔñáôNøÿûÖÿ°pô Ù ¥Ÿõ«É_GÎ 1 ªšçþýÆüeüuüîüÂýÝþ'‹ì/<ý]OÈÆK_ÿtü ù®ö¾óíðZî ìZêéwèwèémêZì×îÏñ*õËø”üb“¹ q ¨MZ˦õÇ1K 0 ýξåZ,hÿÿ+ÿ­ÿ‹¶ž(âà  ¯ b ‘ ;ca^þ#ûÎ÷}ôQñgîÝëÌéIèdç(ç˜ç²èlê·ìïªòö³ùSýÙ*)¾ × h iÛÂ*# Ä # \‹É2ÛØ66ØÛ3Ìe0 Õ : Fä™  ý lp šýøù\öæòµïæì’êÏè«ç0çbç<èµé½ë?î"ñIô•÷èú!þ%Ú*_ 5 † [ ¿ Æ„Š¥zœÿÿÿVÿGÔ®Àó* J 6ÒÁᱠþ Üb®àüùpõòïì—ê?éè„èéSêìBîÏðšó…ösùFüãþ0šž'9ÛÐp Âþ¦ýÑüWüDü¤üzýÃþu†áo · 6w\ϺÁÐ>a; »þ#Mü™ø(õò{ïkíôëëæêKëBì¸í™ïËñ3ô³ö/ùŠû¬ý~ÿðõ‰©]¯°uÿþ¨üKûú&ùŒøZøŸøaù¡úZü‚þØØì õ Õm£]ˆù3ÈÀ-$¿ Y™ÿúûœø˜õóúðï›îNî’îZï—ð1òôö,ø3úü¯ýúþâÿ_nQÿ:þßüWûºù$ø®ötõŽôô ô†ô‹õ÷(ù«ûþ¾Žñ '”–Ñòg4d 8   )ÿÿû-ùÇöàôó¯òhò¥òYóqô×õr÷(ùÜúvüÛý÷þ¹ÿ„ÿþZýÈûÿùø%öKô¢òEñKðÉïÍïbð‹ñFó‰õGøkûÝþ3Ù Q |>~*3’FUɵ.P6 ϽéþiüQú°ø÷ïöÏö$÷à÷ðø<ú¬û&ýŽþÊÿÅk®ƒçÝÿkþ üŽúLøóõ óqñ€ïéíÃì!ìì ìÌí’ïèñ¿ôø’ûWÿ.ú˜ é Ó>OâÏ×ÜX  Ñ eþìþ?ýü=ûðúû£û‡ü­ýþþ_¸íçÖ¬ õjwÿ+ýœúá÷õ]òÏïŠíªëEêoé6é¢é´êgì¯î}ñ¸ôGø üäÿ±T­ ¡ X #£š8 ½ ] ãüj=ÿ|þ-þNþÕþ·ÿß:®!yšoâãhmðû™Þþàû¹ø‡õiòïäìµê éôçç¸çšè!ê@ìçîýñgõù¿ükï, o OžY@÷ [ ‡ ” Å»³Üÿ³²ˆ2æ† ú & õ R . ‚ I † C}(þ©ú"÷±óvðíë&éÎççç»çéèêPí'ðRó±ö&ú‘ýÓÒt¦Y … ' B â  ì íK¶H7¹ÿ¤ÿýÿÂìo7/< E + Õ(sKŽ9Q â û³$lýªùþõ‰òhï¸ìŽêýèèÍç3è;é×êôì{ïQòYõsøûfþO,‘xàÏQvQü'ÝÿÇþþý‘ýýýýßþ-áè0Ÿ … µDYâÑ!Ðåku t£Èüùoõ0ò_ïíZëBêÎéýéÆêìëíð”ò6õå÷‚úôü!ÿõa\àð”ÙÑ‘4ÿÒý…ühû‘úúújúIû¢ümþœ áÄ­ }]5ŠIgÜ«Úv’F ­çVüÉøõºògð£îwíçìðì‰í¤î-ð ò&ôaöžøÂú´ü^þ®ÿ•¹÷ÿäþ’ýü”úùÍ÷¿ö ö¾õìõœöÑ÷‡ù¶ûNþ:c­ø &±ÖppÉvyÙ¤ïÐ e Ì%’ÿ.üùeö-ô|òZñÊðÇðGñ;òŽó)õñöËøœúIü»ýÝþ¡ÿüÿéÿkÿ‡þLýÊûúMø…öÜôlóOòšñ`ñ­ñˆòóóèõ\ø?ûyþñ‰# Ù¸!þ>Ö£°=dA ñ•K2ÿbüôùø÷|ö†õõ$õ¨õöÆ÷3ù½úIü¼ýþþùÿ™Õ¤øþ‹ýÍûÐù­÷õaópñÇï€î°íhí´í™îð+òÃôÎ÷5ûÝþ¦q ‹ œ8H½´4nJÅû +v ÿÿü_û8úù\ùžùDú>ûuüÑý7ÿº¦<o1YÈÿÕý“ûù‚öçóhñ!ï.í©ë§ê8êgê:ë®ì¼îUñgôØ÷Œûdÿ>û| ¤ X„d;×Ön æ \ì°¿,ÿþLý ý6ýÇý°þÛÿ1šû:=î<wZºPÿ˜üªù¢öžó¼ðî×ëêÆèèèÄèêì}îtñÌôiø,üóÿž+ Ø ž¡ ã1xž ” u_j±G;›ÿhÿ¢ÿB>‚úŽ"â Û r ” 7 R æ÷’Ç®þ_û÷÷—ô\ñhîÕë½é5èMçç}ç”èKê‘ìSïuòÝõiùúüq° ' § š ÿ Ý ? 8 Ü E ‹Ì"¥mŠ úÿS=³hC+  ² )ÃÚe\Á œ úíŽùýKú¤ö&óîïíÂêüèÖçZç‰ç`èÔéÕëNî%ñ=ôx÷·úÛýÇc›]¡a   f ÁÁ~“нÿúþ—þžþÿþÿMúó"m ¹ é á†Ày¤5(€GŠ ^Û Lý}ùÕõtòuïòìþê§éöèìè„é´êjì‘îñÉó övù/ü°þà¯öe^ìÀ_ÿÀý³üòûû—ûü ýrþDtì”R  ˜æÕN=‘CPºŒÖ­ +n•Áüù§õœòðÿíìºë‡ëìëàìPî'ðKò ô ÷mù¬û¯ýaÿ±•  ÙÆÿzþýœû>úù(øœ÷}÷×÷±ø úàû#þíÄì  ÷œÛœÌ[A| ys v¼sü!ù+ö¨ó¨ñ9ð_ïïbï+ðdñ÷òÉôÀöÀø­únüíýÿÛÿ4 ¢ÿÁþŽýü~úÒø1÷¶õ|ô™ó#ó*ó¶óÎôpö”ø,û&þhÙZÌ ‹“Ôøo@tV3 Ô ZâŽÿxü¹ùi÷•õHô†óLó“óLôeõÈöZøú¤û&ýpþmÿ FoÿfþýRûmùm÷jõ‚óÐñnðtïõîï ïÕðòïô¼÷îúmþÙˆ  6û=êõU ˜Œ?6 ÷ýCÿÜüßúXùNøÅ÷¸÷øãøùùGû³ü"þ{ÿ¤‡6ë-nþƒüSúõ÷…õóßðãîDíìxëlëþë0íýî\ñ:ô‚÷ûäþ¿Œ* { bÊŸÖgU¥d¥} c ªûs*7ÿ¨ýŠüãû±ûïû‘ü…ý·þ pÅðÛq \ jÀ°ÿFý›úÈ÷èôò|ï+íBë×éþèÄè0éDêùëDîñOôÝ÷žûtÿ;×(  ƒf±_sòìr›‚ C ù·ðuÿÖþ©þéþÿ‡Å0°)ži Î ¾ / ‡xý)ÿü×ø’õdòlïÆìêÝèÃçNçƒçcèééì¨î¹ñõ´øaüv¤q È ™ ÛŠªCc Š Â àAµtŽÿÿY:¤DÅq ê  á 6K  , Öéƒþõú_÷âóð¯í1ë<éáç,ç#çÅç ééêKíð6óˆöìùEýr[ç¡ ¹ J W ì  ïˆýiçzºÿ\ÿjÿæÿξ¤µÙ ó è ›òÙ; Fæó v ƒ/•Ôý úXößò¼ï íàêNéaèèè„éë.í©ïpòfõkøaû-þ³ß ê·äVoDî†&ëþéý7ýåüýý’þÕü`é{ ø DBÙò|iµ_nîò ’é9ýsùäõ©òÜï”íàëËêYêˆêOë ìfîŠðòò€õøšúïüýþ±ýØ=2½íÔŠÿ%þÁüyûeúù5ù:ù¹ù³ú)üþ]ý×ÒÏ ±Y«‹æ¨Ç= 9Ôð¦ OƒÍüJùöPóñMï*î¡í¯íIîaïãð¶òÁôèö ùûêüsþ ÿe¼¤#Fÿþ²ü)û˜ùøÊöÀõõÖôõØõ#÷ðø7ûçýé(…á ¾êŠé˜Ï¥ ~ùÿ¦ü ù÷Ùô9ó&ò¢ñ¨ñ.ò#ósôöÁ÷‰ùDûÖü*þ,ÿÍÿÎÿ,ÿ'þÍü/ûdù†÷¯õüó‡òiñ¸ð…ðÜðÅñ@óFõË÷¿ú þ‘7Ü` ¤‰öÖ² å‰œ3eO  Ç’ÿ×ü€úø7÷Uö÷õö¤ö‘÷Éø3ú´û2ý’þ¼ÿ›9å"ôþfý‡ûnù2÷îô¿òÁðïÄíóì­ìÿììíuï‘ñ4ôJ÷»úkþ: º * <׿Z*QÔ¼ÿˆÎ ñ A¨ZÿjýéûÞúMú4úŠúAûFü„ýáþC®‡Ãò¬ûÿéý‰ûôøDö”óñ®î±ì%ëê®éßé´ê-ì?îÝðòóf÷ûòþÊ„ " Ðö†wÉ~¡CxY ɬÛiÿbþËý§ýðý›þ™ÿÔ7¦ C=áâ*ò?–ÿÃü½ù öˆó—ðèíšëÄé|èÒçÎçuèÄé±ë,î!ñuô øÈû‡ÿ'› ; YèâEd<µ ç í âä r)AÄÿ´ÿÑéGÔw— Þ Ó a w  ’ Ž3ÿ¢û)øºôsñtîÙë»é/èDççnç‚è5êwì1ïKò§õ&ù¨ü 9‚v ä Æ  ò O F î ^²qõ3ØÿéÿgN”)ùìç Ï ˆ ÷›¬,n : ˆlÿ]þ¤úôönó0ðXíþê6éè‘ç¾ç‘èêùëhî2ñ;ôd÷Žú›ýoò¹ä»qÀºu –1õÿùþQþ þ4þÎþØÿI.yÜ = }‚/m(PÜÉ× ÝT“ºýéù@ößòâïaípëêkéaé÷é"ëÐììî\ñôÅö„ù"ü…þ—H‰S¦‡!ÿ°Oÿôý¼ü½ûûÂúåúû‘üþ X쮃 M îIBÁ³ »Å-üD —Û6ýù)ö&óšð™î/íbì2ì˜ì‰íóîÀðÖòõn÷¶ùØû¼ýMÿz<Žpê áþ„ý ü“ú4ù ø+÷¬öŸö÷ÿ÷rù`û¾ýwy¦ã  ¾Î”|¸OJ¼º` Ëpêü§ùÀöKôZòøð)ðìï:ðñ;òÆóŒõs÷]ù2ûÖü4þ;ÿÝÿÜÿ;ÿ;þëü^û­ùñ÷DöÄôˆóªò<òMòéòôÇõþ÷«ú¸ý  éåv‚øÊðj>x)hQ ”/îÿìüDú øJöõ_ô4ô†ôEõ`ö¿÷IùäúsüÞý ÿíÿk)dÿ8þ³üåúæøÎö¹ôÃòñ ï¥î)î;îãî#ð÷ñWô1÷púûý³z0 ³ æ­ñž© ÃÙZVå#+ 6•ÿJýhûüù ùšø øùèùûTü½ý#ÿm„PÀÆ[|.{þpü"úª÷#õ©òYðQîªì|ëÙêÎêdëœìpîÕðºó÷¥úrþN¸  êMRáÏ!å.­  xãwLyÿ þ ýƒünüÅü|ýþ¿ÿÒôÑUm8æðÿký¥ú¹÷Äôãñ6ïÙìçêvéšè^èÊèßé•ëáí°ðëów÷5ûÿÆY  æÀª¹73Àô ê ½ ‹nÚ‹£ÿ(ÿÿ|ÿ<Q¥!­,†Ÿ b º ™ ö Í!úf{ÿOüÿø¨õjòeïµìvê¿è¡ç(ç[çbaresip-1.0.0/share/sound4.wav000066400000000000000000001047741372575704200162230ustar00rootroot00000000000000RIFFô‰WAVEfmt D¬ˆXdataЉ‚ñ7 B b\âíz‡-Ôý› @ iÅþŸû`ùh÷Âõsô€óéò®òÈò3óäóÓôñõ4÷ŒøíùHû’üÀýÆþÿ?©ØÏ‡ÿÍþþý%ýNü„ûÕúLúòùÐùïùQúúúëû ý•þB !9Yq s NóTcbB²²Cj0 Ÿ İr ýÊù…öfó~ðàíëÁéZèoçç#çÃçåè€êŠì÷î¸ñ»ôï÷@ûšþéÜ M bT'ˆy$ïm¬ º § ƒ^GM{ÿÝýzüZûúïù¥ùžùÔùAúÚú•ûgüCýþèþšÿ(Œ½·wÿÿNÿjþZý'üÛú‚ù(øÜöªõ ôËó6óìòóòRó ô"õ‘öUøgú¼üHÿûÉži  ˜ÙË_ˆ>z7t4}VÌì Çnôpþóú“÷dôwñÝî¥ìÚê‡é°èZèƒè(éDêÌëµíñïoò õò÷Ðú«ýowŸ{  . þ q Š N Ä ö ð ¾ m ¤GÛß‚ÿ)ÿ ÿ"ÿpÿìÿŽMöȈ*£éõÀF…5¯ôþýûòøÙöÍôßòñ–ïYîqíéìÊìíÕíïðòúô©÷›ú¿ýX¦Û ä ¬$<çÎý¨Ïy­vâ ä ŸFìÿ¤ü‚ù—öóó¥ñ·ï2îíyìGìƒì'í,î…ï'ñó õ,÷Xù€û“ý†ÿJØ&0ñkŽCÄV}žÅþSÐÿzÿXÿnÿ½ÿEò Bä5t ” ‡ B ¹ ã º 8 [ $ •µ‹#‹ÿÏüú4÷wôÞñzï[í’ë,ê3é±è«è$éêëvíÇïwòvõ³øüœÿ’à ö Â5AÚùšº[‚6py ´ Öò^þÎûyùk÷­õHô>ó’òCòMòªòRó:ôWõœöû÷fùÐú,ümý‹þ{ÿ6ºê]ÿ™þÆýñü&üqûÝúuúBúLú˜ú*ûüýzþ×ÄËÞí ê à jÑ驸|7sN Ð Ï…ý4úðöÎóáð:îêëêˆè‹ççç¦ç¶è@ê<ìîUñSô…÷Øú7þŽÌÜ­ 1 [ x_Ô×mžrö6A ( úÈ ‘ªÿóýxü?ûMú¤ùCù)ùNù®ù>úóúÄû£ü„ý[þÿ¾ÿ6~‘k vÿ«þ²ý’üWû ú¼øu÷Eö9õ]ô¾óeó[ó¦óKôJõ¢öOøIú‰üÿ¤d/ó ž d^ý4ûHi>™… 9  ÍXÕþUûï÷¶ô½ñïÌìïêˆéè3èJèÞèêéfëFí{ïøñªô€÷húOý"ÓQŽ  c H Ð û Î P ‹ ‰ W  —%¹`$-ÿ ÿÔþÕþ ÿuÿ¸S%è’l‹k`rBÔ0ÿ_ýlûeùX÷Uõjó¨ñðÙîæíPí í[íîï¡ðŒòÕôq÷Sújý¤ñ<q | LÎó­ò¸û¹ó®ñÈ?e M ¬KúüËùÐöô¹ñ¶ïîñì9ìôëì¶ì¯íïŸð{ò…ô®öæøûCýJÿ%Ë2U/¿ Î[»ø;Y…Ê2Çÿÿ‰ÿ¾ÿ,ѨªÏ UžÙù ð ³ 6 p Y ì %  ı^Øÿ,ýkú§÷ðôXòòïÎíüë‰ê‚éïèÖè<éê~ëSí“ï3ò%õXøºû7ÿ»2‡ ¨  Í´ç›Ò“êâ‰ð ( DUo¤þü—ùs÷žõ!ôó@òÝñÖñ&òÃò¤ó¾ôöi÷ÝøUúÁûýJþSÿ(Æ)QAú†ëÿ2ÿgþ•ýÉüüqûüú¹ú¯úåú^ûü ýcþâÿ’kaej ` 6 ßKl8¤¨@i%wg ü DN)èýú\÷8ôFñ—î<ìDê¼è­ççççŒèêòëGîöðíó÷púÓý2z˜z  O(–’0Öò|¾É ª s3ûÚÝÿþ{ü)ûú]ùçø¸øÌøù£ùSú!ûüêüËý›þNÿÜÿ:fZ™ÿçþþúüÑû”úOùøáöÓõñôHôâóÈóôôxõ¸öMø1ú[ü¿þQÁ} $ ¥íí–Û±ôYA±®E s *»:ÿ¹ûMø õòQï÷ì ëŽéèèè™è–éëÚìï‚ñ4ô÷þùðüÓÿ”%y‚ 7 ’ )gJÙ  ð — &¨.ÂrGK…ÿ÷þ¤þŒþ­þÿ‚ÿ&ä±G÷‡ìÅ5`Iôhÿ¬ýÍûÖùÖ÷Ûõöó5ò¨ð\ï_î¼í{í£í9î;ïªð€ò´ô>÷úýF‹Ñ  éu¦oÄóÄÞ1˜Ç ´ r¬Rýú÷GôÒñºï îÌìÿë§ëÁëHì6íîðóñô0ösø·úïü ÿû¹9tgkVïXšÁÙðEšÇÿªÿÅÿ¤cO`ŒÈ>] X " ° ø ó š é à €ÏÒ”!‡ýÓúøhõÓòlðDîiìëêÖé2ééYé)êtë5ícïóñ×ôøZûÓþVÐ, U ;ÍûºÈÕíPPýf œ ³»Èíþ9üºù€÷•õôÉòóñ|ñdñ¤ñ6òó&ômõÖöSø×ùTû¼üþ&ÿÌJ‹’buÉÿÿ8þlý­üü†û3ûû6û˜û>ü'ýRþ¸ÿQùïèÖ © RÂìÃ=Sþ=vz $ ˜€JþûÈ÷¤ô®ñ÷î’ìŒêôèÔç3çç}çhèÐé­ëõí™ð‰ó´öúnýÔ&QC ì =,®¿\„:†nÿFO , í¡Z&0þ„üûõùùøKøNø‘ø ù³ùúaûNü9ýþÛþ}ÿóÿ6D·ÿÿSþ^ýHüûàù§ø}÷nöˆõÖôdô9ô_ôÙô«õÔöQøú1üþ¡T © )tz,~cÔÊC?ÂÓ{Ç Ä †žÿü®øeõUò‘ï(í(ëšé‰è÷çèçYèFé¦êqì˜î ñ¿óö“ùü€ÿQö^} I » Í ~ÏÂ_­ ¶ ‡ - µ.¥(Ä‚mŽÿæþyþIþRþ’þÿ—ÿIݤ[õh©²|ILœÿöý*üDúRøbö‚ôÃò4ñãïÜî,îÜíòísî`ï¹ðyò™ô÷ÍùÇüëÿ%f˜ ¨ ƒT,‘{åÉ)m`ï' Úz­ýfúO÷wôïñÄïî¬ìÊë_ëgëßëÀìî“ïlñ{ó±õý÷Oú—üÆþÍ¢:™YÌõÚó;cy‡œÂnÏÿÑÿ {"÷ô=s£À½ Ž & } ˆ C ¨ ¶ nÔïÆgÞý9ûŠøáõPóéð¼îÚìQë.êzé=é|é8ênëí8ï·ñôª÷üúpþñmÎ ò‘Сû×1 bB±¼oÛ  ""$:ÿtüâù’÷õåó—ò«ñ ñöð'ñ­ñ~òóÖôBöÈ÷Wùãú^ü½ýõþýÿÎeÀàÆxü]¤ÿÜþþNý üü°ûûŒû×ûdü4ýEþ’ÿÔzgM  Ä 7hJÓù· ño‰ H µßÖªþnû4øõò[ïëìÙê2éèMççqçIèŸélë¦í?ð'óNöŸù ýtÏ  &)Áç—ÒšôèËÕ ¯ h ¼vOUþ‘üûÑùàø<øã÷Ó÷øuøùÝùÀú²û¦üýeþÿ¦ÿ)ÐÿQÿžþ¿ý»üûpú@ùø ÷!ögõèô¯ôÂô(õäõõöZøú üGþ³Dé“/ « ø¿’š'8Ïó¬  ß}‚üùÀõ§òÖï^íLë¬é‡èâç¿çèúèMê ì*îšðKó*ö&ù,ü)ÿ Â?t W ß Î26á9J  à E µ‘•œÿÚþSþ þüý&þ‚þ ÿ±ÿo8½`à2O/Ï-I&Êÿ<þ„ü°úÌøçöõSóÂñlð]ï îAîEî²î‹ïÎðxò‚ôãöùzüÿÁü+ < ·ÿäYUÑÉ<.£¦A„~ Aár þ¹ú”÷¬ôòÔïûí‘ì›ëëëzëNì„íïæðöò1õ†÷åù=ü~þš†6£Çž'e[ŒÚ!+CtÈHúÿáÿX壋”´ß"! ÷ š ý  ç a † VÔô©2þûùøYöÌófñ7ïNí¼ë‹êÈéyé¥éLêoëíï€ñGôW÷ ú þŒn¨ ¥R ƒðßM8£’$ÞN„ ’‹‚Šÿ³üú©÷‘õÏókòhñÉðŒð®ð'ñïñûò@ô¯õ;÷Õøpúýûpý¿þàÿÊ|ð(%ëð@~ÿµþïý;ý£ü2üñûçûüüFý>þrÿÜu2èÄ 4 ªáÎcškÓÏc“ f ç#( ÿÕû øõƒòÁïIí+ëué3ènç*çkç/èté0ë\íèïÈòéõ8ù¢üv¹É “ "Î Îô]]ÿO[2 ä „ Éþ¤üû³ù©øî÷€÷]÷€÷â÷zø<ùúûüýëý²þTÿÉÿäÿ~ÿäþþ,ýüþúØù·ø©÷¼öúõqõ)õ+õ|õ!ö÷iøúëûþi逴 - zŠN¶¸Je*Ö ÙE _ 6Üfçürùöûòð˜íuëÃé‹èÒçœçéç´èøéªë¿í)ð×ò¸õ¹øÈûÑþÁŠe ^ þ =¦_ÃÛ ³ X Ö =›þsÁ¯ÿÓþ3þÐýªý¾ýþ~þÿÐÿ”]ÉU·çÝ• A8õÿ}þÛüûEùk÷šõãóRòøðáïïªîî÷î»ïèð|òpô½öWù0ü9ÿ_’½Î ±S¥—)·ÂIMÕçÞß §H×hþûÜ÷åô:òèïûí|ìrëßêÂêëàë íîbðrò±ô÷xùßû2þbe.³ïÞ~ÐØœ#x¦¸»¼Çç')÷ÿýÿ9­T&-Lm„ƒ_ z ¦ †  Q 9ÏçƒþþûgùÐöIôåñ´ïÆí*ìíêê»éÓégêuëúìðîMñô÷Eú¬ý'£ N Tl`ßâdbÞÞi‰LÀ÷  õâÝÿöü?úÆ÷—õ¿óDò+ñwð'ð8ð¤ðbñhòªóõ­öQøúù˜ûý„þ½ÿÁkZ€ÛYÿ’þØý6ý·üdüGüdüÀü^ý;þVÿ¨+Ô˜j< þ £ XMð6•§Q— € cxeÿ;ü ùîõñò*ð©í€ë½ékè“ç=çjçèMéùêí•ïkò…õÑø<ü±ÿi† a êÕ%þ`JÂÏ{Ñß´ a ÷‡ Ó­þ»üû™ùxø¥÷!÷ëöýöR÷à÷ø~ùvúyûzümýGþþþŠÿäÿóÿ§ÿ%ÿtþ˜ýü‹ûnúTùHøX÷‘öýõ§õ—õÕõeöG÷}øúÐûßý#‘¬9 ¯ ûÙL[ý*Þ×"~ § Š:ÉLý×ù}öSókðÖí¤ëàé•èÉçç¹çsè§éLëXíºïeòFõKøaûuþtNñQ a  l]éÚJkG ì h ÇmÐNòÇÿÑþþ›ý]ý[ý‘ý÷ý…þ2ÿòÿ¹}0È9{†Uå4Dºþ.ýû»ùí÷&ösôäò†ñhð•ïïúîAïðïñ…òdôœö"ùêûäþþ(O_ DíHFÙ÷˜¶Ph$Û4? ¯<Èþeû(ø#õfòðîmìNë§êxê¿êvë•ìîßïïñ1ô•ö ù~ûãý'@ ½Ï6 Q $ ¸FXWOM]ŠÝ]þÿ { Ũ¨»ÓæåÄw ó . Ä  Ä&B"Ñþ\üÔùG÷Çôeò2ð@î›ìSërêêê‡êëñìÔîñÅóºöíùLýÂ>©ð Æ38Éßt†%¾ê¶0i s `D2=ýtúæ÷£õ´ó"òóð*ðÇïÇï%ðØð×ñóˆôöÌ÷ù0ûÊüEþ–ÿ³™AªÕÆ tÀýÿ6ÿvþËý?ýÜü«ü²üöüzý>þ@ÿyåy+î´p  Š ÌÊxÎÃRz:– • >ŸÄÀÿ üxù]ö`ó•ðîÚë ê¨è¿çVçpçè-éÇêÓìFïò#õkøÖûNÿ¾? ) Ä×<)ž›#>óPa6 ß mðzàþØü û…ùKøa÷Çö}ö~öÅöH÷ÿ÷Ýø×ùáúìûíüÙý¤þGÿ¹ÿ÷ÿýÿËÿbÿÈþþýüûðùçøö÷)÷‹ö(ö ö3ö­öy÷–øú¹û±ýáÿ<´;¿ / {‘aÞú«ê±þÓ2$³ ë Û•+²ý<úÞö­ó»ðî×ëê¤èÅçhçŽç7è[éóêóìNïõñÕôÝ÷úúþ$Ä8 ^ * –=xPÍ÷Ú € ù R šß1š(äÿÕþþlýýüüýrýòý•þOÿÛ•7· +¹"K:óþ}ýâû.úoø±öõvóòñðð‹ï]ï‘ï+ð,ñ”ò\ôöñø§û‘þŸÀáî Õ ƒçð’Às¤R|(\"ˆœ o ¢)ÿ¿ûwødõ—ò ð îdì0ëuê3êhêë#ì—í_ïmñ±óö™øûýèÿ Â/N ˜ Å © I ¯æøóäÖ×ñ.—2 MÃh7&+:GE'áh ² ¶ o ×îµ/bXÿ¸ü>ú¼÷Dõæò³ð¼îí½ëÎêMêAê­ê’ëîì½îôðŠóqö˜ùîü^ØE‘ © {õ ®×¤EgHžÚ ã ̨‹‡ý­ú ø³õ®óòÁðãïlï[ï©ïQðHñƒòõóõE÷ùÄúrüþjÿ Ÿaä'-û˜ ` ÚÿÿcþÊýWýýý1ýœýFþ.ÿN£"Át/â  ÷ =Cýag G ¤ c×ýäùÌöÑóñuî8ìZêêèðçtç{çèéšê–ìúîºñÄôøoûéþ_¿õî šêÔLO×ç¨hÍâ· ] ã[×eÿùüûwù$ø"÷rööö;ö³öb÷=ø9ùGú\ûjügýFþÿþŠÿáÿéÿšÿÿgþýü—ûŒú‡ù•øÃ÷÷®ö~ö–öûö¯÷µø ú§ûˆý£ÿêRÌF ° ù æl”U¥àÉ=Cã , *ïŒþ¢úB÷ ôñ`îì*ê¹èÆçVçjçèéê’ìäî†ñdôo÷‘ú¸ýÑÊ“ U 8 º×ŒÙÂMj Š Þ T•êbÞþðýAýÒü¢ü®üñücýúý­þqÿ8ø¤2—ËȈ NU'ÿÈýAüŸúîø;÷•õ ô¨ò~ñ˜ððÄïåïkðWñ¨òZôgöÅøhûBþBYs~ e ‚–F„HNŒJeØö Ñ {ŒÿüÉø©õÍòDðî`ìëHêóéê¯êµëíáîìð1ó õ'øµú:ý¥ÿçôÂH~c õ 6 * Ø G „˜zaS[ƒÕWþÿ$ʧž£©¥‰JÛ2 H  ’ÁŸ2}‰bÿý¦ú0øÁõgó5ñ;ï‰í+ì/ëžê€êØê©ëñì«îÏðSó*öEù‘üüÿrß/ O +³ØÈ„¼p£[¡ I S 8æÔýéú6øÉõ®óðñ•ð¡ïïóî2ïÍï¼ðòñcóõ½ö‰øVúü»ý:ÿˆ¡|sr þD}·ÿüþXþÖýý\ýqýÃýTþ"ÿ)eÎZýªT ì c ¬ ¹~ð½û „ ¯ ƒ SkdýNú<÷Bôrñßî™ì°ê1é&è˜çŒçèûèqê]ì³îfñgô¤÷ û…þÿg¨¯ kÎÊXn -×ÚGb8Û Z É6´Sÿý$ûnùøéö"ö¯õŒõ´õ öÈöŸ÷šø­ùÊúåûñüäý³þVÿÆÿÍÿcÿÉþþ"ý*ü'û'ú6ù`ø²÷6÷øöýöM÷ë÷Ùøúšûdýiÿœó^Í0 v Žiö*ùZF¼¹B\h uFì|þ û¦÷jôeñ¬îMìVêÔèÎçJçKçÏçÑèLê4ì~îñõó÷'úWý{ƒ]øH A Ù Ö60Éø¥  j  Ëü? ,ìþäýý”üMüCüsüÕüaý þÍþ•ÿY©gyRíKlVÿþüûkùÄ÷%öžô<ó òñ|ð/ð?ð±ð‡ñÂò^ôTöø-ûöýèô ó ©9õCoC•f½£$N 1 ßmïÿxüùñõómð2îbìë!ê¸éÊéRêKëªìeîlð²ò%õ´÷Múáü^ÿ´Ø½Z©¥ M ¢ § c Ý 7.ïÓÉÝôÿD»`+  ê°J¯Õ´HŽ…0“¶¤ÿgý û£ø=öéó¹ñ½ïîì”ëôêÄê ëÆëùìžî¯ð!óèõõø6üšÿ xÌ ò Øl f´ƒÏ–Û£÷âr·  ¥tC%þ*ûeøäõ³óßñnðdïÅîî¿îMï2ðbñÑòrô4ö øåù¶ûoýÿk’G»îä£2šæ"Y˜ÿéþYþðý¸ý¶ýðýfþÿ,~öˆ'ÇY Î  ,ûz¢jÑÓ s ´ ž:–¾Äý·ú¬÷´ôäñLïþì ë|ébèÂç¢çèëèOê)ìoîñ ôB÷¤úþ Wk 7¬¼]ˆ9n)oH¿ß·X Ó 7˜’ÿIý8ûjùç÷µöØõOõõ1õ‘õ/ö÷û÷ù6ú]ûxü~ýbþÿ¦ÿûÿüÿªÿ&ÿwþ¥ýºüÁûÆú×ùþøIøÃ÷u÷i÷¥÷,øù%ú“ûEý3ÿQ–òV± ó é~¼™  ’¤Ap6¡ ½šJàþpû øËô¿ñûîŽìˆêôèÛçDç1ç£ç”èÿéÛëî®ð‡ó’ö½ùôü#8#Ñ5 D ó;Ž™AŒ„5¬ ÷ % Ef–ãXÿþÞýüü[üüûÝûùûKüËüný)þñþºÿw£þ&ËB~ÿQþõüyûçùLøµö2õÑóŸò©ñûðŸðžðüð½ñáòfôFözøöú­ý™› € 8°× üãL4™}çÝl¢ Ž BÓRØütù=öDóšðMîiìøêêƒéƒéúéåê9ìëíîï3ò©ô?÷ãù…üÿ|¶²hÏâ   ë q » ÕË©~U;;_°4ïÿâÿ kú²ŠwncI·(]PùVe)¤ßãÿ¹ýoûù¸ökô=ò@ð‚îíþëOëë@ëèëí—î”ðóò©õ¨øÞû9ÿ¦g ’ "d;›}ܶ æH@Ù#0 Ü¢xþoû˜øö¾óÓñLð-ïzî1îPîÑî«ïÕðAòãó«õŠ÷rùSûýËþJ”£rþHS$Á5ˆÆû4|ÿÞþdþþþ!þ~þÿíÿ÷3–¦;Æ 8 … t7¦ \ ´ ´fÔ !þûø(õWò»ïfígëÍé¢èñç¿çèáè1êùë0îÉð´óâö@úºý;°$ ÿ …¨]a©v̲3Z5Ö K ¨ý\ÖÿxýPûkùÐ÷†ö’õôô«ô²ôõ˜õeö]÷vø¡ùÓúýûý þßþÿðÿ&$ìÿÿåþ%þHýZüfûxúžùâøRøö÷Ù÷øsø1ù<úû*ýÿ =‰à2 o …fJ4µÆb‰;~YÕ  ì¦Dÿ×ûtø/õòNïÔì¿êéîçDçç|ç\è·é…ë¹íEðó$öRùüÉÿëå¦ B eYáþµ  Ä< „ « ÀÓò*ˆÿÝýáü'ü°ûzûƒûÅû7üÐü†ýMþÿÞÿ$‘ÏÖ¤5ЧÿþJýáû_úÒøE÷Çõgô2ó6ò}ñññLñøñótô>ö[øÃúhý;..) ÅBrF±¨#— ±ó é ¤7·8ýÎùŒö†óÌðmîvìñêåéTéAé§éƒêËëtírïµñ.ôÊöxù&üÄþA£pï î l • o  T r hCÙ¯«äNðÿÈÿÙÿ˜=äÒ¨v!âç¥@±þÐûƒù2÷íôÃòÅðïŒílì¯ë]ë|ëìí•î~ðÊòoõ^ø‡ûÚþ@© 1 'Ó# |pãÐ9#•™< EÎþ¶ûÏø'öÍóÍñ0ðüî3î×íåíXî'ïJð²ñTó!õ÷üøíúÌüþ#†¯–;½¡NÍ(jŸÓgÿÝþ}þNþWþ›þÿÖÿÇë9¦(±3 ¢ î ë ƒÉ¶Es @ ¯ ÅŒY|þ†ûŠø›õËò-ðÑíÉë"êèè&èáçèÜèêÏëõíð_ó…öÝùUý×Q®Ú à YW«„ß¾%¤Ò²R Ä d´«ýnûqù¿÷]öRõžôAô7ô{ôõÊõÀöÚ÷ ùFú~û§ü´ýœþXÿàÿ0H(ÔÿOÿ¡þÔýñüüû>ú~ùäø|øNøbø¾øeùWú“ûýÔþÇæ"k´ ê ÿ âƒÔÊ[}-h0‡v B ;¦ÿ>üÜø”õ|ò¤ïíúêDéèJçç[ç)èté4ë\íàï®ò·õæø)ülÿš£u : ‰’.^%‰”PÊ  2 =BPu½4ÿàýËüøûiûûûAû¥û4üäü¨ýwþBÿÿÿ¡ s‘x"’ÈÿÉþšýFüÖúVùÔ÷\öþôÈóÅòòŒñjñ¢ñ9ò1óˆô:öBø”ú&ýéÿÍ÷˜ QÒ èagõš)CñAA œšý*úÞöËóñ’î‰ìðêÏé+ééYé&êaëíøî9ñ²óSö ùÅûsþeŽs L 7 Ê  ð ë   Ü¡`'ünõÿ³ÿªÿÙÿ:ËS8"ÖˆczLÖ ¸"RSþ-üñù¬÷nõIóLñ‡ïîÞìì±ë¾ë>ì3í™îmð¦ò8õø4û|þÜA™Í Ë€ÞÔW^ääa\Þïœõ ë®f&ÿü ùPöâóÍñðÏîòíƒí€íãí§îÁï%ñÆò–ô…ö„ø„úuüKþùÿsµ¶tí#×cÇCr©òÿXÿåþ¡þ“þ½þ#ÿÄÿœ¨à:«'¡ W w ^ VT÷ :  ¤ Ñ®E¡ÔþëûøøöAó ð?î.ì{ê3é`è è2èÝèêªë¿í:ðó)ö{ùðüsñUŒ ƒ )pL´¡xzH-Î > ŒÍgãýû}ù²÷9öõMôÛóÀóõósô1õ$ö>÷uø¹ùýú6üWýUþ)ÿÊÿ5ga#µÿÿ]þ‡ý¢ü¼ûàúúyùùÆøÈøùžùxú›ûý«þ‰“½ù6 f x [[]ü/óB‹Ž1  †X¤üDùüõÞòþïmí:ëté%èUçç@çüç6éæêí}ïEòKõ{øÂû ÿF^Aà - §Æw¹ÛX ¹ ¼´²ÄöUÿéý»üÎû'ûÄú¤úÁúûšûCüýÔý¥þlÿ¬GF ”äÿþþæý§üIûØùaøñö—õ_ôWóŒò ò×ñüñòaó¡ô<ö-øjúèüšÿpZF" Û _ž† "Áá¡Cn-‹— bÿýý‡ú3÷ô=ñ¼î ìôê¿ééÍèéÍéûêìî¾ð8óÝõ›øaûþ¾5up y { # r m   ¨ ¡ v4é¢kPZ“¤ÿÿ—ÿâÿ\Åžc5íàîæó¹=„šþˆü[ú#øïõÐóÔñ ðˆîTí|ì ììrìQí£îað†òõÕ÷ãú þxÙ0g k*”™-Gßó‚!AùZs W ÊÿPüIù}öüóÒñ ð©î·í4íísí*î;ï™ð9ò ôö øúüþÈÿ[¶Ñ§8…]öd°çB€ØÿRÿùþÓþåþ1ÿ¸ÿvj‹Ñ1 t ¾ á Ï | ß î ¤ ý ÷ ” ØÌwç*ÿNüeù‚ö·óñ°î—ìÙêƒé è6èLèãèùéŠëíùï¿òÐõùŒüû; ? ôM;·¸;?ÇØ{»¥I· 7mµþ·ûù¬÷öáôô{óMósóåóšôˆõ£öÝ÷)ùzúÂûöü þõþ°ÿ4”o‘ÿäþþ?ý^üƒûºúúùCù2ùdùÝùžú¨ûøü‡þND\ˆºâ ï Ó|Þë˜Ü²Š¡X · Ï®e ý­ùdöBóZð¿íëªéIèfçç+çÔçýèžê­ìïÞñàôø[û¬þð º  Àô¹÷x˜cä) A < )4|ÿøý°üªûêúpú:úEú‹úû£ûaü1ýþ×þ”ÿ4­ùî‘ûÿ.ÿ.þýºûYúîø†÷/ö÷ôìóó‰òHò\òÊò–ó¿ôCöøDú®üNÿòÖ­ d ë/!²Ø‡ºn¡W•dÑê ¾aåaþçú‹÷aô|ñëî½ìýêµéèè›èÍèyé™ê#ì îDð½òfõ+øüúÆýwVi.   ¹ w Ú æ    A =  Étبœ¼šÿ]ÿYÿÿóÿƒ8âÀ”QìZ’ŒB±×¶R±ÝþßüÃú™øpöVô]ò”ð ïÍíéìhìQì«ìví²î[ðkòØô–÷•úÆýrÆÿ ÑFYþ)Õüž¾`ŽS½Ü  ‚/Þÿ¡üŒù¯öôÜñþïˆîíêìÂìí±í·îð­ñó|õ÷ªù½ûºý”ÿ>²æÕáà‡ÿRеÝYÃÿUÿÿÿCÿ°ÿU0:k¹Ý% I < ô c ƒ L ¹ Ê ~ Úä¥(|ÿ¯üÑùöö.ôñ$ïí;ëØéäèjèmèðèòéoëaí¼ïtòzõ½ø)ü«ÿ-žç ÷ »$%´É`w1á+Ã0 t £Î^þãû£ùª÷ö±ôºóóßòôòZóôïôöE÷˜øôùKû‘üºý½þ‘ÿ/–ötgÿ¬þÛýÿü&ü[ûªúúÃù¡ù¾ù úÊú»ûñühþøý?^ g Iö^u0„må냯z ì ÃoýúÎö¨óºðîÉëäérè}ç çç²çÉèZê[ì¿îyñvô¥÷óúJþ˜ÉÌ  Ó÷`Yéèn´ É ½ Ÿlu§ÿ þªü‹û²ú úÕùÍùúmúû¾ûŽühý?þ ÿ¹ÿE¦Ôˉ Yÿrþ^ý'üÖúxùøÈö‘õ‚ô¨óó¾òÀòóÑóãôPöø#úxüÿ¼f7 ì t½·UˆHŽUœe¶—9  ÁJÆþHûå÷±ô¿ñïßì ë°éÐèoèŽè*é;êºëšíÍïDòïôº÷”úký-Ê3\9  ò Æ = [ $   Ø × ª ^ŸGãë$”ÿ>ÿ!ÿ<ÿŒÿ ¯pCñ²VÐ%ðvµ®cÚÿ2ý)ûùïöÝôèòñïJî[íËì£ìéìŸíÆîZðVò¯ô[÷Júoý´ \– ¤ tôÉÅÿ´æš×©C , ë•<õüÒùåö>ôëñøïmîPí¥ìkìŸì;í7î‰ï#ñ÷ò÷ô÷9ù\ûlý[ÿ¨õþÀ9m_˜ò.Wz£ß6¶ÿbÿBÿ[ÿ®ÿ8úí E–ðFŠ ¯ ¨ h ä  ï q ˜ c ×÷ÎeËÿ ý<úi÷¦ôòšïsí¡ë1ê.é¢è’èéðéZë9íƒï-ò'õ`øÆûFÿÊ? « }÷ ¬Õ©U…C˜;¨ é 0[¡þü½ù®÷ïõ†ôxóÈòuòzòÒòtóVônõ­öølùÒú)üfý€þlÿ$¥ìùÎqèÿ;ÿuþ ýÉüüûFû°úGúúúiúúúÒûðüNþçÿ°¢®ÆÛ Þ ¾ mÛüÃ("®Év¸—  UPÓýú8÷ôñnîì#ê¡è™ççç•çšèê ìfîñô;÷Šúçý=zŒ` è á@/«·Vk÷>Q ? 鯻×ÿ#þ©üqûúÖùuùYù}ùÛùiúûëûÇü¦ý{þ:ÿÙÿN”¤{€ÿ±þ´ý‘üRûú­øa÷,öõ:ô•ó7ó)ópóô õbö øúGüÁþf)øÁ s ûHJó4\6‘nÒÅR… o !­*ÿªûAøõòWïí!ë±é½èIèUèàèâéTë*íWïÌñxôH÷+úýàÿŽ J> ß &  › Ë ¤ , l p D ôŽ!ºe.>•ÿ$ÿíþðþ*ÿ•ÿ(ܦ{M½Dš¹š7Ž nþWÿ‚ýŒû€ùm÷dõró©ñðËîÐí2íúì-íÏíáî_ðEòŠô#÷úýU¤ò+ = žÌÞ¯üÅ Ïûz§ • UûœLýú÷fôòøïWî&ífìì<ìÉìºíïšðnòqô”öÇøøúýÿöš"üÕÚŸ/‘Ðù8g¯°ÿyÿxÿ±ÿ!ʤ«Ób°ð  Ù a   # ` C ÎóŸiý¤úÛ÷õ€òðæí ìê}éàè¾èéôéJëíOïéñÖôøeûâþfÞ7 \ ;ÄéžÛ™Ö”Õ¡± ^ •²èþGüÝù·÷àõ`ô<ówòòòMòåòÀóÔôöt÷ãøUú½ûý>þCÿ°6#ÛdÈÿ ÿ@þmýŸüãûEûÏú‹ú€ú¶ú0ûðûôü9þºÿmJDNY T 2 âURÆÒq¡d»¯ H “x6þèú£÷{ô‚ñËîhìgêÕè»ç"ç ç}çpèàéÃëî·ð¨óÒö!ú‚ýà(H, Ç é^añ¾ë}ÇÙ Á V# @þ®ü]ûRú‘ùùéøüøKùÏù|úHû&ü ýêý¸þhÿóÿOxi!¡ÿìþþøüÊû‰ú?ùú÷Çö´õÎô ôµó—óËóVô;õyö øðùüþÇŠL ù ÑÚÛ»$€qéîŒÍ à ~ÿ üŸøZõPò“ï3í;ë¸é°è)è"è›èéòê¾ìäîVñôÖöÀù¯üÿNß3> ö T T ô 7 ´ þ  Ü Š ¦0É}V]šÿÿ¿þ©þÌþ"ÿ¥ÿJ Ùªq#´J?óbtŽÿÏýëûðùê÷êõþó6ò¡ðNïIîžíUívíîïið:òjôñö¿ùÇüøÿ>‡À Ô ±D~Q°“ôÐ'þ\IÔ ü ¾cþ¥ýiú]÷“ôòýïGîí,ìÌëÝë\ìAí‚îðåñìóöRø’úÅüÜþˇ@3Û9Q'Ã.rœ·Ïò*‚´ÿšÿ¹ÿž`Pe–ÖUy x H Û ' & Ñ #  ¿Ô_Âý ûLø–õûòŒð[îxìñêÑé$éïè7éþé@ëùì ïªñ‰ô®÷û~þ|Û õËۭþÎ úfp%– Ó îû 3ÿüúÅ÷ØõAôó+ò¯ñ‘ñÌñXò,ó<ô}õàöXø×ùOû³üøýÿµ0otBÞQ£ÿßþþCý‚üÜûYûûèú ûkûüýü)þ‘ÿ-öÞØ×Ë ¥ UÍþÝ_|/tL¹ o ÍçϘþQûøæôéñ,ï¾ì¯êéãç7ççlçLèªé~ë½íZðDójö¹ùýÔõ ¡ øìuŽ2c"vhO` D ŃRCbþ·üMû*úPùÂø}ø~ø¿ø7ùÝù¥ú…ûoüXý2þôþ“ÿFQ#¾ÿ!ÿSþZý@ü ûÏù’øc÷Pöeõ®ô7ôô*ô¡ôpõ–öøÞùñûBþÃh× Xg#~mççioúÁ  Ùrôÿqüù³õŸòÔïdí[ëÅé©èèôç[è=é”êUìtîáðŒócöTùMü:ÿ ¯8  | “ Hž—:Ž u ®,¨0Ð’¤ÿÿþ•þgþsþ´þ$ÿ¼ÿp7φ!”Öß©1tu7ÀÿþGü]úeøoö‰ôÄò-ñÔïÆîî¶íÅí?î&ïyð4òPôÂöùxüœÿÙT i Kç- }ræÕ@)—“*ib 'Êaþ¹úŸ÷Äô8òð=îáìøë„ë„ëóëËìîï^ñfó–õÜ÷)úlü—þ›nYd$˜Ä«TÉ>Vh€©îZôÿÁÿÆÿw!úúL†ºÜÞ ³ Q « » y á ò ¬.¤þpû¼øövóñÓîéìWë*êlé&é[é ê;ëàìõînñ?ôX÷¨úþœ}´ ¬R˜rÕ»eOÈܘ G _chÿ¼ü*úÙ÷Ôõ&ôÕòãñTñ$ñOñÏñšò¦óåôLöÌ÷VùÝúTü®ýâþçÿµJ£À¤TØ7}ÿ³þçý#ýuüçû„ûUû`û«û9ü ýþmÿò¥zeWC  Ç B{dô"èA.²Ð ’ .$÷þ¸û{øSõSòïíýêLéèRçç`ç-èzé>ëoíðâòöQù·ü!|µ¹ w à釵n±äá‚Õç È ‡ 6夀ˆþÆüDûúùpøøø5ø¡ø?ùúãúÒûÃüªý|þ.ÿ¸ÿ4!ÖÿRÿœþºý²üû_ú*ùøíöþõ?õ¼ôôŽôñô©õ¸öøÐùÍû þw µc ‰ Ýñµ¤·Mg2òS c 2ÒWÖüaùöðòð™í€ë×é¨èùçÌç èòè;êðëîmðóðõçøéûãþÃz÷.  Ÿ Ì — ¼1 ¶ ? ´#›'Óª´ÿõþqþ)þþIþ§þ/ÿØÿ—b+èŒ ^{[úWqLíÿ[þ üÈúÞøóöõRó»ñ]ðGïƒîîîîQïŽð3ò:ô˜öCù,üCÿv³çý ã‡×ÅDKÑÔRNÍÙ|ÆÆ Ž2Å]þ ûä÷úô\òð8îÇìÉëBë/ëŽëYì†í ïØðáòõd÷½ùüNþgQm‘hó2+âb²àö+_¶8îÿØÿûÿUæ§“ Äò ?B  à + K  š Á “D2ålþÓû+ù…öòó…ñNï]íÁë‡êºébé„é"ê<ëÍìÏî7ñùó÷Lú¸ý7µ\ ^hTÊÃ;1¦ &D» ÏÍÇÒÿüüWúñ÷Öõô©ò¢ñýð»ðÖðIñ òóOô¸õ>÷Óøhúñû`ý«þÈÿ°_ÑÇ[ÉVÿ‹þÅýýxüüÅû¼ûñûfüýþNÿ»XôÙ» Š 8 µôç…Û  ¥Ù ° 3pvUÿüçøÀõ¿òõïuíNëéCèrç$çZçèOéë%íªïƒòžõéøQüÀÿ#gy H Äá”Ö£úÜNWYmK  ©KøÁ´þÚü?ûêùàø#ø´÷÷¯÷ø£øcùBú4û-ü ýþÆþeÿÖÿèÿÿáþþ!ýüìúÁùœøŠ÷˜öÓõEõùô÷ôFõèõàö,øÈù®ûÔý.±Lð‹ `xD¶Á]+Y L ® ˆ1»;ýÄùlöEóbðÔí©ëîé¬èêç©çëç¬èåéŽë›íüï£ò}õyø„ûŠþyAÒ  ½ á^z:¤à ¡ L Ñ =¡‚ØÈÿïþRþñýÍýãý-þ¥þBÿùÿ¾‡Hô€â¾4h\›þõü/ûVùv÷ õâóKòéðÊïûî…îqîÄî‚ï©ð8ò)ôsö ùãûìþJy y#}x¸Í_mþË ( ô™*¼þaû-ø4õ„ò,ð9î³ì¡ëëàê.ëëë í‰îSð\ò”ôëöOù±ûþ./ö{¸§Hœ§møP—¡¯Ó‚ðÿøÿ8¯Y/)>`†¡¥„ 3 § × » M ‹ t VZ"¼þ3ü˜ùüöoôòÊïÔí/ìéê ê£é²é=êBëÀì®îñ·ó¶öòùWýÒP¼ Î40¹ÆQZá뀩uñ/ @ 8(%@ýˆúøÝõôƒòeñ¬ðVðaðÆð~ñ}ò¹ó$õ°öNøñù‹ûýoþ¥ÿ¦núI[5ÜX³÷ÿ/ÿhþ­ý ýŒü:üü;ü˜ü7ýþ4ÿ‰¼…\3 ü § &jg_IËã’Ü É `¯Å±ÿ„üRù/ö,ó^ðÕí¤ë×ézè˜ç7çZçè)éËêÞìWï&ò:õ‚øêû]ÿÇ6  ¢Ó›òÔ>1³É}ÛñÎ ‚ ³Pãþóü?ûÒù¯øÛ÷V÷÷-÷÷ øÃø¡ù–ú•û“üƒýZþ ÿ–ÿíÿ õÿ¦ÿ!ÿlþýüxûWú9ù)ø5÷iöÑõwõeõŸõ,ö ÷AøÅù“û£ýêÿZæ~ áüÏKdFE `FÉ ö ÜŽ¡ý)úËöœó¯ðîØë ê¶èàçŒç»çkè•é1ë3íï0ò õ øû.þ+¨  Õ /%·å´+R6 á c È yàb âÿïþ8þ¾ýýý·ýþ­þ[ÿã§Zòc¥¯~ Yg9×þGý”ûËùø÷+örôÛòwñQðwïôîÏîï¸ïÉðBòôRöÖøû˜þ´á ! ½ 'Äí˜Áf‡*Wv‡ Y ÿ¹ûzøqõ±òGð?î¥ì}ëÍê•êÓêë—ì îÑïØñôqöàøPû°ýóÿç„Ùá™  õŒí"7957JzÐT ûÿ ~жºÐíé  _ T û P Qb}[ ÿ‘üúq÷ëôƒòIðMî ìOëdêêéçé]êNë·ì’î×ðxóiöšù÷ünëY¤ ¹ †ú£Ãb~2Õ ßa¡ ± £‹{‡ý¾ú0øêõøóbò.ñ`ð÷ïðïGðôðìñ$óô!öÈ÷wù!û·ü/þ|ÿ–y†°ŸYåK—Ôÿ ÿLþ¡ýý²ü‚üŠüÏüUýþÿ[Êbá­n  • Þã™öò‡µzÚ Ü ‰ë èü¾ùö›óÉð9îýë#ê·èÄçPç`çóçé™êìïÌñÙôøƒûúþjÂîÜ |Àœþ|‚7ö[tQ ”«OÿýEû¿ù„ø˜÷ýö°ö¯öòör÷%øù÷ùüúüýêý²þQÿÁÿûÿþÿÈÿ\ÿ¾þõýýüìúÕùÈøÓ÷÷`öúõ×õþõvö?÷[øÇù~ûwý©ÿƒ˜  aXݾÖ, piý : -é€þŽú-÷÷óÿðVî ì.êÆèÜçuç‘ç/èIé×êÎì!ïÀñ™ôœ÷´úÐýÚÃzð è Xd K*®ßÈ v õ T ¡ìB°Aôþ#þý;ý#ýEýšýþ¿þyÿ>¿aà4S8ÞEmXÿ•ýöû=úxøµöõmóòÛð÷ïgï2ï_ïóïïðRòô6ö§ø[ûFþUyž± ž S¿Ò}¶s¯gœQŽ]Êä ½ gõ~ÿüÉø³õâòfðKîœì`ëœêPê}êë%ìíPïVñ’óöõnøëú\ý²ÿÝÓˆöåc “ z  ‡Á×ÖÊÀÄâ#-RËtF9BTegM • â é ¤  (ïiœRÿëümúæ÷hõóÉðÊîí¹ëÁê6ê!ê„ê`ëµì|î­ð>ó öEù™ü …ôE b :¼Ú‡ºl›Gs&hGÏ ! ðÕÒýøúVøûõóóGòýððœï„ïÌïmð]ñ‘òüó‘õ@÷üøµú]üêýOÿ‚~>¾Ònâ6v°ÿìþ9þ¡ý/ýëüÞü ýxý%þÿ2Š °h(á „  P]‰–?\Ó ë ¬"Y`Ký(ú ÷ ô6ñ î[ìtêùèõçoçkçëçíèlê_ì¼îuñyô¸÷û•þ l¤¡ Q¨˜#µÍo¡kØöÓ  ‰ ›Pÿ3ýPû²ù^ø[÷©öHö4öhöÝö‰÷`øWùbúsû~üwýRþÿÿäÿåÿ“ÿ ÿYþýˆüûpúgùrøœ÷òööMöböÄöw÷{øÏùmûOýlÿ¶"Ÿ à ÿÝlgÀ£ þz†-z {Bákþôú÷TôRñîDìUêÛèßçdçmçøçéêmì·îPñ(ô-÷Kúoý†~GÑ õ |žY¬œ.iY ‡ à $b§}#ÿþþfýùüÊü×üýŒý$þ×þ›ÿa!ÍZ¾òí¬,nsAÿÞýTü­ú÷ø>÷’õô˜òhñ{ðÞï™ï´ï4ðñgòôö{øûøýù1@ . ç[x1yH—b«sÁŸ>  Ì[áÿoüùøõóŠð\î˜ìHëoêê+êºê·ëíÑîÔðózõû÷…úýmÿ­¹‡ D+ ¿  ú «  _wtaLBNyÎT*ŠÚ»µ½Çǯs b z I ÉùÙk¶Á—ÿCýÔúYøäõ„óKñIïí'ì"ë‡ê`ê¯êxë¸ìkî‰ðóÛõòø=ü¨ÿã  êz§e«q´r°r«;‚ ’ |V0 þ5ûøöôó1òÑðØïGïïUïéïÐðÿñjóõ·ö~øEúü¡ýÿh~WñKgHõvÔSŽÿÓþ0þ®ýYý6ýMý¡ý3þÿMºJò¥T ò p ¿ Óž4ñH9Ç õ ËUžµ¬ý’ú|÷|ô¥ñ ï¼ìÊê@é,è“ç|çéçØèDê'ìuî!ñôT÷·ú0þªVa "ŠŽ#BèÆÝSuTý „ ÷jëŒÿZý`ûªù>ø#÷Zöäõ¾õâõKöîöÁ÷¸øÇùàú÷ûýïýºþZÿÇÿþÿýÿÅÿWÿ¹þóý ýü ûúù9ø‡÷ ÷ÇöÊö÷´÷ øÜùbû,ý3ÿiÃ3§ ^ }`ö3 ujèî~ŸX¶ Æ™@ÐþZûõ÷³ô©ñéî‚ì‚êöèæçXçNçÇçÀè0êìPîãð¹ó¾öáù ý/6® ý šÒ¢  ©ðç›  m ©ÚW¼Kÿ þBý¼üvümüüýŒý7þ÷þ¿ÿ‚7ÑEŒžuiˆoÿ$þ®üûsùÆ÷"ö”ô,ó÷ññYððð{ðLñ‚òô öTøãú¬ý ®ÄÐ ½ yóà8yX´ïÞf– ~ 0ÁCÍüpùAöRó³ðrî›ì6ëIê×éßé^êMë£ìUîTð’òþô‡÷ú«ü%ÿy›€nl  n w 6 µ üùÚÂ½Ô ùÿOÉr@+(*&ØvÞ è~ŽhËíØÿ˜ý9ûËø_öôÎñÊï î™ì‡ëÞê¥êáê•ëÀì_îiðÖò™õ£øâûFÿ¹(€ « —3o?—pÆ˜çº ¤ð  꽎rþwû±ø-öúó!ò«ðœïöîºîâîiïGðpñØòqô.öþ÷ÓùŸûTýæþJyl’ĺxp¼ø/oÿÁþ2þÊý“ý“ýÎýGþþþïÿlè~#È` Û , F¡Ïž ´ ù æƒß þûúë÷îôòwï!í#ëŒégè½ç“çìçÈè!êóë1îÑðÂóóöRúËýH¸ î h(\ThKÊóÔ| ü gÍ>Íÿ…ýuû§ù#øðöö…õKõ`õ¼õVö#÷ø+ùLúnû†üˆýhþÿ¦ÿ÷ÿñÿœÿÿcþŽý ü¤û¦ú³ù×øø•÷E÷7÷p÷ö÷Ëøîù[ûýþþhÈ1’ Û úà}Ū$,¾Ø}²î íž4ÿÁû[øõò8ïÃì´êéôçRç5ç›çƒèäé¶ëìíxðJóOövù©ü×ÿëÖ†í ÿ ²å`r!ts+© û / U{°x"ÿþ#ý„ü&üü$üwüöü˜ýSþÿãÿžDÉ"I8ê_˜˜ÿeþý„ûíùMø±ö(õÁóˆòŒñ×ðvðnðÇðƒñ¢ò#ôö2ø­údýIKX^ J ‰¹‹ñâVH·¥®ê Û ”&¨-ýÈùŽöóáðŽî£ì)ë(ê¢é˜éêçê2ìÛíÖïò‚ô÷±ùNüÙþ@xt*’¨ i Õ ï ¾ H – µ¯’jF/4\°7õÿëÿz È£“ކo<âVŽƒ.Œœ`Ûéý›û;ùÚö†ôRòMð‡îíñë9ëïêë¸ëÏìXîOð©ò[õVøŠûæþSÁ K Aè3}iÒ·üii \p W%îÆþ¼ûäøMöôòŠðeï«î\îsîíîÀïâðGòâó£õ}÷_ù;ûý«þ&n{HÓ'ø– ]œÒ Uÿ¸þ@þõýÞýþaþýþÕÿâ"‰ £=Í F ˜ ¶ ”'dEÅâ ø û®UgþbûZøaõ‰òæï‰íëÝé¨èíç°çöç½èêÄëòí„ðjó“öîùeýæ[²Ö µ Ak(p=fŵ>nRú v Ø2•µýû©ù øÂöËõ*õÞôáô/õ¿õ‡ö{÷ø¶ùãú üýþàþÿêÿÝÿmÿÐþ þ-ý<üEûTúvù¸ø%øÇ÷¨÷Í÷>øûøúZûõüÎþÚ`¼ W u^SEÏ鎽wÀ " Q >ù—ÿ(üÂøyõ`ò‹ï íëê<éèRç"çuçKèœé`ë‹íðÝòáõ ùDü|ÿ—YÔ ü Å)$²×•ôýº9 ˆ ¶ Ñé Iª<ÿþ ýQüÛû¦û¯ûñûbüûü°ývþAÿµIµñöÂQ£½ÿ¡þXýëûeúÒø@÷½õWôóòZñêðÒðñ¾ñÈò2ôùõø{ú ýõÿêíí× —T1¦§-2µ·<Lò;6 õ‹ Žý"úÝöÓóñ®î°ì#ë êséVé³é…êÄëdíYï•ñô›öDùîû‰þQd1±ß ¶ 7 d B Ø / R M,üË¥–©åS÷ÿÓÿçÿ0¬TòåÍžLËÙNvRæ7N6þúûªùS÷õ×òÑðïˆí_ì™ë>ëUëáëâìWî9ð€ò!õ ø5û†þîZ´ê ç™òâ]\ÙÑE:¶ÃnÇÝ ÄŽPÿüùröôòoð4ïeîî îtî<ïWð¸ñSóõúöèøÔú¯ülþÿÿ_…lq‘t"¡ý@v«ìÿBÿ¹þZþ.þ9þþÿÀÿ´Ü-Ÿ%³; °  % ©õè|¯  ò ÓV ÁþÈûÈøÔõýòWðôíãë2êîè"èÓçè¹èíéšë¸í;ðó6öŠùý‚ý[‹ y Q!~`Å­°çÏw ð KšîYêý®û±ùý÷šöŒõÕôtôgô¦ô+õìõÞöó÷ ùVúŠû®ü·ýœþTÿÙÿ&;Áÿ9ÿˆþ¸ýÒüãûöúúTù·øMøø/øŠø0ù"ú^ûàü¢þ˜ºúH– Ô ï ÚƒÝÜu XœjɽQ ‘ ŒSùÿŽü*ùÞõÀòáïTí'ëhé èXççUçèYéë.íªïqòtõžøÞûÿKU(· ó ÓM\ÿ6qƒGÈ  = OZl•àZÿ þöü$ü•ûJû>ûnûÑû_üýÒýŸþiÿ$ÅC“°”<©ÝÿÙþ§ýOüÚúVùÎ÷Qöíô±ó¨òàñcñ;ñnñòóòGôöõü÷Múßü¤ÿŠ„|b #«ëÓUfþ­ÂZ|2ˆŽ Uïqðý~ú/÷ôJñÔîÃì"ëøéJééfé(êZëðìßîñŠó%öÖøŒû6þÃ%N3Ë þ ” Ô Â e Æ î êÆSýû tÿÿÀÿºÿìÿPãœqXE+ÿ³=“« J?ëUƒ€þWüúË÷ˆõ\óXñ‹ïîÑìýë’ë—ëìüì\î)ð\òëôÇ÷âú)þŠòM† ŠG¬«9JÚælrþÏ/J 1 ø³uÿQüXùœö+ôòYð ï%î¯í¤íî¼îÎï*ñÄòôvöoøjúVü(þÓÿKŠŠGÀöìª7œäKƒÎÿ6ÿÄþ‚þvþ£þ ÿ¯ÿŠšÕ4©+ª k ‘ ~ '‚†-u ] æ  ô‹çÿ,ü5ùGöróËðbîHìŒê:é\èûçèºèÚéuë‚íöïÃòÚõ)ù›üœ= 8 ä2†|õðq}]Jó j ¾K¥#þÑû½ùò÷wöRõ…ôôðó!ôšôSõAöW÷ˆøÈùû<üYýTþ$ÿÂÿ)XOžÿÿ@þgý€ü—û¹úñùMùÖø–ø–øÜøjùDúgûÑüzþZh–× P h SdnRuYÌÕ| Í ØªXõü’ùEö"ó;ð¢ígë˜é?èdç ç:çëçéÁêÔìFïòõ3øvû¿þ÷ó• æ ÛkG‘pêÒV£ Æ ÎÍÏå}ÿþçüüûTûòúÒúïúCûÆûmü.ýüýÌþ‘ÿ?Í2ea#ª÷ÿ ÿòý¯üLû×ù[øæö…õHô:óiòàñ¨ñÉñGò$óaôùõè÷$ú¢üUÿ- î ­ 9€q!ÊõŸÈs§mÒä ³SÖSþÛú…÷bô…ñþîÛì&ëèé'éãèéÏéôê€ìgîœðó­õfø(ûáýô3/ß< @ ì @ ? ð Z ‰ † `#ÝšgP_š ²ÿ’ÿ«ÿùÿvã¿¥‰^¬8 Á&ìn³Æþ°üúBøöâóßñðƒîGífììëÞëCìífîð=ò¹ô…÷‘úÎý'Šä *ñbp2ÕôަAj,”´ bÑÿ ü˜ùÊöFôòIðãîêí`íCíí?îGïžð7òôñõõ÷ýùûûàý¡ÿ1Š£y Va0Ê9†¾ì\¶ÿ2ÿÛþ·þËþÿ¤ÿf]‚Ì0¤ƒ Ó û ï ¢ Ú 7 5 Õ  ¼+mÿŽü¢ùºöèó@ñÓî±ìéêŠéœè(è4èÁèÎéUëQíµïuòõÉø7üºÿ;§ë ó ¯‰“-¿Ú‡ÐÃoã 3 o©ô_þùûÏùí÷Zöõ:ô°ó~óŸó ô½ô¦õ»öð÷7ùƒúÇû÷üþïþ¦ÿ'qYÿÿvÿÆþúýý9ü[û‘úäùbùùù2ùªùkúvûÇüXþ!6gŸÌ á Ì}çü²ÿÝHAÊç¢  ÿ·Zýûù­ö†ó˜ðõí¬ëÍécèuç ç%çÃçâèyêìæî ñœôÇ÷û]þ Åºn Ó Ýƒ½‰æÖ_‡Zã/ N O B69Z¥ÿ#þÝüØûûŸúiútú¸ú/ûÎûŠüYý-þûþ¶ÿTÌ)¥ <ÿ9þ ý¼ûVúæøy÷öàôÎóöòaòò)ò“òZó€ôöÙ÷ÿùiü ÿÓ´œx 7 Å §Ö͋ȇͥ6  µ;·þ;ûÝ÷¯ôÅñ.ïøì0ëßé é²èÙè|é’êìòí#ð”ò5õõ÷Áúˆý7À'îb ~ ? § · v ì ! " û¸iÕª¢Å©ÿoÿoÿ¥ÿ  X(æ¼{ˆÂ½tã ç‚ßÿýæú·øˆöhôhò˜ðïÀíÔìJì+ì|ì@íuîð#òŒôG÷DúuýÅ#{¸ È —1ßËýªÓ€¸…÷ Í}-òüÛùýöeô"ò?ðÃîµííçì#íÅíÄîðªñwólõx÷ùœû•ýkÿ„·¦O²Ñ±ZÓ'b޹î8¤ÿ9ÿþþùþ.ÿžÿF$2gºŠì9 c \  Ž ³ ó  ¾  (él¾ÿîü ú,÷_ô·ñFïíKëÞéáè\èUèÎèÇé;ë$íxï*ò+õjøÔûUÿØJ— « uåDe 3í@:é] ¨ Ü F þ&üæùì÷BöîôôóUóó!óó(ô õ öX÷¦øýùOû‘ü¶ýµþ…ÿ „®Ÿ[çÿIÿ‹þ·ýÚüþû1û~úñù•ùqùùïù˜úŠûÁü:þíÿÐÙú%I Y B÷g†I¦—$Âôà 9 dR¿ýcú÷ìó÷ðKîöëêŒèŒççç¡ç®è5ê-ì‰î;ñ2ô\÷¦úûýGy}C » Ú•åÆ78Ðàm» × Ñ ¹žÒÿ8þÙü»ûâúQúúüù0úšú0ûèûµüýcþ*ÿØÿbÀìáœfÿ{þcý(üÓúpù ø¶öyõeô…óåòòŽòäò–ó¥ôöÐ÷àù5üÃþ{O- ¿ NŸ£I‡Q¡q•î×Z… h Ÿÿœû7øÿôòbïí@ëÚéñè†è›è-é4ê©ë€í«ïò¾ôƒ÷Yú,ýìÿ‡ð÷ƒ ¶ + ú { ¸ ½ • Nö™Fêõ2¦ÿRÿ7ÿVÿ¨ÿ(Ï’hDÝ‚þGU!§æÝ‘FÿXýKû*ù÷îôòò!ñ‹ï=îEí­ì}ì»ìkí‹îðòdô ÷úùýd¼P c :ÂìªñºÿÀüºÛW„ s 7ãŒFý"ú3÷‰ô2ò9ð¨î…íÒìì¼ìPíDîïñíòæôûöù:ûEý1ÿðzÅÍ =0çlÈ0V¿šÿIÿ,ÿHÿÿ+ðçGœûV  Ê È  C # ª Ô ¢  :¨ LývúŸ÷Öô/ò¼ïŒí±ë7ê+é•è{èàèÅé&ëýì@ïãñØôørûðþtë@ _ 7·Ò}¯c—MˆO­®aÖ  Jn›äþWüúñ÷0öÄô³óÿò§ò§òùò–ósô…õ¿öøtùÕú'üaývþ_ÿ’Öà³SÈÿÿQþzý¢üÓûû„úúåùíù9úÊú£ûÁü!þ½ÿ‰¬Ç Ð ¸ nä ÜIKß´üà i ¤¡o#þÌú÷TôZñ¤îDìGê»è©çç ç„çèöéßë0îÙðÊóòö=ú—ýì)< ž Ò¢þ‚–=~cöF` T 2 ëäQþÙü¢û±úú¦ù‰ù¬ùú”úFûüìüÉý›þXÿõÿg«¸'‹ÿ¹þ¸ý‘üMûøùŸøN÷öýôômó ó÷ò:ó×óÏô"öË÷Äùüþ&ìÀŽ F Ö+6ç2 nR· ˜Ñ ¿ t€ÿþû“øSõOòšïBíUëÜéÞè`ècèãèÛéCëí5ï¢ñFô÷ïùÎüÿJÇûž è Ö f › y  M V / å…ºi6*M§ÿ9ÿÿ ÿGÿ´ÿIÿË¡v=éqÉèÉg¾Î›)ÿ§ý¬ûœù„÷tõ|ó¬ñð¾î»ííÔìí›í¦îðÿñ@ôÖö´ùÉüV§å ý Úl£pɤüÐîE-´é Ü ¡Jíýmún÷²ôGò:ð”î[í“ì>ìYìÞìÇíï–ðcò_ô|ö¨øÕúòüòþÈjÏðÊ[¤ªqf¨ÓôH’™ÿdÿfÿ¢ÿÁŸ©ÖnÁ 0 1 þ ‹ Ï Á [ ›  H5áW§ýÞúøMõ©ò3ðÿíì•êzéÓè§èøèÉéëÛì ï ñˆô´÷ûŒþ‹æ õ…±oµ}Č׭ ØN “ ¹Óô,ÿŒü"úû÷#ö ôxó®òBò1òuòóÝóëô&ö€÷êøWú»ûý3þ5ÿ›ù¼D¥ÿéþþEývü¸ûû¡ú\úRú‡úûÁûÆüþ‘ÿG('5F H , ã^kçû¢Ù¢ÿ÷ ” áíÈ…þ4ûì÷¾ô¿ñï•ì‹êïèËç(ççmçVè»é–ëÚíyðdóˆöÔù2ýŽ×÷ß } Ī%/Èî¥ôã}Ïè × ¬xI/8pþßüû…úÃùKùù+ùyùúù¥úoûKü.ý þÕþƒÿ dŠy.«ÿòþþöüÄû~ú0ùæ÷¯ö—õ«ôøó‰óeó•óôÿô:öÌ÷®ùØû?þÔ‹S Í \´ÆÙÃ6-¦  -Ñ  Ñeåÿbüòø©õšò×ïoíoëãéÒè@è/èžè†éáê¤ìÁî+ñÐóžöƒùnüKÿ šîú´   ¿ ô ß î È | ¢1Άcn®ÿ&ÿØþÅþêþBÿÇÿn0Ò›NàFxm!º Fµÿòý ü úÿ÷ùõô8òœðAï4îí0íJíÐíÆî)ðôñ!ô¤öpùxü©ÿð=z ” wV1›ˆôÚ=…{KC ²O÷ýºú­÷àôbò@ð„î6íZìòëûëqìMí†îðÚñÙóüõ3ømúœü°þ›UÓ ÿ¨ ø–Jv“¯Ôiíÿ¡ÿŠÿ«ÿ—]Pižã,k” ™ m  V Y  ^ Z ÿPTžÿýDûøÅõ#ó­ðtîˆì÷êÎééØèéÓé ë½ìÝîañ;ô\÷±ú(þ¬)‹½ ¯M‹[´ëÅ"|LÄ  );OxÿÅüGú øöôBócòãñ¿ñôñ{òHóSôŽõëö^øØùKû«üìýÿîÿŸSV"¼-~ÿ¹þèýýXü°û-ûØú»úÛú>ûåûÑüÿýiÿ ÕÁÁÅ¿   WÖö€¥_«‰ü » 6æþœûWø)õ&òaïëìÔê(éóç=ç ç\ç2è†éQë‡íðó ökùÌü/¯¦ V ±¬<\A e_Wp [ ( èª~r“þêüû^ú„ùõø¯ø®øíøcùúÌú©û‘üwýOþÿªÿX`/Æÿ&ÿTþXý9üûÀù~øK÷2öBõ‡ô ôØóõóiô4õXöÒ÷ù±ûþ†-è¦T á ;S|uù1Q] d ,ÇHÆüRùöèòð íëðéËè&èè^è6éƒê;ìQîµðYó+öù üöþÄhÑôÅ = X mln „ a  ¦)ª7Û¡”ºÿÿ°þ„þ’þÕþGÿàÿ–_.ù±MÁ Ö] Ÿ_åÿ9þfüvúzø~ö’ôÅò'ñÇï±îñí‘í™í îìî9ðïñôvö1ù)üNÿŒÓ ) ¶îggåßTHÀÅdª© s³Rþ ûï÷õòKðzîí'ìªë¡ëì×ìî‰ïRñRó{õ»÷úBüiþj;Ñ%0ðe’{'žë3HbŽ×Eâÿ²ÿºÿúÿqû#Z˜Ñøþ Ø z Ù í ¯  . êSnEâTþ¨ûðø<öžó(ñìîøì]ë'ê_éé:éãéë¦ì³î&ñòó÷TúÅýGÆ-h e`B®ž ùg[Þû¿:} š¤¬ÇÿýqúøögôóòˆñRñxñññ¶ò¼óöôWöÑ÷VùØúJü¡ýÑþÒÿ/†¡ƒ1³Vÿ‹þ½ýùüJü»ûXû(û3ûûüáüõýGÿÏ…_NF8  É LŒ}Jwkô Ü O|sEÿüÂø•õòÄïEí!ëfé!èXççQçèVéë9íÂïžò¹õùfüÏÿ*dj + ™¨M‚ChÓÙƒÞ÷ ß ¥ Zа»þúüyû=úKù¤øIø5ødøÎøiù+úûóûâüÆý•þDÿÊÿ A+ÜÿVÿœþµýªü„ûNúùç÷ÏöÛõõ‘ôOôZô¹ôoõ|öÞ÷‘ùŽûËý:Ñ2Ú e Áݪ!¶Òr”=p7ž ² …'­+ý´ù]ö:ó]ðÖí´ëêÊèèÚç$èëè*êÖëâíBðäò·õ©ø§ûžþ|2°èÐ ` ‘ `Ïß–û  ø © 8 ²&£3ä¾ËÿÿþHþ>þlþËþTÿÿÿ¿‹U·8Ч‡%šs|þ½üàúòø÷õSóµñPð2ïfî÷íííLîïOðïññóMöõøÞûõþ)j¢½ ªU®¦/@ÑÞgmö ¶ Ú‚°þ^û5øHõ¥ò[ðvîþìøëhëMë¤ëeìŠíïËðÍòúôC÷–ùåûþ5Ë7[3¿ú´6ŠºÔâóH¢(àÿÎÿôÿQ媚ªÒ7[b B í Y } Q Ò ü ÐQƒp"§þ ü^ù²öô¥ñfïlíÇë„ê­éKédéùé ë“ìŽîïð¬óµöøùcýâaÍ Ñ/#£¦((§«<c/®ò  DýŸú8øöSôçòÛñ2ñêðÿðlñ'ò'ó_ôÂõB÷ÒøbúæûQý˜þ²ÿ—C³æà£6¢ñÿ-ÿaþ›ýåüLüÛû™ûûÅû<üõüðý)ÿ™:ÿÞɰ † ; ¿¥ëÊ>Gæ ù ¾Ä¢ÿjü.ùöûò*ð¢írëªéSèyç çKçûç+éÕêïìlï>òTõ›øÿûmÿÐ) ü |ŸY£x×Â=Ob~c # Ît&òçþýuû úùXøç÷À÷ß÷;øÍøŠùfúUûKü:ýþÚþvÿäÿ!íÿ€ÿßþþýüÛú¬ù‚øl÷vö¬õõÊôÄôõ¯õ¤öï÷Šùpû—ýôÿxÀa è Dd9´ÉnœP†B‰cÚ ý Û†ýú»öó¦ðîÞëêÏèè·çïç¥èÕétëwíÐïpòDõ:øAûDþ1øŠ×Ö | Ä ©,N„ª Ž ? Ê <¥*íáÿ ÿpþþïýþRþËþiÿ ç±s¬=2è]8»þýGûhùƒ÷§õâóDòÛðµïßîaîFî’îIïkðõñáó(ö¾ø•ûŸþÈ5P @òTYñ·×sŒ'Lao A é|ÿ´ûø‚õÎòqðxîêìÐë,ëþêDë÷ëí„îFðGòxôÉö(ù…ûÑýüÿú¿Dqiv?Í(\u~…—½sçÿòÿ6°^75Mtž½Å© \ Õ  ï „ Å ±I“—^öþiüÊù(÷•ô#òâïãí5ìæêêé“éêë†ìmî½ðjóeöžùý}ükµ Æ ú’¨>Qâ÷•Èœ!e } yml‰ýÑúVø#öEôÂò ñáð†ðŠðéðšñ“òÉó-õ³öLøêù~ûýü[þÿ‹QÛ'8¶1ŠÎÿÿ>þƒýàüaüüòûüoüýñýÿhò£qM* ù « 0|€1†wÒ!  «üýÿÎü™ùpöhó“ðîÈëñé‹èŸç3çKçççéžê©ìïáñðô4ø˜û ÿtÃåÇ [‘_¾¨¢Á~äç ¢ DÝ8ÿ)ýwû úçøøŠ÷P÷]÷¬÷4øêøÄù¶ú²û­ü™ýmþÿ£ÿöÿùÿ¦ÿÿeþ‚ýüeûAúù ø÷Bö¦õIõ2õjõôõÒöøˆùVûgý°ÿ#³Oè j ÆéÄJl!a'rCžŠD .âsõý{ú÷çóóðPîì8êÙèùç›ç¿çdè„éëíaïýñÑôË÷Ùúçýâº_ÂÖ “ ò í„¸Ž 9# Õ \ È%ƒïu!üÿ ÿWþßý¥ý¥ýÝýEþÕþƒÿD Ñ…ŽÏÙ¦3‹ZõþaýªûÜùø1öqôÔòiñ<ð[ïÐî¤îÞî€ïŒðò×óö‹øQûKþi™Èâ Ô ‹÷®á—Êz¦SˆP¸Ï ¦ Pâpÿ üÌøÀõüòŒð~îÝì­ëõê´êéêŽë›ìîÃïÃñ÷óNö·ø"ûý¾ÿѯL¡©cÎíÆ`Äü6iÂIöÿ€ÙÃËå ' É M ˆ 2 ‰ Œ<ž¹–AÿÆü4ú÷õ¢ò`ð\î¦ìLëXêÔéÇé5êë~ìRîð,óöGù£ü—W r EÁÖ{¥Nt=ë*‘Ø î åÑÄÑýûyø1ö<ô¢òjñ–ð'ððjðñò4ó™ô#öÅ÷oùû¦üþcÿzZýc‹y2½"mªÿâþ"þwýëüˆüXüaü¨ü/ý÷ýýþ<®KÓ¤l    ðü¹ ¼ïº $ Ó7]U2ýúßö×óþðgî"ì>êÈèËçLçQçÚçåèlêgìÊî‡ñŽôÎ÷1û¦þož 4}`ÔÒYg/öd†j ! ºHÛ‚NÿHý~ûøù½øÐ÷2÷ãößö ÷÷Lø$ùúûüýüýÁþ]ÿÉÿÿÿÇÿXÿ¶þéýøüîûÕúºù©ø°÷Ûö6öËõ¥õÉõ>ö÷ øŒùBû<ýpÿÐPào ì FlMÜ Ï úY>¬¬Fˆ =ÕZþàú|÷AôCñ”îBì[êéèöç„ç•ç)è8é¼êªìôîŒñ_ô\÷púˆýx0§Ò ¥ +׎ƶ j ï T §øRÄYÿDþ²ý_ýIýlýÂýDþèþ£ÿh/é‹ ]{_jx+ÿ®ý üMúƒøºöõfóøñÆðÛïCïï.ï¼ï³ðòÑóíõ\øûúý 2[r f "–²gªq¸{ºy¿– + ·HÒÿgüùö.ó¬ð‹îÔìëÄêpê“ê(ë)ì‹íBï@ñuóÒõEø½ú*ý|ÿ¥™N¼Ý®. a J ñ^œ¶¸°ª±Ò†'UÒTKWn‚ˆr3 Á   Ú G a*¤×ʉÿýúøõ!óàðÙîí¶ë´ê!êê\ê0ë|ì<îgðòòÑõòøEü¶ÿ1¤ø  ù‚¨_›X’H;‡oÿJ _ R6þCû øCö8ôˆò9ñPðÍï®ïðï‰ðsñ òô“õ<÷òø¦úJüÓý4ÿd^šÚÞªF¸ M†ÿÃþþwýýÃü¶üåüTýþîþoöž[ ß ‰  bu=¯Ãr»› 2 öm¤«”ýnúN÷FôkñÍîìê éüçkç]çÒçÊè?ê*ìî0ñ/ôi÷ËúAþ¶SS e[ä÷‘²^™lâí   3 ¶:ЇÿlýŠûìù˜ø“÷ßö|öeö—ö÷°÷ƒøwù~ú‹û’ü‡ý`þÿ–ÿçÿâÿÿÿLþnýtügûTúHùOøu÷ÈöRöö.öŽö?÷Aø”ù3ûý4ÿ€ðr÷n Å ìÓj¤wÚÆ93¶ÉvÇ Í–5¿þFûß÷žô—ñÛîzìƒêÿèøçsçqçòçñègêIìŠîñîóìöú'ý;3üˆÈ ± =d%u PFý ‚ á +n¹–@ÿ6þŠýýñüÿüCý¶ýNþÿÅÿ‹KöƒçÑO‘\ÿöýgü¼úùC÷õùóŠòRñ_ð»ïoï„ïþïßð&òÑó×õ1øÒú­ý°Ìî ö ·2XmF vÈšòÙZ† k ®4ÃünùHödóÑðœîÒìyë˜ê0êAêÇê»ëíÃî¾ðôòVõÑ÷UúÒü6ÿtLÒ ó‰ Ð Ê  ö:VVG70?nÇO /“(éÎË×åèÓ›3 ‘ ¬ } 2¥ïùÍÿvýû„øö¢óañWï“í$ìërêAêˆêHë€ì+îCð½ò‹õ øéûTÿË>– À ©@u=Œ]ªs»ˆáÓkº Ð ÀzlþûÌø[ö:ôsòñðxïGïyïðæðòróõ³ösø6úìûˆýÿI\3Ì$?ËLªð)dÿªþþ†ý1ýý(ý~ýþåþòÿ4¥9æžS ÷ { Ñ ë¾=a$w ;  Ÿèÿôý×ú¼÷·ôÚñ7ïàìåêRé3èçnçÐçµèêñë7îÝðÒó÷eúÜýV¿ Ø GQîÄøµÿÞ]ˆn ¬ %œ!Åÿ”ý›ûåùyø\÷‘ööðõövö÷ä÷Øøâùøú üýûýÃþ_ÿÉÿýÿùÿ½ÿLÿ«þáý÷üøûîúçùïøø]÷Ûö–ö—öâö}÷hø¢ù)ûôüüþ5“€ð D kVõ:"ºá   ì”$ÿ¬ûDøþôîñ'ï¸ì°êéègçSçÁç¯èêìë#î¯ð}ó}ö›ùÄüåÿêÅc¸ ¸ Z—mÚâ‰×Õ  o ±è"n×j/ÿ-þhýãüžü–üÇü*ý¶ýaþ!ÿèÿ«`ùm²Ã˜0‰¥‰ÿ:þÁü(û|ùÊ÷ öŒôóáñæð6ðÜïßïEðñBòÖóÆõ ø™úbýWh‚’ … IËûÊ+‚kѶ ¦Ý Ê ˜"ýÃù’öŸóúð³îÔìgërê÷éõékêQëìFî=ðtòÙô\÷ëùvüíþ>`Dâ33 à : F Œ ×õôàű¯Ë } üÿYׂTBBHH4¢ 8  ´ýö¡$ Éýgûõøƒö"ôäñØïî–ì{ëÉê†êºêfë‰ì î$ðŒòJõQøûòþfØ3 c Vù=x[¼˜òÏ74Õ(@ -Ù¾þÄûüøwö@ôdòèðÔï(ïåîï†ï\ð~ñßòrô(öó÷Ãù‰û:ýÈþ)UFøi›NÝE’ÎFÿ™þ þ¤ýnýoý­ý(þàþÕÿþXØsÈe ç ? _:ÇûÐANö > - Í)ORþ?û+ø)õKò¤ïEí>ëžéoèºç†çÔç¥èöé¾ëôíðwó¤öúwýód³Î ¤ $Bò.ñ9`LÔîž % •uÁý²ûãù_ø*÷Höºõ~õõçõ}öF÷8øFùcúû•ü’ýoþ#ÿ¦ÿôÿ èÿÿÿPþxý†ü‡û†úù°øõ÷h÷÷÷;÷À÷“ø¶ù#û×üÈþì8 r Á èÖ|Ì»>Oé ¸ôÆ: ^ ?ñ‡ÿüªø`õHòvïúìâê;éèbç:ç–çrèÊé’ë¿íDðóö/ù`ü‹ÿž‰;¤ º rŰ1KZa!¥ ý 8 cȘEÿ)þKý¬üPü2üOü¡ü!ýÃý}þDÿ ÇlïHmZ }³±ÿzþý‘ûõùPø®öõ±óròpñµðLð?ð’ðHñcòàóºõê÷dúý!  Ù`™tåà^[ÔÌHPî1( äzü‚ýúÞöÝó)ñÏîÝì[ëRêÃé¯éêëê,ìÌí¿ïôñ\ôæö€ùü þ<7íWn 1   ¾ ‘  q ”“zV5#+W¯9ûÿôÿ#‰Ý»¯¬¨”d…¿¶cÂÓ—JHþÈûdùüö£ôgòZðŒî íåë$ëÑêòê‰ë˜ìî ð_ò õø7û’þqÎ ÿ®ê^Tȸ$ˆ‘;•¯ ›n9ÿ ü1ù˜öMôZòÈðžïÞî‡î˜î ïÕïððNòâóõp÷Mù$ûèüŒþJT ªòüÍkß3r©äÿ.ÿ’þþÑý¼ýáýBþáþ¼ÿÍzž=Ô R « Ï ´MwýÝ < B öe­þ¦û™ø›õ½òð­íœëîé°èêç£çÞçœèÙéë¶í@ð óDö›ùý_† k ü-ñBsT½¶Im Ÿ fÍLòýÍûçùKøþööaõõõ[õçõªöš÷ªøÌùõúü&ýþâþ~ÿæÿ Ïÿ\ÿ¼þöýýü$û0úPùŽøø÷˜÷v÷š÷øÄøÎù#û¿ü™þ¨á5—õ ? dTZVè ¹ð±çn ¡ MêÿyüùÃõ¥òÉï@íëaé"èbç'çpç;è‚é<ë_íÛï¡òŸõÃøúû/ÿOJ ‹ ¶ „ítÛë°6 ‹ ¿ àþ&gË`ÿ+þ2ý{üüÒûÛûüü&ýÚý þjÿ,ÜnÙám½Ôÿµþhý÷ûlúÔø<÷³õGôóüñ8ñÂð£ðãð…ñŠòðó´õÍ÷3úØü®ÿ¥¬±  gó4™¤5DÑÝl…2‚‚ Fßaãýuú.÷ ô[ñðîëìUë7ê”éméÁé‰ê¾ëUíBïuñßóoöù¸ûOþÇ%ót£ }  2  ¯ 1 0鼚¥æWþÿÝÿôÿ@¿j7óÆwùCK ƒ¬ˆk€fþ&üÑùu÷#õìòßð ï…íSì„ë ë/ë²ë¬ìîõï7òÓô¼÷âú3þœ h¢ ¥_¿¸>GÏÑPOÕëŸÿ לjÿSüjù¾ö^ôUò®ðnï˜î.î.î‘îRïeð¿ñRóõíöÕø¼ú’üKþÜÿ9]BåEeHövÓMƒÅÿÿ•þ8þ þþbþçþ¨ÿ Ë –!´B ½  > *Î!³ê ¿ 5 Q žçÿ üù ö1ó„ðîþëDêöèèÅçíç—èÁéfë{í÷ïËòçõ8ù¬ü,¨; . ÏëO:©›ºúëš  {Ï'•(þíûðù;ø×öÆõ õ¨ô—ôÒôSõöüö ø5ùgú–û·ü¼ýþQÿÓÿ. ¯ÿ$ÿpþý´üÂûÒúðù*ù‹øøì÷ý÷Vøûøìù)û¬üoþhÑ$x ¼ Þ Ð‚äìŽÂƒÎ¤ œ à Þ¦Jàüxù(öóðŠíUëŒé;èhççPçè?éëêíuï5ò2õWø“ûÑþýÜm ­ ‘&ÐäWr=Å  H _p‡´€ÿ1þ ýOüÁûvûkûšûýû‹ü8ýûýÇþ‘ÿJêfµÏ±WÁòÿëþ¶ýYüàúVùÉ÷GöÞô›óŒò¾ñ;ñ ñ:ñÇñ¶òô²õµ÷ú˜ü^ÿFC@, ó ƒÌ½Id(É芴rÏÚ ¦CÆEþÒú÷fô“ñïþìUë"êké1ésé,êTëáìÇîøðcó÷õ£øUûûý…æôÔ Ä ^ ¢ ” < ¡ Πί|E÷ø!yËÿÈÿýÿdú¶ŽxgQ'ÞkÂܲ>t ˆ´®þü<úì÷£õpóeñïîÅìéëuëqëáëÆìîæïòžôw÷úÖý8¢> H z‚5Ïåw‡Ag‰ v BÿÄÿ ü¦ùèötôVò™ðCïYîÛíÉíîÑîÜï1ñÃò†ôhö[øPú9üþ®ÿ#`_“È¿~ qºñ#\©ÿÿ£þbþXþ‡þòþ™ÿwŠÊ,§-²' ~ ª L­·c° œ ( [ ;Ò.]ÿnüsù€ö¥ó÷ð†îcìêAéZèîçè™è¯éAëFí³ïzòŒõÖøGüÉÿG¯í ì žóÞWVÙÞh~(qf” ï9…âbþüþù2øµöõ½ôDô!ôMôÂôvõ_öp÷øØùûDü\ýSþ ÿ»ÿK>üÿˆÿçþ$þHý_üsû’úÈù!ùbaresip-1.0.0/share/sound5.wav000066400000000000000000001047741372575704200162240ustar00rootroot00000000000000RIFFô‰WAVEfmt D¬ˆXdataЉ»]Ë ï ²ÔÎð‚Œ:þ| É û+nÚÿ€ýqû¸ù_øj÷Ûö®öÝö]÷"øù9úhû˜üµý¯þyÿJEòÿSÿlþHýòûxúìø_÷æõ“ôxó¨ò0òòvòCóƒô3öMøÄú‹ý޹÷- E %¸ç¡Ö|Œä6\R û pÉ"ÿ‘û2øõ]ò ð7îäììÖëìÕìî“ïrñóÏõ"øqú§ü³þ„F(°áÀV®Øâßáÿøþ4þ¦ýYýVý¤ýFþ;ÿ{«­µ ® „ !ulù©ÁYu  cRˆþûúv÷ôèðîë£é1èPççYçBèºé¶ë&î÷ðôe÷Ðú>þ”¾¤4 ^ Zj@¨±g ß * \‰Å!­w‰ÿèþ—þ•þÞþjÿ-"29%æk¨“#U*¦Ѷþdüíùd÷ßôuò:ðEî©ìxëÀê‹êáêÄë2í&ï”ñnô¡÷û¼þs#´ ¯×y‹í@ S-¬ã ë ÚÉÏþuû7ùW÷ÝõÐô0ôüó,ô¶ôõ£öä÷@ù£úûû6ýFþÿ°ÿúÿøÿ¨ÿÿ9þ,ýöû©úVùøæöîõ7õÐôÆô õäõ÷«ø¤úõüÿ_SUM #ÀùobÇ™Ô}›9f7 Áb­üù·õ§òøï¾íìÓê1êê“ê‹ëøìÊîïðSóÞõ|øû•ýèÿýÆ:P^[l™‹ti|¾ÿ8ÿ÷þÿ[ÿ÷/ ;ò±e û _ I°©,6Ç ä —ëòÀÿiüù°õòŒïîì¹êþèÍç.ç(ç»çåèœêÕìï‡ò×õVùëü{ð1' À ì Ô…³c vô- 4  ñÿ=ºÿþ•ýý¿üÏü(ýÁýŒþyÿxwf2Ë%5òYh#“ÿ¿ý¶ûŠùM÷õñòþðLïðíúìwìrìòìøíƒïŒñ ôêöúý%È_Ð ÛK?©€¾ctùÿ—ÓÉ “GÿÔþÙû$ùÆöÌôAó+òŠñ]ññ@ò8óvôéõ|÷ù¸ú<ü—ý¼þ ÿ9†…9©ÿÝþäýÌü§û…úzù–øë÷†÷u÷À÷lø|ùìú¸üÕþ5È{9 ì {ÒÚ€³f(0ªž( áY©ìý9ú«ö\óaðÐí¸ë&ê$éµèÚèéÅêuìŒîùð¤ówö\ù:üýþŽÝÜ~¼’   Á $ E4ÇŽlp¨ àÿìÿDèÐóC²/¦ 9 0 Ù (  Œ – 0 ^)œÉÂýœúo÷Rô^ñ«îNì[êäèõç˜çÓç¤è êúëhîCñwôî÷Žû?ÿåi± ¨ ;ZúŸ¤%,Æø ¸ X ï‘SG|þüüÒûûúoú£úûÖû¸ü¶ý¾þ½ÿ¢_ä&ÂÓþLý‘û²ùÁ÷ÑõöóEòÑð­ïéî’î²îOïkðòôöjùüêÿdæU ˜ ˜=t,WîêM`%~~ < ÑUãÿ‘üwù©ö9ô6ò©ð˜ïïïîMïð;ñ­òZô.öøùùÉûrýçþ›âÙ‡ô+>ÿ9þ/ý3üUû¦ú4ú ú:úÀú¢ûßüpþNk¹$™  HWtíáK)€Wº º já6ÿƒûâ÷lô;ñdîüëê´èêç¶çè éˆê}ìÚîŒñ{ô’÷¶úÒýÌ‘6ù P 8 ± ¾ g ¸ ¿ Œ 1ÁOí¬›Æ6òÿûÿNéÂÍü>´Ä  7 { c æ ²ñ‘ñþ"ü7ùIönó¾ðOî7ì‰êUé¨èŠèé ê¤ëÄí\ð]ó°ö@úôý±^á" ‰ ùX)q:“Œ9¯  S¬(ØþÌüû³ù´øøÚ÷÷÷eøùýùû'üFýTþ@ÿýÿ{µ¢A“ÿœþdý÷ûeú¾ø÷yõôÅòÏñ2ñúð1ñÝñóšô¡ö ùÏûÖþ ^°ì ø½$’{ÏŠ­=CÏñ¿ O»‹ý"úøö!ô¯ñ±ï1î5í¾ìËìSíMîªïZñIócõ“÷ÄùáûÙý›ÿJ(¯áÂZ¶ãññÿôþ þJý½ürürüÅünýkþ¹ÿO#%Dm ‹ Š U×ÿ¾Ð×ß ; ;ñtÞüEùÄõtòmïÆì’êáè¾ç1ç>çãçéØêí¯ï¡òÎõùzüÈÿïÜzº ñ ÛMKÝï Œ û Ošñeánÿ(ÿ1ÿ„ÿçßò"ë~ȽWiããÿ€ýñúLø¤õó§ð€î­ìBëOêÞéúé¤êÞë¡íåï›ò³õù³üj%É< g3j¹v2:ÁÕˆî  -6M‹ÿýÀúÖøN÷.öyõ+õ@õ¯õjöd÷ŒøÏùû]ü…ý‚þHÿÌÿöÿ—ÿðþþæüœû9úÍøk÷'öõ?ô»ó”óÔóôõ%÷ùbûÿýÙàû  Þa…9l&£‰à²  ª iµþû¤÷yô¨ñCïZíõëëÍêëÆëúì–î‰ð¿ò"õ÷úƒüÅþΑØ8@÷i¢³¬ Ÿ½ÿÿŠþRþfþËþ€ÿƒÌRض H Ó £Æq RŒ T ·Æ’2þ½úL÷øóÚð î›ë£é0èNççRç9è±é¯ë%îñ)ô‹÷ û“þLQ L $€]ºœ » P _ bn”ærEÿdþÖýšý®ý þ¦þsÿcfi\-Ì*=übm"…£þ†ü@úä÷‡õ=óñ;ï«íìÆëŒë×ë¬ì îêïDò õ+ø’û)ÿÔ} ^ e5Ýõv`´y¼Œú Ú¦…ýÖúmøböÀôŽóÎòò›òóïó õ[öÏ÷RùÓú?ü…ý˜þjÿöÿ3%Ìÿ.ÿTþLý$üíú¹ùšø¢÷âöjöFöö÷!ø‹ùUûuýßÿ‚L'ý · >{[Ê»#ú=ð¾ô Ë X´øÿ>üŸø5õò[ïíJë êaéFéºé´ê)ì îCðÁòmõ1øöú¥ý*trbGÈè®&]bFõãö=ÃÿÿªÿÅ¿õ\ã{ Ž ã ý É ;Eà  ¹ ú ÒLxjÿ3üíø°õ”ò±ïíñê;é èjçaçñçéËêí¯ï¼òöžùBýåoÇÖ ˆ Ιâ¤Þ–Ô£7" è  _7<~ÿþáüü›û{ûªû üÑü­ý¥þ¨ÿ¢„=¾üíŒ×Ï{ÿáýüúøöõõóòzð(ï4î­íí îïtðdòÆô÷¨úþƒž .shÕ¯ð˜ª--»êÏ ‚¶iþKûqøîõÑó$òïð5ðóï&ðÂð½ñóŒô;öøÇù|ûýqþ”ÿnû8'Í1bÿkþ\ýIüAûXúžù!ùðøù”ùsú°ûFý-ÿXº?Ôb Ô  ¥Ó‡µWjòõ~œ bå=„ýÓùDöðòðïVí5ëšéèè<èîè*êãëîˆðLó?öGùMü;ÿùx§wá à r › b Ò ÷ á¢Lò¦y{¶6|'-pÇ"n˜ Ž ? ž ž 8 f ' €vmýú„÷…ô©ñ ïºìÑê^épèèGèérê[ìÄîœñÏôHøîû§ÿXêC L ò#Ôû•¢%*»éÇi æ SÆUþWüöúñùKùùùqùúëúèûùü þ ÿîÿŸC%·ûÿóþ¨ý&ü{ú·øíö1õ—ó2òñNðíïýï…ð‡ñóóôN÷ú ýH¨m ¡ •2dGßßDXnd  ™~ÿüÚøïõaó@ñ˜ïoîÉí£íùíÁîíïnñ1ó#õ/÷AùDû%ýÖþEmCÆôÔlÈôÿþýTüÄûwûwûËûwü{ýÒþv[t¯ø< d \k]Ú×O>¨” " æmÒþ*û‘÷!ôñðî¯ëÁé^èŽçWç·ç¬è+ê(ì’îUñ[ôŒ÷Ðúþ/Ä ÿ | † >ö N S  § ƒõ€6#SÎÿ–ÿ«ÿ «†Œ­Ùþ éŽéï–Ûº8[.¾þü\ù”öÙóDñêîáì<ë ê_é<é«é¬ê;ìOîÝðÔó!÷¬ú_þÎX £ ˜"2»µñ9þL5Ë% Y ¬øvþ7üIú¸øŠ÷Âöaö_ö¶öZ÷<øLùyú°ûàüöýãþ™ÿ:­ÿõþúýÆügûëùdøæö„õOô[ó¶òpò‘ò"ó%ôšõ{÷¿ùZü;ÿM}³Ö ΃ßÐC-ƒBiü“´} f¸ýšùYökóâðÍî8í*ì¥ë¨ë-ì*í‘îRðYò“ôéöGù–ûÅýÀÿyåý».íf¨ÁýÅÿèþ7þÀýŽýªýþØþèÿAÛ¦”‘‹ l !–¸xÉ ùÑ+ ‡ ¢sŽüù”õOòPï­ìzêÇè¢ççç¿çöè·êõìžïžòÝõEùºü$m|=   — ¤³NZé A t ˜ÁgæÿÿþYþtþ×þxÿKBLWS,Ó:T‚Ž?š«ÿ}ý û¨ø(ö¶óiñWï“í0ì?ëÌêßê~ëªì]îð5ó>ö•ù$ýÓˆ) Ëâ9ý)ÀÇHQôEZ K/2ÿzü úô÷@ö÷ôô±ó®ó ôÀô»õíöDø­ùûiü›ý›þ]ÿØÿëÿƒÿÕþìýÒü—ûLúùÌ÷½öåõUõõ=õÈõ¼öøÝùýûlþ÷ìä Æ {ì°à‡ž!mF§¡ J ·Hþžú ÷åóñŽî“ìë8êáéêÕêì·í¼ï òŽô/÷Öùoüåþ$Ç‘À— htYA=]±ÿBÿÿBÿ¸ÿz…ÏLí¡U õ n ­  8h'o> ˜ ‚ 9'æýŒú3÷óóäðî¹ëÅéSèoç"çnçRèÉéÇë@î ñSôÂ÷TûïþxÙúÆ -”†óàQTöI_ L 'ô ]òþÔý ý•üuü£üýÅý þ–ÿ—‘s,­êÙt¹¨GŸþºü¨ú{øFöôòMðÊî¤íêì¨ìçì¬íõîÀðó²õ½øü“ÿ/ËN ž ¢Fu!=ïÈÌ-=  Èt0ý5ú¤÷rõªóVòxññññbò„óäôpöø¾ùYûÖü#þ5ÿ±•/Šÿ¯þ¬ý‘üoûYúaù—ø øÍ÷ä÷Yø0ùiúüíý#–2ä– 1 ŸÉœó^;ˆFz-o P åGŽÿÓû0øÀôšñÔî€ì¬êeé°èèéþézëgí²ïIòõû÷èúÄýxó$ýu… - n O Ø  ö¸t<"5êÿƒ>9jÂ1¦ S g 7 ´ Ñ † Ì ¢ ¯ÿ üæøÅõÁòòïníJë™ékèÊç½çHèiéëNíøïóaöóù¡ýRìWz B}Ø©ï­ë´'ö š )¹_-5ÿ„ý$üûsú#ú)ú}úûâûÔüÚýâþÛÿ´]ËñÊQˆrÿþ~üºúÚøðöõPóÂñyðˆïûîàî?ïðuñIóõ6ø3ûqþÚVÌ# B}qÞ»ÿ©¼?<Ãç¾ _ãcùý¼úÁ÷õßòñÃïñîîÃî[ïXð¬ñEóõøöéøÐúšü7þ˜ÿ±~ø"ý‘éÿþý üUûÀúmúiúºúfûlüËýzÿn›ðXÀ  7«Ôˆ¼hŠ#8Ó  ÚlÐ!ývùëõ—ò”ïöìÏê.éè¢çÀçqè°épë¢í3ðóöDùnü„ÿmrn  & Ù  ÷ r š ~ 0 ÁFÑs>>~ÞÿmPŽÇçݘ  " Ü / ¡Æ–ký”ú®÷Ïôò„ïFígëúéé¬èÝè¡é÷êØì8ï ò8õ®øTüÉdÉ à •Ö•Ên ’±z \ ¢éGÒÿ™ý«ûúÝø ø—÷„÷Ç÷Wø%ù!ú;ûaü€ý†þeÿ u•fëÿ#ÿþÎüWûÂù øƒöÿô¨óòÇñ]ñ\ñÌñ²ò ôÚõø¤ú…ý à.r ’ w 4ç­¯ì1ôD5 Ý S²ÿ‘ûBø<õ”òYð™î[í£ìpì¿ì†í¹îHð!ò1ôböžøÒúêüÔþ€äö³(ëi°ÎÓÒÿÜþþSýÞü°üÐüDý þ(ÿ;%A^ g Fè:+¬³:=¾ T ‚]ûsþÛúO÷èó¿ðêíëé(èUççyçmèïéòëfî7ñPô™÷ùúVþ™¬yï ÿ ž Çv­sÑÔ ‹ ` ¤êBÀqa›ÿ"ÿùþÿ‰ÿ2%<D*ÞQvD´ÄvÎÕ™þ(ü•ùõö]ôåñ¢ïªíìäê6êêuêjëëìñîqñ[ôœ÷ûËþ…6Ä  £½PRÀ™á¡æÀB‚ — ˜¼ þ›û}ù½÷börõíôÏôõ¨õ‡ö÷Ùø(úyû¹ü×ýÅþvÿâÿ×ÿ_ÿ¢þ§ýzü*ûÈùfø÷ìõøôLôõóÿórôRõ öWøpúàü—ÿ¢¨ ‰,{cһ׬=`) ®Q£üùÄõÃò&ðþíVì8ë§ê¢ê$ë$ì”íeï„ñÜóWößø^ûÁýóÿäŠÙÍbœl’„w~©ÿÿ¡þ„þ¶þ8ÿ$ÏŸs 6 Õ <Xt[Ⱥ1 4 Ì÷°ÿGü×øwõ@òLï°ìêÏè©ççç¿çõè·êøì¨ï²òöyùý‰íû } ‘.Kè¨Ü®/o „ |ˆ·¼ÿ¨þåývýYýŠýÿý¯þŒÿƒ‡„j&«ëÜw¹¢7‚ÿŠýbûùÃövôGòKð—î=íNì×ëáësìŽí.ïMñÞóÓöú—ý8ã}î ïU<™b’+1®®Dƒ€ UäÏþîûTù÷6õÈóËòBò)òxò&ó#ô`õÊöPøÝù_ûÄüýýýþ¹ÿ)M$³ÿÿþýÚû¨ú€ùuø˜÷úö¨ö®ö÷à÷ù¤ú’üÐþOÿËž a üXb1Úõ~vÞÂ,/ ÝNšÜý,ú¥ö_óqðîíæëeêtééFéêBëöì ïrñôÖö§ùmüÿ…´‘/ç< 2 Ò(B2 س©Ë&Äÿ¬ÿáÿb.;ïxŒ ó (  ¸ ÷ Ë /  › «X¯¤ýjú,÷ôñRîöëê™èµçeç­çèêýëuîXñ‘ôø¦ûQÿíc› € ÿ ”˜ WT ! ÔƒB$:“þ:ý5ü‰û5û6û„ûüÚüÅýÅþÇÿº4œ½:ªþÿü#û'ù÷õ2ózñðäî(îßíîÂîõï§ñÏócöSùŒüùÿ ‚ È Çg–CbìÛ1õ/îDE  ¥6Õÿ—ü“ùÞöˆôŸò+ñ1ð´ï®ïðêðò‚ó&õêö¼ø‡ú8üÀýÿÚKk?Ì?ÿ?þ0ý"ü(ûTú´ùYùLù–ù>úDû¥ü\þ\›Œ ‘ ãù¾ y^¶ÄˆÙ É kÖ%ÿnûÌ÷Zô0ñcîì+êÜè èûçjèhéêêâì?ïëñÑôÙ÷ëúðýÑzÚ↠À Œ ì å  Æ É ˜Fåˆ@00­mgÖ*y²Á •  Q ! ‰ … E—ÚþñûðøðõóNðÛíÄëêîèLè<èÁèÛé„ë²íWðbó½öRúþ¿fß ìYJµ“ã¦ä§þú° 3 œuàþ÷ü`û$úGùÉø¨øÜø\ùúûü(ý9þ3ÿ¢ÿÙOxÿZþýüpûÁùøDöžô"óãñóðað9ð„ðGñ…ò9ô\öãø¿ûÝþ(‰é. >hXţꗬ0,°Í™ ,†ý-ú÷Tôùñð©îÁí]íyí î ïkðòûóö!ø8ú7ü þ«ÿ Ä&5øw¿Ýãÿâþêýý_üêû»ûÜûSü!ýEþ¹ÿtjŒÆ 5 @“·l§_‘=g ` KñfÅü%ù¡õRòPï°ì†êáèËçLçgçèYéëZíúïèò öRùü×ÿçº>b  b 3|+ « $ ˆê\ð´¶ÿÿ”ÿwÿ¦ÿÒ¼Êí*!æiyõÄ×ÿTýªúí÷1õòððíì¸êÍéié“éNê™ëníÃï‰ò®õùÀü{6ÖB c#p;z'AÉÈI\ » Üú+…ÿýùú0ùÉ÷Èö/öúõ$ö¢ög÷dø‰ùÂúþû*ý7þÿ¶ÿ%ëÿcÿ•þ‡ýFüàúfùé÷|ö4õ!ôUóÞòÊò!óèó õÇöÕø@ûùýî 9a j =Âä’¼W]Ê¢ë±ð “ U¨þû¯÷”ôÕñ„ï®í]ì–ëXë¡ëgì¡í=ï,ñWó«õøtúÀüâþÇf³¨Am mš¦ œ«ÿÜþ@þâýÍýþ“þqÿ𠳆th P  §ïÞdw(Ââ ‘ ÜÓ‹þ˜ú÷Ãó£ðÕímë~éè@çç^çQèÔéÛëWî3ñ\ô¸÷/û¨þ <+à õ ³ø¿ Û>>ë U ±Ëò8­_Zÿ¡þ:þ$þZþÕþŠÿjhswd(´ûñÒ¹H‡þDüáùl÷úô¡òwðîíÛë,ëÿê[ëBì´í©ïòðô!ø–û7ÿé–! r q +ÅÏBg#`.žÇ ¿ ž~t˜ýûú°øÃö?õ)ôƒóJóxóôßôüõG÷°ø"ú‹ûÛüþíþ™ÿûÿÙÿYÿ—þžý{ü=û÷ùºø˜÷¥öïõ‡õxõËõ†öª÷4ùû`ýéÿ¨‹|c *¸÷Õ?&J~ 7Ïø Å K£èÿ1ü™ø:õ*ò}ïDíŽëbêÆéºé:ê<ë¶ì–îÊð>óÜõŒø9ûÌý2Z7»â¦ Â+Y[C" @©ÿSÿGÿ‰ÿõpö˜Eê r Ë â ¦ ‡• , P k}Wÿ ü·ønõJòcïÑì¨êúèÓç?çDçáçéÕêíËïÜò4ö¼ùYýònµ° N }3f?éé[… | T #üõƒÿ2þ3ý‰ü6ü5üüýÐý¸þµÿ´§z„£rìáfÿ¨ý¶ûŸùv÷Oõ?ó[ñ·ïfîyíýìþìíˆîðò“ôp÷žú þ˜4Ã+ T&wפØsyòìw¦ Lóžeþ^ûžø6ö3ô¡ò†ñâð´ðöðñòåódõ÷¸øgúÿûqý®þ©ÿ[¿Õž"iÿ€þuýYü?û8úUù¨ø>ø%øeøùúfû ý*ÿvö—B â a¨¡:b ,¾À5&ž¬ dÝ.rýÁù6öêòóïfíTëÉéÎègè•èSé–êSìyîõð°ó”öŠùzüNÿðP^Y : ² Å z Ý ûå¬cèÙü]úÿ:Å–£ß;§d ( v b â ô ˜ Ѩ*enýWú9÷,ôGñ¡îRìlêéèËçèêèWêOìÄî¦ñàô\øü¸ÿbé4 - Áß}‘K/Þ l ï}*)þ•üXûvúòùÇùðùdúûöûõüþÿøÿÁVª´pÚõÿÆþVý²ûèù ø-öcôÀòXñ=ð€ï-ïOïìïñœò¦ô÷ìùýXÉ@¤ Ý Ñk—Deñã;8óA6 ê tíqÿüóøö§óŸñðüîjîVî¸îˆï¸ð7òòóÖõÏ÷Èù­ûnýùþCBñNY”Ùõÿ÷þòýõüü`ûæú´úÒúHûüBý¿þ‡È€ ×  ÁvdɤùÐ5 7 êe¿þûu÷ôÛð îªëÉésè±çˆçõçõè|ê}ìèî¨ñ¦ôË÷ÿú*þ3’Å’ ó â _ n  e f * ÄEÂM÷Ðã;ßÿÐÿ TLjž× å} Å ³ ? e#€2¤þæûù1ögóÇðgî]ì¼ê“éñèÜèZélê ì0îÍðÐó'÷¹úoþ,Ú] „ÿÿwa¸€¾{DZO´ ù3zâ€þaü–ú&ùøp÷)÷?÷¨÷Xø@ùPúvû ü»ý¸þ‡ÿjn%ÿ¯þý9ü»ú'ù÷ö˜ôcótòÚñ¤ñÚñƒò¡ó2õ0÷‘ùHüBÿk¯ô" Ø3‰g±bzþ›a éM¦ý¡ùqö–ó"ñ"ï¢í¨ì5ìGì×ìÛíDïñó,õo÷´ùæûôýÌÿ`§™2ue p£´´µÿÇþüýcý ýøü8ýÌý´þëÿk(3 ? . ê`~5w=C†Q ² ·tqüáøhõ"ò%ï‡ì]êµèœçç1çáç#éíê0íÜïÚòöqùÙü2f] N + ’òï~©€  s ¶ï2Þçÿ;ÿÞþÑþÿ’ÿN9@Ud\+úêw®œÿMýÓú@ø«õ)óÑð¹îôì•ë¬êEêhêëVìîbðó2ö–ù/ýäœ=¬ ÓšðÄ ÁßigáèŒã  ù-ÿ’üBúJø¶ö‹õÌôxôŠô÷ôµõ´öã÷1ùŠúÝûý)þÿ ÿóÿúÿ´ÿ$ÿRþGýü¾úaù øÑöÃõòôoôGô‚ô(õ:ö·÷šùÙûgþ2(3; * ç\sBÞç[9ˆS¨™ ; ¥ñ:þ˜ú$÷÷ó&ñÂîÚìyë£ê\êŸêfë¦ìOîQð—ò õš÷*ú¨üþþóx¢oÜð°'dtjWM^™ÿ ÿ¿þ¾þ ÿ«ÿ•Ç6Ô‘\" Î M ‹y%з ö Å 1IËýaúüö´ó¡ðÜízëé%èNç çgçXèÚéãëcîHñ|ôç÷rûÿ}ÌÙ ß ºõP-”‘2‰ © § —žÙN ÿþoý ý!ýnýûý¾þ¦ÿ¤¦špŸnæÍFyþrüAúú÷°õxóhñ”ïîðì@ì ì\ì4í“îtðÍòõ®øü¡ÿGêo ½ ¼W|*¢Ê„»}Þò Ñ “Q"ýXúâ÷Íõ"ôèò$òÒñîñoòIólôÇõI÷ÜøoúïûKýtþ_ÿYb—ÿÑþÚýÁü–ûkúRù^øž÷#÷ùö+÷¾÷µøúÊûÙý0ÁyB ° &U'ŠpÎÙ…¨K~ R Þ9}ÿÃû%ø½ô¡ñèî£ìàê©ééòèoétêöëäí,ðºòxõNø%ûçý~Úê¡øét œ i ãøÄop£ËÿÍÿ·™¹ ~ˆú E V  Ž ˜ 6 c  g IÐ ÿàû¨øyõkò–ïíðêFé!èŒçç&èUéëSíðózö ú¶ý^îJ] X$k)_D l[  ´^!<ÿ°ývü”û ûÜúþúiûüëüâýæþæÿД#qu(ˆ—Zÿ×ýü:ú?ø@öPô…òòðªï¿î>î3î¥î˜ï ñöòSõø'ûyþñzùU uB§‘ôÃú˜ž ް‰ 1¿MõýÍúê÷^õ:ó‡ñOð“ïRïˆï*ð-ñ€òôÑõ¨÷‚ùMûöüoþ©ÿ›@“—PÆÿþýüû[úÙùžù·ù(ú÷ú"ü¥ýyÿÝNÏK « ÚÂPsCßïsuý  âg ý_ùÕõ†ò‹ïøìÝêJéHèÜçèÄè êÑëî“ðfóhö€ù—ü•ÿcñ- € ‡ ! N  † § Š Aßv×ÃèPMá´½î5ƒÄçØ ˆ è í Ä öú©EýUúZ÷kô ñïÎìñê‹é¨èSè’èféÌê¼ì+ïò@õ¼øeü ÕhÂ Ë pŸMoƒ|!ð ì F¦ Ëÿ³ýèûuú`ù¬øWø]øµøTù+ú*û@üZýhþXÿ¡å݆âÿòþ¿ýSü¾úùW÷ªõôÃò®ñîð‘ð¢ð(ñ'òó†õÙ÷‡úý²c² Ù ÁRx#DÒÇ"é"Û$ ¹ 4›ÿ”ûVødõÒò®ðïÛí6íípí@îwïñÖòÙôøöù5û-ýôþz¸¤:|m{°ÂÄÿÅþ×ý ýsüü üMüåüÕýÿ¥twÒ  ¨øáWO°„ eó^þ½ú,÷ÃóœðÍíjë…é+èeç8ç¤ç¤è.ê8ì®î~ñ‘ôÐ÷"ûoþœ—J¥ ™  ,ÄèŸó ñ © . “ëI¿^4L¯ÿ_ÿ]ÿ§ÿ3üò(EL+Ò2?ñB0¾ó×{þìû?ùˆöàó[ñïí~ëZê¶ééêë­ìÅîVñNôœ÷(ûÚþ—GÏ  Ž™n:w0qKÓ ? So©þÅûÇù'øíöö°õ¨õüõŸö„÷šøÐùûPüwýwþCÿÏÿ µÿÿ2þýÉû`úêøz÷"ööôôfó ó?óËóÆô2öø@úÍü ÿ£Äëÿ èßÃ*T '²´9S ˜ó@šüùÕõåò[ðFî³ì¨ë(ë1ë¾ëÅì9îðòjôÓöDù¨ûìýüÿÊKvEºÖ "i……{z”ÿÖþOþ þþlþÿQÓˆ`J2  ª +ä0]7• ~ ý ùŸÿ'üªøBõòï{ìSê«èç ç çÍçéÛê$íØïãò-ö ù ý•çÿÉ 3 /³ºBNåàc ¬ Ï àônõ¿ÿÓþ8þïýöýGþØþŸÿ‹Ž–lˆ­øÚJoÿVýû©ø=öÞó¢ñŸïéí’ì«ë@ëZëþë,íáîñ¹óÀöú ýKû˜ .ùT0~8[çãXUê,3 èÉÌþü‰ùe÷¦õTôsóóüòZóôõMö°÷&ùŸúüMýcþ=ÿÑÿÃÿ,ÿWþQý&üéú«ù~øt÷žö öÏõìõnöX÷ªø^únüÌþi5ÿ Ð u×â¥CPʱ Ý9/ Õ?‰Ìý!ú£öió‰ðîì¯êÎé~é¼é„êÉëí“ïòñ†ô9÷ôù ü)ÿ{ˆC¡ž7qPÞ(=- è×ç'¦ÿiÿyÿ×ÿt§š;Ýo Ü  ý ‘¿Ê Ÿ ô„Àº†ý9úíöºó¹ðî¦ë¾éXè€ç=ç“çèê ìŠîtñ¯ô'øÀûbÿóZ R »°%fÐÊ`¤ª † Nñô.­þzý›üüáûühü ýàýÓþÔÿиzRRY^þ²ü¶úžø}öhôsò´ð>ï"îpí4íwí=î‡ïPñó;ö@ùŒü1¬ ò PbÞÀ Ãõ¯ Ð xÇÿŸü³ù÷Ýôó´ñÒðjðuðíðÅñðò[ôõõª÷fùû¨ü þ6ÿ°ùó¢EÿPþAý(üû!úVùÇø€øŽø÷øÀùéúnüIþlËSò’  x“Xµ™ûÐвò Ó hËÿZû»÷Nô,ñjîìOêébèJèÆèÍéVëPí«ïQò+õ$ø"ûþÕa¡‰ ) Ú "  ‘ Ï Î¡X¿’Æ>h ð P®n¬ ¹ …  Ù &  x†7›ÃþÁû«øšõ¦òåïoíYëµé’èûçøçè¶émë©íZðnóÏöeúþÍkØý Æ!ÿW$cM ab ³ /«<õéþ$ý±û™úÝùùzùÅùVú ûüý*þ,ÿÉH‚p[]ÿþ—üéúùG÷yõÈóFòñð—ïïÞï¹ðòÞóö¼ø°ûåþB³ j ~B¢‹í¿ù™¡ ˆ¢n ~ô‚ý;ú9÷ŽôKò{ð)ïVîî/îÍîÔï2ñÙò³ô­ö²ø®úŽüAþ¹ÿéÍ]šˆ,’Å×ÿÕþÓýâüüuûûûIûãû×ü!þ»ÿš²ñFš Ú ïÅHf>å›°L  XîW­üùƒõ6ò:ï£ì„êìèäçsçšçWè¢énë­íLð5óQöˆùÁüæÿÝ–ý   Ì „ Ë ¦  B  Å J¿7ÅzcŒþÿ»ÿÇÿ·‘µç0"ÝO o 0 ‡P0Éÿ*ýeú‘÷Ãôò™ïií—ë7êUéþè6éê^ëDí©ï}ò®õ'ùÎü‹DßC X H1ÎÙVLÉÚ” T ˆ¼€ÿ4ý5ûŽùHøg÷êöÎö ÷™÷høhùˆú·ûâüøýéþ¥ÿ"XBÞÿ/ÿ9þý§û%ú•ø÷‘õEô4óqòòòtòUó©ômö™ø!ûõý5v« ½ •9à‡ç±í§ïØ x è@œþû¾÷´ô òÍï îÏììíëBìíPîìïÔñõó8öˆøÑúþüþþ¿9`0¦Ç— n—“™ÿ¶þüýzý<ýJý©ý]þbÿ³H  ß tº¢ ¥§)1 È üÞƒþuúòö”ótð©íHëbéè=ç çvçuèêìînñ“ôè÷Tû½þ ) — <hPlg … Ì ÿ1tÛuNpÿàþ þ¯þÿ ÿmbnƒi ™È¡@m‡`þü„ù÷örô òØïîí`ì@ëœê|êéêãëgípïññÛôøœûFÿý«4 € v£žÒÃûÈ;l p aUc£ý#û÷ø)÷ÃõÊô>ôô[ôóôÕõòö7ø”ùóúEüvýzþBÿÆÿÿÿëÿŒÿåþþèüªûXúù¾÷›ö¬õõªô°ôõôõ7÷âøíúNýôÿÏÊÎÅ –*kF©‡Õ³FNÙö º ;’Øÿ&ü—øDõBò¦ïíÛëÁê6ê8êÃêÎëKí*ïXñÁóNöéø}ûóý9?øY]G4Ò,QQ=($@ÿÿäþÿþjÿ#'méŽK À Q ­ À|Ò¸'˜ ¡ B†€Eÿèû„ø0õòïìiêÃè§ç ç2çÝçééê4íîïóZöÝùrýþjŸ† %Äâ}–4`(›Í Ñ ¼¢™±ý‰ÿ_þ‡ýýÓüòüZýþýÑþÃÿÃÁªnüHHôIFñPÿoý\û(ùæö¬ôŽò¡ðûî¬íÇìWìgìýìîºï×ñfôW÷˜úþ­QåM s?œ|ÏŽ´C=®¢+\L È…cþuûÏø‚öœô&ó$ò—ñ}ñÎñòƒóÉô@öÕ÷sù ûƒüÒýéþ½ÿF‚pvÿŸþý€üXû7ú1ùUøµ÷_÷^÷º÷yøœùûüü(ÿ”2ì¬ ] è51Ç膘 oN¶¶ cÓaý²ù-öêòÿï€í|ëêé¿èúèÂé ëÍìòîhñôîöÐù¨üaÿå%¡Ì í é ãüæ´xD*9~Öÿóÿ\5…ûV ƒ n I  ‡ }  ×;[Lý úòö×óêðAîòëê®èÕççâçËèGêKìÌî¶ñöôtøüÈÿiä  ˆ’•„ñær¥’ N îˆ2ÿDþÖü¾ûÿúœúúÑúYûüýþ ÿá“ >$¹ûîÿ˜þý>ûWùb÷qõ™óîñ…ðnïºîuî©î[ïð<ò_ôíöÖùýiékÖ œÀcx÷Û'àà  º LÒeÿüùRöôóòð’ïïï€ïXðŠñó¸ôöqøPúü¶ýÿ?žÔ»Z»êÿõþíýãüëûûoú úóù0úÈú½û ý®þšÄ l ®µkÀ£æ:BW H ìZ¬þùú]÷ðóËðî¯ëÛé“èàçÅç>èHéÖêÜìFïòöôø0ûEþ5î\p c 7 ˜ 2 w t : Ýmÿ¥nj¤$ñÿ nþHŽÒ Ý g œ r ã êˆÃ£5‰þ±ûÁøÒõúòPðìíâëEê%éè†èé5êåëîÃðÒó1÷Éúþ;ã\ iÔÂ)J8ï9'Ì > •åFÌ‹þüæú™ù­ø"ø÷÷#øžøYùGúVûtüý—þzÿ)šÄ .oÿiþ#ý¬ûúeø¹ö!õ²ó|ò“ññßð*ñêñ#óÐôêögù8üKÿ‰Þ1 i m%~bÄ—Óvûîh|? É2• ý¬ùöÈóiñ€ïî0íÏìïìŠí”îþï·ñ¬óÉõ÷÷"ú7ü$þØÿEf1§Èš&wœ¦¦ÿ«þÊýýüTüdüÈü‚ý‘þðÿ”u€¦Ò ï ê ¬#<éÒ­Ù Ø ÉtñÿVü¾øBõûñïkìJê®è¢ç-çRçèZé,ëtí ðóNö ùùü?\<Ê÷ ¸ Ú9$¦Ê Ÿ 6 ¡ õD¢ Í·èÿeÿ1ÿJÿ¬ÿN''>\nb'¯êÏW}C¬ÀŒÿý‡úÜ÷3õ¢ò@ð"î^ìë#êÈéúé¼ê ìåí<ðó*öšù<ýõ®M¶ ÓלÔzŠüqvz ¦ ¶Âá*ÿ­ü}ú¥ø1÷$öõFõkõèõ¯ö±÷Ýø újû¦üÅý¶þnÿãÿ êÿ{ÿÄþÍý¢üOûæùxø÷ÙõÍôôózóÍóô½õY÷[ù¹ûdþIWv ‰ MÄÙz™)%ŠYšX¢‹ ' Þ-þ”ú-÷ôPñÿî*íÜëëáê1ëìFíðîíð)óõø€úàüÿÅ%,Ö$Å+\h`UZ€ÿÕþfþ=þcþÙþŸÿ² œZ3 ë ¢ &cJËÛr‹)M  UV±ý9úÉözóeð¢íEë`éè7ççkçiè÷éìŽîvñ©ôø’ûÿ€¼´S Š M”\¤rÏÆgÄ ð þG¥@#ÿTþ×ý¬ýÐý:þáþ·ÿ­²´¢kþORTNñDSþ+üÝù|÷õÕò»ðãîaíFì ëzëÛëÆì9î/ðòtõ£øü°ÿ^Š Õ Î`y  uG…6f&‰£ Œ \,)ý~ú&ø.ö ô‚óÖòšòÇòUó5ôYõ¯ö%ø§ù#û†üÁýÅþ‰ÿ0¨ÿüþþý×ûúiùNø^÷ªö?ö+övö'÷>ø»ù–ûÇý=콜r (§Ø¨ã4ô »Ía† P Ô*mÿµûø¿ô°ñïÐìëøébé^éèéõê{ìiî­ð1óáõ£øcû þ‚½¬AvH¶Æ~é÷Ϋ¡¿¨ÿ†ÿ°ÿ(ìõ8©8Óh ã 1 @ ÿ `Yà ò ¾ ƒí óþ¶ûmø2õòBï½ì êýèâçYçgçèLéëaíð6ó—ö&úËýjí99 Ú Âô Åi•UºÕ » <ãõEÿßýËü ü¨û˜ûÖûXüýõýñþóÿéÄsç÷…¾¤@ÿ™ý½û»ù§÷“õ”ó¿ñ(ðãîþíŠííîï¥ðªòõö÷ûþœ" ¡iǧþÁêzuãÑPsP ÿ™8óýáúø¥õ›óòâð=ððSðñòZóåô—ö[øúÊûSý§þºÿ„, ¡úÿ ÿ"þýüûøúúeùõøÓøùšù‹úÚû‚ýyÿ²ªC Ñ >uaí ©ÁLJ»© . æ`³ùüKùÄõ|òŠïíöêréè!èYè!épê:ìnîùðÄó¸ö¿ùÀü¥ÿWÇ䢸 ã c z 2 ” ® ’Oú£^<I”$(›ULs¾u¾â Î s à ² 9 S  F+»ýú ÷ ô6ñ î^ì…ê&éMèèSè6é«êªì%ï òMõÎøxü0ßhµ ¯ C`û Ž…ôæh‰_ü w çaúÅÿÐý)üÚúçùSùù;ù§ùTú4û5üFýUþPÿ'Í4S$¥ØÿÀþhýÚû&ú\ø‘öÖôAóäñÓððÍïðïŒð¤ñ4ó8õ¥÷múýÅ*•î ’³UjëÓ!Û ºþé ’ ‚ýþ™ûnø’õó ñvïcîÒíÁí*îï<ðÇñ‘ó†õ‘÷žù™ûpýÿsŠOÀÞ®9Š®¸ÿµþ¹ýÔüü–ûWûgûÌûŠüŸýÿ»®Ñ` ¤ È ¹a­øàBoG® ³kéIþ¡ú ÷¤ó€ð¸í_ë†é9èçbçÚçäèxê†ìþîËñ×ô øNû‡þžU - – ‹ Ä   à P Ã.¦;ýù9ÅÿÿÃÿ1àÆÔú(KQ)  šË˜Ø\þ±ûëø ögó×ð‡î‹ìöêÚéAé5é»éÓêxì¡îAñGô ÷4ûêþ§TÖ  ùqlßÁеóÏ\± ä A–"þòûú—ø|÷Çöwö‡öìö›÷†ø›ùÉúþû(ý6þÿÀÿ%A’ÿËþÁýüû—ùøö2õôó‡òQò…ò)óAôÉõ½÷ú½üªÿÅú1 Q Bì:xKŠ1@¾³.@þ Ü0”ü ùìõó—ð—îí ì²ëÊëbìpíåî±ð¿òüôR÷¬ùóûþ® » ½+dxwsÿªþþ›ýxý¥ý$þöþ%ûðòì Ê xâ÷¦ä§ê­ò  ( 5úŽÿüøõÖñãîOì/ê‘èƒç ç-ççç4é ëXíðó_öÉù=ý¡ßá’ ã Å 1!”> ‘ ä  =k³&ÓÄÿÿþjþ”þÿ³ÿŽŒ˜£šlblvpZ\ÿ!ý»ú=ø»õKóñúîCíðëë³êÜê’ëÓìœîãð›ó²öú«ý]® :üKX™‹ùòˆÐ à з­Êþ üÁù¼÷öçô ôÇóÕóBôõö?÷˜øúcû°ü×ýÉþ|ÿçÿØÿ`ÿ¤þ®ýŠüIûúù±ø÷vö©õ&õúô0õÎõÖöGøúMüÊþ„jd\ ; éOXó   â+ï?+ È/x¾ýú¥öxó§ðEî`ìë2êñé=êëZìî!ðxòþôŸ÷BúÓü>ÿoZñ,ƒ¡iæ%4& øû%†ÿ&ÿÿGÿÎÿ¡»šCû° M À õ Ûc,_ _ 7 ¬Ï°hý ú±övópð·íaëé#èVç ç„çè êì¨î–ñÓôHøÜûtÿ÷Na  pN­‰á¹ ¢ë û ç Ħ Å#Éþ¼ýý üüÍüNýþçþâÿâÙ´cØåo¡ WþeüJúøàõºóºñöïîhíÀì“ìçìÁí!ïñWóö0ùü·SÐ   ¼RWŚ؆±g» “ G÷»ÿ©ü×ùV÷7õ„óDò{ñ'ñDñÈñ¨òÓó:õÉömøú§ûýYþ[ÿ…¥ySÿmþbýCü!ûúù\øÝ÷­÷Õ÷\øFù’ú:ü8þ|úŸU   &êBr9o4Ô Ø c¾ÿIû­÷Gô/ñzî9ì|êLé®è¥è,é=êËëÇíð¼òŠõqøZû.þ×De, " Q " ž ÓЦg&õä]ýÿèÿ¡lu°…û` ¡ ¬ o Ý ê Œ ¾ € ÔÃV«þ’ûiøIõJòƒï íøêZé@èµçÀçcè›éaë©ídðóäö{ú+þÙmÍâ ™àªïªÙƒ®g½ÃŒ . ¿UÝôþSýüûxú9úOú±úTû(üý&þ,ÿïìËAf@ÿÕý1üdú}ø‘ö²ôöòpñ3ðPïÕîÍîAï2ð¡ñ‰óàõšø¥ûíþ\ÛP ¡ ¶xÒ³ ÐüŠ÷âYq> Ú^áýMúa÷Îô£òìð±ïôîµîîî—ï¢ðò¡óoõW÷Eù%ûåütþÆÿÏ‹ô Ø_«ÌÿÐþÇýÅüÛûûúJúVú¹úvûüÿý¾ÿÀøUÂ+ z ˜rô ­Ìbnððy ˜ bêH—üïøjõ!ò,ïŸìŒêéè¥çÚç¢èõéÇëî¥ð‡ó˜öÀùæüóÿÑm·   / Ï Ê 6 R . Ûlóƒ/cþÿåÿ”RGfžß2 Ï 1 ; â # ün‚B»ÿÿü!ú8÷YôžñïéìëÀéèèèåèÁé-ë#í—ïxò³õ3ùÞü›Qå? GêÀÝjgØÇ?Q‘ ê 1~å|ÿQýuûñùÌø øª÷§÷ù÷•ølùnúŠû®üÈýÆþšÿ5Žœ]ÑÿùþÝýˆüûlùÇ÷*ö«ô[óNò“ñ9ñJñÎñÈò8ôöbøûóý^¯ð åj„#9¼§ùµå•Õº Y Ë*þûÑ÷ÛôDòðsîJí¨ì‹ìíìÆíï¢ðƒò—ôÈöù.û<ýÿ¶  µ ½0m…‡ˆÿ•þÂýý¸ü˜üÉüNý)þUÿ̆sƒ¤Â È ¢:~_ÍÀ2Šz ù æzìýTúÊöjóLð†í-ëQéèEç"ç™ç£è:êOìÒî®ñÏôøzûÓþ Ò6 2 ½ ÑkD“‰ 7 ¯  K•ö>>‰ÿ!ÿ ÿ<ÿ·ÿlSZs‰l{‘N¬©H†=þÂû(ù…öîózñ@ïSíÈë¯êêêêë$í?ïÒñËôø¤ûUÿ¾C ‡ tõúwb¸z­YZÒ  !+T¯ýOûBù”÷MöqõÿôòôCõçõÏöì÷+ùzúÆûÿüþóþ–ÿòÿÅÿ=ÿqþiý2üÛúuùøÆö¢õ¸ôôÒóîótôgõÉö“ø¾ú=ýô ! ü•Ö­ ÜÉÞb\Úî « (~Èÿü™øSõaò×ïÃí2ì+ë°êÁêWëiìèíÅïìñIôÄöIùÂûþ>!¶óÔW€TÞ*GE7.;qÿÚþ„þwþ¹þMÿ.YÄc&ûÑ ’ + ‰˜K’f¿›þ í sž2ÿÅûSøöôÇñÞîQì4ê—è‡ç ç+çäç0éëZíð.óƒöúŠý d„U Å ÆMUÜåvš_Õ  " ! 4nÞ‘ÿŽþÝýýrý²ý5þïþÓÿÎÓͬ`Ø ês£{ÿ:ÿ6ýû³øZöôãñïïFîûììºëÚë‚ì³íiïœñ?ôC÷”úþÁl j ‹O£v»m…÷`PØ  ÖœmbþŽûùÔö õ±óÉòSòLò¬ògónô³õ!÷§ø0ú¬ûý4þ%ÿÐÿ0C ‰ÿÉþÕý»üŒûXú2ù-øZ÷Çö„ö›ö÷ò÷6ùÛúÚü(ÿ³l> Ó h»·JcöúmMŸnǺ ]ÆQý¦ù(öðòð¡í¯ëDêjé!éié;êëOírïáñ†ôK÷ú×üsÿØ÷Â0:à#  ›æøä¹‹lk™°ÿ¨ÿîÿ€[wÈ?Í_ã D p V ç Ö % i fJQ*ýìù­öˆó”ðéíœëÀéfè˜ç`çÀç·è@êQìÛîÍñõø0üÙÿoÜ Û G=² æI8Âøî ¹ m çÔùÿaþý&üŒûIûZû¶ûRüýþÿÿËd¿Ð’ÿæÿjþ²üÌúÉø»ö¸ôÔò#ñ¹ï¦îüíÆí îÓîðâñôÄöÂùýz“ A3Ãßw€ñȵ܊ÒÉ † "µZÿ&ü0ù‹öGôròñ/ðÆïÓïOð.ñbòÚó‚õG÷ùÚú‚üýý>ÿ9èHX›áÿùþôýãü×ûâúúù3ù6ù’ùLúdû×üžþ®ùmù… ý JV ]8_¡Uƒ3r S êOšþäúH÷àóÃðî¾ë÷é¿èè è’è¥é:ëBí«ï`òKõTøcû`þ6Ò!¨ Î ‡ Ô ¼ G ƒ } Fò“;üåeFÒ¡§Ø%|Ë  Ð L n , j èÃ6nþ|ûwøwõ’òàïyípëØéÁè5è<èØè êÈë îÁðÚó@÷Úú‘þHéX ~ G |јѩ[¤•C Ä -–¸—þ¿ü9ûúEùÙøÉø ù—ù^úQû^ütýþsÿ:ËÑ6Oÿ!þ¸ü ûiù¦÷éõFôÐòœñ¹ð7ð!ððYñ«òsô©öAù+üUÿ§ k ª ²k¿œô»ê~ëÔGV ¦ƒýºù±öô¸ñæï’îÀíqí íFîUïÀðtò^ôjö‚ø“ú‰üSþâÿ)"ÈÌ?}•˜ÿ—þ£ýÏü)üÁû¡ûÓû[ü;ýqþöÿ¿Áë+m ›  gÝñ”»]y$à ø Öqáÿ<üžø õÚñæîWìAê±è³çLç~çFèœétëÀílðcóöÒùýKQˆš ? q .wRÈ å ¹ U Ë0–¯’ìÿ‘ÿ…ÿÅÿI ÿ;bve –¼†ðõ™ßÐ|ÿîü<úz÷¾ô òµï”íÐë{ê¥éVé—éjêËë¶íðõò(ö¡ùJý¿Xº Í{´j’(*ˆ÷û¦ E g‰Â(ÿËü»úù°÷Ãö<ööRöÝö­÷±øÙùûJüpýrþCÿ×ÿ#$ÙÿBÿdþIýýûúù“÷)öæôÝóó·ò´òóùóEõÿö ù›ûbþa…·Þ â «#5ÐåiX®o¢T•v  yË!þ“ú;÷.ôñDïƒíHì—ëoëÌë¦ìïí˜ïñÀóözø×úý.ÿ”ϱ9hEØ-SZTShÿ£þþÃý¾ý þ§þ•ÿÏMßÒÉ ¯ p ø4‰ˆ “Ÿ ; v`—ýú™öFó0ðpíë=éëç,çç{ç…èê7ìÂî«ñÛô<ø³û(ÿ©‰ . غð¯ô– ù 1 RqŸðr4>ÿ—þAþ;þþ ÿÈÿ±´¿Á¨c㎿”@-þåûzù÷Žô9òð:î¹ì¤ë ëñêcëaìèíòïsò]õ›øüÀÿt¡ ç Ø_lðâ>5Ý Ç,N C #6ý¨únø”ö#õ!ôóhó§ó@ô'õKö›÷ùtú×ûý6þÿ±ÿÀÿ0ÿ`þ\ý0üîú¥ùjøN÷cö¹õ`õaõÇõ”öÌ÷iùfû·ýLôÚ › S!xJ@\èêoˆ H Æ]ÿ©ûøÆôÅñ*ïíeëPêËéÖéjê€ë íöî4ñ®óMöûø¢û,þ…ŸjÝð¢ôêŽìôÖÆÓ„ÿ=ÿBÿ–ÿ6"Q·GðŸC Ç  #Ù,‚{ þ  ¹ ÞþŽû6øïôÑñõîqìYê¿è®ç2çNçèMé#ëxí;ðXó¸öDúáýué$ œ ·Wu "ºÝš#  ïÁ¢¥ÚPÿþ"ýŠüHüWü°üIýþÿÿì·P©¸vÞñ°&ÿ[ý^û?ù÷êôÝòÿðfï#îFíÞìóì‹í©îIðdòðôÜ÷û‹þ¼H ¨ ňݳý²ÎRA§ / Êr"óýøúGøñõô…ò~ñîðÔð'ñÝñèò9ô½õa÷ù¹úIü¯ýÞþÊÿj¾Ã|òÿ-ÿ:þ*ý üòúïùùrøø ø^øù#ú–ûaý{ÿÔ^³ R Ì ÷€–*5°›úÖ;: æW£çü:ù¸õxò‘ïíë¤éÀèqè¶èˆéßê­ìàîeñ&ô ÷úêü´ÿIš—4l 9 Ÿ   G ²–[Ф Ð@úÿþÿOëÊã)Œüeµ Ù À Y ˜ q ß Ý l ’XÊúÿùüÝù½ö²óÔð9î÷ë#êËèýçÂçèé”ê¡ì(ïò_õãøŒü@æe£ Ÿ÷\GÆëÇ r ÿ†ÓÀÿïýlüAûrúÿùåùúúXû?üAýLþOÿ8÷Å¿iÂÌÿŽþýaûù®÷Ïõôjò ñþïQïïFïøï(ñÒòðôw÷WúýØMÄ% U>Éã{…ùÔÃçк g îiòþ ûŠøÅõaómñòïõîxîwîìîÌïñòQô7ö.ø!úþû³ý1ÿkY÷B=î]˜­ÿ¬þ¦ý­üÓû(û»ú˜úÇúOû1ülýúþÒç)†ê @ qhZ4‘i¸}¼Ò Åmß5þ‡úðöŠókð¬í^ë‘éRè¨ç—çè0éËêÝìUïò"õIø{ûŸþžeà »  â L I ã #  × mïp·œ¾'ÜÿÝÿ)½Ž¶î'OS# ® ç Ä = PûE5Ø>þwû™ø»õôòZðî ìxêcéÖèØèné–êLì…î3ñFô¨÷Aûúþ¶_Ø âJ5–iª[…0lKà B †Ä„0þ!ügú ùøz÷D÷j÷à÷›øŠùžúÅûëüþôþ·ÿ;{onÿþQýðûjúÐø5÷«õGôó8ò®ñ‰ñÒñòÁófõx÷êù¯üµÿæ.s ”@Œdº‚´MO¿©&à bÄü*ùö=óÜðñî‡í£ìEìlìí#î™ï`ñeó“õÕ÷ú?üAþ Å¥-_?×1]ihkÿƒþÁý4ýèüçü8ýÞý×þ­wm~– ¢ Œ @«º`@nH O Fø}ÿêûZøçôªñ¹î,ìê‚èççEç èdéAë•íNðVó•öôùYý«Õ¿W U §ßÉGd0 º  Z—àHß±Êÿ/ÿäþçþ5ÿÆÿŒ¢¯¢iõ7'»ñÇAiHÿíüjúÓ÷<õ½òkð\î¥ìWëê/êhê/ë„ì`î¹ð‚ó¨öú¸ýo&À& ?ö8÷(ÄË?(‡ n ‰ ‰„’Êþ=üýùø–öõÔô’ô´ô0õùõ÷5ø„ùÛú(üYý_þ.ÿºÿüÿòÿ›ÿûþþýÅûmúùº÷ƒö}õ¹ôDô,ôyô2õXöé÷ßù.üÊþ ¬µ   U¾Æ[nôæA Bú= ¸f±ýú­öŽóÍð}î«ì_ë¡êpêÈê£ëóìªî¶ðó{õø“úýRÿb)œ´nÊÍë) eÿåþ¨þ¸þÿÇÿÂ~&ê¹~ & ž Ò±-:ÑíŽ ¹ u ÐÚ¦KýÞùzö7ó.ðví$ëKéøç8çç€ç‰è!ê=ìÍî¿ñüômøùû†ÿù>< â ä-ô:ZGÝ, H E 74N–æþþný0ýAýœý5þÿðÿïñá®J¦·tÚçŸ,þüàù“÷Gõóñ>ïÈí·ììúë`ìNíÃî¹ð%óùõ$ù‘ü'Ðqð 3%¯ÀI@ hš@dlx S Ö¯ÿ¶üþùš÷—õôÛò*òìñòªòó¼ôö¡÷3ùÁú8ü‰ý¥þ€ÿXPþÿgÿ•þ”ýuüGûúùøe÷øöÝö ÷Æ÷Ðø>ú ü(þ)èµz ޱsÅ—ß–¼Q_î Ø Z¯òþ:û£÷Fô9ñ’îaì³ê“éé éé¶êIìEî˜ð-óíõÂø”ûMþØ&%Êìe | 9 ¦ÓΨtE+7wöÿ½ÿÐÿ0ÛÌùTÐYßM ’ ™ T ´ ­ 7 O õ , ürž“þdû*øüôôñ(ï°ì ê éùç{ç“çEèŠé]ë±íuð–óþö”ú?þäl½Á d—M~&Fãºò ¦ MýÊÆÿ…ý]üûû÷ú(û ûTü3ý-þ2ÿ-ËNŽ#ro"ÿ’ýÌûàùß÷Þõðó+ò¡ðfïŠîî$î«î³ï:ñ;ó«õ|øœû÷þv} Ò è¦úÐÕôyi̯"9 ­;Îýbú÷õóeñAðšïnïµïhðwñÕònô/öøÚùû<ý§þÒÿ³G‰|&ÅÿÒþÉý»ü¹ûÖú"ú¬ù€ù©ù,ú ûJüßýÂÿæ>·< · ;—©?PÕÎ=)Ÿ ­ gã8‚üØøUõò&ï¤ìžê"é7èâç$è÷èSê*ìkîñßóãöúù ýÃBm7 ™ Œ  . ç H ^ : í‹%ΗÃ;ÿÿj î:†Õ1  ½   ³ l¾±Q¬ÿÕüßùâöôó.ñ¦îsì§êSé†èHèžè‰éë íŒïyò½õBùðü«\ç5 .ÁÜsüëQ8­À† { Ø>Ãzÿqý¸ûWúTù²øoø…øëø”ùsúwûü¦ý­þ”ÿIÄ÷ßwÂÿÂþý ükúµøûöQõÉówòmñ¼ðpð•ð/ñCòÎóÊõ.øìúóý-†å1 R.±Æ]gÞ»ÿ¯Óz´– 6 ¬†þûé÷õ†òvðáîÎí@í3í¡í‚îÆï^ñ8ó>õ\÷}ùûzý4ÿ«×²7hHá>kxyÿ{þ“ýÐüCü÷ûøûKüöü÷ýJÿçÄÒÿ8 i } ^ù:uX¶â¼ % /ëpÖý5ú§öFó+ðkíëKéèYçDçÇçÝè|ê–ìïõñõQø¢ûèþ ûžç È 8 2¶Çm² ¥ U Ö 9”øx#/£ÿdÿrÿËÿf:8Rv’”kYVö4‹¯„þ‚ûÏøöoóðð¯îÁì9ë(ê™é–é#ê@ëêìï¹ñÁôø¯ûeÿ"ÍM ˆ iÝÓ?c@æäb§ ÈßE¾ý~û’ùøÝööÅõÏõ1öàöÎ÷éø!úbûšü¹ý®þlÿéÿÿíþûýÑü}û ú”ø%÷Òõ®ôÊó6óó1óÑóáô`öIø“ú/ý @h y [ø9 ^&[øÿtaÔß – i¸ÿüžøhõ‡òðî’ìžë4ëSëôë íŽîhð†òÕô>÷«ùü@þBqŠGª¶qç%;904Uÿ¡þ(þôý þuþ1ÿ:ŒÛ»©‘ _ ÿ ^iK O] 2 Ÿ³ÿ¢û&øÂôñ§îì êvèqçç0çöçMé.ëˆíJð_ó°ö%ú¤ý[f w _ο3+°Í N o ƒœÏ+Àšÿ¿þ5þýýþsþÿâÿÔÚáØ¬O±Çˆïú­ #ÿýü«úAøÒõtó=ñCï™íRì}ë'ëVëìVí ïgñô3÷“ú'þÕ… œWŸe@KÀ¦ô}¶ · —nUcþªû=ù,÷€õBôtóó#ó‘óTô_õ öø{ùïúPü‹ý”þ_ÿâÿ£ÿýþþ ýÚû™úZù0ø-÷böÞõ¯õÞõsöp÷Ôø›ú¼ü)ÿÒ¦v D â95ÃÔ[R´„džѹ S·þBýù(öüò,ðÌíêë‘êÇéŽéãé¾êìÚíùï`òøô«÷aúý„ÿÈÆnº¤+S#¤äòß½ž“­ûÿ‡ÿ[ÿ{ÿêÿ¥§çYí“7 Æ - X 8¼Ù…¼ | É ª)WE ý¹ùmö>óEð™íOëzé(èfç;ç©ç®èDê`ìóîêñ0õ­øIüéÿsÐé © ÿß?m@˜ FF é¶›©óÿþ_ý‘üüúû(üüLý'þÿú²3p`ýD7Ýÿ;þ`üZú<øöôò^ðôîçíGííwíSî²ïñãóŸö²ù ýŒ$¸- jXâô|àªÝŸIŠ O õ˜Pÿ1üTùÉö¡ôæò¡ñÔððð%ñ ò@ó³ôPöø½ùfûîüEþ_ÿ2¹ðÚzÛÿÿþôüÚûÌúÛùù—ø_ø}øøøÔùû¦ü‘þÂ-¾a ˆ ßï¦òÃÎþ »Yˆ [ æBˆþÑú8÷ÕóÁðîÕëêõè`è`èñè ê¨ë±íðÅò¤õœø–û|þ6³ã¹* 2 Ð  Ú W Š O·vR\ (ûÿ„7)PhÁù ý ¾ + 9 à  ä D?à6SþIû0ø õ0òxïíëuégèççüç¨èèéµëîÆðçóR÷îú£þUìN e d-n$Mï½ýµ E ÃEߤ¦þñüûŠúáù”ùžùøù”úfû]ühýtþrÿMûl–s<-ÿÚýMü•úÃøêöõoóõñÂðæïqïlïßïÏð;òônöù!ü_ÿÃ7¡ ç ñ¨÷ÌÓõ}oѱ*î ørýËùØö>ôòSðïYîîZî ïðˆñ6óõ÷ùûÛüþêÿ Ü[ˆeüVÿ‰þˆýœüÕûCûôúòúEûñû÷üRþýÿé T® A Ož6Nàèiiò  àlÐÿ$üøõÀñÒîMìBêÀèÏçvçµçˆèçéÆëî¾ð¯óÏöú;ýVCíC7 ¿ × { ¯ y ã ú Î p òiè?5nðÿ¿ÿÛÿ@éÊØ7eze y ‰ 9 „iëÞjÿ¿üôù÷Oô¤ñ1ï íKëýé0éïè?é!ê”ëíðìò*ö¬ùYýÌ`¹ ¿_ˆ-EË¿& uy)™ à O¤(ÿëüýúhù5øf÷üöñö>÷×÷¯øµùØúü,ý:þ ÿÏÿ=c;ÇÿÿþÅüZûÒù=ø°ö=õøóòò<òäñôñuòjóÓô«öéøûbþy²õ) 5zˆ&žÇz¡H€\ ô_·þ•úM÷Rô¹ñ‘ïåí¾ì ììqìSíŸîGð8ò\ô öíø/ûRýEÿøav4™©jç,GKHRÿvþÇýRý"ý@ý±ývþÿígboz o 9ÄþÖ?.Šöê n ’g~ýîùnöóðFí÷ê%éßç-çç–ç«èMênìýîæñõkøÖû;ÿ“[È Ì \t3ä-¿ * o ¤Ú&˜@([ÿÜþ­þÌþ3ÿÙÿ°«ºË̬YÅä­&×0;þŸûù‰öô¡ñwï˜íì ë{êrêõêì í½ïQòKõ˜ø!üÐÿˆ2³ ó ÛVUÊ­û³Ú{¢`Êô öèâúÿEýÕúºøÿö­õÇôNô=ôô2õöB÷‹øæùBûü´ý«þeÿØÿÜÿlÿ·þÄý¢ü]ûú±øn÷RölõÎô†ôôõö^÷ù9û©ý[@AH < ’Æß§ßŽ þv„ < µMÿ ûøÒôàñWïEí¶ë´ê?êWê÷êìŸí‹ïÂñ/ô½öVùâûNþ‡~&ufø- ›ëðÞà_ÿöþÔþÿ|ÿFY­6ã¥i  ¦ ù ­ñÃþ e [ ê Èþgûø°ôñ°î/ìê‹è†çç?çèYé9ë—í_ðóÞödúøýâ á V [äìqvØAl m YECgÀ\ÿBþ{ý ýêüýý<þÿ  î¨*hXó5!» ÿýÿúÄøöEô+òFð«îkí—ì;ì`ì í>îôï&òÇôÇ÷û–þ5Úi Ê ãŸê´ñ™§`C¾å Î “J ôýû}øBöpôó ò§ñ ñòÀòÏóõ˜ö-øÈùWûÈü þÿØÿPzXîÿAÿ_þUý2ü ûêùéøø‚÷:÷J÷¸÷Šø¿ùTûCý~ÿ÷] Ï S—… ¢žâ0ûPA ãK“Öü,ù°õzòŸï3íEëàé éÌèéúéXë(íYïØñŽôd÷CúýÃÿ9jEÂÙŠ Õ Á V ¢²—c)ûêXïÿÐÿþÿw;?zÝYÛQ § Ë « 9 f * ~ ` Ò Ú‚×íÿÔü¤ùtö]ówðÚíšëÊé{è¹ç‹çôçõè‡ê ì2ï+òvõûø¢üPì]Œ c ÑÇ:%†`ºŸE+ ã „#Õ­¼ÿþ²ü¬ûû®ú±úû•û^üLýNþSÿIÆ0T)¬ÝÀÿ[þ¹üéúûø÷õ<ó™ñ:ð1ïŽî\î¤îlï³ðvò­ôL÷Dú€ýënðW Šrø —•üÉý »^›† 7 ÇOéþªû«øýõ³ó×ñuðŽï%ï5ï¶ïðÚñ^óõìöÍø¦údüöýNÿa'Ú+€¦ÿ«þ ý˜ü¤ûÕú;úäùÜù*úÔúÛû;ýïþé €øq × ºÿÏè$Ö°ð ÓlÓ"þpúÙöuó^ð¨ífë§évèÛç×çgè†é'ë<í³ïwòqõŠø©û·þœG¥§C s 3 † p û 3 ' 舱^3<…ôÿ’J;Z–à#OQ  • º  Ü Ï[ƒSÖþ>ûJøZõ†òãïŠíëêøèvè†è,édê)ìqî-ñJô³÷Rû ÿÄfÖ ü ÄôD8Ýü¢ÞÀ^ Í $yât@þTü½úƒù©ø1øøQøÙøžù’ú¤ûÂüÙýÙþ²ÿT¶Ï›Iÿ3þàü^û¼ù ø_öÊôaó6òZñÜðÇð&ñûñHó õ6÷Äù¤üÁÿ`² å àŒÔ¦ò®Ó^R¶•ÿ¾ BªŒü7ù(ösó'ñSïþí.íâìíÄíÝîTðòô.öZø€ú‹ülþo~8œ¬pï6UZZÿdþ‰ýÚüfü8üYüÏüšý»þ(ÜÉÞ 7 T Ilv1Ðꀗ8 q TõkÿÎû7øÁô„ñ˜îìêèŠç-çiç<èžé‚ëÛí“ð—óÏö"úwýµÈ™ 0 Ý Ö!ûm„ N ß G ›ïTÝ—‘Òÿ`ÿ<ÿfÿ×ÿ†ipŒª¹§bÝ ÞSgqu4ÿºüúk÷Âô4òÙïÇíìÈêüé¶éÿé×ê>ì,î—ðpó¤öúÅý7Ï. =çËìzsÛ»° . ?OwËþ]ü=úxø÷öŽõdõ™õ#öôöþ÷.ùrú¸ûíüþèþ’ÿöÿÜÿ\ÿ–þ’ý[üû“ù#øÆöŒõ‰ôÎóhócóÉóôàõ÷¤ùüËþ»Ðò ÿ º$*¸Â; m%Qû5 £T¦ýú¸ö©óûð¾îÿìÆëëøê]ë@ì•íKïRñ”óûõsøäú<ýfÿRõC8Ð õ‘ì Eÿ¦þEþ,þbþêþÁÿäJé°s H û v¨€ðìnsû ® ñä›.ý´ùFöýòóï=íñê éÙç%ç çˆçè@êdìúîîñ*õ•øü—ÿú* ¡ Ä s¥W‹F’{g ž©ÂühÿGþÜýÂýõýmþÿýÿ÷þþç§/qdB*¼þÎûxù÷²ônò[ðŽîíì|ëkëãëäìnîxðùòàõù—ü8èŒ J4µ¹5q+Rï¿)  à´¥ÿÅü)úâ÷ýõƒôyóáò·òöò’ó}ôªõ÷{øûùpûËüúýðþ¤ÿ *ûÿ‚ÿÇþÖý¼üˆûLúùø÷söööpö4÷_øîùÛûþŸX0 ç ˜3ó>Aêÿ„€ Ó NŸâþ-û÷JôJñ²î‘ìõêæéhézéê9ëÏìËîñ£óTöùÎûlþØád‡F¢¡K«Ïɨ€caŠìÿÿ~ÿºÿC.}÷+À 7 } 2ƒiÜ Ú d ~ 1‹{þ8ûí÷´ô¤ñÕî^ìRêÃè½çLçrç1è„édëÁíð³ó÷¯úSþîh©š )F癩9T_r T  ؤ‘°ÿºý·ü ü¸û¸ûü’üVý?þ=ÿ=/¦-ýy¡wÿOýgû^ùD÷/õ3óeñØï îÌíjíƒíî<ïÛðóòzõaø–ûÿŽ#¦ þ Ìã#ÎàY=—sãû Ð |»€ýzú¾÷_õhóåñÙðHð.ð„ð@ñSò¯ó@õóöµørúü“ýÙþÝÿ–ësÀÿÜþØýÃü¯û¯úÔù.ùÌø¹øÿø£ù§úüÁýÇÿ ƒ² ? ¨Öµ2=ÈÊ?%Z¾ ¼ iÚ(nüÅøFõ ò'ï²ìºêMéqè+èyèWéºê•ìÖîjñ;ô2÷6ú1ý ²É ä P V þ T e Bý¨Vt:¾†Š» lÉ + ¥ å  6 = × Ý]ÿ«üŸùö”óÅð8îì=êñè.èýçbè]éèêüìŠï€òÌõUùýºdå% ™„dÀ (õ Ž |ý yÿ“ýþûÀúáù_ù8ùgùàù—ú}ûü’ýžþ“ÿ`ùQ` ²ÿ‹þ%ýŒûÏùø4ö{ôìò™ñ”ðíï°ïçï˜ðÄñióõÿ÷×úôýC¬m ’pïþ‹ŠôÃúž¸WŒl  ‹ý}þ"ûø8õÏò×ðYï[îàíãí^îFïŒð!òñóéõò÷úùíû¸ýMÿž£W¶Ä†Jgmÿiþpý’üàûiû9ûZûÐû üÇýAÿ/xÈ ,°î¾æ1ô3÷ L BídÀýúˆö(óðYíëOéèyçqçè éÇêæìkïCòUõŠøËûýþ ßg“ W « Œ ù ø Ì » o økÛYøÇÑ"¾ÿ¨ÿÞÿ[Ix˜˜gô2  ™¸rËÌ€øýDûxø¬õõòlð&î7ì´êªé'é2éÏéþê¸ìöî¨ñ½ô!ø¼ûuÿ2ÙR ƒ W¼¢þÊ«Éi—gí = o›Ö7Ðý°ûåùyøq÷Ðö‘ö±ö#÷Þ÷ÐøêùûKüoýsþIÿäÿ9Etÿþ†ý;üÉúAù¶÷;öâô¾óáòZò5ò|ò4ó`ôýõøjú#ý?x¯ Ë ´S’^©f|]ÆÊ } øS©ÿü¨øõ´òPðeîüììÂëïëšì¸í;ïñ&ófõº÷úNüfþEß)·ùè‹î-+);ÿnþÔýxýfý£ý3þÿG¿rRNS M ' Î,3Ñûª×…µ r ÇÅ~ ÿ‚ûû÷’ô^ñxîõëçé_ègççAçèué^ë¾í‚ð–óâöMú¾ýPDå " ñ G"iâøº 8 ‡ ¹âi飥ÿòþþ~þ¸þ7ÿïÿÔÖåîàª;†#gOÜ ÿÄüUúÑ÷MõàòžðŸîõì³ëçêêÜê©ëíßî:ñô(÷•ú3þè›1 ’ ¦W“JsnK§‘Z f U?=eþÉûzùˆ÷ûõÚô'ôàóÿó{ôGõTö’÷ìøRú°ûôüþôþ˜ÿòÿÂÿ:ÿpþnýAüúú¨ù_ø2÷1öoõúôÞô&õ×õóöwø_úŸü+ÿñÞÜÕ ¯ U°ª3:¶žò±ä–Ô² E¦í5ý˜ù-öóNðî0ìéê0êêgêKë¨ìmîˆðåònõø­ú5ý”ÿ·’@ r€9ªßéØ¿°»ñÿ^ÿ ÿÿPÿçÿÊôXêšV ¥  ;‹–.Lò # èMa9éüˆù0öúòýïQí ë=éöç@ç"çžç°èRêxìïòTõÏøcüùÿtÀÅ p °yÉÌÞÂL ˜ ƒ bJNíÿ¢þ§ýý®ü®üùü†ýHþ0ÿ,- ô˜íe†SÒÿ þüëù²÷zõVó\ñ ï6î0íšììëìÛíPïEñ®óö¦ù ýž@ÙQ Œv÷ÿmÀ¨BZGF  ÇzFÿ@ü|ù ÷õaó6òñAñoñòïò$ô‘õ#÷ÅøfúòûYýŒþÿ)‡—ZÙÿÿ)þýõûÓúÃùØø"ø°÷÷É÷bø_ù½úxü…þ×` Çz m7|D‚2Qâëw— ] ß4wþÁú+÷ÑóÇð#î÷ëOê6é°è½è[éêì)î‹ð0óöçøËû—þ4’¢V¨’  1 ó b Œ‚UÚ¯©Ô=íÿèÿ/óùaÚP³ í ï ¦  ÿ ¬ Z ›wû47þûì÷ÍôÔñï«ì¨êéè¥çÈç‚èÐé¬ëîÒðúóh÷ûµþ`ì@ G ìÔ¦ÀUna^" à Wòª‘¶þ&ýêûûúSúxúçú”ûpüjýrþuÿa(¹ È-A ÿ’ýâû ú ø1öTôò ñïïï²î¾îFïMðÑñÍó7öùükÿà`Ó  (Ü%ñ3àõpU­…ìø ¾ VÙaýàù÷‚ôkòÉð£ïûîÐîïÕïíðVòýóÎõ¶÷ ùxû-ý¯þòÿê”íô±*l†ÿ…þ{ý{ü—ûÞú`ú*úFú»úŠûµü6þX¼- – á ùÇ;BÏØXMº¥ + çfÀÿ ühøêô­ñÇîLìNêÙè÷ç¬çøçÖè=ê!ìpîñô÷<ú]ý`3ÀøÎ : 5 Á à š ø Þ † 7ìÎëKöÿîÿ1½‰‰°í0f|a  X P æ  Ù9;ëWÿ‘ü­ùÁöäó-ñµîìÐê‰éÆè’èñèäégëríøïéò1ö¹ùiý&Ød² ª;SçícJ¦‚êï¥ x Á…)ÿ ýBûÐù¾øøÁ÷Î÷.øÕø´ù»úØûúüþÿÍÿY£¡Q´ÿÌþ¢ýAü·úùm÷ÒõWôó òaññ<ñÔñãògô[ö¶øiûdþ‘Þ0o ‚RÈÒ\\È›Õ{–3d= ÔC¢ þ›úc÷|ôøñæïPî>í±ì©ìíîXïýðæòýô.÷cù‰ûŒý[ÿé+³öçô);<>ÿPþ…ýíü“ü„üÆü\ýHþ†ÿ ÓËã ' * ü‰ÀìÊ%üR. œ ªløeýÌùGöîòÜï%íÞêéÞç9ç.ç¼çÝèˆê®ì?ï'òNõøûûNÿy'z c Ù Ø^oR= â V ©òB­Azÿ#ÿÿ_ÿçÿ¨˜¦ÀÖÕ¬K£©T ‹M5àýZûºøöóñßîÿì„ë}êøéýé‘ê³ëaíï5ò>õ˜ø+üàÿ›DÀ ø ÕD4šn­Xu2ò`• ¦«»ïÿWýû ùp÷<ösõõõxõ(ö÷<ø}ùËúüCýLþÿ³ÿþÿýÿ°ÿÿ=þ)ýèûŠú!ù¿÷vöYõzôéó²óßóyô€õõöÓøûýki€˜ š mü/õ<ù$¸¶#uz + ¡ó>ÿ™ûøåôò‹ïíì!ë½êãêë°ì>î&ðUòµô1÷²ù#üqþ‡[Þ ØIb'¥çýùëæüÿ:ÿ°þiþmþÀþeÿW‘ ³~X/ í € ÓÖx®m±yÆ ¢ 3 ³þAûÏ÷wôPñrîõëêébèhçç=ç èoéYë¾í‹ð«ó÷†úþ‡Ùì­ öh[ÍÂAV{ ° À ÁÆã)¦iÿxþØý‹ýýÝýlþ0ÿí—$ôlŠPÄðþßü¢úLøñõ¥óñ”ï÷í¼ìðë¡ë×ë•ìÜí¨ïîñ£ô¶÷û¢þJõ† å ù­î«Ústߺïj• ‡ X ø÷ý0û·ø™öäôóÊòhòròâòªó»ôöx÷ýø‚úöûGýgþIÿåÿ35íÿ]ÿþ‘ýpü<ûúæøç÷÷—ödöŒö÷ø_ùû&ý‚ÿÛ²ˆ F Ô Œ‘üW ]_C Û=ƒÇü"ù®õ‚òµïXí{ë'êcé2éévêÙë«íÚïPòúô¾÷‡ú?ýÐÿ'6ðKBÕ Ýb¢®•j?&/iáÿžÿ§ÿþÿ¡Œµ‘$·9 ” · ‘ .Ü  Þ 3 ¨âÞÿ¯ümù/öó"ðƒíEë|é6èç^çÖçåè„ê©ìDïCò‘õù¹ü_ðRp 3 Œm̤ôÀïl˜ˆ P ¿Ž‡ºÿ3þûüü’ûaûûêûüfýZþ\ÿZB’ßà‘íö²ÿ'þbüsúiøYöWôwòÎðoïlîÓí°í îèîFð!òqô'÷4úƒýþŽ„ ¸&¨™ó²Ûs†$_L  Ÿ5áþ·ûÏø;ö ôIòÿð0ðÛïûï‡ðuñ³ò2ôÞõ¤÷où,ûÊü9þkÿUóBAõg¢ÿ³þ©ý–üŒûœúÙùPùù$ù‘ù^úˆû ýäþXÖfô i ¯±Zša¤]‡&>Ú ÜhÆþ[úÅögóXð­íxëÇé¥èè"è¾èæéë¤íðÖòÅõÍøØûÎþ™'fIÆ Ø ~ ¹ ‘  = / ôŸBð¹®ÜL `û×é#vÏL K v ˆ 4 u J ¶¾nÓþûþ÷þôòtïíë™é—è!è?èôè<êìfî-ñTôÃ÷dûÿÑjÎ æ žäªè˜»Tk G/× U À-³dRþ‰üûÿùFùìøìø=ùÕù¤úœû«üÀýÇþ²ÿnñ/"Å"ÿæýpüÎúùJ÷õîó€òWñ‚ððððnñÕò²ôúö£ùšüÎÿ'ì & $ÐÝÏædK£yÛÞ ˜ ŒüIùNö¯ózñ½ïîÃí‰íËí‚î ïñÒòÁôÍöâøìúØü•þL4È÷9KLÿLþ]ýüöû›û‹ûÎûgüYý þ4 L‘Ô ÿ¼%)¹ËX^ÞÞj _ðZÿ³ûøŸôeñîìÿé†èžçOç™çwèâéÍë(îàðÞó ÷Qú•ý¾¸oÐÎ _ } &\&Œ h þ sÙEÇqQqÛÿ’ÿ–ÿæÿyHE`аÀ¨XÁ×çÚjŸ€ÿ†üÍù÷Lô±ñOï9í…ëBê€éHéŸé‰êìî|ðcó£ö&úÔý‘GÙ0 3Ðõ”¦$mD£™9™ Ï ò\Îþü€úÝø›÷ÁöMö;öƒö÷ô÷þø)úbû–ü´ý¬þpÿôÿ0!Åÿÿ0þ ý³û>ú»ø<÷Öõšô›óéò’ò¡òó ônõ;÷nùùûÍþÖ5Z Xƒ„  xO7Võ%ú ‹ïA›ýúÉöËó0ñï\í7ìœëŠëûëæì?îôïôñ)ô€öáø8ûpýyÿA¾è¸.L ë   'ÿlþèý§ý²ýþ¾þ½ÿ’S81*  É HxHª–òaY ã êýŒùöÊò¿ï íÈêéÅççç›ç¼èiê•ì/ï#ò\õÀø7ü¨ÿøåZ d ú±Ó€Ã¨@ Ó õNª: &ÿþLþVþªþ?ÿù  ëœ9Ѝk×øÿÖýƒûù”ö"ôÑñµïåísìpëèêæêoëƒì!î?ðÓòÌõùžüHþ¤ Z<±©ñ5ãÿ”®_¹Ô Ç©’›ÿÖüXú/øhö õôžóŠóØóôqõœöð÷YùÅú!ü]ýjþ;ÿÆÿûÿ£ÿÿ'þýäûúTùø÷#ö†õ;õNõÆõ§öñ÷¢ù°ûþ²†vl P ‡­j­k™27¬š  Ê ?ŽÒþ#ûœ÷TôbñÚîËì@ëBêÔéõéžêÆë_íXïŸñô¾öiù üŠþÖàšûü›ÛÂbaresip-1.0.0/share/sound6.wav000066400000000000000000001047741372575704200162250ustar00rootroot00000000000000RIFFô‰WAVEfmt D¬ˆXdataЉúÓj ¢_Ž IâàRNëG ~ ¯÷p4ÿSýÝûÚúLú1úú)ûüBýƒþÆÿïë¡û‹¬c¸þºü}úø¥õAó ñïŒíwìîëþë¯ìîòïsòtõÞø•üznNù P6”VpÛ—¬%—Á ³ Œjl­þCüAú´ø¥÷÷ýöW÷øùWú³ûý^þ{ÿVÞÆÿ¨ýóûúö÷àõßó ò†ðcï·î”îïð°ñâó–öºù5ý꼈. ‡é*¼›ÊTG¹Ãƒ ¡@þ.û°ø§ö õ"ô«ó·ó9ô õYöË÷]ùôúvüËýßþ¡ÿ˜ÿÍþªý?üŸúáø÷tõúóËòýñ£ñÍñƒòÇó˜õì÷´úÚýEÚy QLÓÑ0åæ5×ÙLJí T ñiý$ú;÷ÇôÖòtñ¤ðfð±ðxñ©ò,ôêõÇ÷§ùqû ýfþjÿ K!—ÿµþ‹ý-ü³ú4ùÌ÷”ö¤õõïôIõ%ö†÷gù¾ûyþ‚Âm ™€ Sxê®ËRVò DkŠÁü/ùóõ%óÚð!ïî€í—í=îaïñðÓòîô$÷Zùvû^ýýþC&ž¬U¥­ÿþ2ýàû¢ú’ùÆøSøIø³ø˜ù÷úËüÿ™nkr e &—œ RîÜ#Ííš ð $ü_øæôÔñ@ï?íÛëëë†ëœì1î/ð}òýô”÷#úüÀþ  5Ù ØFfOÖþ¦ý üÛûiû[ûºûŒüÎý{ÿ…Üi º D”ŒJlèÈí `Ž—ÿûÀ÷#ôâðîßëCêOééiélêÿëî„ðAó(öùýû±þ0Ø Æ ÝMlO Á‚lÿ‘þþÚýþ½þÏÿB S  æ èn‚ j)Nâ ö Ÿø!ÿ7û]÷µó]ðtíëHé'è¶çöçáèkê‚ìï÷ñõcø§ûÌþµKz1i  T  j j+ÄP馟æÿ‡ÿŽÿüÿÏ@&  Ä BeGé÷p Z ºY»þýú@÷¦óNðXíÝêõè°çç8çè~éë%î'ñyôú÷‹û ÿ]d6 à ÿ ‘ › ( H ‘ ì9“ÌÔ7-¾«æ[ö6 ¦ Õ «  f @ ’ b¾ºoþöúp÷üó»ðÌíJëOéïç8ç3çáç<é:ëÉíÑð8ôß÷¥ûjÿ ms  ‘xɋʘ ; D @Ló·ÙÿaÿQÿ¥ÿUTŽíX·ïçŠ Æ Œ Ôšã¸'Eþ*ûò÷»ô¦ñÐîWìWêäèèèçoè¦éƒëùíóðXô øíûÛÿ´Xª Ž ð¿ñ‚vÖ°%ò œ ?÷ÝŠÿoþÀý}ý¢ý'þüþH‘ÏéÈV‚@‡W´©EþœûÇøãõ óbðîìˆê›éOé¬é´êcì®î…ñÑôxøZüVLŸ Àctæ±ÔT>¢•3— Þ'+ÿcýüCûàúìú\û ü&ýVþ˜ÿÑëÌb›lÍÀHsþMüîùn÷çôxò=ðQîÐìÎë^ë‹ë\ìÏíßïòšõùâüÐǤD ‹[ŸEB20—|÷$ "‡þEümú ù&ø¼÷É÷?øù$úgû¾üþFÿEüZTå Ñþ=ýbûTù-÷õüò*ñ¬ï˜îîýíî¹ï~ñÒó§öçùzý@ì äÎ5(žbxìÎ5<ÿ Ÿ;ñáý"ûÊøêö‹õ³ô`ô‰ô$õö]÷ÏøWúÜûCýwþdÿùÿ+ùÿ`ÿgþý‹ûÎùú÷,ö|ôóäñ*ñìð5ñòyópõé÷ÒúþšAêv ó+[ôÚ—„èÛ{ æ= 0ýúB÷ñô&óéñ=ññƒñ]òšó!õÙö¨øsúü—ýÅþ›ÿÄÿ ÿþ¸üAûµù.øÆö˜õ¹ô@ô<ô¹ô½õG÷QùÎû¬þÔ-˜õ $€w֘ ” â 6üùäõ6ó ñvïzîîIîï9ðÐñ²óÄõé÷úüÂý7ÿNI*ªØÿÂþ~ý%üÏú—ù•øß÷‰÷£÷5øDùÏúÍü2ÿéÜñ É5.žsŸïª´Q ›µ¾ÿØû$øÀôÉñSïqí.ìŽëë,ìTíõîøðAó¶õ8ø¬úöüÿ´ídnaiAÿÃýžü«ûû²úËúUûTüÄýÿÐL÷· o P@¹¦÷£¦Åú ¸ <AÿHûu÷æóºð îìënê˜éméééë£ì½î3ñéóÂö ùeüöþ<$Ÿ§6SZf=ú´‡ÿˆþÍýiýgýÑý¨þèÿˆz«d · Ý»68®ŒÊhkß Ö h®ÊþÛú÷bóðCíøêJéFèñçLèNéëêí¤ïŒò«õàøüÿÝLRßî| 1 rd»TÜùÿhÿ8ÿnÿ kôôü î ° &:ÖêlW« r ¸‘eþ™ú×ö=óíïíêÍè¢ç(çaçJè×éúëî¥ñõônøðûZÿtóú } v å Ñ E S  “öTÇfH{d$;›/à–4 ¡ Ä † Õ ¡ ã — Á k£þúùö€ó?ðXíåêýèµçç/çøçné‚ë"î6ñ¢ôHøü»ÿFs ã Í &êÃî°  Q gx¡ø”…×ÿÿ®ÿ.'|íbÂñÙ d € " B ßÿ«ôòý¼úp÷-ôñ>îÎëÝéèÄç·ç[è®é¥ë1î=ñ¯ôhøHü.ù‰À ‡ Èu…øÐãBN # ݘnzÏÿ“þþüýLþõþèÿW¥Þë´$-Ã߃´õý+û<øDõbò´ïWígëúé%éóèmé“ê`ìÆîµñõÇø¯ü«šZÌ Ô[N MS»’è×w å >¡'ëÿzý^üµû|û®û>üý2þkÿ«Ûâ©.ÔÌ''þÜû]ùÃö+ô²ñvï‘íì0ëÙê$ëì¨í×ï“òÈõ[ù1ý'õ‰ ½vŸ(9Á©ÚRƒ ‹ ‰›ÝhþOü¢úlù°ønøœø-ùú2ûxüÊý ÿ) ›Î›üõÿ‹þÍüÍú¢øcö-ôòNðÙî×íZípí!îoïWñÌóÀöúÂý—|M ê 3 [syL«° y &Ö§¸ýûíø5÷ÿõNõõeõö÷eøÔùQûÂü þÿâÿIMêÿ!ÿûý†üÔúûø÷:õ‰óòñað>ð¨ð¥ñ5óQõí÷÷úWþð§Y æ .yKxöÁÚL%{f vÚRüüôùP÷%õ€óiòßñßñ]òJóôöË÷Šù<ûÉüþÿÆÿæÿ_ÿ}þMýãûSú¸ø*÷Åõ¡ôÖówó“ó4ô_õ÷Bùåûåþ*™ y ©†ó× ¿¬çubÀ¦1 ~¯æÿAüßøÝõPóJñ×ïüî¹îïÖïñµò•ô›ö­ø¯ú‡ü!þiÿQÔí¡úÿÿÒý{üûÀùø÷ÿöÈö÷À÷úø¯ú×ücÿ<MxŸ ¤gʶÎßAõ}s D[jÿûî÷£ôÇñqï¯íì ì*ìÝìîÁïÅñ ôpöÜø2ûYý9ÿÁåæÇGvh2ÿíý±ü™û¼ú/úúCúùú%üÂýÆÿ!¾†[ ! ¸ìT+bðÕ¸Ô } Ïèëþ÷ú.÷±óœðîì¦êîéßétê ëQíqïæñ”ô]÷#úÉü6ÿS^9ž•&a[*æ«ÿþªýýÒüüü”ýšþÓí?±' … ®†ôã@œ~Ô ° +asþ€ú«öóÜïíêêXéqè9è®èÇévë¦í?ð%ó9ö]ùrü\ÿþF!„iÑÂHtY²YXÿòþïþUÿ#TܪªÃÛ Õ •‹ƒä«Ü € ¥bÐ þ7úpöÚò”ï»ìiê±è¢çCç˜ç™è<êpìï(òuõãøSü¤ÿº}Öµ  ã 0 þ [ Y  ’ÿpþÀÉ*íÿ¢ÑTË / — ¬ YŒ8U ã ç k‚@Âý#ú…öóÊïíìŠê·èˆçç9çèªéÓëƒî¢ñõ³øfü}¦j ¶ { °Reó Á , f ‰²ùu;ZÜÿÄÿ¾¾ÿlîkÉî Ä 5 2 ¯ § —½œýMúïö¡ó‚ð³íOëné&è…ç“çTèÂéÒësîñ õÇø¥ü€:³Î u •bSfs R òêœzÿ¾þlþƒþûþÈÿÖg·êç™ëÐ=/§­O¡ý¸ú±÷¨ô¼ñ ïµìÒêxéºè¤è;éêhìèîíñ\õùýå•ò àIOÜÇÜ(¶ 1 ŸÆ²ôþ™ý¬ü/ü üwü&ýþAÿ½âÔк4:Ð×ýgûÊøöróñð¶îÙìuëêaêÉêØë‹íÙï°òüõ¢ùƒý~tA Æ å†“ÿÀÖD_1¨ß ö 8Oþ`üàúÕùDù'ùvù"úûDüŠýÔþ É4<Ú Õÿ?þYü6úí÷šõXóCñxïî í»ìïìÀí1ï:ñÐóàöSú þïÚª ? y>wý;ɯü ð ­sb”ý ûù‹÷~öòõäõGö÷"øoùÚúJü¥ýÓþ¿ÿX’fÓÿÛþŠýîûú(ø0öLôšò3ñ.ð¡ï›ï&ðFñûò<õú÷"ûœþI Æ R ’h»v‰ëššõ¼ì Œ zÎüçùh÷dõåóóòŒòªò?ó=ôŒõ÷½økúüoý™þpÿéÿûÿ¨ÿóþçý“ü ûeù¼÷)öÈô±óúò¶òóò¹ó õäö<ùü#ÿƒŽ ú )ý\,]á³ÒFiDÉ Q—ÿüÁøÞõtó’ñCðŠïfïÌï°ðþñŸózõs÷pùTû ýzþ”ÿMŸŠDÿ,þàüxû ú´øŒ÷¬ö'ööröU÷¸ø˜úéü™ÿ”¿ÿ3 <ýW3zXðäF*¬ éÿLû¿÷ôÏñ™ïùíøì•ìÎì—íàî“ð˜òÔô*÷~ùµû¶ýmÿǼEbuˆeÿ"þØü£û™úÒùcù[ùÄù¥úþûÇýõÿv4þ Ï k³Žå¤À1÷¢¥ ; €“–þ©úíö„ó‡ðî+ìêêPê^ê ëIìî+ðžòAõø÷£ú)ýpÿcòÂþÏAdNÔÿ£þšýÑüYüDü™ü_ý“þ.%dÖa è OyJªƒÆihć¿ ‚ éþ(úYöÐò©ïíèêsé©èèéKê ìDîàðÁóÉöÙùÓüœÿ7è ÜíXpK©`=Vÿ¾þƒþ®þDÿA REb’ · · uØÉ6Põ„ ‹-†³ýÕù ö}òCï|ì@ê¡è®çlçÛçôè¬êîì£ï±ò÷õXù³üêÿà~¯f ™ F q " i Y  9QàÿÒÿ*èkܵ % † Œ#:Ľ &  dZühýºùö“ò\ï‹ì9ê}ègççOçNèóé/ìíîò„õùÅüS­·Y €  /®¤ Í 7 x¬íT÷é6éÿ}TyÙ^îqÌ æ § þ Ú 2  N|€BýÜùoöóùï0íØê éÙçRç}çYèâé ì¿îéñlõ*ùýÏvÖÔ Z W¾ŒÁd„2„ •  _OiÃp}ÿñþÎþÿ±ÿŸÉvÇñÞwªj®užIýCú%÷ ôñkîìGêé\èaèévê{ìï,òªõqù_ýS,Ê á+Þñ`0j`Ió | j~ìþÀýý±üÌüGýþÿQ”ÎåÁO|=‹dÍÒÿýïú5øoõ»ò5ðüí*ì×êêôézê¨ë{íåïÖò7öìùÖýÔň ü ‹|Élf¼{µø 9 `ŒÚb=þzü&ûHúàùèùWúû$üWýþÜÿûä‚Å¡¯ÿîýàûœù9÷Òô†òoð©îNísì(ìyìkíýî'ñÜó÷‘ú\þH6 ·g†Õöj:u/ƒ‹ f 4!xý+ûMùê÷÷ ö²ö1÷ ø,ù|úáûBý…þ”ÿZÉÕxµÿþýQû_ùT÷Lõbó±ñTð`ïëîï®ïòðËò/õøTûåþ¤s/ ¸ î´ò”ÓgN”KŠl  •Âÿ¦üáùˆ÷«õUôˆóBó}ó)ô6õ‹öø°ùJûÇüþÿ»ÿæÿcÿþLýÔû0úvøÁö,õÑóÈò'òÿñ]òHóÀôÁö?ù(üfÿÞt v ¡lºuö¬° Î Û ] °ôLÿÔû«øéõ¢óåñºð#ðð›ð‘ñêòôböLø1ú÷û†ýÌþ¹ÿAc}ÿˆþPýíûtúù«÷ŽöÁõWõ`õèõóö€ø‰úýÖÿï3„ à ЋۥÖ_9aÞ¹Ú R ‹§Èþ û—÷€ôáñÍïOîní*í}í[î²ïkñoó õä÷ú4üþ™ÿÅ‹åÕdž–ÿ_þýÆû—úùïøŸø»øNù[úßûÔý)Ϭ¦  zY'je o ô .<Bþ^ú³ö^ó{ðî\ì:ë¿êèê«ëûìÃîìðZóðõ‘ø!û…ý¤ÿkÎÁCVVb>Âþžýªüþûªû½û?ü2ý•þ\{ßo ¦ =UAƤᅢ M ¢¾ÄýÒù ö‘òïîìóê›éîèîè–éÙê§ìêî†ñ`ôZ÷Tú1ý×ÿ,!¥²Eaci:ï¡jbÿœþ+þþuþ;ÿgòÌâ` ‘ •N¥ƒÖ’±3€ ió8Yýuù®õ&òúîGì"êŸèÇç¡ç*è[é%ëuí0ð=ó|öÍùý*ÿw€    © ? r UŒ°xƒáÿÿ¿ÿG4z Ï´ž s  oeäÝF^  U,´ ýPù£õ%òõî2ìôéPèTç çsç‹èFê”ì_ïŠòùõŒù"ýšØÁ? @ ¸ £ Ù 8 / Ô ? ŠÐ,´ýÿEïð9¶Pîu Ê × ƒ ¾ x « U xZ>åükùðõ”òvïµìlê²è™ç-çsçlèêLìïHòÑõù\ý¬òÑ 5 Rþ ¬Ož ´ ¬¡¯íqKˆÿ+ÿ7ÿ¦ÿl{¾„ÔõÏN ` û³ÕˆßÿìüÌùšöuó}ðÑí‹ëÆé–è è+èýèzê™ìIïsòþõÊù¸ý¤où$ Ù•‡Ø²W‘z . Çd Qíþïý_ý;ý~ýþÿ$c©Üä© ¸Ú†Ãžÿ&ýtú ÷ÇôòïKí…ëDêšé”é7ê„ëuíûïóxö;ú,þ*É * …X† ê)ÖËE ‘ Ë.3þœüuûÃú„ú±ú?ûü2ýlþ¯ÿáí¹4Oÿ@‚ÿ–ýcûÿø„ö ô·ñ ïâí–ìÐë ëì"íÕîññó6÷Ôú­þ¡V Ô ì…ŠëŸ¤ÿ¹ä•æó Û½·çÿbý>û‹ùRø–÷V÷‰÷"øù9úŠûçü7þaÿOï2ƒÿ=þ—ü±ú¡øökô|òÎð|ïœî?îtîBï©ð¦ò,õ*øŠû1ÿÿÖ” Aö§ƒ®'ö(Ðè ‘ $¾€ÿ„üäù²÷ýõÎô&ôôYôõ4ö÷ù¢ú'ü‡ý¬þƒÿÊÿÿ þ¬üûTùˆ÷Éõ3ôàòæñ\ñRñÑñáò€ô§öIùSü­ÿ;á| í Ñ ²±þ™ƒÇu¤m î F˜ÿ¦ûœøüõÚóCò<ñÆðÝðtñzòÛóõK÷$ùðú•üþýÿÖÿ. ¯ÿâþÇýqü÷úqùø÷§ö—õÞôôºôgõšöQø‚ú ýM¨ O ]T %”R_À„½ƒ ó +MzþÓúu÷|ôýñ ð°îðíÊí7î(ï‹ðIòIônöžø»ú®ü`þ¿ÿ¼R}BªÃÿ þWýüµúù¨øøã÷$øàøúÉûçýd-'7 ? ¼öµäsWW0 § Øåïýú~öAóyð<î˜ì—ë:ë}ëVì¶í‡ï±ñôŸö*ùœûÛýÒÿm¡g¼§/f],ëþ²ýœü¿û1ûû>ûìûýþ×]¿ b Õú·ö¢°Õòy|  Wjmý€ùÅõ[ò^ïèì ëÏé@é\éêrëMí•ï1òõê÷ÌúŠý 9[<¥.g](Þ›xÿ‹þçýžý»ýDþ9ÿ“JK‚Ö, h m i2kg1s A´èÿüùTõÖñºîìê¨èíçãç†èÍé©ëîÄðÍó÷AúlýghH«Ž ð Ù T tLõˆ Ô¼îÿvÿaÿ³ÿl†÷¬† a P4šv½nŒ " ?øi¯üèø7õ¼ñ—îãëºé.èMçç£çÔè¤êí×ïóröùù}ýÝýÄ õ G J  O 8 × D›öm Xg‘ý•Cët à Á V t  œ ˜2øÿ†üúøtõòúîDì êfèfççwçŠèEê˜ìnï®ò:öóù·ýdÞÄ  ºÚe_ÒÍf ´ Ð Øåv%-šÿnÿ¨ÿA-[¶&‘Þò¹   ‚ uçàlžÿüSùöáòæï>íëQé7èÅçèðè‰êÂì‡ïÁòVö&úþó­ 0 ÆÏ@Eàñˆ½¨ f ʧÁ+õþ&þÄýÌý7þ÷þûÿ,v¼çÞŠÙ¼+  ±cÿÈüöù ÷!ôXñÏî¡ìéê¼é*é@éêmëzíð:ó¿öŒú‚þ}^ P 'u(7Ÿc‹'JŽ ç 6™)0þÆüÌûFû0ûû,üýCþÿ¿åÚ‰àÑTg Nÿ:ýãúaøÏõJóîðØî$íèë9ë$ë±ëäì·î ñôk÷ûÿùæ¤ ˜Å\Fˆ.KôDX OH_±ÿSýYûÑùÃø0øøgøùúIû™üìý*ÿ8}”B†dÿäýüúã÷®õóšñòï­îáížíòíáîkð‹ò2õMøÆû€ÿ[9õ q.>¬m{Ú’±M~_  ³dCÿiüîùå÷YöQõÎôËô<õö7÷•øú”ûýBþBÿïÿ<$¦ÿÅþ‹ýüNúwøšöÔô?óõñ ñ›ð®ðPñ…òJô–öZùƒüøÿšMï ^}-VãÇùxIv6ù { Ý>Àþ~û•øöô«òÈñtñ§ñTòióÑôsö5øûù¬û/ýpþ^ÿìÿÖÿ7ÿ@þýûúnøòö§õ¥ôôÐóôðôKö*øƒúFý\­‹ Ø ãÄgh½^O—El& Éó0þžú[÷€ô$òUðï}îuîúîýïkñ+ó%õ=÷VùVû$ý¬þÝÿ«¨êÿãþ§ýNüðú§ùŒø¸÷>÷/÷—÷|øßùºûþ¤Ž£Ç Û ÁZŠ9RǨä$ë U €ŸýÕùPö,ó‚ðdîáìÿëÀëì ízîRð{òÙôO÷Áùü-þùÿfl.ðVqUÿÖý¥üŸûÚúkúbúÇú¢ûñü­þÊ7Ý£l ¯`Œ!ZúùdO Ò ý1ùƒõ,òHïìì+ëêžéÕé¬êìûíHðßò¥õzøBûßý:>Û½þÑDgOΘÿŠþ¹ý9ýýcýþ?ÿǧÎ$ ÷ ;?ê#ÖôsQ9] p–¥ü¼øÿôñƒîüë ê¿è!è2èîèJê6ì™î\ñaôˆ÷³úÄý)Q@ú8  cq@é….ü_ÿÿ,ÿ¯ÿ—ßyQSe k K è*úG)¶° # !¿Qü‚øÏôZñ@îžë‹éèTçAçàç)é ëzíWð‡óìögúÖý¾ï¡ Ì m ‰ * _ ; ÖH­³ƒ¡øÿ:âå7Äv5ç p ¶ £ !!— € Û ° ®ÿ&üŠøûôšñ…îÛë´é&è?ç çˆçµè‡êîìÒïó§öYúþ© ¯ Ë [XŸûç w Æ ë,zß³ÿ·ÿâó>¯,›ãë › ã ²  ËãHYÿ*üÚø‡õPòUï´ì‡êçèäççççñè¥êõìÍïó³ö„úiþ>æ@ 4 ©‘ߦ)'²ã Ó ^33u ÿeþ2þeþöþ×ÿó6ˆÎïÓd’P”^±˜#ÿeüwùuö}ó®ð&îìWê?éÇèøèØéaëŠíCðwó ÷áúÙþÏ¥8 m )XìÜ'ÐâoŠNÕ = £$ÙÙÿ4þøü,üÒûãûWüý%þUÿ•ÎäÂR„K¢†þÿÙü_úÂ÷õ‰ò)ðînìEë­ê³ê`ë²ì¥î,ñ4ô¦÷fûUÿQ9ì K: m“ Û™©Lž ¼ ÄÕ ÿLý}û!ú=ùÓøÜøLùú"û[ü©ýðþ ´îm1ÿ†ý’ûhù#÷Ýô²ò¾ðïçí0íí{í‹î8ðyò@õwøüÒÿ¸˜Q ÃÏ[R¥I<#2ÂîÓ D ÿUüú!ø¾öÞõ€õœõ'ö÷>øžùû„üÙýùþÒÿRq){ÿlþý_ûˆù™÷¯õãóPòñ=ðäïðÚð3òôösùºüEú¸^ ÊÞ~’ÑçK¨Á€  sæþ]û•ø?öiôó_ò+òzò<ó_ôÌõj÷ ùÑúeüÅýÜþœÿúÿòÿ…ÿ¸þšý9ü¬ú ùm÷ðõ­ô»ó/óóŠóƒôö øŒúqý¦’ [c)¶ŸØ^3cûà ) g›êýoúH÷ŽôUò©ð”ïï*ïÆïÚðPòôö ø úìû•ýòþõÿ’Ș$ÿÿý¬üEûáùœøŽ÷Ïöqö„ö÷!ø®ù´û#þêò U t \ð²´º¶½çž þ%6Rý˜ù*ö!ó•ð˜î6ítìRìÈìÊíEï#ñIóœõÿ÷Uú†üxþX/™—3xyLÿþÃüšû¦úûù­ùÊùYúaûÜüÄþ ›`>  ÍC]“h’õF ‹¸¿ÄüæøHõò;ïüìZë]ê êZêGëÀì°îÿð‘óIö ù´û0þc<¬«5NÿUb=þ¿ÿ—þŸýíü’üœüýúýLÿ TÈJ ¿  ¬ÔprÒ­7@ Ü(BKüeø¯ôLñVîçëêâèaèèbéÒêËì7ïùñöôø$ûþÎ31¼Ë]w!ki1Û‚>(VÿÖþ·þÿ²ÿÉ>ÿú< N 0Çû·é†ŠóÊ  üÊÿóûølôþðóídëiéèhçqç*è‰é€ëùíÜð ôh÷Óú,þT2¯¹C G Ä À G h : ÒK¿Hýó<åÿòÿe;iáX' ß f £ }âÃÚ  ¾øÐ`ÿÃûø…ô%ñî|ëiéòç&ç ç¥çìèÕêMí=ðŠó÷¿úfþê. ‡ ò ËÖú „ Ô 2uå™ Õÿœ‰½$©1£ä Ü w   M u  6ÞÿÅûaøõÄñËî2ìêˆèžçbçØçþèËê2íðqó÷äúÀþ†Y . ‚GsýhTÖ ú Ó¬žÃ/ôÿÿ¬þ¦þÿ»ÿºïB™ÜñÁ7DÚõ“»yÞþÿûöøàõÜò ð„íiëÐéÎèpè¾è»éaë¥íuð¼ó\÷9û0ÿæf !1¤u¢20¯Ãˆ  ’³¸ÿ@þ3ý”üeüžü4ýþ/ÿhªÚठ½çèÕþsüÙù"÷iôÍñkï^íÂë¬ê,êOêëŒìî@ñaôç÷´ûªÿ¦ˆ/ {RLT±exúÿžô  9d»WÿLý©ûyúÀù~ùªù8úû1üoý¸þòÿÙ^ƒ@‘vøþ#ý ûÁødöôÛñéïPî*íŠì~ìíAîðròVõ¨øLü%õ¨ }Z‘ð©©0ZE Ö»ÙþHüúfø,÷tö:övö÷øIù¨úürý¬þ«ÿ[¯Ÿ'Iÿ þü´úÀø¼öÅôõòhñ6ðuï7ïˆïoðìñúóö“ùõü–[!È /7ÆÄÍȱ¶4E  ‘FþBûžønöÀôšóóíòUó+ôZõÊöcø ú¥ûýUþBÿÓÿÉÿ,ÿ4þîümûÇùøoöóô¸óØòeòoòó ôÊõø÷œú£ýôu‡ ÙÛq‚úÈæP #¨²Z ÀE§ýFú>÷¦ôò ñð¹ïéï›ð¾ñ<óýôåöÚøÀúüþ1ÿryaÿZþý°û<úÕø–÷–öíõ¬õáõ—öÏ÷†ùµûKþ4Yâ ñ~• JٸK £Éßýaù öó²ð×î–íôìïì~í’îðùñô`ö­øçúôü¾þ1Cê&úo”~ÿ?þóü±û”ú³ù#ù÷ø:ùôù(ûÐüâþOåØ ¿ |ñ”—ù±½!æÝ @cirü øõèñ8ïí”ë¶êêêêìëtílï¼ñFôïö—ù$ü{þ…2tF¥—%`Z*êÿ±þšýºü(üóû'üËüàý`ÿ@qÝl ƒ ÑÏdzþä%ÁÀ, ¡Üíÿóûøfôñ3îÝë$êé®èõèáédëiíÚï›òŽõ•ø’ûgþù5 hM·­:n^ ÎS[ÿ«þTþbþÚþ½ÿ¢Š¦Ü - ŸÃi€þß&Û Ñ?vÿ•û¼÷ôªð®í5ëRéèˆç­çèôéüë€îgñ“ôå÷>û~þ‡B™zÛ ·  î \ l 4ÌMÓuKißÿµÿóÿ–šóY9 Ô W ˆOš\Œ* 9 ÅÜ—ÿ`û¬÷ô¶ð´í'ë)éËçççÐç/é-ë´í¯ðÿó‡÷&û»þ&Lh 9 } 3]5  Œ áaÁV3hýÿ_!5Š £5§ à Ç I U Þ à Y PÒïÀþ_ûè÷}ô=ñGî¹ë¬é6èeçDçÖçéýêyísðÒóx÷DûÿËFj  PñûlIzó ! û Xïãÿ:ÿûþ"ÿªÿ…¢íM©çï© ì[L¿½S”þ–ûtøMõ?òiïéìÛêTéiè%èèªélëÊí°ðô²÷’û†ÿk"Œ þQ‰tç÷¿ [ èƒFHÿTþuýýý_ýþÿ:}¾ä×Ï´&#­Ìþ üQù‚ö¹óñ²î®ì ëê·é÷éáêrì¡î^ñ–ô-øüúÓj ¢_Ž IâàRNëG ~ ¯÷p4ÿSýÝûÚúLú1úú)ûüBýƒþÆÿïë¡û‹¬c¸þºü}úø¥õAó ñïŒíwìîëþë¯ìîòïsòtõÞø•üznNù P6”VpÛ—¬%—Á ³ Œjl­þCüAú´ø¥÷÷ýöW÷øùWú³ûý^þ{ÿVÞÆÿ¨ýóûúö÷àõßó ò†ðcï·î”îïð°ñâó–öºù5ý꼈. ‡é*¼›ÊTG¹Ãƒ ¡@þ.û°ø§ö õ"ô«ó·ó9ô õYöË÷]ùôúvüËýßþ¡ÿ˜ÿÍþªý?üŸúáø÷tõúóËòýñ£ñÍñƒòÇó˜õì÷´úÚýEÚy QLÓÑ0åæ5×ÙLJí T ñiý$ú;÷ÇôÖòtñ¤ðfð±ðxñ©ò,ôêõÇ÷§ùqû ýfþjÿ K!—ÿµþ‹ý-ü³ú4ùÌ÷”ö¤õõïôIõ%ö†÷gù¾ûyþ‚Âm ™€ Sxê®ËRVò DkŠÁü/ùóõ%óÚð!ïî€í—í=îaïñðÓòîô$÷Zùvû^ýýþC&ž¬U¥­ÿþ2ýàû¢ú’ùÆøSøIø³ø˜ù÷úËüÿ™nkr e &—œ RîÜ#Ííš ð $ü_øæôÔñ@ï?íÛëëë†ëœì1î/ð}òýô”÷#úüÀþ  5Ù ØFfOÖþ¦ý üÛûiû[ûºûŒüÎý{ÿ…Üi º D”ŒJlèÈí `Ž—ÿûÀ÷#ôâðîßëCêOééiélêÿëî„ðAó(öùýû±þ0Ø Æ ÝMlO Á‚lÿ‘þþÚýþ½þÏÿB S  æ èn‚ j)Nâ ö Ÿø!ÿ7û]÷µó]ðtíëHé'è¶çöçáèkê‚ìï÷ñõcø§ûÌþµKz1i  T  j j+ÄP馟æÿ‡ÿŽÿüÿÏ@&  Ä BeGé÷p Z ºY»þýú@÷¦óNðXíÝêõè°çç8çè~éë%î'ñyôú÷‹û ÿ]d6 à ÿ ‘ › ( H ‘ ì9“ÌÔ7-¾«æ[ö6 ¦ Õ «  f @ ’ b¾ºoþöúp÷üó»ðÌíJëOéïç8ç3çáç<é:ëÉíÑð8ôß÷¥ûjÿ ms  ‘xɋʘ ; D @Ló·ÙÿaÿQÿ¥ÿUTŽíX·ïçŠ Æ Œ Ôšã¸'Eþ*ûò÷»ô¦ñÐîWìWêäèèèçoè¦éƒëùíóðXô øíûÛÿ´Xª Ž ð¿ñ‚vÖ°%ò œ ?÷ÝŠÿoþÀý}ý¢ý'þüþH‘ÏéÈV‚@‡W´©EþœûÇøãõ óbðîìˆê›éOé¬é´êcì®î…ñÑôxøZüVLŸ Àctæ±ÔT>¢•3— Þ'+ÿcýüCûàúìú\û ü&ýVþ˜ÿÑëÌb›lÍÀHsþMüîùn÷çôxò=ðQîÐìÎë^ë‹ë\ìÏíßïòšõùâüÐǤD ‹[ŸEB20—|÷$ "‡þEümú ù&ø¼÷É÷?øù$úgû¾üþFÿEüZTå Ñþ=ýbûTù-÷õüò*ñ¬ï˜îîýíî¹ï~ñÒó§öçùzý@ì äÎ5(žbxìÎ5<ÿ Ÿ;ñáý"ûÊøêö‹õ³ô`ô‰ô$õö]÷ÏøWúÜûCýwþdÿùÿ+ùÿ`ÿgþý‹ûÎùú÷,ö|ôóäñ*ñìð5ñòyópõé÷ÒúþšAêv ó+[ôÚ—„èÛ{ æ= 0ýúB÷ñô&óéñ=ññƒñ]òšó!õÙö¨øsúü—ýÅþ›ÿÄÿ ÿþ¸üAûµù.øÆö˜õ¹ô@ô<ô¹ô½õG÷QùÎû¬þÔ-˜õ $€w֘ ” â 6üùäõ6ó ñvïzîîIîï9ðÐñ²óÄõé÷úüÂý7ÿNI*ªØÿÂþ~ý%üÏú—ù•øß÷‰÷£÷5øDùÏúÍü2ÿéÜñ É5.žsŸïª´Q ›µ¾ÿØû$øÀôÉñSïqí.ìŽëë,ìTíõîøðAó¶õ8ø¬úöüÿ´ídnaiAÿÃýžü«ûû²úËúUûTüÄýÿÐL÷· o P@¹¦÷£¦Åú ¸ <AÿHûu÷æóºð îìënê˜éméééë£ì½î3ñéóÂö ùeüöþ<$Ÿ§6SZf=ú´‡ÿˆþÍýiýgýÑý¨þèÿˆz«d · Ý»68®ŒÊhkß Ö h®ÊþÛú÷bóðCíøêJéFèñçLèNéëêí¤ïŒò«õàøüÿÝLRßî| 1 rd»TÜùÿhÿ8ÿnÿ kôôü î ° &:ÖêlW« r ¸‘eþ™ú×ö=óíïíêÍè¢ç(çaçJè×éúëî¥ñõônøðûZÿtóú } v å Ñ E S  “öTÇfH{d$;›/à–4 ¡ Ä † Õ ¡ ã — Á k£þúùö€ó?ðXíåêýèµçç/çøçné‚ë"î6ñ¢ôHøü»ÿFs ã Í &êÃî°  Q gx¡ø”…×ÿÿ®ÿ.'|íbÂñÙ d € " B ßÿ«ôòý¼úp÷-ôñ>îÎëÝéèÄç·ç[è®é¥ë1î=ñ¯ôhøHü.ù‰À ‡ Èu…øÐãBN # ݘnzÏÿ“þþüýLþõþèÿW¥Þë´$-Ã߃´õý+û<øDõbò´ïWígëúé%éóèmé“ê`ìÆîµñõÇø¯ü«šZÌ Ô[N MS»’è×w å >¡'ëÿzý^üµû|û®û>üý2þkÿ«Ûâ©.ÔÌ''þÜû]ùÃö+ô²ñvï‘íì0ëÙê$ëì¨í×ï“òÈõ[ù1ý'õ‰ ½vŸ(9Á©ÚRƒ ‹ ‰›ÝhþOü¢úlù°ønøœø-ùú2ûxüÊý ÿ) ›Î›üõÿ‹þÍüÍú¢øcö-ôòNðÙî×íZípí!îoïWñÌóÀöúÂý—|M ê 3 [syL«° y &Ö§¸ýûíø5÷ÿõNõõeõö÷eøÔùQûÂü þÿâÿIMêÿ!ÿûý†üÔúûø÷:õ‰óòñað>ð¨ð¥ñ5óQõí÷÷úWþð§Y æ .yKxöÁÚL%{f vÚRüüôùP÷%õóiòßñßñ]òJóôöË÷Šù<ûÉüþÿÆÿæÿ_ÿ}þMýãûSú¸ø*÷Åõ¡ôÖówó“ó4ô_õ÷Bùåûåþ*™ y ©†ó× ¿¬çubÀ¦1 ~¯æÿAüßøÝõPóJñ×ïüî¹îïÖïñµò•ô›ö­ø¯ú‡ü!þiÿQÔí¡úÿÿÒý{üûÀùø÷ÿöÈö÷À÷úø¯ú×ücÿ<MxŸ ¤gʶÎßAõ}s D[jÿûî÷£ôÇñqï¯íì ì*ìÝìîÁïÅñ ôpöÜø2ûYý9ÿÁåæÇGvh2ÿíý±ü™û¼ú/úúCúùú%üÂýÆÿ!¾†[ ! ¸ìT+bðÕ¸Ô } Ïèëþ÷ú.÷±óœðîì¦êîéßétê ëQíqïæñ”ô]÷#úÉü6ÿS^9ž•&a[*æ«ÿþªýýÒüüü”ýšþÓí?±' … ®†ôã@œ~Ô ° +asþ€ú«öóÜïíêêXéqè9è®èÇévë¦í?ð%ó9ö]ùrü\ÿþF!„iÑÂHtY²YXÿòþïþUÿ#TܪªÃÛ Õ •‹ƒä«Ü € ¥bÐ þ7úpöÚò”ï»ìiê±è¢çCç˜ç™è<êpìï(òuõãøSü¤ÿº}Öµ  ã 0 þ [ Y  ’ÿpþÀÉ*íÿ¢ÑTË / — ¬ YŒ8U ã ç k‚@Âý#ú…öóÊïíìŠê·èˆçç9çèªéÓëƒî¢ñõ³øfü}¦j ¶ { °Reó Á , f ‰²ùu;ZÜÿÄÿ¾¾ÿlîkÉî Ä 5 2 ¯ § —½œýMúïö¡ó‚ð³íOëné&è…ç“çTèÂéÒësîñ õÇø¥ü€:³Î u •bSfs R òêœzÿ¾þlþƒþûþÈÿÖg·êç™ëÐ=/§­O¡ý¸ú±÷¨ô¼ñ ïµìÒêxéºè¤è;éêhìèîíñ\õùýå•ò àIOÜÇÜ(¶ 1 ŸÆ²ôþ™ý¬ü/ü üwü&ýþAÿ½âÔк4:Ð×ýgûÊøöróñð¶îÙìuëêaêÉêØë‹íÙï°òüõ¢ùƒý~tA Æ å†“ÿÀÖD_1¨ß ö 8Oþ`üàúÕùDù'ùvù"úûDüŠýÔþ É4<Ú Õÿ?þYü6úí÷šõXóCñxïî í»ìïìÀí1ï:ñÐóàöSú þïÚª ? y>wý;ɯü ð ­sb”ý ûù‹÷~öòõäõGö÷"øoùÚúJü¥ýÓþ¿ÿX’fÓÿÛþŠýîûú(ø0öLôšò3ñ.ð¡ï›ï&ðFñûò<õú÷"ûœþI Æ R ’h»v‰ëššõ¼ì Œ zÎüçùh÷dõåóóòŒòªò?ó=ôŒõ÷½økúüoý™þpÿéÿûÿ¨ÿóþçý“ü ûeù¼÷)öÈô±óúò¶òóò¹ó õäö<ùü#ÿƒŽ ú )ý\,]á³ÒFiDÉ Q—ÿüÁøÞõtó’ñCðŠïfïÌï°ðþñŸózõs÷pùTû ýzþ”ÿMŸŠDÿ,þàüxû ú´øŒ÷¬ö'ööröU÷¸ø˜úéü™ÿ”¿ÿ3 <ýW3zXðäF*¬ éÿLû¿÷ôÏñ™ïùíøì•ìÎì—íàî“ð˜òÔô*÷~ùµû¶ýmÿǼEbuˆeÿ"þØü£û™úÒùcù[ùÄù¥úþûÇýõÿv4þ Ï k³Žå¤À1÷¢¥ ; €“–þ©úíö„ó‡ðî+ìêêPê^ê ëIìî+ðžòAõø÷£ú)ýpÿcòÂþÏAdNÔÿ£þšýÑüYüDü™ü_ý“þ.%dÖa è OyJªƒÆihć¿ ‚ éþ(úYöÐò©ïíèêsé©èèéKê ìDîàðÁóÉöÙùÓüœÿ7è ÜíXpK©`=Vÿ¾þƒþ®þDÿA REb’ · · uØÉ6Põ„ ‹-†³ýÕù ö}òCï|ì@ê¡è®çlçÛçôè¬êîì£ï±ò÷õXù³üêÿà~¯f ™ F q " i Y  9QàÿÒÿ*èkܵ % † Œ#:Ľ &  dZühýºùö“ò\ï‹ì9ê}ègççOçNèóé/ìíîò„õùÅüS­·Y €  /®¤ Í 7 x¬íT÷é6éÿ}TyÙ^îqÌ æ § þ Ú 2  N|€BýÜùoöóùï0íØê éÙçRç}çYèâé ì¿îéñlõ*ùýÏvÖÔ Z W¾ŒÁd„2„ •  _OiÃp}ÿñþÎþÿ±ÿŸÉvÇñÞwªj®užIýCú%÷ ôñkîìGêé\èaèévê{ìï,òªõqù_ýS,Ê á+Þñ`0j`Ió | j~ìþÀýý±üÌüGýþÿQ”ÎåÁO|=‹dÍÒÿýïú5øoõ»ò5ðüí*ì×êêôézê¨ë{íåïÖò7öìùÖýÔň ü ‹|Élf¼{µø 9 `ŒÚb=þzü&ûHúàùèùWúû$üWýþÜÿûä‚Å¡¯ÿîýàûœù9÷Òô†òoð©îNísì(ìyìkíýî'ñÜó÷‘ú\þH6 ·g†Õöj:u/ƒ‹ f 4!xý+ûMùê÷÷ ö²ö1÷ ø,ù|úáûBý…þ”ÿZÉÕxµÿþýQû_ùT÷Lõbó±ñTð`ïëîï®ïòðËò/õøTûåþ¤s/ ¸ î´ò”ÓgN”KŠl  •Âÿ¦üáùˆ÷«õUôˆóBó}ó)ô6õ‹öø°ùJûÇüþÿ»ÿæÿcÿþLýÔû0úvøÁö,õÑóÈò'òÿñ]òHóÀôÁö?ù(üfÿÞt v ¡lºuö¬° Î Û ] °ôLÿÔû«øéõ¢óåñºð#ðð›ð‘ñêòôböLø1ú÷û†ýÌþ¹ÿAc}ÿˆþPýíûtúù«÷ŽöÁõWõ`õèõóö€ø‰úýÖÿï3„ à ЋۥÖ_9aÞ¹Ú R ‹§Èþ û—÷€ôáñÍïOîní*í}í[î²ïkñoó õä÷ú4üþ™ÿÅ‹åÕdž–ÿ_þýÆû—úùïøŸø»øNù[úßûÔý)Ϭ¦  zY'je o ô .<Bþ^ú³ö^ó{ðî\ì:ë¿êèê«ëûìÃîìðZóðõ‘ø!û…ý¤ÿkÎÁCVVb>Âþžýªüþûªû½û?ü2ý•þ\{ßo ¦ =UAƤᅢ M ¢¾ÄýÒù ö‘òïîìóê›éîèîè–éÙê§ìêî†ñ`ôZ÷Tú1ý×ÿ,!¥²Eaci:ï¡jbÿœþ+þþuþ;ÿgòÌâ` ‘ •N¥ƒÖ’±3€ ió8Yýuù®õ&òúîGì"êŸèÇç¡ç*è[é%ëuí0ð=ó|öÍùý*ÿw€    © ? r UŒ°xƒáÿÿ¿ÿG4z Ï´ž s  oeäÝF^  U,´ ýPù£õ%òõî2ìôéPèTç çsç‹èFê”ì_ïŠòùõŒù"ýšØÁ? @ ¸ £ Ù 8 / Ô ? ŠÐ,´ýÿEïð9¶Pîu Ê × ƒ ¾ x « U xZ>åükùðõ”òvïµìlê²è™ç-çsçlèêLìïHòÑõù\ý¬òÑ 5 Rþ ¬Ož ´ ¬¡¯íqKˆÿ+ÿ7ÿ¦ÿl{¾„ÔõÏN ` û³ÕˆßÿìüÌùšöuó}ðÑí‹ëÆé–è è+èýèzê™ìIïsòþõÊù¸ý¤où$ Ù•‡Ø²W‘z . Çd Qíþïý_ý;ý~ýþÿ$c©Üä© ¸Ú†Ãžÿ&ýtú ÷ÇôòïKí…ëDêšé”é7ê„ëuíûïóxö;ú,þ*É * …X† ê)ÖËE ‘ Ë.3þœüuûÃú„ú±ú?ûü2ýlþ¯ÿáí¹4Oÿ@‚ÿ–ýcûÿø„ö ô·ñ ïâí–ìÐë ëì"íÕîññó6÷Ôú­þ¡V Ô ì…ŠëŸ¤ÿ¹ä•æó Û½·çÿbý>û‹ùRø–÷V÷‰÷"øù9úŠûçü7þaÿOï2ƒÿ=þ—ü±ú¡øökô|òÎð|ïœî?îtîBï©ð¦ò,õ*øŠû1ÿÿÖ” Aö§ƒ®'ö(Ðè ‘ $¾€ÿ„üäù²÷ýõÎô&ôôYôõ4ö÷ù¢ú'ü‡ý¬þƒÿÊÿÿ þ¬üûTùˆ÷Éõ3ôàòæñ\ñRñÑñáò€ô§öIùSü­ÿ;á| í Ñ ²±þ™ƒÇu¤m î F˜ÿ¦ûœøüõÚóCò<ñÆðÝðtñzòÛóõK÷$ùðú•üþýÿÖÿ. ¯ÿâþÇýqü÷úqùø÷§ö—õÞôôºôgõšöQø‚ú ýM¨ O ]T %”R_À„½ƒ ó +MzþÓúu÷|ôýñ ð°îðíÊí7î(ï‹ðIòIônöžø»ú®ü`þ¿ÿ¼R}BªÃÿ þWýüµúù¨øøã÷$øàøúÉûçýd-'7 ? ¼öµäsWW0 § Øåïýú~öAóyð<î˜ì—ë:ë}ëVì¶í‡ï±ñôŸö*ùœûÛýÒÿm¡g¼§/f],ëþ²ýœü¿û1ûû>ûìûýþ×]¿ b Õú·ö¢°Õòy|  Wjmý€ùÅõ[ò^ïèì ëÏé@é\éêrëMí•ï1òõê÷ÌúŠý 9[<¥.g](Þ›xÿ‹þçýžý»ýDþ9ÿ“JK‚Ö, h m i2kg1s A´èÿüùTõÖñºîìê¨èíçãç†èÍé©ëîÄðÍó÷AúlýghH«Ž ð Ù T tLõˆ Ô¼îÿvÿaÿ³ÿl†÷¬† a P4šv½nŒ " ?øi¯üèø7õ¼ñ—îãëºé.èMçç£çÔè¤êí×ïóröùù}ýÝýÄ õ G J  O 8 × D›öm Xg‘ý•Cët à Á V t  œ ˜2øÿ†üúøtõòúîDì êfèfççwçŠèEê˜ìnï®ò:öóù·ýdÞÄ  ºÚe_ÒÍf ´ Ð Øåv%-šÿnÿ¨ÿA-[¶&‘Þò¹   ‚ uçàlžÿüSùöáòæï>íëQé7èÅçèðè‰êÂì‡ïÁòVö&úþó­ 0 ÆÏ@Eàñˆ½¨ f ʧÁ+õþ&þÄýÌý7þ÷þûÿ,v¼çÞŠÙ¼+  ±cÿÈüöù ÷!ôXñÏî¡ìéê¼é*é@éêmëzíð:ó¿öŒú‚þ}^ P 'u(7Ÿc‹'JŽ ç 6™)0þÆüÌûFû0ûû,üýCþÿ¿åÚ‰àÑTg Nÿ:ýãúaøÏõJóîðØî$íèë9ë$ë±ëäì·î ñôk÷ûÿùæ¤ ˜Å\Fˆ.KôDX OH_±ÿSýYûÑùÃø0øøgøùúIû™üìý*ÿ8}”B†dÿäýüúã÷®õóšñòï­îáížíòíáîkð‹ò2õMøÆû€ÿ[9õ q.>¬m{Ú’±M~_  ³dCÿiüîùå÷YöQõÎôËô<õö7÷•øú”ûýBþBÿïÿ<$¦ÿÅþ‹ýüNúwøšöÔô?óõñ ñ›ð®ðPñ…òJô–öZùƒüøÿšMï ^}-VãÇùxIv6ù { Ý>Àþ~û•øöô«òÈñtñ§ñTòióÑôsö5øûù¬û/ýpþ^ÿìÿÖÿ7ÿ@þýûúnøòö§õ¥ôôÐóôðôKö*øƒúFý\­‹ Ø ãÄgh½^O—El& Éó0þžú[÷€ô$òUðï}îuîúîýïkñ+ó%õ=÷VùVû$ý¬þÝÿ«¨êÿãþ§ýNüðú§ùŒø¸÷>÷/÷—÷|øßùºûþ¤Ž£Ç Û ÁZŠ9RǨä$ë U €ŸýÕùPö,ó‚ðdîáìÿëÀëì ízîRð{òÙôO÷Áùü-þùÿfl.ðVqUÿÖý¥üŸûÚúkúbúÇú¢ûñü­þÊ7Ý£l ¯`Œ!ZúùdO Ò ý1ùƒõ,òHïìì+ëêžéÕé¬êìûíHðßò¥õzøBûßý:>Û½þÑDgOΘÿŠþ¹ý9ýýcýþ?ÿǧÎ$ ÷ ;?ê#ÖôsQ9] p–¥ü¼øÿôñƒîüë ê¿è!è2èîèJê6ì™î\ñaôˆ÷³úÄý)Q@ú8  cq@é….ü_ÿÿ,ÿ¯ÿ—ßyQSe k K è*úG)¶° # !¿Qü‚øÏôZñ@îžë‹éèTçAçàç)é ëzíWð‡óìögúÖý¾ï¡ Ì m ‰ * _ ; ÖH­³ƒ¡øÿ:âå7Äv5ç p ¶ £ !!—  Û ° ®ÿ&üŠøûôšñ…îÛë´é&è?ç çˆçµè‡êîìÒïó§öYúþ© ¯ Ë [XŸûç w Æ ë,zß³ÿ·ÿâó>¯,›ãë › ã ²  ËãHYÿ*üÚø‡õPòUï´ì‡êçèäççççñè¥êõìÍïó³ö„úiþ>æ@ 4 ©‘ߦ)'²ã Ó ^33u ÿeþ2þeþöþ×ÿó6ˆÎïÓd’P”^±˜#ÿeüwùuö}ó®ð&îìWê?éÇèøèØéaëŠíCðwó ÷áúÙþÏ¥8 m )XìÜ'ÐâoŠNÕ = £$ÙÙÿ4þøü,üÒûãûWüý%þUÿ•ÎäÂR„K¢†þÿÙü_úÂ÷õ‰ò)ðînìEë­ê³ê`ë²ì¥î,ñ4ô¦÷fûUÿQ9ì K: m“ Û™©Lž ¼ ÄÕ ÿLý}û!ú=ùÓøÜøLùú"û[ü©ýðþ ´îm1ÿ†ý’ûhù#÷Ýô²ò¾ðïçí0íí{í‹î8ðyò@õwøüÒÿ¸˜Q ÃÏ[R¥I<#2ÂîÓ D ÿUüú!ø¾öÞõ€õœõ'ö÷>øžùû„üÙýùþÒÿRq){ÿlþý_ûˆù™÷¯õãóPòñ=ðäïðÚð3òôösùºüEú¸^ ÊÞ~’ÑçK¨Á€  sæþ]û•ø?öiôó_ò+òzò<ó_ôÌõj÷ ùÑúeüÅýÜþœÿúÿòÿ…ÿ¸þšý9ü¬ú ùm÷ðõ­ô»ó/óóŠóƒôö øŒúqý¦’ [c)¶ŸØ^3cûà ) g›êýoúH÷ŽôUò©ð”ïï*ïÆïÚðPòôö ø úìû•ýòþõÿ’Ș$ÿÿý¬üEûáùœøŽ÷Ïöqö„ö÷!ø®ù´û#þêò U t \ð²´º¶½çž þ%6Rý˜ù*ö!ó•ð˜î6ítìRìÈìÊíEï#ñIóœõÿ÷Uú†üxþX/™—3xyLÿþÃüšû¦úûù­ùÊùYúaûÜüÄþ ›`>  ÍC]“h’õF ‹¸¿ÄüæøHõò;ïüìZë]ê êZêGëÀì°îÿð‘óIö ù´û0þc<¬«5NÿUb=þ¿ÿ—þŸýíü’üœüýúýLÿ TÈJ ¿  ¬ÔprÒ­7@ Ü(BKüeø¯ôLñVîçëêâèaèèbéÒêËì7ïùñöôø$ûþÎ31¼Ë]w!ki1Û‚>(VÿÖþ·þÿ²ÿÉ>ÿú< N 0Çû·é†ŠóÊ  üÊÿóûølôþðóídëiéèhçqç*è‰é€ëùíÜð ôh÷Óú,þT2¯¹C G Ä À G h : ÒK¿Hýó<åÿòÿe;iáX' ß f £ }âÃÚ  ¾øÐ`ÿÃûø…ô%ñî|ëiéòç&ç ç¥çìèÕêMí=ðŠó÷¿úfþê. ‡ ò ËÖú „ Ô 2uå™ Õÿœ‰½$©1£ä Ü w   M u  6ÞÿÅûaøõÄñËî2ìêˆèžçbçØçþèËê2íðqó÷äúÀþ†Y . ‚GsýhTÖ ú Ó¬žÃ/ôÿÿ¬þ¦þÿ»ÿºïB™ÜñÁ7DÚõ“»yÞþÿûöøàõÜò ð„íiëÐéÎèpè¾è»éaë¥íuð¼ó\÷9û0ÿæf !1¤u¢20¯Ãˆ  ’³¸ÿ@þ3ý”üeüžü4ýþ/ÿhªÚठ½çèÕþsüÙù"÷iôÍñkï^íÂë¬ê,êOêëŒìî@ñaôç÷´ûªÿ¦ˆ/ {RLT±exúÿžô  9d»WÿLý©ûyúÀù~ùªù8úû1üoý¸þòÿÙ^ƒ@‘vøþ#ý ûÁødöôÛñéïPî*íŠì~ìíAîðròVõ¨øLü%õ¨ }Z‘ð©©0ZE Ö»ÙþHüúfø,÷tö:övö÷øIù¨úürý¬þ«ÿ[¯Ÿ'Iÿ þü´úÀø¼öÅôõòhñ6ðuï7ïˆïoðìñúóö“ùõü–[!È /7ÆÄÍȱ¶4E  ‘FþBûžønöÀôšóóíòUó+ôZõÊöcø ú¥ûýUþBÿÓÿÉÿ,ÿ4þîümûÇùøoöóô¸óØòeòoòó ôÊõø÷œú£ýôu‡ ÙÛq‚úÈæP #¨²Z ÀE§ýFú>÷¦ôò ñð¹ïéï›ð¾ñ<óýôåöÚøÀúüþ1ÿryaÿZþý°û<úÕø–÷–öíõ¬õáõ—öÏ÷†ùµûKþ4Yâ ñ~• JٸK £Éßýaù öó²ð×î–íôìïì~í’îðùñô`ö­øçúôü¾þ1Cê&úo”~ÿ?þóü±û”ú³ù#ù÷ø:ùôù(ûÐüâþOåØ ¿ |ñ”—ù±½!æÝ @cirü øõèñ8ïí”ë¶êêêêìëtílï¼ñFôïö—ù$ü{þ…2tF¥—%`Z*êÿ±þšýºü(üóû'üËüàý`ÿ@qÝl ƒ ÑÏdzþä%ÁÀ, ¡Üíÿóûøfôñ3îÝë$êé®èõèáédëiíÚï›òŽõ•ø’ûgþù5 hM·­:n^ ÎS[ÿ«þTþbþÚþ½ÿ¢Š¦Ü - ŸÃi€þß&Û Ñ?vÿ•û¼÷ôªð®í5ëRéèˆç­çèôéüë€îgñ“ôå÷>û~þ‡B™zÛ ·  î \ l 4ÌMÓuKißÿµÿóÿ–šóY9 Ô W ˆOš\Œ* 9 ÅÜ—ÿ`û¬÷ô¶ð´í'ë)éËçççÐç/é-ë´í¯ðÿó‡÷&û»þ&Lh 9 } 3]5  Œ áaÁV3hýÿ_!5Š £5§ à Ç I U Þ à Y PÒïÀþ_ûè÷}ô=ñGî¹ë¬é6èeçDçÖçéýêyísðÒóx÷DûÿËFj  PñûlIzó ! û Xïãÿ:ÿûþ"ÿªÿ…¢íM©çï© ì[L¿½S”þ–ûtøMõ?òiïéìÛêTéiè%èèªélëÊí°ðô²÷’û†ÿk"Œ þQ‰tç÷¿ [ èƒFHÿTþuýýý_ýþÿ:}¾ä×Ï´&#­Ìþ üQù‚ö¹óñ²î®ì ëê·é÷éáêrì¡î^ñ–ô-øüúÓj ¢_Ž IâàRNëG ~ ¯÷p4ÿSýÝûÚúLú1úú)ûüBýƒþÆÿïë¡û‹¬c¸þºü}úø¥õAó ñïŒíwìîëþë¯ìîòïsòtõÞø•üznNù P6”VpÛ—¬%—Á ³ Œjl­þCüAú´ø¥÷÷ýöW÷øùWú³ûý^þ{ÿVÞÆÿ¨ýóûúö÷àõßó ò†ðcï·î”îïð°ñâó–öºù5ý꼈. ‡é*¼›ÊTG¹Ãƒ ¡@þ.û°ø§ö õ"ô«ó·ó9ô õYöË÷]ùôúvüËýßþ¡ÿ˜ÿÍþªý?üŸúáø÷tõúóËòýñ£ñÍñƒòÇó˜õì÷´úÚýEÚy QLÓÑ0åæ5×ÙLJí T ñiý$ú;÷ÇôÖòtñ¤ðfð±ðxñ©ò,ôêõÇ÷§ùqû ýfþjÿ K!—ÿµþ‹ý-ü³ú4ùÌ÷”ö¤õõïôIõ%ö†÷gù¾ûyþ‚Âm ™€ Sxê®ËRVò DkŠÁü/ùóõ%óÚð!ïî€í—í=îaïñðÓòîô$÷Zùvû^ýýþC&ž¬U¥­ÿþ2ýàû¢ú’ùÆøSøIø³ø˜ù÷úËüÿ™nkr e &—œ RîÜ#Ííš ð $ü_øæôÔñ@ï?íÛëëë†ëœì1î/ð}òýô”÷#úüÀþ  5Ù ØFfOÖþ¦ý üÛûiû[ûºûŒüÎý{ÿ…Üi º D”ŒJlèÈí `Ž—ÿûÀ÷#ôâðîßëCêOééiélêÿëî„ðAó(öùýû±þ0Ø Æ ÝMlO Á‚lÿ‘þþÚýþ½þÏÿB S  æ èn‚ j)Nâ ö Ÿø!ÿ7û]÷µó]ðtíëHé'è¶çöçáèkê‚ìï÷ñõcø§ûÌþµKz1i  T  j j+ÄP馟æÿ‡ÿŽÿüÿÏ@&  Ä BeGé÷p Z ºY»þýú@÷¦óNðXíÝêõè°çç8çè~éë%î'ñyôú÷‹û ÿ]d6 à ÿ ‘ › ( H ‘ ì9“ÌÔ7-¾«æ[ö6 ¦ Õ «  f @ ’ b¾ºoþöúp÷üó»ðÌíJëOéïç8ç3çáç<é:ëÉíÑð8ôß÷¥ûjÿ ms  ‘xɋʘ ; D @Ló·ÙÿaÿQÿ¥ÿUTŽíX·ïçŠ Æ Œ Ôšã¸'Eþ*ûò÷»ô¦ñÐîWìWêäèèèçoè¦éƒëùíóðXô øíûÛÿ´Xª Ž ð¿ñ‚vÖ°%ò œ ?÷ÝŠÿoþÀý}ý¢ý'þüþH‘ÏéÈV‚@‡W´©EþœûÇøãõ óbðîìˆê›éOé¬é´êcì®î…ñÑôxøZüVLŸ Àctæ±ÔT>¢•3— Þ'+ÿcýüCûàúìú\û ü&ýVþ˜ÿÑëÌb›lÍÀHsþMüîùn÷çôxò=ðQîÐìÎë^ë‹ë\ìÏíßïòšõùâüÐǤD ‹[ŸEB20—|÷$ "‡þEümú ù&ø¼÷É÷?øù$úgû¾üþFÿEüZTå Ñþ=ýbûTù-÷õüò*ñ¬ï˜îîýíî¹ï~ñÒó§öçùzý@ì äÎ5(žbxìÎ5<ÿ Ÿ;ñáý"ûÊøêö‹õ³ô`ô‰ô$õö]÷ÏøWúÜûCýwþdÿùÿ+ùÿ`ÿgþý‹ûÎùú÷,ö|ôóäñ*ñìð5ñòyópõé÷ÒúþšAêv ó+[ôÚ—„èÛ{ æ= 0ýúB÷ñô&óéñ=ññƒñ]òšó!õÙö¨øsúü—ýÅþ›ÿÄÿ ÿþ¸üAûµù.øÆö˜õ¹ô@ô<ô¹ô½õG÷QùÎû¬þÔ-˜õ $€w֘ ” â 6üùäõ6ó ñvïzîîIîï9ðÐñ²óÄõé÷úüÂý7ÿNI*ªØÿÂþ~ý%üÏú—ù•øß÷‰÷£÷5øDùÏúÍü2ÿéÜñ É5.žsŸïª´Q ›µ¾ÿØû$øÀôÉñSïqí.ìŽëë,ìTíõîøðAó¶õ8ø¬úöüÿ´ídnaiAÿÃýžü«ûû²úËúUûTüÄýÿÐL÷· o P@¹¦÷£¦Åú ¸ <AÿHûu÷æóºð îìënê˜éméééë£ì½î3ñéóÂö ùeüöþ<$Ÿ§6SZf=ú´‡ÿˆþÍýiýgýÑý¨þèÿˆz«d · Ý»68®ŒÊhkß Ö h®ÊþÛú÷bóðCíøêJéFèñçLèNéëêí¤ïŒò«õàøüÿÝLRßî| 1 rd»TÜùÿhÿ8ÿnÿ kôôü î ° &:ÖêlW« r ¸‘eþ™ú×ö=óíïíêÍè¢ç(çaçJè×éúëî¥ñõônøðûZÿtóú } v å Ñ E S  “öTÇfH{d$;›/à–4 ¡ Ä † Õ ¡ ã — Á k£þúùö€ó?ðXíåêýèµçç/çøçné‚ë"î6ñ¢ôHøü»ÿFs ã Í &êÃî°  Q gx¡ø”…×ÿÿ®ÿ.'|íbÂñÙ d € " B ßÿ«ôòý¼úp÷-ôñ>îÎëÝéèÄç·ç[è®é¥ë1î=ñ¯ôhøHü.ù‰À ‡ Èu…øÐãBN # ݘnzÏÿ“þþüýLþõþèÿW¥Þë´$-Ã߃´õý+û<øDõbò´ïWígëúé%éóèmé“ê`ìÆîµñõÇø¯ü«šZÌ Ô[N MS»’è×w å >¡'ëÿzý^üµû|û®û>üý2þkÿ«Ûâ©.ÔÌ''þÜû]ùÃö+ô²ñvï‘íì0ëÙê$ëì¨í×ï“òÈõ[ù1ý'õ‰ ½vŸ(9Á©ÚRƒ ‹ ‰›ÝhþOü¢úlù°ønøœø-ùú2ûxüÊý ÿ) ›Î›üõÿ‹þÍüÍú¢øcö-ôòNðÙî×íZípí!îoïWñÌóÀöúÂý—|M ê 3 [syL«° y &Ö§¸ýûíø5÷ÿõNõõeõö÷eøÔùQûÂü þÿâÿIMêÿ!ÿûý†üÔúûø÷:õ‰óòñað>ð¨ð¥ñ5óQõí÷÷úWþð§Y æ .yKxöÁÚL%{f vÚRüüôùP÷%õ€óiòßñßñ]òJóôöË÷Šù<ûÉüþÿÆÿæÿ_ÿ}þMýãûSú¸ø*÷Åõ¡ôÖówó“ó4ô_õ÷Bùåûåþ*™ y ©†ó× ¿¬çubÀ¦1 ~¯æÿAüßøÝõPóJñ×ïüî¹îïÖïñµò•ô›ö­ø¯ú‡ü!þiÿQÔí¡úÿÿÒý{üûÀùø÷ÿöÈö÷À÷úø¯ú×ücÿ<MxŸ ¤gʶÎßAõ}s D[jÿûî÷£ôÇñqï¯íì ì*ìÝìîÁïÅñ ôpöÜø2ûYý9ÿÁåæÇGvh2ÿíý±ü™û¼ú/úúCúùú%üÂýÆÿ!¾†[ ! ¸ìT+bðÕ¸Ô } Ïèëþ÷ú.÷±óœðîì¦êîéßétê ëQíqïæñ”ô]÷#úÉü6ÿS^9ž•&a[*æ«ÿþªýýÒüüü”ýšþÓí?±' … ®†ôã@œ~Ô ° +asþ€ú«öóÜïíêêXéqè9è®èÇévë¦í?ð%ó9ö]ùrü\ÿþF!„iÑÂHtY²YXÿòþïþUÿ#TܪªÃÛ Õ •‹ƒä«Ü € ¥bÐ þ7úpöÚò”ï»ìiê±è¢çCç˜ç™è<êpìï(òuõãøSü¤ÿº}Öµ  ã 0 þ [ Y  ’ÿpþÀÉ*íÿ¢ÑTË / — ¬ YŒ8U ã ç k‚@Âý#ú…öóÊïíìŠê·èˆçç9çèªéÓëƒî¢ñõ³øfü}¦j ¶ { °Reó Á , f ‰²ùu;ZÜÿÄÿ¾¾ÿlîkÉî Ä 5 2 ¯ § —½œýMúïö¡ó‚ð³íOëné&è…ç“çTèÂéÒësîñ õÇø¥ü€:³Î u •bSfs R òêœzÿ¾þlþƒþûþÈÿÖg·êç™ëÐ=/§­O¡ý¸ú±÷¨ô¼ñ ïµìÒêxéºè¤è;éêhìèîíñ\õùýå•ò àIOÜÇÜ(¶ 1 ŸÆ²ôþ™ý¬ü/ü üwü&ýþAÿ½âÔк4:Ð×ýgûÊøöróñð¶îÙìuëêaêÉêØë‹íÙï°òüõ¢ùƒý~tA Æ å†“ÿÀÖD_1¨ß ö 8Oþ`üàúÕùDù'ùvù"úûDüŠýÔþ É4<Ú Õÿ?þYü6úí÷šõXóCñxïî í»ìïìÀí1ï:ñÐóàöSú þïÚª ? y>wý;ɯü ð ­sb”ý ûù‹÷~öòõäõGö÷"øoùÚúJü¥ýÓþ¿ÿX’fÓÿÛþŠýîûú(ø0öLôšò3ñ.ð¡ï›ï&ðFñûò<õú÷"ûœþI Æ R ’h»v‰ëššõ¼ì Œ zÎüçùh÷dõåóóòŒòªò?ó=ôŒõ÷½økúüoý™þpÿéÿûÿ¨ÿóþçý“ü ûeù¼÷)öÈô±óúò¶òóò¹ó õäö<ùü#ÿƒŽ ú )ý\,]á³ÒFiDÉ Q—ÿüÁøÞõtó’ñCðŠïfïÌï°ðþñŸózõs÷pùTû ýzþ”ÿMŸŠDÿ,þàüxû ú´øŒ÷¬ö'ööröU÷¸ø˜úéü™ÿ”¿ÿ3 <ýW3zXðäF*¬ éÿLû¿÷ôÏñ™ïùíøì•ìÎì—íàî“ð˜òÔô*÷~ùµû¶ýmÿǼEbuˆeÿ"þØü£û™úÒùcù[ùÄù¥úþûÇýõÿv4þ Ï k³Žå¤À1÷¢¥ ; €“–þ©úíö„ó‡ðî+ìêêPê^ê ëIìî+ðžòAõø÷£ú)ýpÿcòÂþÏAdNÔÿ£þšýÑüYüDü™ü_ý“þ.%dÖa è OyJªƒÆihć¿ ‚ éþ(úYöÐò©ïíèêsé©èèéKê ìDîàðÁóÉöÙùÓüœÿ7è ÜíXpK©`=Vÿ¾þƒþ®þDÿA REb’ · · uØÉ6Põ„ ‹-†³ýÕù ö}òCï|ì@ê¡è®çlçÛçôè¬êîì£ï±ò÷õXù³üêÿà~¯f ™ F q " i Y  9QàÿÒÿ*èkܵ % † Œ#:Ľ &  dZühýºùö“ò\ï‹ì9ê}ègççOçNèóé/ìíîò„õùÅüS­·Y €  /®¤ Í 7 x¬íT÷é6éÿ}TyÙ^îqÌ æ § þ Ú 2  N|€BýÜùoöóùï0íØê éÙçRç}çYèâé ì¿îéñlõ*ùýÏvÖÔ Z W¾ŒÁd„2„ •  _OiÃp}ÿñþÎþÿ±ÿŸÉvÇñÞwªj®užIýCú%÷ ôñkîìGêé\èaèévê{ìï,òªõqù_ýS,Ê á+Þñ`0j`Ió | j~ìþÀýý±üÌüGýþÿQ”ÎåÁO|=‹dÍÒÿýïú5øoõ»ò5ðüí*ì×êêôézê¨ë{íåïÖò7öìùÖýÔň ü ‹|Élf¼{µø 9 `ŒÚb=þzü&ûHúàùèùWúû$üWýþÜÿûä‚Å¡¯ÿîýàûœù9÷Òô†òoð©îNísì(ìyìkíýî'ñÜó÷‘ú\þH6 ·g†Õöj:u/ƒ‹ f 4!xý+ûMùê÷÷ ö²ö1÷ ø,ù|úáûBý…þ”ÿZÉÕxµÿþýQû_ùT÷Lõbó±ñTð`ïëîï®ïòðËò/õøTûåþ¤s/ ¸ î´ò”ÓgN”KŠl  •Âÿ¦üáùˆ÷«õUôˆóBó}ó)ô6õ‹öø°ùJûÇüþÿ»ÿæÿcÿþLýÔû0úvøÁö,õÑóÈò'òÿñ]òHóÀôÁö?ù(üfÿÞt v ¡lºuö¬° Î Û ] °ôLÿÔû«øéõ¢óåñºð#ðð›ð‘ñêòôböLø1ú÷û†ýÌþ¹ÿAc}ÿˆþPýíûtúù«÷ŽöÁõWõ`õèõóö€ø‰úýÖÿï3„ à ЋۥÖ_9aÞ¹Ú R ‹§Èþ û—÷€ôáñÍïOîní*í}í[î²ïkñoó õä÷ú4üþ™ÿÅ‹åÕdž–ÿ_þýÆû—úùïøŸø»øNù[úßûÔý)Ϭ¦  zY'je o ô .<Bþ^ú³ö^ó{ðî\ì:ë¿êèê«ëûìÃîìðZóðõ‘ø!û…ý¤ÿkÎÁCVVb>Âþžýªüþûªû½û?ü2ý•þ\{ßo ¦ =UAƤᅢ M ¢¾ÄýÒù ö‘òïîìóê›éîèîè–éÙê§ìêî†ñ`ôZ÷Tú1ý×ÿ,!¥²Eaci:ï¡jbÿœþ+þþuþ;ÿgòÌâ` ‘ •N¥ƒÖ’±3€ ió8Yýuù®õ&òúîGì"êŸèÇç¡ç*è[é%ëuí0ð=ó|öÍùý*ÿw€    © ? r UŒ°xƒáÿÿ¿ÿG4z Ï´ž s  oeäÝF^  U,´ ýPù£õ%òõî2ìôéPèTç çsç‹èFê”ì_ïŠòùõŒù"ýšØÁ? @ ¸ £ Ù 8 / Ô ? ŠÐ,´ýÿEïð9¶Pîu Ê × ƒ ¾ x « U xZ>åükùðõ”òvïµìlê²è™ç-çsçlèêLìïHòÑõù\ý¬òÑ 5 Rþ ¬Ož ´ ¬¡¯íqKˆÿ+ÿ7ÿ¦ÿl{¾„ÔõÏN ` û³ÕˆßÿìüÌùšöuó}ðÑí‹ëÆé–è è+èýèzê™ìIïsòþõÊù¸ý¤où$ Ù•‡Ø²W‘z . Çd Qíþïý_ý;ý~ýþÿ$c©Üä© ¸Ú†Ãžÿ&ýtú ÷ÇôòïKí…ëDêšé”é7ê„ëuíûïóxö;ú,þ*É * …X† ê)ÖËE ‘ Ë.3þœüuûÃú„ú±ú?ûü2ýlþ¯ÿáí¹4Oÿ@‚ÿ–ýcûÿø„ö ô·ñ ïâí–ìÐë ëì"íÕîññó6÷Ôú­þ¡V Ô ì…ŠëŸ¤ÿ¹ä•æó Û½·çÿbý>û‹ùRø–÷V÷‰÷"øù9úŠûçü7þaÿOï2ƒÿ=þ—ü±ú¡øökô|òÎð|ïœî?îtîBï©ð¦ò,õ*øŠû1ÿÿÖ” Aö§ƒ®'ö(Ðè ‘ $¾€ÿ„üäù²÷ýõÎô&ôôYôõ4ö÷ù¢ú'ü‡ý¬þƒÿÊÿÿ þ¬üûTùˆ÷Éõ3ôàòæñ\ñRñÑñáò€ô§öIùSü­ÿ;á| í Ñ ²±þ™ƒÇu¤m î F˜ÿ¦ûœøüõÚóCò<ñÆðÝðtñzòÛóõK÷$ùðú•üþýÿÖÿ. ¯ÿâþÇýqü÷úqùø÷§ö—õÞôôºôgõšöQø‚ú ýM¨ O ]T %”R_À„½ƒ ó +MzþÓúu÷|ôýñ ð°îðíÊí7î(ï‹ðIòIônöžø»ú®ü`þ¿ÿ¼R}BªÃÿ þWýüµúù¨øøã÷$øàøúÉûçýd-'7 ? ¼öµäsWW0 § Øåïýú~öAóyð<î˜ì—ë:ë}ëVì¶í‡ï±ñôŸö*ùœûÛýÒÿm¡g¼§/f],ëþ²ýœü¿û1ûû>ûìûýþ×]¿ b Õú·ö¢°Õòy|  Wjmý€ùÅõ[ò^ïèì ëÏé@é\éêrëMí•ï1òõê÷ÌúŠý 9[<¥.g](Þ›xÿ‹þçýžý»ýDþ9ÿ“JK‚Ö, h m i2kg1s A´èÿüùTõÖñºîìê¨èíçãç†èÍé©ëîÄðÍó÷AúlýghH«Ž ð Ù T tLõˆ Ô¼îÿvÿaÿ³ÿl†÷¬† a P4šv½nŒ " ?øi¯üèø7õ¼ñ—îãëºé.èMçç£çÔè¤êí×ïóröùù}ýÝýÄ õ G J  O 8 × D›öm Xg‘ý•Cët à Á V t  œ ˜2øÿ†üúøtõòúîDì êfèfççwçŠèEê˜ìnï®ò:öóù·ýdÞÄ  ºÚe_ÒÍf ´ Ð Øåv%-šÿnÿ¨ÿA-[¶&‘Þò¹   ‚ uçàlžÿüSùöáòæï>íëQé7èÅçèðè‰êÂì‡ïÁòVö&úþó­ 0 ÆÏ@Eàñˆ½¨ f ʧÁ+õþ&þÄýÌý7þ÷þûÿ,v¼çÞŠÙ¼+  ±cÿÈüöù ÷!ôXñÏî¡ìéê¼é*é@éêmëzíð:ó¿öŒú‚þ}^ P 'u(7Ÿc‹'JŽ ç 6™)0þÆüÌûFû0ûû,üýCþÿ¿åÚ‰àÑTg Nÿ:ýãúaøÏõJóîðØî$íèë9ë$ë±ëäì·î ñôk÷ûÿùæ¤ ˜Å\Fˆ.KôDX OH_±ÿSýYûÑùÃø0øøgøùúIû™üìý*ÿ8}”B†dÿäýüúã÷®õóšñòï­îáížíòíáîkð‹ò2õMøÆû€ÿ[9õ q.>¬m{Ú’±M~_  ³dCÿiüîùå÷YöQõÎôËô<õö7÷•øú”ûýBþBÿïÿ<$¦ÿÅþ‹ýüNúwøšöÔô?óõñ ñ›ð®ðPñ…òJô–öZùƒüøÿšMï ^}-VãÇùxIv6ù { Ý>Àþ~û•øöô«òÈñtñ§ñTòióÑôsö5øûù¬û/ýpþ^ÿìÿÖÿ7ÿ@þýûúnøòö§õ¥ôôÐóôðôKö*øƒúFý\­‹ Ø ãÄgh½^O—El& Éó0þžú[÷€ô$òUðï}îuîúîýïkñ+ó%õ=÷VùVû$ý¬þÝÿ«¨êÿãþ§ýNüðú§ùŒø¸÷>÷/÷—÷|øßùºûþ¤Ž£Ç Û ÁZŠ9RǨä$ë U €ŸýÕùPö,ó‚ðdîáìÿëÀëì ízîRð{òÙôO÷Áùü-þùÿfl.ðVqUÿÖý¥üŸûÚúkúbúÇú¢ûñü­þÊ7Ý£l ¯`Œ!ZúùdO Ò ý1ùƒõ,òHïìì+ëêžéÕé¬êìûíHðßò¥õzøBûßý:>Û½þÑDgOΘÿŠþ¹ý9ýýcýþ?ÿǧÎ$ ÷ ;?ê#ÖôsQ9] p–¥ü¼øÿôñƒîüë ê¿è!è2èîèJê6ì™î\ñaôˆ÷³úÄý)Q@ú8  cq@é….ü_ÿÿ,ÿ¯ÿ—ßyQSe k K è*úG)¶° # !¿Qü‚øÏôZñ@îžë‹éèTçAçàç)é ëzíWð‡óìögúÖý¾ï¡ Ì m ‰ * _ ; ÖH­³ƒ¡øÿ:âå7Äv5ç p ¶ £ !!— € Û ° ®ÿ&üŠøûôšñ…îÛë´é&è?ç çˆçµè‡êîìÒïó§öYúþ© ¯ Ë [XŸûç w Æ ë,zß³ÿ·ÿâó>¯,›ãë › ã ²  ËãHYÿ*üÚø‡õPòUï´ì‡êçèäççççñè¥êõìÍïó³ö„úiþ>æ@ 4 ©‘ߦ)'²ã Ó ^33u ÿeþ2þeþöþ×ÿó6ˆÎïÓd’P”^±˜#ÿeüwùuö}ó®ð&îìWê?éÇèøèØéaëŠíCðwó ÷áúÙþÏ¥8 m )XìÜ'ÐâoŠNÕ = £$ÙÙÿ4þøü,üÒûãûWüý%þUÿ•ÎäÂR„K¢†þÿÙü_úÂ÷õ‰ò)ðînìEë­ê³ê`ë²ì¥î,ñ4ô¦÷fûUÿQ9ì K: m“ Û™©Lž ¼ ÄÕ ÿLý}û!ú=ùÓøÜøLùú"û[ü©ýðþ ´îm1ÿ†ý’ûhù#÷Ýô²ò¾ðïçí0íí{í‹î8ðyò@õwøüÒÿ¸˜Q ÃÏ[R¥I<#2ÂîÓ D ÿUüú!ø¾öÞõ€õœõ'ö÷>øžùû„üÙýùþÒÿRq){ÿlþý_ûˆù™÷¯õãóPòñ=ðäïðÚð3òbaresip-1.0.0/share/sound7.wav000066400000000000000000001047741372575704200162260ustar00rootroot00000000000000RIFFô‰WAVEfmt D¬ˆXdataЉ§:  Ç œ–˜iO»ºY¨ º ¡rA!þ%û]øÚõ©óÕñfðaïÈî›îÖîsïið­ñ4óïôÏöÅøÂú¹üšþXëJlNîLkOÿƒä,h¡â6¥8ôÿÝÿöÿ>´T÷êäÝÆ–A¼ÿ ¼.T0Å4"ÿíü¤úWøöîóóñ4ðÀî¢íæì–ì·ìLíWîÓï¼ñô«ö˜ù¿ü kÊ 1  ÍŠËˆº_y "Äè ŽfÄý5úÎö£óÈðKî<ì¤êŒéøèêè_éQê¹ë‹í¹ï4òëôÊ÷Àú¸ý gþT^  i _ñ"õpœ „ 4 ¸ uÊ*¢;ÿøý'ýü2üüü^üÆüMýéýþ8ÿÖÿ^Ê-Ô[³ÿÝþàýÃü‘ûTúùç÷Ñöáõ!õžô`ônôÎô‚õŒöè÷“ù„û²ý’(ÁL · ñéÙ¸$Žˆ ¼  ý¹LÊýFú×ö’ó‹ðÕíëžé8èXçç<çèOéë]íðóEö·ùBýÒR­Î ¥ !4Õü¤Íx¬pÏ×–  ~Ënçýûoù—÷öÚôÿó}óRóyóîó¥ô–õµöö÷Kù¨úüHýuþ~ÿ[‚ÈÚ¼t~äÿAÿ¡þ þý4ýýûü+ý‘ý/þÿ ?™–!¤ Y q M á $ž Î    7 û4þYû{ø¬õóŠðYîì ëêvéjéàéØêPìAî ðaótöÈùIýâ j cÖÚabÙà ÷M0«Ñ ² c÷†#ýáùÕöô ñ“ïòíÆììÓë ì¶ìÈí8ïùðüò3õŒ÷÷ùcüÀþýì‡Úà– þ  î ‚ Þ üéãó"xûÿ­ÿÿ¡ÿàÿGÐr$Ü3¼!Y](´æ…öþAýsû˜ù¾÷ôõGôÇòñƒðÖï…ï—ïððð9òåóîõJøìúÇýÉâý ï ž³â’½a}0Ø ®&ƒÛüBùÐõ˜ò¯ï$íëféFè°ç¥ç#è'é©êì÷î¥ñ˜ô»÷úúAþ|˜‚* ‚ }<õ?‘¥eÚ  " õÙÎáÿþŽü9û'úZùÒøøøÆø3ùËù„úRû+üýÑýŠþ$ÿšÿåÿïÿ­ÿ?ÿ©þóý#ýDü`ûƒú¶ùùø(ø ø,ø“øAù7úrûíü£þ‡’µâ  Æ=d0–2Úð p ¥œiýÐù‘övó”ðþíÄëõéžèÈç{ç¹çƒèÓé¤ëëí›ð£óóöuúþ½WÎ ™Æ|³d3Uþ7’Ô æÝËÄÿÚüúŸ÷kõóòòð>ðïïðxðAñVò¬ó5õãö§øuú<üñý‡ÿô05þ‰ØìË{nÅc¿1Ãÿzÿ]ÿoÿ²ÿ%Ç“ƒ¨ÉæñÞ¢ 2 … ’ T Å æ¶:wwBèýuûúø†ö,ôüñð\îíì—ë‰ëôëÙì6îð>òÖô¿÷èú@þ±*“Ø å¥ }wèË!î9 t F ÖF¬ÿü®øtõòçï³íñëªêãéžéÙé’ê¿ëVíLïñôÄöùbü+ÿØ[¥©^ ½ ¿ e ¯ Ÿ < Ž Ÿ z , ÁGËZÿÅ´ÿÑþ#þ«ýjý]ý€ýÎý@þËþhÿ §6­/,ö‹ëÿíý£üCûÙùpø÷ØõÂôáó@óèòâò3óÞóäôCöö÷÷ù:üµþWב . žÎ®0Gê¹ßˆ¸xÔ Û - ÿ ü‚øõïñ ï†ìlêÌè¯çççžç¯èCêOìÆî˜ñ´ôø{ûûþqËôÙ k›_®ƒÝ½'#»ûñ ­ @ º.¬Eÿýüú2ù±÷öŸõõØôëôFõàõ¯ö©÷ÂøíùûIüdýdþ@ÿóÿvÉéÚž:·ÿÿsþÇý!ýŽüüÄûžû­ûôûwü5ý.þ\ÿº@ä™T ¢  ] b‰0sQ Í î »?‰¨ÿ«ü¦ù¬öÐó%ñ½î©ìùê¸éðè«èêè°éúêÁìýî¡ñŸôå÷`ûûþ¡<· ü ø˜Í‹Æz¡=Pãþ¯ èœBïþ·û¬øáõdóCñˆï;î_íøìízíXî’ïñëòíô÷NùûÀýÚÿÌŒTOj‹kÊô /QŒæhôÿ;¡,טe4ú«>§ßÝRHþzÅÿæýëûáùÖ÷ÙõùóGòÐð¢ïÉîOî;î’îXï‹ð(ò(ôƒö+ùü(ÿZ—ÉÜ ½X{æÓ;m9„V½Æ … nÅþ#ûŸ÷OôEñ”îLìxê#éSè èOèé[êì6î°ðrójö„ù­üÐÿÚº`¼  i«‚ïó”×Ço Ý  @TgˆÃ%ÿ¶ýü„ûÉúOúúúMú³ú?ûçû ü`ýþÉþ^ÿÒÿ@2õÿ‡ÿîþ.þNýWüSûMúPùhø¢÷÷¢ö{öšö÷¹÷»ø úœûnývÿ¦ôO¨î  ­ Äv²x͸ B zm.ÑþgûøÅô¶ñíî}ìtêáèÎçCçDçÑçéè…êœì ïò6õ¡ø3üÔÿnî> J S5œ‚ä xˆC¸ ú .EtþÉûVù&÷Fõ¾ó“òÉñ`ñVñ¥ñGò1óYô³õ1÷Åøbúúûýìþ0F)ÔE~Tü‚ïN¨{ÿÿ´þ‹þ‘þÉþ5ÿÓÿ ™´ë2~Ãô é ” þ  ì e ‡ S Ìùâ‘ÿ|üÕù3÷¦ôAòð2î¦ìëÈê‡êÃê}ë³ìbîðóãõùcüáÿkïU Š x<ô+ÙûŽ—#¼õß ˆþ’úP÷MôœñJïdíóëýê…ê‹ê ëÿë^íï'ñuóôõø:ûßým×´  Í ( / è [ ‘ m-á“P".vÿîþšþyþˆþÅþ(ÿ©ÿ@ãˆ#«ZqUu°µ‹ÿ4þ½ü/û•ùþ÷vö õÌóÄòÿñˆñgñ¡ñ<ò7ó’ôGöPø¢ú2ýñÿ͸žl wLžzÙ¶ä<•° „äýIúÊözópð¼ípë˜éAèrç.çwçKè£évë¸íZðKóyöÎù8ýžð ¥ ëË<9¿Ïmžmã È s»wXþhü³úAùø;÷¬öiönö¶ö8÷ë÷Æø»ùÀúÉûËüºýŽþ>ÿÅÿE> ªÿ'ÿ‡þÓýýXü§û û“úCú&úBú›ú4û ü%ýwþýÿ¬}bM1 þ ¥ L0½é¯ ý‡ ® { ù5>'þûß÷Öôúñ]ïí%ë¨é¤è#è)è¸èÎégëyíúïÜò özùý¸^ëJ f.‘óàCm<“|C C à¤}ý{ú±÷.õó2ñÊïÐîCî$îoîï$ð|ñóãôÖößøïúöüçþ´U¿ëÕ{Ýþâl®áEŒîrøÿ8ž-á²–ƒoN·,jj%™Ã¥AŸÆÂþœüdú(øùõæóÿñTðóîéí@íí2íÖííîsðdòµô[÷Húký± ]˜ ¦ tï®Ù~™(,«­>kF âT¯ ýùöúò(ð¹í¹ë2ê-é®èµè@éHêÇë®íòïòJõ:ø>ûCþ5¡ú ¶ ÷§mÚ÷ Î l Þ 2wº oúÿ°þšý¼üü´ûˆû”ûÐû6ü½ü[ýþ³þWÿéÿ_±ÚÔ4œÿÖþêýßü½ûúcùBø9÷Uö¡õ'õñôõiõö(÷ø'úü5þˆüƒ ƒ Û ävªuÍ­þqu S I›ý£ù?öóðmí-ë`éèGç çZç6è™é{ëÐí‰ð–óåö`úóý‡a~ N¿ÇYo±Ï}ǹd Ø 'cŸìÿYýøúÓøøönõ;ôcóæòÃòôòtó8ô8õfö¶÷ùŠúóûLýŠþ¤ÿ‘MÕ(F2òŒqÑÿ0ÿšþþ¸ý}ýpý•ýïýþGÿ>c¬…ÿpÌ  Û b š }  / þ s –no´ýæúøZõÁò_ðCî~ìë.ê·é¿éHêSëÚìÙîCñ ô'÷~úþ–-¯ àB1£ŽîÀÆÔ=Q # ÇRÚÿrü.ù$öbóùðöîaíBìëqë½ëzì í%ïúðó]õÉ÷EúÁü,ÿw•yrz 0 – ­ {  Z ~~gD"  )oáÿƒÿVÿZÿ‹ÿæÿbû¤V£+ÊÒ¢7ލ‰6¶þýUûŒùÅ÷ ösôóÑñãðFðð!ð¤ðŽñÝòô—öñøûdþ]jxs H ä5,¹Ñj€œ¦@v Y únËÿ%ü’ø(õûñï¥ìšê éè‚çç#è>éÖêàìNïòõDøûâþ#D0Ø , !®Ìy´€ãæ’ô   ò•zÿ®ýü¶úœùÉø>øú÷ù÷4ø¦øDùúÝúÁû¦ü€ýGþñþvÿÑÿþÿüÿÊÿlÿæþ>þ|ýªüÑûþú:ú’ùù»øŸøÁø%ùÏù¾úðûaý ÿáÝï  û ¡Ó(œ:p D Â÷óÇÿ„üAùöó5ð²íëÔé”èÖç çôçÓè8êìtî2ñGô ÷)ûÍþu  ¶ Ÿ)Gë¬ÀNZìÑ@p rZ;+ÿ9üwùööÃôèòmñYð®ïlïïðêðòyóõÔö¬ø‹údü*þÐÿK”¥x az[ “ûN–Þ1˜ÈÿœÿŸÿÓÿ5Ç‚a[fy‡…g ¨ ô ü º + M!ªïøÑÿ„ý û¶øUöôòñðzî;í`ìñëõëqìeíÎî¨ðéò†õqøšûïþZÊ' _ [ Y:¡…Ý©é Ö–íì ¤ +”öþfûù÷ÄôÙñIï"íoë9ê…éTé¥ésê¶ëcínïÇñ^ô ÷ûùÝü³ÿjõDL  ] \ ü =#´ ø û Æ g ë_ÒOã˜wÿ†þÊýFýùüãüþüFý³ý<þØþ{ÿ¯,‰¿Çž@®ìÿúþáý¨üZûú©ø_÷0ö)õUôÀósóuóÌó|ô„õãö”øúËü<ÿÒ5Þ h Äߪ¦¹NcüÔ' ( çwîþ^ûÞ÷„ôdñ’îìêŽè‡ç çç½çäèŽê®ì8ïòFõ¥ø#üªÿ%€¦ ‡ 8ï/õ= _GÉôÖ ~ þgË:Çþ}üjú›ø÷âõõzôDô^ôÂôfõAöI÷pøªùëú'üSýcþQÿ¦75¬1ŸÿüþTþ±ýý¥üPü&ü.ümüæü™ý„þ¤ÿòhûŸHèr × ÿ ªþ›Ö ¯ ( G Ÿðÿ'ü0ùFö|óäð‘î’ìøêÍééìè@éêuëMí–ïFòMõ™øü³ÿVì^ — …8ᤵ96±·T—“ ZžEþûü÷2õ¹òŸðíî«íÞì…ì¡ì*íîjï ñëòõ:÷‡ù×ûþAA šã㘠! ýœGgru{޹uàÿÝÿ^Üy.ð¶t®LKÐÏqÿ¢ý·û¿ùÆ÷Üõôqò ññï)ï¿îºîïïï+ñÏòÓô/÷Õù¹üÉÿñ"F I  Ï—ìÂÛÑ Ë#! ÖV¶ þmúïö§ó©ðîÍë êÊèèßç7èéqêAìwîñÚóãö ú@ýl~c f i Dqgø*ž ø & 678HtÈþLý üûCúÃù„ùƒùºù"ú²ú_û üèü®ýgþ ÿ‹ÿçÿëÿŽÿÿUþ…ýžü¨û¯ú¿ùâø%ø’÷3÷÷2÷›÷NøMù”úüçýâÿCÔ  ñŠÑ¼@Uø%à+ ” ɽ‚+þÊúv÷BôDñî0ì=êÁèÅçQçiç è;éëêíªïœòÙõNùæüŠ&£í ñ âµ Ý+ó; gai ™ ©®¹Þý,û³øö¡ôóöñ3ñÓðÔð0ñàñÚòô}õ ÷³øbú ü¤ý ÿs˜ˆ?»üߊÜ2øÿ{ÿÿêþäþÿkÿùÿ¶ž©Î@v˜› r  s Š S É é ¶3eUŸþü}ùëöqô ò ð:îÄì²ëëãê1ëûëAíüî&ñ³ó•ö½ùý‘ë ïrŒ.Næðl^ÌÀFnJ ëi×LýÜùœöŸóõð®îÕìsëŽê)êBê×êàëTí&ïHñªó;öêø£ûVþñe£ R ± ¹ g ¼ ¼ k Ò ú î ºk¯[ý>ÿ¨þFþþþOþ©þ$ÿ¶ÿUø”ŒÖôá˜`tXÿþ¬ü/û¨ù"ø¬öSõ#ô*ósò òòñ6òØòØó5õëöñø?ûÇý{M*ÿ¼ Lž¢H„K”]¢f®ƒï  Ë]Í1ýœù%öâòåïBíëEéèKçççjèØéÁëîÌðÎó ÷kúÞýK¡Êµ P eʹ/.¹Ö‘ó é œ 4Ä[ Þýäû&ú®ø€÷¢ööÒõÜõ*ö´öq÷WøYùlúƒû”ü“ýwþ8ÿÏÿ7pxQŠÿõþKþ–ýàü4üû%ûÕúµúÍú û±ûüŽýÓþIêª~W( â w Ù ùÍKi"t]á  ÒQ‘¢”ýzúg÷nô¤ñïãì ë§éºèOèkèé9êäëî•ð‚ó¼ö/úÈýpšð º êI m/j"b5¬Ö Æ IÕüÏù÷‚ôXòð2ïBîÃí³íîÍîçïRñÿòàôæöù#û;ý<ÿÅ9o` q“v!ò,Uy¢Ü/¤@ )ÿ£e<ýÑ+›ÖÔ5Ã,_iþSü,úøæõæóò|ð/ï7î¡írí²ídî†ïñ óbõ øöúþT£ê Ð7:ËÞlpè×B1²Ñ ¡ 4ŸøÿTüÊømõSòï+í;ëÇéÕèkèˆè)éHêÝëÚí2ðÕò°õ°øÃûÔþЦF¡ « Z §Ž 'à>J ý >q¢ß5±ÿXþ5ýLü û2ûûû@û¥û-üÎü}ý1þÝþyÿúÿXŽ–nÿØþýýýðûÓúµù¢ø§÷Ïö%ö´õ„õõöºöÁ÷ù¶ú˜ü²þù_ÖL² ö ÖTs*o=“oÖÏd ¡ –Síÿvüù­õ„òžï íáê)éðç>çç€çsèëéáëIîñ.ôˆ÷ û¦þ=¿ , óZT×Ü__áê‚¶”* ‹ Éõ"cÿÇü^ú5øWöÌôœóÈòRò7òsòÿòÑóßôö~÷õøtúïûYý¨þÒÿΚ/޶¬t•_¾ÿ&ÿ¡þ9þöýßýùýGþËþ‚ÿj~¶ mÕ5€ ª ¤ d à  è i ] ÓøÖwéÿ9ýzú»÷õŠò<ð5î†ì<ëaêÿéê·êÒëjíuïêñ¼ôÛ÷5û¶þHÙQ › ¤W¦Ü±ú´äŒ¸qÇË '©*ÿ¿û{ørõ¶òUð\îÔìÄë/ëëtëEì€íïñ0óŽõ ø›ú&ý ÿö ±  Ë - @  Š Ò êÝ·…R+(]ÀÿRÿÿ ÿ/ÿ~ÿñÿ!Ìvš>K!¾F4ðÿþëü@û‰ùÔ÷.ö¦ôJó'òIñ»ð…ð¯ð;ñ,òó3õ>÷–ù0üýþìíì× š "^?¶·::´©£Î © E¶ÿqûä÷ƒôcñ•î+ì4ê¹èÅç[ç~ç+è]é ë*í¬ï€ò”õÔø+ü†ÿÎòß… Õ ÃFXø#Þ/· ÿ ɈJÿ9ý“û-ú ù6ø¨÷d÷d÷¤÷øÀø‰ùlú\ûNü6ý þÅþZÿÅÿïÿ¡ÿ*ÿþÛýýGü}ûÁúú ùOù3ùSù´ùXú@ûiüÏýkÿ4!*-  á uÆÈpµ‘˜Ç ˜ LL'ÿïû·ø”õ›òÝïoí_ë½é“èìçÍç7è+é¤êšìïÎñîôPøßû…ÿ-Â- [ 9µÂTcëêaVÑß‹è  ÷ѧþ”ûÏøLöôBòÏðÃï#ïíîï°ïšðÓñMóûôÎö¸ø©ú”üjþ©ÿ÷’í íž#‡ÔTùq ÔÿÇÿëÿ=¾i8!"#ë› a e " “·m€fÿ'ýÓúzø+öøóðñ$ð¡îví®ìRìhìóìõíjïLñ”ó6ö#ùJü›ÿÿe· ß Êf¡m½‰Ë€¨JlaR ÿ|ß?þ¯úE÷ô4ñ¯î–ìóêÏé.ééxé\êµëxí˜ïò°ô„÷oú^ý?“æð ¥ þ ø Ç¢'] O š oÐ<¾c3ÿ3þjýÚüƒüdüyü¼ü%ý­ýHþîþ’ÿ+¯UiLýzÇÿæþÝý¶üxû0úéø¯÷ö•õÎôDôô ôgôõ#ö€÷.ù#ûWý¾ÿHèŒ" š âèôá[ZÜál,x u2Ã>þµú?÷ñóàðî½ëÍéXèhçç-çãç"éàêí±ï¥òÞõHùÎü[Ù4X 3 µÑ{¬`•NbÐå² G ´ `ÁBþïûÕùøxöDõgôâó²óÔóAôñôÙõîö$øoùÀú üIýkþiÿ;ßOŒ–q"°#‡ÿâþAþ®ý3ýÚüªü«üáüOýõýÓþåÿ#‰ œ3Â9 ° – 3~p8 ƒ £u[Žþ©ûÁøçõ/ó«ðmî„ìÿêëéPé5éžéŠê÷ëÞí4ðïòýõOùÏüi ˜ - ‹›0AÇÀ-xhñ" Çd÷˜ýXúK÷„ôòýïVî íaììEìâìçíIïüðòòõi÷Èù(ü{þ°»‘'vz0 ™ ¶ Ž ' ‰¿ÔÓÈ¿ÃÞzÄÿ±ÿÍÿ„¿w4ì’‚º¼ƒ S[(½$ÿeýŒû¥ù¿÷çõ.ô¢òPñFðï4ï=ï®ï‰ðÍñvó}õÙ÷~ú\ýcƒ¨½ ¯ kßù«é¨â”¾b‰;†y % þUý¹ùBöóð}íUë¦éyèÔç¹ç)èéêuìÁîcñJôb÷™úÙý&·  ªÙ›îÕVvBÅ ' #dþÜüŽûú¸ù3ùòøðø(ù’ù'úÚú£ûuüFý þºþKÿ¶ÿöÿëÿžÿ%ÿ…þÅýìüüû3ú`ù¬ø øÆ÷¦÷È÷1øáøÛùûüZþG\ŠÃ÷  Ú^’jÜát•D†c å ؉ý2úêöÆóØð5îìëê©èÄçgç–çQè”éXë“í9ð9óöþùœýBÝW› •6m.r1iNM2à 0 1''Cý‹úøÛõüóyòYñŸðIðVðÀðñ‰òÓóOõñö©øjú&üÐý[ÿ¾ñí¯5l£hºqëÿƒÿCÿ/ÿKÿ˜ÿÚ”©Ïû!5+ ÷ å ö º - M œÕÎ’/þ²û+ù¬öEôòðLîêìíë^ëDë¤ëìÒíšïÍñaôH÷qúÊý?½-{ ’_ÏÔ`jêÜBvVÊâ ¯ F»$–ü'ùêõóòRðîJìøê%êÓéê«êÉëRí:ïqñçó‹öJùüÔþz÷=?ó Q W N E ê E _ D  ¡3Ã]ÞØÿÿ[þëý±ý«ýÔý'þœþ*ÿÇÿi’V|r5Á:.ÿùý¤ü8ûÃùNøéö õ€ô–óíòŽòòÍòuóyôØõŒ÷ù×ûWþÆ”Y  €¾¬=bHü/ãäF Q ¦üòø…õNòaïÏì¨êúèÎç,ççç‘èêì~îDñVô ÷ ûˆþûT}e ú 1üT4š†ý­ûþ È g îmõ–ÿ^ýZû•ùøçööyõ<õKõ õ3öûöí÷üøúDûeütýiþ:ÿâÿZ£º¡\òÿhÿÇþþjýÂü-ü¶ûeûBûUû¡û*üïüðý(ÿ Ï‘X ¾ A ‘ ¡eÓä’Ú½ < ] *¬ñ ýùùôö ôUñàî¾ìþê®éØè„èµèmé«êgì™î5ñ,ôm÷æúþ(ÆF ’ —A‚M—Y:]ÿ(çJb C ÿ¬_ÿ*ü!ùUö×ó²ññïœî¹íGíGí³í„î²ï0ñðòåôÿö-ù`û‰ý˜ÿ;¹÷îž( ±'u¦ÄÜù%iÎ[ýÿYÉ^Û°†Q B@ýw¬œK¿þüüùå÷Ûõïó0ò¬ðrïîîéí7îõî"ðºñ·óö¸ø¡û»þó7r |%wdÞÚQ?¡{Ò° 2 ÷ ‚è@ÿûøÀô°ñöî£ìÄêbé…è0ècèéPêûëî{ð1óö-ùMüjÿnKîJ S ý D"–£Nœ˜L Æ  Bb­ó`ÿúýÊüÖû!û«útúwú®úûžûBüøü²ýhþ ÿšÿI`Gÿÿ‡ÿâþþ-ý+üûú ùøL÷«öBöö5ööS÷Xø©ùBûý*ÿc»!†Ù À)4× È Ü8(· ðã£BÿÒûkø õò1ï´ìêûèÙç>ç/ç®ç·èEêOìÈî¢ñËô0ø¼ûZÿôuÇ Ø –ñÝOB± ýžfé 7 cŸÕþ0üÁù“÷´õ*ôýò/òÀñ¯ñöñòoóŒôÛõM÷ÕøfúóûoýÎþíú-+ùž#ïK¯ÿ%ÿµþjþHþVþ˜þ ÿµÿ‘¸úL¤ó/ I 5 é Y ~ Q Í ñ ½ 4^BëhÿÅüúg÷Îô\ò"ð0î—ìbëœêNê~ê,ëXìýíð”òmõøêûjÿøï , %ÇÈÌý ¸KaK? õƒýyþ ûÇ÷Âô ò´ïÆíKìKëÇêÀê3ëìiíïñWóÈõYøøú“ý{¬ L© ² f Ä Ð  E P 5¾|D"C–ÿÿÎþµþÍþÿzÿ›Açƒ s´Ç¥K·êå°ÿPþÍü3ûŽùê÷Wöáô–óƒò´ñ4ñ ñ?ñÕñÌò%ôÙõã÷8úÌü‘ÿuiY3 ã XIª•íS5—ƒ$ ÷Žþ]þ¿ú9÷ãóÏðî¹ëÔéoèç=çwç;è„éIë}íðøòöhùËü-{¢ 2 |bÛáqŒ6tPÔ á ˜E÷½¦þ¾üû¡ù{ø ÷÷ÍöÐö÷’÷?øùúýúüûóüØý¡þFÿÂÿ-Ýÿtÿèþ@þ…ýÁüÿûJû­ú2úâùÅùãù@úÞú½ûÜü6þÅÿZKB2 À @o< nfô  í j¤©Œþ^û3ø õ8òŽï3í9ë­é›è èè‚è‹éëí•ïnò™õù–ü=äuÙ ý Î;6¶±# kJ¯¦>‡ “ vB ëýìú$ø¡õqóžñ2ð0ï›îsî³îUïQðœñ)óêôÐöÍøÐúÌü³þvp–{}œ€/²X‘ÆT¾Lçÿûÿ=­HáÎŹŸkŒÍΊü#˜ïÿÑüŽúFø öêóöñ>ðÐî¹íí¹ìßìzíˆîðóñAôæöÓùùüC û@ Y 3»á—Ñ…°M`íü˜Ï³ UË)‡ýøù’öjó’ðîì}êléßè×èSéMê½ë–íËïMò õï÷éúæýÑœ4‹• I ž ’!O”» ž G Å &vÅ ’&çþÚýýiü üâûðû/ü–üý¹ýbþ ÿ«ÿ6¦ñÁMªÿÚþâýÌüŸûgú0ùøóööKõËôô ôõ·õÀöøÄù³ûÞý8¶GÚ_ Ä ÷èˆÊ£õeZ×áƒ È Á}ýú¤öcóað²ídë‰é*èQççEçègé;ëƒí1ð4ózöïù}ýé Ý Vf#Å猸uÍΆ  b©îC¸ý\û<ùb÷Ùõ¥ôËóJó"óMóÄó€ôvõšöà÷;ùúûûHý{þŠÿlçýã3¬qÿÐþ<þ¾ý`ý*ý#ýOý±ýKþÿL¡‘“ú = Q ' · ÷ ß k ™ j à ÖkË þ2ûYøõëòzðQî~ìëê‹é…éêë~ìsîÖðšó¯öú†ý¹@ž ¾ŽûøxráÃç7‡§ ƒ /ÁLèü¦ùšöÖóhñ^ïÁí™ìéë²ëñë¡ìºí0ïøðó@õ ÷ú‚üãþ%<¸  É 1 K  ¯  3<.ýñû%vóÿ ÿ}ÿŠÿÅÿ'¬Kú°aŒñ)/ûŠÛîÆjàþ1ýhû“ùÀ÷ûõUôÛò›ñ¢ðûï¯ïÅïAð%ñoòô&ö‚ø#ûüýû', ¶¶Ý†ªF\í¦ä Í séEžüù—õcò~ïùìãêGé/è çœç"è.é·ê³ìïÈñÀôè÷+ûvþ³Ñ¼d » ´Fl"g>­¼uä   åijÁÿùýeüûùù*ù¡ø]ø\ø–øùžùYú+ûüäü¶ýsþÿÿÝÿÿÿòÿ¶ÿMÿ½þ þ@ýeü…û«úâù5ù¯øYø<ø^øÄøqùeúûýÆþ¦¬Éñ   »+Lrgì¥ß · 6 kd2ëüŸùeöPótðäí°ëééšèÌç†çÌçèôéËëîÍðÙó,÷±úSþú” F 6Éñ¢Ò} =Xù+úw³ À²œ’ÿ¥üæùg÷3õVóØñ¿ð ðÃïÝïUð$ñ?òšó)õÝö¨ø{úHüþžÿQY&´û«3ó?ŒåTâÿ•ÿsÿ€ÿ¾ÿ,Èx}“¯ÇÍ·w  U ` ’ ³„ JLÆýXûâøuö!ôøñ ðeîí0ì´ë­ëìíhî;ðwòõú÷#ûzþê_Å È$Š}åÁÕåHP   oÿàûqø9õIò²ï‚íÅë„êÃé„éÇé†ê»ëZíVï¢ñ,ôâö²ùŠüXÿŽÚß” ò ô ˜ Þ Ë e ² ¾ ” @ ÐPÎX÷·¡ÿ¹þþŠýEý4ýUý¡ýþœþ8ÿÚÿx ‚Ù  ØqÖ ÿèý¤üJûåù‚ø.÷ôõäôôjóóófóôõyö+ø*úküâþ8÷« C ¬Ô®(8Ôõ–·Z…B› Ÿ `ðeÿÑûKøéôÀñâîbìOê¶è¡ççç§çÀè[ênìëîÃñåô;ø²û5ÿ­0  £ÏÙªþ×;0Áúé ž + Ÿ‡ÿÙüÌúù~÷Kökõàô§ô¼ôõ·õŠöˆ÷¦øÖù û=ü]ýcþEÿýÿ…Ý÷¿_àÿGÿ þõýQý¾üFüóûÌûÙûüœüWýKþuÿÍNìœQý“  B AöW[ÿ? – ¶ „ Uwÿ~ü~ù‰ö³óñ®î¡ì÷ê¾éþèÀèéÓé"ëïì/ïØñØô!øû9ÿÝwï 0 'Âò¨Ý‰©<HÓç‘áè ¹i ·þ}ûrø§õ+ó ñTï î4íÑìáì_íCî„ïñêòóô÷`ù¥ûÝýüÿò¶>ƒ€3œ½œ?®ô.:If›ñmîÿõÿ*‹¸u> Í}v®¬më&ØX¨ÿÎýÙûÔùÏ÷ÙõôTòäð¼ïèîsîdîÁîŠïÀð`òaô¼ödùJü^ÿÆó Üq¯†éÎ/R\)Š K Ï1‡þæúd÷ôñdî!ìSêé<èýçFèéaê"ìKîÌð”ó’ö±ùÝüò˜ô ú ŸÞ²¶óÞ€ ç ! >KXsªÿ”ýXüZûú!úåùåùúƒúû¹ûuü8ý÷ý§þAÿºÿ 1(ñÿ‰ÿõþ:þ_ýnünûmútù‘øÍ÷5÷Òö­öÍö6÷ë÷ìø8úÈû—ý›ÿÆd·÷  ü¢÷î M„F—  ?2õ™þ2ûÖ÷™ôñÌîbìaêÕèÊçGçOçäçé¦êÃìMï6òlõÛønü«+x ‚ 5„`Á¡ýÔ*s|0Ÿ Ú öBþ•û ùðöõˆó^ò—ñ1ñ*ñ~ñ$òóAô õ$÷¾øaúÿûŒýüþEaH÷l¨®‚+²}Ö5¥ÿ-ÿØþ¬þ­þáþHÿáÿ¨›±â$kªÖâ  j Ð í ¹ 1 R  ™Ç²eíþXü·ù÷”ô5òð4î¯ìëßê¥êçê¦ëâì•î¸ð?óöDùŸü¤%ˆ ·  0W8Þø„…–É­ WÛMÅýUú÷ôdñï4íÈë×êfêrêùêôëYíï1ñ†ó ö­ø\ûþ˜?9èG P Z ^  ƒ ´ ± ‡CñT!"dÿ×þ~þYþeþžþþþ}ÿ´Xó|ç.G.ÞU•Ÿyÿ(þ¶ü.û›ù ø‡ö#õèóåò%ò²ñ•ñÓñpòmóÈô~ö†ø×údýøß¿ˆ %…—L–kÃ™ë» ë^v C×G¨ýú’öGóAð“íLë|é,èdç(çyçTè´éŽë×íðvó¨öúoýØ+T@ Þ "þldåyêú º _úœT0þ=ü…úùå÷÷yö6ö=ö‡ö ÷Â÷ øšù£ú±û·ü¬ý…þ;ÿÇÿ$SP ÆÿGÿ«þúý?ý…üÖû=ûÄútúVúqúÈú^û5üIý—þÂlQ/ ö — 1˜¿€ÙÈP v B Áþ öýÓú¶÷³ôÜñFïíë¦é«è1è>èÔèñéë¨í-ðóGö¶ùMýö›&‚ š]»¥öR$m5ƒeé  î®oEýBúw÷õôÈòüð—ï îîþíNîïðmñ óáôÛöêøÿú ýÿÕyç«0Á?™Ø3e¨ƒ*ÿÿ4”Í™xaI%è‰ü98ôh“wx££þƒüPúøòõåóòaðïî`í&í\íîï©ðœòïô•÷‚ú¤ýè=Ã Ì ”¹ÛyŒ‰„8 ©rÏüBùâõÂòôï‰íŽëêé—è¥è7éGêÍë¼íðœòkõaøjûsþh:Ø1 < í >*°Ò”üå } é 7v³ü]ãÿ”þyý˜üòû‰û[ûeû ûüü,ýØý‡þ.ÿÃÿ<“À¿)–ÿÖþïýéüÍû¦ú~ùaø]÷}öÍõVõ"õ7õœõSö[÷´øWú>ü_þ®Ÿ!” å àk™\®‰éÏ>>×  Ê`æünùöÛòêïLíëMéèCç çeçIè´éœë÷í¶ðÈó÷™ú.þÃE¹ …ôöƒ”#2Âـ®R ¿ ?v¿ÿ)ýÅúŸøÂö8õô/óµò”òÉòLóôõMö£÷ù‚úñûPý“þ²ÿ¤fóIkZ¹7 `ÿÉþGþãý¦ý•ý·ý þšþ\ÿNm°~ò]³ ç ë ´ 7 l K Ñ ú È > a;×AŠýÁúø÷Aõ®òRð>î€ì'ë>êÎéÝélê}ë í ï{ñGôc÷»ú=þÒgå8 J dL·›ó½ü³í´% ò ’ ÿ6üóøèõ)óÂðÂî1íìwëRë¤ëgì•í ïýðólõß÷aúâüRÿ¡Â©L¥­ d É Þ ª 3 ƒ £Ÿ‚Z3*j×ÿsÿAÿ@ÿmÿÄÿ=Òy(Ôsû`›¥wh‡l£þýMûŠùÉ÷öƒôóíññlð.ðPðÖðÂñóÄôÏö(ùÆû˜þ–Ÿ• d úD3¹É[iñòrw >  ¾1ŽÿéûWøðôÈñðî|ìwêïèíçtç‡ç%èGéçêøìlï4ò=õsøÃûÿ\~k d Wáû¤Ú þúŸû   å°}]]ÿˆýéû‰úmù˜ø øÈ÷Ç÷øwøùÛù·úŸûˆügý3þáþlÿÌÿÿÿÖÿ}ÿüþXþ›ýÍüøû(ûgúÁù?ùìøÐøòøUùýùêúü‡ý+ÿýô%  ó “ñÿ²è`i8 ‰¾»‘ÿRüùæõáòð›í}ëËé“èÜç®ç èðè[êEì£îfñ~ôÚ÷eû ÿ³J¹ í ÓXp,ÂÏUZäº$M J- ÷þü?ù¾öŠô°ò8ñ'ð€ïAïhïðïÏðûñió õÑö¯ø”úsü>þéÿi·Ë¢8ªŒ<Ã*{ÁU¹:àÿ°ÿ­ÿÜÿ9Å{TIO]f`>ôy Ã Ê ‡ øð{ÃЬÿdýû¡øFöôðñð‡îNíyìììœì”íïÞð"óÀõ¬øÕû(ÿ‘þX Š )rL¬‡ØœÔ„´m¿¹ n ñX¹þ)û½÷Šô¢ñïóìEëêgé=é•éjê´ëií{ïÛñxôA÷!úýáÿœ)z‚ 8 “ -kNÛ   Ý y ÷eÒJ؇aÿkþ«ý"ýÒü¹üÒüý„ý þ¨þLÿîÿƒb›§‚)œÞÿòþßý¬ücûú½øy÷OöLõ}ôìó¢ó¦óô°ô¹õ÷ÇøÁúúühÿú¤Sõ z Ïã§ Žš)8Ìëœí ì«;³þ%û©÷Sô7ñjîýëþé{è|çç"çÈçøè©êÐì`ïIòxõÛø\üåÿa¼â Á HkZ[!pQÌðË l æI¨›þNü9úgøâö®õÏôGôô0ô–ô>õö*÷Vø•ùÜúüOýeþXÿ¸ST(Ó[Ëÿ*ÿƒþáýNýÕü~üRüXü”ü ý¸ýŸþ»ÿtŸBÜ` ¿ í Ü ‚ÖÏi¢ x ñ  àk¾éþüû ù&öaóÐð„îìùêÖé,éé_é?ê ë|íËï~òˆõÕøUüðÿ’%” Ê ³=Zý±¹6+Ÿž4qg *Îg þÎúÁ÷øôòiðºî|í³ì`ììí î^ïñìò õI÷œùñû:þei8ÈÊ3 S . Ë3oŒ“’’¡Æ wØÿÏÿõÿF¿Y È‹Gð}äßc¦¨lùVÿý¨ûµùÂ÷ßõô€ò"ñ ðJïåîåîNï"ðañó õh÷úðüýÿ#On l 4µÞŸìºÄü­ßœïé œyÏý1úµöpóvð×í¤ëéé®èûçÑç2èézêQìî$ñÿó ÷:úsý¢¶œD Ÿ   @v?œD¬ ' 1,'2X¨þ(ýáûÚúú“ùTùRùŠùòùƒú3ûöûÂü‹ýHþîþuÿÖÿ êÿ“ÿÿeþšý·üÆûÒúåù ùRøÁ÷d÷C÷d÷Í÷€ø}ùÂúJüþ#[ á  ê|½¡/Ìö¬ôÕ Y ŽƒIôý—úG÷ôñoîì-ê¸èÄçWçwç#èXéë>íÙïÐòö‰ù#ýÇcß( (ÑÞ-ú@B _RñM w ‚‚‰«ýöú|øJöjôåòÁññ¥ð©ð ñ¿ñ¾òüómõ÷¯ødúü²ý3ÿ‹µ©dã'4 ºB¯ `¹ ¡ÿAÿ ÿýþ#ÿ{ÿ»£Ãô*Zxv I æ D Y • µ ‚4'äyþòûaùÕöbôòð?îÐìÅë)ëëVë'ìqí1ï]ñíóÐöùùSýËNÅ =’¥@Yèê_J±ž@ µ/›ý ùaöeó¾ð{î¦ìIëjê ê,êÈêØëRí,ïTñ½óUö ùÈûþ•ÖÕ‡ ç í š í ê – ù  Ò~¶\ôøÿ*ÿþ(þöý÷ý'þ~þ÷þˆÿ&Èdï_«Ì»vúG_Iÿ þ¨ü2û°ù0øÀölõBôNó›ò5ò"òhò óôlõ!÷&ùrûøý¨vN Ô ^ª¦Ez9|=|;~N· Ç  ‘õücùïõ°ò¸ïíçê+éñç?ççƒçvèìéÜë8îóðúó;÷¡úþ†Ýð ‰ Å˜ùãSLÐè›÷ß ‹ ¨:åÿ´ý¶ûöù|øM÷nöàõ õ«õûõ‰öI÷3ø9ùQúmûƒüˆýqþ8ÿÔÿB€k¬ÿÿtþÁý ýcüÍûUûûåúûúLûÚû§ü¯ýðþbý¸…X# × f Á Ü«#=óA(ª Í ™[ndýNú@÷Mô‰ñïÕìë¨éÃè`èƒè.é^êì7îÊðºó÷ölúþ­OÔ' 3è5 c4z4fPŒ° › aÎÿœü•ùÊöIô!ò[ðïî™íŽíïí´îÕïEñùòáôíöù7ûTýZÿ:ëc›<¢Ä§QËU{›ÀõC³J#sîJùÕ§büj¤£_Öò›?Mþ<üú÷÷áõèóò‹ðDïSîÂí™íÞí”îºïLñEóœõDø/ûMþŠÕ@ 8íMIÒÞd`ѹ‚ i ùb»ÿüø3õòZïýìë¤éºèVèzè#éJêæëëíJðóòÔõÙøðûÿÝ~Ú ã ‘ Û¿;Q^e% «  @m˜Ï –ÿ:þý%üvûûÑú×úûtûýûŸüPýþµþTÿÙÿ;vƒ` ŠÿÛþþýüëúÒùÄøÍ÷øöQöãõµõÏõ7öíöô÷HùåúÄüÛþ~ð`À ý ÐF_Ng?¢˜* f Z´ÿ?üÑø}õYòyïîìÉêéçç=ççŽçˆèêìrîBñbôÀ÷GûâþzûQ f *‚þ{uðñ‚¯† p §Î÷5ÿ•ü*úÿ÷ ö–ôgó•ò!ò òIòÙò¯óÃôöm÷éøoúïû_ý´þãÿåµO±ÝÖ BÄ0îÿTÿÍþcþþþþcþáþ”ÿv…¸cÅ f Š € < ³ Þ ¶ 5 [ ' žÄ¤H½ÿýWúž÷ùôzò2ð3î‹ìHëtêê;êÝêþëšíªï#ò÷ôøqûòþƒ† Ì Ï}Å™î»ü¯ÖwœNŸ \ ñpïþƒû?ø8õ}òð)î¦ì›ë ëøê]ë6ìxíï ñ<ó¡õ&ø¹úJýÈÿ"M<å@ I ÿ ` p 5 µ ù ûЙa4&V³ÿ?ÿþþïþÿZÿÊÿUõžGãjÑ÷—ü&Úÿnþàü;ûŠùÚ÷;ö¹ôbóEòlñãð±ðßðnñbò·ókõu÷Ìùdü/ÿö ³ 5jC³­)!”ƒñæn– n y×þ5û«÷Mô1ñhîìê è³çPç{ç/èiéëEíÍï§òÀõù`ü½ÿ- ¿ øx†!GüG0  ö ºr/ÿòþýhûÿùÝøøv÷2÷3÷t÷í÷•øaùGú;û2üýúý¸þSÿÃÿþÿ´ÿBÿ¬þüý:ýoü¨ûïúNúÑù€ùdùƒùãù…újûüòýŠÿM4030  × d¯«MeÐÎb _ Üóþ¾ûŠømõyòÂïZíQë¶é•èõçÝçOèJéÊêÅì2ïò'õ‹øüÃÿjþg ’ kâéu~ÿöeSÇÍrÈ à Í¢tWþ\û–øöáó òšð’ïõîÄîúî‘ïðÀñ@óôôÎö¾øµú¦üþ;Ê$C"À;ÎS¶?{ÀŒ#äÿÓÿñÿ>º_( îÁnì0 3 ï`…_òBZCÿ ý»úhøöòóññ,ð°îŒíÊìtììí%îžï„ñÎóqö^ù…üÓÿ5˜å  |ʼnÃp‘,Gï1 ÇA£þrú ÷Üóþð}îiìËê­ééýèkéVê·ëí¨ïòÍô§÷—ú‹ýo4È' Û 4 +ÁõÌL} j  © rÍ3°PÿþIýµü[ü9üLüüöü}ýþ¿þeÿ†ï3K2èj½ÿáþÞý¼ü„ûBúùË÷°ö»õøôqô0ô<ôšôNõWö´÷`ùTû…ýèÿm§8 © êé—çÍ@9µµ:Lô > 9ö‡þ}ú ÷ÁóµðùíŸëµéHè`çç4çòç8éþê9íÛïÔòöùý–q“ l ë¨Ô‚²džiÐÞ¤ 2 ™ë;˜þ¾û¢ùÌ÷Cöõ3ô¯ó‚ó§óôËô·õÑö ø\ù´úüHýoþsÿKóhª¸–KÛQµÿÿqþÝýbýýÕüÓüýpýþìþùÿ2‘ š+³% t ‘ q Q@Ñ  Ö L m?Ð+aþûøÉõóšðbîìëöécéOé¾é±ê#ìîjð(ó9ö‹ù ý¦DÐ5 ^8±»IRÑÂ'cLÏú à •.¾]ýú÷IôØñÈï$îóì8ìöë)ìÌì×í@ïúð÷ò'õz÷ßùEüþÖæ¾W¨­c Ë è ¾ U ´ç÷òãÕÓéy¹ÿ ÿ·ÿûÿfó˜N¾bìR‰ŒUß*6  ÿSýûžù¾÷íõ:ô´òhñdð²ï]ïjïÞï¼ðò­ó¶õøµú’ý–³Óã Ï …ò°æÐ{ž<] P@ êcÀý~ù öÎòàïPí.ë…é_èÁç¯ç&è"éœê‰ìÛî„ñpôŽ÷Éú þE_Hñ I FÞ ÉùsŽTÐ  % îèAþµüdûTú‰ùùÀø¾ø÷øcùùù¯úzûPü%ýîý¢þ7ÿ§ÿíÿìÿ¥ÿ2ÿ—þÛýý$ü<ûZú‹ùÙøOø÷÷Ø÷ú÷bøù úGûÅüþhw Ó   ÐN|M¹¹GdN) « ßÖ¡Týú½öžó¶ðîØëê£èÆçqç§çiè³é~ë¿íiðnóºö:úØý“Ô Ëg™U“K|(RB «ó ù÷ÿýTúÖ÷£õÄóCò&ñnðð-ð›ð_ñoò¿óBõéö¨øoú1üàýqÿØÖ_«¾›JÓ>–æ9˜¤ÿ_ÿFÿ]ÿ¦ÿÆ—Œ›¼ã Í ` µ Ä ‡ ù  ék¦¢j þ“ûù™ö8ôòðSîùììzëfëÌë¬ìîÏïò›ôƒ÷¬úþxó`ª ¼‚ìêoqéÔ2X1Ÿ² { èÿZüêø¯õºòðäíìÑêê¸éíéžêÃëTíBï€ñýó§ölù:üÿþ©)qt( ‡ ‹ 3  r  j € `  ²=È\ÒÆÿéþ?þËýŽý„ýªýûýnþûþ—ÿ9ÖdÙ,UO¥("ÿòý£ü=ûÍù_øÿö¼õ¡ô»óó»ò²òó©ó¯ô öÁ÷Ãù ü†þ,í¶u  Æ®7Uÿ-Û¶ê®  ÙjÜÿEüºøQõò6ïªìŠêãè¾ç$çç–ç è,ê1ì¡înñ…ôÓ÷CûÁþ6¸Ÿ 3f.\¼¢´ûø » T ÕNÑnÿ2ý+ûdùä÷³öÓõFõ õõsõ öÕöË÷ßøú1ûWülýfþ=ÿêÿhµÑ½}ÿñþFþ˜ýòü]üæû”ûpûûËûQüýþBÿ¥0Ú–W ± - w @ª·a§‡  % òu½ÙÿÙüÏùÐöîó=ñÎî³ìûê²éäè—èÏèŽéÒê“ìÊîkñeô©÷#û¾þd Ç Çm¨l¯j™<WñË(:  Îw(ÿñûçøöózñ¼ïkîŒíí$í–ínî¢ï&ñíòéô ÷=ùvû¤ý¹ÿ¦cå%Ï8Z:àT Íèü;{Ûbùÿ JµFõº‹]&ÙnØÍHr$œâÿÿýþûîùÝ÷Ùõôó;ò¾ðŠïªî+îîeî'ïVðññðóIöñøÚûòþ'gž¶ ?‹pã×G,‡Z«ƒïý ¾ G«ÿ`ûÛ÷‡ôzñÅîwìžêBélèèXèéUêì!î•ðQóCöXù}üÿ¤‚'ƒ Š 3wRÃÌqº°^ Ò  A[t›ÜCÿØý¥ü­ûõú}úDúFú~úãúnûüÌü‰ýAþëþ|ÿìÿ3O<ùÿ†ÿèþ"þ=ýAü8û-ú,ùAøw÷ÙöröJögöÐö†÷ŠøÙùoûEýPÿ…Ø8—ä  ·»çŸàªð | µ¨h ÿœû9øòôÞñï˜ìˆêíèÓç@ç9ç¿çÐèeêuìôîÓñõhø÷û—ÿ1±  Ì" vb˰|“UÑ  ?Wr¥þýû‹ù]÷}õôóÈòüññ‚ñÍñjòPósôÇõ>÷ÍødúöûwýÝþ- ±UV&ÍR¿yÝÿPÿÞþþjþtþ±þ!ÿÅÿ—•·ó@‘Ü '  ¿ , N  ™ ¼ ˆ +¾?ÿ üôùL÷¹ôNòð0îžìpë²êkê êTë…ì/îKðÍò¨õÌø'ü¥ÿ2¸" [ Oë ÞÓü˜¨3Câ  ÁKÂ=þÎú‹÷ˆôÔñï”íì$ë¦ê¥êë ìcíïñfóÞõtøû¸ýB©ÝÒ€Ý ç ™ ö ¼ 2 k q QЈJ#9†ÿÿ´þ—þ«þëþQÿÕÿn¸SÛD‡œ}&–ÍÍÿBþÄü0û‘ùô÷fööô±ó£òÙñ^ñ9ñpñòó[ôöømúÿüÁÿ¢‘|P ú hˆK¤ˆîÒ1 jQÌê »QÁ!þ„ú÷®óŸðæí”ë¶éXè€ç5çwçCè“é_ëší6ð!óIö›ùýe¶ÝÊ l ´–  ˜®RŠ_Ü Õ †-Ùš€þ“üáúqùIøm÷Þö›öŸöåöe÷øìøÝùÞúâûßüÈý—þBÿÃÿ9,óÿÿÿcþ¬ýëü,üyûÝúbúúöùúnú ûæûýWþáÿ–lWH2  ³ -fPâÝ=1¾ æ ´ 1lsYþ/û øûôòuï!í/ëªéŸèèèè¬é>ëKíÇï¥òÓõ>ùÓü{!° 2þf\ÕÉ3mC¡‘#e l IÙ´ý´úê÷hõ9óhñþïïoîKîî8ï:ð‹ñóæôÓöÖøßúáüÌþ•1—À¨L­Í±`á?ƒ¹ë%pÖ_ðÿþÿ;¦;ôʲ¤”w@å\œœXÊóÓmÇêáþ¶üxú7øöèóúñIðáîÑí"íÝìí¨íºî=ð+ò{ô!÷ú2ýzÕ,l € TÖõ£Õ‚¥;GÌÕk} ìJý»ùWö2ó]ðéíäëWêLéÆèÆèIéJêÁë¢íÞïfò)õøûþÐjÂÍ  Ô ÅQ{E·Ù ¶ Z Ò ,wÀÌþºýáüBüßûµûÂûÿûfüíüŠý4þßþÿ‚Ñõë®@£ÿØþæýÕü®û{úIù#ø÷.övõùôÀôÓô5õëõôöOøöùâû þ`Úeór Ð ü总ŒëÑ<,¤«J Ž …AÖWýÙùqö5ó9ðíHëtéèLççOç$èéZë©í\ðeó¯ö'ú¸ýJË%D ‹–.IåŸÄzËÄv ð E†Ç‰ý*ûù-÷£õpô—óóòò óœó\ôVõ€öË÷+ù“ú÷ûJý‚þ–ÿ~5¹! Ç_ÚB¡ÿÿkþìýŒýTýJýrýÑýfþ2ÿ.X§Œ ‚ã ! /  É ® 8 d 4 © Ë¢9Þý û7øuõÖòlðJî~ìëê¡é¡é$ê)ë¬ì¦î ñÔóëöAúÃýZóxÒ í·€èÂ×ób| S üŠ­üjù_öœó1ñ*ï‘ímìÃë‘ëÖëì¬í*ïùð óNõ´÷*ú¡üÿNhJé?F ý c | L Û 1 Y^K-þ(sëÿ’ÿjÿrÿ¨ÿ‡#σ2Ó[ÀúÎ`´Ë¨OËþ!ý^ûùÂ÷öcôïò¶ñÂð ðÙïóïrðYñ¦òUô_öºøZû0þ,=PP + Î&#¸×x•+9ÅÕs­ “ 6¬aüÌø_õ/òNïÏì¾ê)éèç”ç"è5éÆêÉì0ïëñéôø]û¬þë öž ó êzœNŽ_ÉÑ„ì   þÔ­—¡ÿÔý=üâúËùúøpø,ø*øeøÕøqù/úûäûÄü›ý]þÿÿ×ÿþÿöÿÀÿ\ÿÑþ$þ^ý‡ü«ûÔúúcùßøŠømøøõø ù‘úÇû;ýéþÄÅÝþ  ®3òM=¾Îp¨ ~ ü1+ýÿ·üpù:ö*óTðËížëÞé–èÑç“çàç·èêóëFîÿðôf÷íúþ8ÑD ~ kúÇñ•±FYóæ\’ ™†l^ÿoü¯ù.÷ûôó£ñŒðÞï—ïµï3ðñ'ò‰óõØö©ø‚úVüþ·ÿ-rOà3K+ÛcÌ jµ v¯ÿˆÿÿÉÿ1ȉml}”§©L Ö $ . í ^ €RÚ"öÿ¥ý<ûÌødöôôñ ðoî*íGìÒëÑëGì6í›îqð°òKõ6ø_ûµþ"•÷2 4é?(–âµü»ø¾ Û dÏ3ÿ£û5øþôò}ïRíšë^ê£éléµé|ê¸ë^íbï´ñDô÷Öù³ü…ÿ9Á Ë ( ( Ê ÷ Ö Ý ­ T ÞXÑTí¨Œÿ þéýhýý ý*ýtýâýlþÿ«ÿJÜW±ãèºXÂúÿÿäý¥üQûòù•øF÷öõ.ô•óDóDó™óGôOõ®ö`ø]ú›üÿª]Å V ¸Ú¬ )¾×r+R a d $´)ÿ—ûø¶ô’ñºî@ì4ê¢è”ççç²çÒètêŽìïïñõpøêûoÿéCk M Ú¿ÏñN<Æ÷à  ƒíañþ«ü›úÍøJ÷ö7õ­ôvôôíôŽõeöh÷ŠøÀùûú2üWýbþJÿ•òá…sÿÎþ$þýîüvü!üùûüEüÁüxýhþÿà\ôžMóƒ î & Ð,-Í å _  MÔ"GÿRüWùgö—óùðŸî™ì÷êÅé éÕè#éöéKëícïòõ]øÚûvÿ²' d VìÅó—¯;?ÃÐs¼¾ Š6Õ~þCû7ølõòòÕð ïÛíí«ìÀìDí/îvïñêòùô,÷sù½ûûýál³²eÎïÍnÛAQXb{«ûrèÿéÿu÷™Rà¡NÞF}|=½û÷´8Œÿ¸ýÈûÉùÊ÷ÚõôbòøðÖïï™îîïî¼ïöð—òšôõöù‚ü”ÿÀô & ú‰¿ëÉ!ð6õ3úWY  “ôJþªú*÷ßóÝð5î÷ë/êçè%èíç>èéiê1ì`îèð·óºöÞùý7G+Ñ- 1 ÕâFA×ó ð $ :AI^èþpý1ü0ûpúòùµù´ùëùRúáúŒûJüýÒý‡þ$ÿ¢ÿùÿ# îÿ‹ÿýþGþrý…ü‹ûŽú™ù¹øù÷d÷÷ßöÿöh÷øùfúôû¿ý¿ÿæ)yÆ  ÷–äÖ_{"UaG Î ø»bþþú¦÷môiñ¬îIìOêÊèÇçKç\çøçéÈêëì{ïiò¢õùªüMég³ º j³‹æÀä3no„ º ÐÙèþaûêø¹öØôQó*òeññÿðVñòöò)ôŽõ÷¸øaúü˜ýÿ\|g“ÒÚ°[âO¬aÏÿTÿüþËþÉþøþZÿíÿ¯­ÙV·¿ š > ¢ ¼ † ý  êe–ƒ9Æþ5ü™ù÷‚ô*ò ð7î¹ì¡ë÷êÃê ëÑëíÈîïðyóZö€ùÛüVÝ[º ä ÈRrCâôyrèânœ| "¢‰ýúØöÙó,ñáîíë²êGêZêèêêëVí!ï<ñ˜ó"öËøû.þÄ5ql | „ 4 ‹ @ « × Ð ¡W¦XRÿÀþbþ9þAþwþÔþQÿåÿ…(ÄMºº6z‰hÿþ±ü.û¡ùø™ö:õôóLòÝñÃñò¤ò£óÿô´ö¼ø û–ýM#ࢠ9’J[¬{Ǒ޷'< š lýÕù\öóðjí*ë`éèWç#ç{ç_èÆé§ë÷í¥ð¡óÙö6ú¦ýfz  X2›  Å†ïò « Jà|/þüVúßø³÷ÕöFöö öXöàö™÷{øyù‡úšû¥üŸý~þ9ÿËÿ-ad8ãÿhÿÏþ"þjý²üümûôú¥ú†úŸúôúˆû[ülýµþ0ÖœuT, ì ‡ ï ïq”R§“ = ‰ÇÕÅý¦úŽ÷ôÀñ/ïñìë¦é²è@èTèñèê¹ë×íaðJóöóù‹ý3×`¹ ÎŒäÈ- `*l,sNËû ñ ¿|9 ý ú>÷¼ôòÆðdïqîííØí-îçîûï_ñóàôàöõøû#ýÿöŸB1Û?aEñnÆ/V„”6/й€Z?#û¼ZÌÂ7dJíR†þkü>úøëõåó ònðïî€íLí‡í4îRïßðÔò(õÐ÷¼úÝýp¼í ñ ² *ÂÝs~þôf[áØ nÛ5’üù§õŠòÀïZídëêéòè€è–è/éGêÔëËíð¸òõˆø–û£þœpi s # r\ßýº/û ó ;t«îJÊÿwþXýrüÉû^û.û6ûpûÕû]üýüªý\þÿžÿu¦ª}‘ÿ×þöýõüÞû¼ú™ù‚ø‚÷¦öøõ…õSõjõÐõ†öŽ÷æø‡úkü‰þÔ?»7£ î Û`†Cc¾Ÿ ž Ü ÒŽ&®ü9ùÝõ¯òÃï,íúê:éúç@ççrç]èÏé¾ë îäðûóQ÷Óújþ‚Ùó ½'&­¸AIÒ₽¡? ¦ éL‘ÿøü’újøöõÑóüòƒòfòžò%óóóüô4ö÷ù{úðûTýþÂÿ¹kƒHæfÐ/ÿøþtþþÎýºýØý+þ³þoÿ\v´ väJš È È Œ =  Å ’  -§aýúÙ÷(õœòGð9îƒì1ëOêæéûé‘ê§ë9íAï²ñ‚ôŸ÷øúyþ   j w0…gʦ÷¹ð Ó“ïø Á ]âeÿúû·ø­õïò‹ðîííëSë3ë‹ëVìŠíïñ%ó}õõ÷}úýxÿËðÙØá — û  Ù _ « ǾpC!*dÌÿcÿ,ÿ&ÿOÿ¡ÿ©Mú¥CÊ0lxLæDfP‘þ÷üFû‰ùÎ÷"ö”ô2ó ò&ñ“ðYðð ñ÷ñJóüô÷_ùûûËþ½Âƶ  R9¸ÀKRÓÎGGØ ä ôQÿ¬ûøºô•ñÂîSìUêÔèØçgç‚ç'èRéøêíŒïZòhõ£ø÷ûOÿ•¸¥K œ *ÎÿÀ ¬  Øœd>:ÿaý¿û[ú=ùgøÛ÷–÷–÷Ô÷Iøìø²ù‘ú}ûjüNýþÓþbÿÈÿâÿŽÿÿtþ»ýñüüRû”úïùpùùù#ù…ù+úûAü«ýLÿ !*  ë „Üä‘ܽ06Î Ò O…ƒ\ÿ üäø½õ½òúï„ímëÄé“èäç½ç è éêoìÒîšñ¶ôø¢ûHÿð†ô $ ‡™2H×Ý\XÛð£* !ÿÙÂþËûù…öRôyòñõïQïïCïÐï´ðçñ[óõÏö³øžúƒüTþ‰ÛóÌe¾Ú½móY¨ë-yÙV÷ÿÂÿ»ÿäÿ;ÂrF57@E:ÈJ ’ — T Åé¿M˜¨‰ÿEýìúø8öþóðñð“îbí“ì1ìAìÇìÄí5ïñ[óûõèøübÿÈ2‡ µ ¦HŠ]µ‰ÒŽ¿hD† 6 ·|þìú÷PôkñâîÄìëòéJé'é†ébê´ëpí‰ïðñ”ôb÷Hú3ýÎ^°¹ n É Ä _™x< 4 ô Š kÑCÌuKÿPþ‹ýÿü«üü¦üêüUýÝýxþÿÀÿWØ;x‡fŠÒÿìþÞý°ümûúÓø“÷oöqõ¥ôôÑóØó3ôåôîõL÷ûøòú)ý“ÿ!Æp ‹ Ùæ¢ôu{ œ¶d³ °nÿxþíús÷!ô ñDîÝëåéièrçç'çÕç éÄêòìˆïvò«õù•üø ú žMƒ=y8ZÎë¿ Z Í+„êoþüú4ø­öyõ›ôôãóôlôõûõ ÷=ø‚ùÎúüLýgþ`ÿ-Ë7ouLú…øÿXÿ²þþ~ýý¬üü‚ü»ü,ý×ýºþÐÿž;ÏM § Ï ¹ [ª 7m B º Úª7Œ»þÒûåøöHó½ðxîˆìüêàé>éé~édêËë­íÿï¶òÂõù’ü,Í_Ê ü àd{/¼½2ŒƒJ; ù™/Òý“ú†÷¾ôHò3ðˆîNíŠì<ìcìùì÷íSïÿðïòõX÷±ù üZþŠ’d÷EGýf … ^ ù^˜°³­©²Òy ÎÿÀÿáÿ.¢7ä `ÁM³êë±7|JÛ=ÿxý™û¬ùÀ÷ãõ#ô‘ò9ñ)ðlï ïï~ïUð—ñ>óDõ ÷Fú&ý0S|– Ž PÊì¥ë±ó­Ýˆ´l»± aÝ;’ýõù{ö:óCðªí|ëÇé“èççÅç-èé…êcì¨îCñ$ô7÷iú¦ýØîÕ} Ø Ø u¨nű7^0¹  ' *;†þý¸û®úçùcù#ù!ùYùÂùUúûÌû›ühý)þÔþ_ÿÅÿ êÿ˜ÿÿtþ¯ýÑüåûôú ú6ùøð÷•÷u÷–÷ÿ÷±ø¬ùîútü4þ&@s²ì  ãn¨†þ¡Åx½œ  TI¾ýdú÷îóûðQîìê°èÃç_ç†ç:èué3ëhíðóIöÄù_ý a _?PUHWCÛ0 T ZUXwýÁúEøö3ô¯òñÐðwððäðžñ£òçó^õùö¬øgúüÀýFÿ¤Òˉ Sb<êrß9äIÆÿbÿ&ÿÿ7ÿŠÿ Àœœ·â>WQ º  ( í a OÎú»TþÒûFùÀöSôòðEîÝìÙëCë#ë}ëRì¡íeï•ñ'ô ÷5úý…ùL h:±½QbéäQ4”zôã ~õ`Óücù%ö,óˆðHîxì!ëGêïéê¹êÐëRí2ïbñÒóoö)ùíû©þKÆ  ½  " Í   À  > ( ê'½]ééÿÿuþ þÔýÑýþýSþÊþYÿ÷ÿ˜5À2€£–UÝ/L;ÿþ¦ü5û¹ù?øÔö†õaôróÄòaòQò›òAóCô¢õW÷[ù¥û(þÕžq< ì p´ªAn'bVM Œ RãTºü*ùºõòŒïõìÇêéßç5çç‰çƒèê÷ë[îñ(ôm÷ÖúOþÀA*  ûÊ' wiçø¤ùÔ z ‹¾ÿ‰ý‰ûÆùJø÷;ö¬õnõ{õÎõ^ö"÷øù7úXûsü}ýmþ9ÿÛÿN‘£†=ÏÿAÿþíý;ý’üýû…û5ûû(ûwûüËüÐý ÿyÄ‹Y Ë T ª ¿ˆûÂò s • aã&<5ý#ú÷,ônñòîÉìë«éÍèqèœèMé„ê:ìgîÿðóó2÷©úCþë‹ ] e\-}G…8b <lŠ o 0á—ÿdü[ùöôéñ&ðÎîæípíjíÐíœîÃï:ñôòâôööùKûnýyÿ]ŽÉ¿mÔöØùJ} ¼Ý WÁSfÜv/üÕ®|5Í:sq.¦ÙÇrâ2þ'ü úî÷Þõëó&ò›ð[ïoîäíÁí îÄîîïƒñ~óÖõ~øhû„þ¿Eh [ cWÙÝ[PºšøÜQh 0 ¾%}ÿÚûRøúôæñ(ïÐìëêƒéŸèCènèéMêðëüíbðóøõùü7ÿ9¶  Ç ñi{*}9 ¹ Bh¿ {ÿþîüþûLûØú£ú§úßúDûÍûqü$ýÜýŽþ0ÿ¹ÿ _qSˆÿÞþ þýüûðùæøó÷"÷~ööçõöjö ÷&øyùûðüÿ@ tÍ  È8Jô-ð:m`ñ + Ýzÿ üøNõ/òUïÐì³ê éàç=ç'çžçŸè&ê*ìîqñ–ô÷÷ûÿ·8Œ Ÿ `¿°( –Šý÷§vÿ T …§ÌÿcüõùÉ÷êõ`ô2óbòññÜñò³òó§ôðõ\÷ßøjúñûgýÁþõÿüÑoÕÌpó_¿‚ÿùþŒþDþ&þ8þ~þøþ¥ÿ‚‹¸Xµ K j [  ‡ ® ƒ  & ò i‘s’ÿëü5ú‚÷ãôjò)ð1îìTëˆê3ê\êë+ìÌíßï[ò2õSø®û.ÿ¾I» ü û£ä±þÄý¨Èb+un ) º6´þGûøýôDòéï÷íxìrëéêÜêHë'ìpíïñIó´õ?øØúnýðÿN|mt ~ 2 ’   b ß  / é¬o= #M¥ÿ,ÿæþÓþïþ6ÿ¢ÿ*Èp³:¢âòÎqÙÿÅÿ^þÖü6û‹ùâ÷HöÌô|ódòñ ñÞðñ¡ñ—òîó¢õ¬÷ú™ü`ÿH@6 Ì GuG¯¡t\ĵ8] 2 Ë<šþúúr÷ôñ<îÞëóé‡è¡çFçxç5èvé3ë`íïïÏòíõ6ù•üõÿAhU ø D-©´Ij^@Ì  ì ©\ÞÌþçü;ûÐù¬øÒ÷D÷ÿö÷D÷¿÷jø:ù#úûü ýèý¬þLÿÂÿ # Èÿ[ÿÊþþ_ý˜üÔûû}úú±ù•ù´ùú²ú”û¶üþ¨ÿfG>;1  Ì S—*e8Ÿš+W & £Ûß¿þŽû_øFõXò§ïFíEë±é—èÿçïçhèjéðêñìdï9ò`õÆøYü§:  Ç œ–˜iO»ºY¨ º ¡rA!þ%û]øÚõ©óÕñfðaïÈî›îÖîsïið­ñ4óïôÏöÅøÂú¹üšþXëJlNîLkOÿƒä,h¡â6¥8ôÿÝÿöÿ>´T÷êäÝÆ–A¼ÿ ¼.T0Å4"ÿíü¤úWøöîóóñ4ðÀî¢íæì–ì·ìLíWîÓï¼ñô«ö˜ù¿ü kÊ 1  ÍŠËˆº_y "Äè ŽfÄý5úÎö£óÈðKî<ì¤êŒéøèêè_éQê¹ë‹í¹ï4òëôÊ÷Àú¸ý gþT^  i _ñ"õpœ „ 4 ¸ uÊ*¢;ÿøý'ýü2üüü^üÆüMýéýþ8ÿÖÿ^Ê-Ô[³ÿÝþàýÃü‘ûTúùç÷Ñöáõ!õžô`ônôÎô‚õŒöè÷“ù„û²ý’(ÁL · ñéÙ¸$Žˆ ¼  ý¹LÊýFú×ö’ó‹ðÕíëžé8èXçç<çèOéë]íðóEö·ùBýÒR­Î ¥ !4Õü¤Íx¬pÏ×–  ~Ënçýûoù—÷öÚôÿó}óRóyóîó¥ô–õµöö÷Kù¨úüHýuþ~ÿ[‚ÈÚ¼t~äÿAÿ¡þ þý4ýýûü+ý‘ý/þÿ ?™–!¤ Y q M á $ž Î    7 û4þYû{ø¬õóŠðYîì ëêvéjéàéØêPìAî ðaótöÈùIýâ j cÖÚabÙà ÷M0«Ñ ² c÷†#ýáùÕöô ñ“ïòíÆììÓë ì¶ìÈí8ïùðüò3õŒ÷÷ùcüÀþýì‡Úà– þ  î ‚ Þ üéãó"xûÿ­ÿÿ¡ÿàÿGÐr$Ü3¼!Y](´æ…öþAýsû˜ù¾÷ôõGôÇòñƒðÖï…ï—ïððð9òåóîõJøìúÇýÉâý ï ž³â’½a}0Ø ®&ƒÛüBùÐõ˜ò¯ï$íëféFè°ç¥ç#è'é©êì÷î¥ñ˜ô»÷úúAþ|˜‚* ‚ }<õ?‘¥eÚ  " õÙÎáÿþŽü9û'úZùÒøøøÆø3ùËù„úRû+üýÑýŠþ$ÿšÿåÿïÿ­ÿ?ÿ©þóý#ýDü`ûƒú¶ùùø(ø ø,ø“øAù7úrûíü£þ‡’µâ  Æ=d0–2Úð p ¥œiýÐù‘övó”ðþíÄëõéžèÈç{ç¹çƒèÓé¤ëëí›ð£óóöuúþ½WÎ ™Æ|³d3Uþ7’Ô æÝËÄÿÚüúŸ÷kõóòòð>ðïïðxðAñVò¬ó5õãö§øuú<üñý‡ÿô05þ‰ØìË{nÅc¿1Ãÿzÿ]ÿoÿ²ÿ%Ç“ƒ¨ÉæñÞ¢ 2 … ’ T Å æ¶:wwBèýuûúø†ö,ôüñð\îíì—ë‰ëôëÙì6îð>òÖô¿÷èú@þ±*“Ø å¥ }wèË!î9 t F ÖF¬ÿü®øtõòçï³íñëªêãéžéÙé’ê¿ëVíLïñôÄöùbü+ÿØ[¥©^ ½ ¿ e ¯ Ÿ < Ž Ÿ z , ÁGËZÿÅ´ÿÑþ#þ«ýjý]ý€ýÎý@þËþhÿ §6­/,ö‹ëÿíý£üCûÙùpø÷ØõÂôáó@óèòâò3óÞóäôCöö÷÷ù:üµþWב . žÎ®0Gê¹ßˆ¸xÔ Û - ÿ ü‚øõïñ ï†ìlêÌè¯çççžç¯èCêOìÆî˜ñ´ôø{ûûþqËôÙ k›_®ƒÝ½'#»ûñ ­ @ º.¬Eÿýüú2ù±÷öŸõõØôëôFõàõ¯ö©÷ÂøíùûIüdýdþ@ÿóÿvÉéÚž:·ÿÿsþÇý!ýŽüüÄûžû­ûôûwü5ý.þ\ÿº@ä™T ¢  ] b‰0sQ Í î »?‰¨ÿ«ü¦ù¬öÐó%ñ½î©ìùê¸éðè«èêè°éúêÁìýî¡ñŸôå÷`ûûþ¡<· ü ø˜Í‹Æz¡=Pãþ¯ èœBïþ·û¬øáõdóCñˆï;î_íøìízíXî’ïñëòíô÷NùûÀýÚÿÌŒTOj‹kÊô /QŒæhôÿ;¡,טe4ú«>§ßÝRHþzÅÿæýëûáùÖ÷ÙõùóGòÐð¢ïÉîOî;î’îXï‹ð(ò(ôƒö+ùü(ÿZ—ÉÜ ½X{æÓ;m9„V½Æ … nÅþ#ûŸ÷OôEñ”îLìxê#éSè èOèé[êì6î°ðrójö„ù­üÐÿÚº`¼  i«‚ïó”×Ço Ý  @TgˆÃ%ÿ¶ýü„ûÉúOúúúMú³ú?ûçû ü`ýþÉþ^ÿÒÿ@2õÿ‡ÿîþ.þNýWüSûMúPùhø¢÷÷¢ö{öšö÷¹÷»ø úœûnývÿ¦ôO¨î  ­ Äv²x͸ B zm.ÑþgûøÅô¶ñíî}ìtêáèÎçCçDçÑçéè…êœì ïò6õ¡ø3üÔÿnî> J S5œ‚ä xˆC¸ ú .EtþÉûVù&÷Fõ¾ó“òÉñ`ñVñ¥ñGò1óYô³õ1÷Åøbúúûýìþ0F)ÔE~Tü‚ïN¨{ÿÿ´þ‹þ‘þÉþ5ÿÓÿ ™´ë2~Ãô é ” þ  ì e ‡ S Ìùâ‘ÿ|üÕù3÷¦ôAòð2î¦ìëÈê‡êÃê}ë³ìbîðóãõùcüáÿkïU Š x<ô+ÙûŽ—#¼õß ˆþ’úP÷MôœñJïdíóëýê…ê‹ê ëÿë^íï'ñuóôõø:ûßým×´  Í ( / è [ ‘ m-á“P".vÿîþšþyþˆþÅþ(ÿ©ÿ@ãˆ#«ZqUu°µ‹ÿ4þ½ü/û•ùþ÷vö õÌóÄòÿñˆñgñ¡ñ<ò7ó’ôGöPø¢ú2ýñÿ͸žl wLžzÙ¶ä<•° „äýIúÊözópð¼ípë˜éAèrç.çwçKè£évë¸íZðKóyöÎù8ýžð ¥ ëË<9¿Ïmžmã È s»wXþhü³úAùø;÷¬öiönö¶ö8÷ë÷Æø»ùÀúÉûËüºýŽþ>ÿÅÿE> ªÿ'ÿ‡þÓýýXü§û û“úCú&úBú›ú4û ü%ýwþýÿ¬}bM1 þ ¥ L0½é¯ ý‡ ® { ù5>'þûß÷Öôúñ]ïí%ë¨é¤è#è)è¸èÎégëyíúïÜò özùý¸^ëJ f.‘óàCm<“|C C à¤}ý{ú±÷.õó2ñÊïÐîCî$îoîï$ð|ñóãôÖößøïúöüçþ´U¿ëÕ{Ýþâl®áEŒîrøÿ8ž-á²–ƒoN·,jj%™Ã¥AŸÆÂþœüdú(øùõæóÿñTðóîéí@íí2íÖííîsðdòµô[÷Húký± ]˜ ¦ tï®Ù~™(,«­>kF âT¯ ýùöúò(ð¹í¹ë2ê-é®èµè@éHêÇë®íòïòJõ:ø>ûCþ5¡ú ¶ ÷§mÚ÷ Î l Þ 2wº oúÿ°þšý¼üü´ûˆû”ûÐû6ü½ü[ýþ³þWÿéÿ_±ÚÔ4œÿÖþêýßü½ûúcùBø9÷Uö¡õ'õñôõiõö(÷ø'úü5þˆüƒ ƒ Û ävªuÍ­þqu S I›ý£ù?öóðmí-ë`éèGç çZç6è™é{ëÐí‰ð–óåö`úóý‡a~ N¿ÇYo±Ï}ǹd Ø 'cŸìÿYýøúÓøøönõ;ôcóæòÃòôòtó8ô8õfö¶÷ùŠúóûLýŠþ¤ÿ‘MÕ(F2òŒqÑÿ0ÿšþþ¸ý}ýpý•ýïýþGÿ>c¬…ÿpÌ  Û b š }  / þ s –no´ýæúøZõÁò_ðCî~ìë.ê·é¿éHêSëÚìÙîCñ ô'÷~úþ–-¯ àB1£ŽîÀÆÔ=Q # ÇRÚÿrü.ù$öbóùðöîaíBìëqë½ëzì í%ïúðó]õÉ÷EúÁü,ÿw•yrz 0 – ­ {  Z ~~gD"  )oáÿƒÿVÿZÿ‹ÿæÿbû¤V£+ÊÒ¢7ލ‰6¶þýUûŒùÅ÷ ösôóÑñãðFðð!ð¤ðŽñÝòô—öñøûdþ]jxs H ä5,¹Ñj€œ¦@v Y únËÿ%ü’ø(õûñï¥ìšê éè‚çç#è>éÖêàìNïòõDøûâþ#D0Ø , !®Ìy´€ãæ’ô   ò•zÿ®ýü¶úœùÉø>øú÷ù÷4ø¦øDùúÝúÁû¦ü€ýGþñþvÿÑÿþÿüÿÊÿlÿæþ>þ|ýªüÑûþú:ú’ùù»øŸøÁø%ùÏù¾úðûaý ÿáÝï  û ¡Ó(œ:p D Â÷óÇÿ„üAùöó5ð²íëÔé”èÖç çôçÓè8êìtî2ñGô ÷)ûÍþu  ¶ Ÿ)Gë¬ÀNZìÑ@p rZ;+ÿ9üwùööÃôèòmñYð®ïlïïðêðòyóõÔö¬ø‹údü*þÐÿK”¥x az[ “ûN–Þ1˜ÈÿœÿŸÿÓÿ5Ç‚a[fy‡…g ¨ ô ü º + M!ªïøÑÿ„ý û¶øUöôòñðzî;í`ìñëõëqìeíÎî¨ðéò†õqøšûïþZÊ' _ [ Y:¡…Ý©é Ö–íì ¤ +”öþfûù÷ÄôÙñIï"íoë9ê…éTé¥ésê¶ëcínïÇñ^ô ÷ûùÝü³ÿjõDL  ] \ ü =#´ ø û Æ g ë_ÒOã˜wÿ†þÊýFýùüãüþüFý³ý<þØþ{ÿ¯,‰¿Çž@®ìÿúþáý¨üZûú©ø_÷0ö)õUôÀósóuóÌó|ô„õãö”øúËü<ÿÒ5Þ h Äߪ¦¹NcüÔ' ( çwîþ^ûÞ÷„ôdñ’îìêŽè‡ç çç½çäèŽê®ì8ïòFõ¥ø#üªÿ%€¦ ‡ 8ï/õ= _GÉôÖ ~ þgË:Çþ}üjú›ø÷âõõzôDô^ôÂôfõAöI÷pøªùëú'üSýcþQÿ¦75¬1ŸÿüþTþ±ýý¥üPü&ü.ümüæü™ý„þ¤ÿòhûŸHèr × ÿ ªþ›Ö ¯ ( G Ÿðÿ'ü0ùFö|óäð‘î’ìøêÍééìè@éêuëMí–ïFòMõ™øü³ÿVì^ — …8ᤵ96±·T—“ ZžEþûü÷2õ¹òŸðíî«íÞì…ì¡ì*íîjï ñëòõ:÷‡ù×ûþAA šã㘠! ýœGgru{޹uàÿÝÿ^Üy.ð¶t®LKÐÏqÿ¢ý·û¿ùÆ÷Üõôqò ññï)ï¿îºîïïï+ñÏòÓô/÷Õù¹üÉÿñ"F I  Ï—ìÂÛÑ Ë#! ÖV¶ þmúïö§ó©ðîÍë êÊèèßç7èéqêAìwîñÚóãö ú@ýl~c f i Dqgø*ž ø & 678HtÈþLý üûCúÃù„ùƒùºù"ú²ú_û üèü®ýgþ ÿ‹ÿçÿëÿŽÿÿUþ…ýžü¨û¯ú¿ùâø%ø’÷3÷÷2÷›÷NøMù”úüçýâÿCÔ  ñŠÑ¼@Uø%à+ ” ɽ‚+þÊúv÷BôDñî0ì=êÁèÅçQçiç è;éëêíªïœòÙõNùæüŠ&£í ñ âµ Ý+ó; gai ™ ©®¹Þý,û³øö¡ôóöñ3ñÓðÔð0ñàñÚòô}õ ÷³øbú ü¤ý ÿs˜ˆ?»üߊÜ2øÿ{ÿÿêþäþÿkÿùÿ¶ž©Î@v˜› r  s Š S É é ¶3eUŸþü}ùëöqô ò ð:îbaresip-1.0.0/share/sound8.wav000066400000000000000000001047741372575704200162270ustar00rootroot00000000000000RIFFô‰WAVEfmt D¬ˆXdataЉà¦5 uO°‰Íx†ûÞ;!¤Ø Õ ´w‹ýÛúzøvöÙô«óîò¡ò¾ò<óô)õyöí÷rù÷újü»ýÝþÅÿkËåºRµÿîþ þý2ü\û«ú-úïùüù[úûüxý#ÿ-qÅ M VŽ˜,AÏÔQMÒ ï¶>žþïúL÷Ðó•ð´íAëPéðç+çç†ç¤èYê–ìMïhòÏõkùýÑhÉÞ ’ Ö›ÙŒµX~4‰ ]  Ÿ>÷Þÿÿýhü"û3úù]ùoùÈù_ú%û üÿüòýÕþ—ÿ*‡£{ [ÿjþCýóû‡úùŸ÷Göõ'ôó4óJóÌó¼ôöá÷ ú‰üLÿASls Nè)ýSTïïY6’  dŒ©ýÔù)öÁòµïíëxé‡è4è|è\éÉê¶ìïÇñ¿ôã÷ûHþY7Í æ S N Õ í œ í í ¬ ; ®†¿£Çÿ.ÿÝþÓþ ÿÿ&òÔ½cÿe‡^âízÁÿÌý¬ûpù.÷øôäòñvïBîyí*í]íîWïñYóöùfüîÿ3¼ »ä„øÀçrnèó¦ e§ùüuù2öHóÈðÂîAíKìâëì¨ìÆíOï1ñXó±õ$øúýKÿ[)©Ò¢7‘â=€öÿ¥ÿ–ÿÍÿHý't×>˜Ó Ý ¦  ; ó @ •§^Èùþü÷øôõó_ðýíýërêkéôèéÍéëílïMò’õ$ùêüʨjó ,ýSUïëL]*’« Œ N ÚÿÓü ú”÷}õÑó—òÓñ„ñ£ñ)ò ó4ô›õ*÷Ïøvúü‰ýÔþçÿ¶@{3²5ÿSþpýœüçû^ûû ûNûåûÏü þÿSMj™Æ Ý È uÏÆLVÝß\\ é äzëýNú¾öVó/ðbíë)éÝç-çç±çâèªêûìÄïðòiöú×ý–9£À y¾‚»g„+Êð $ š©jÿhý¯ûJú?ùø=ø?øø#ùêùØúÚûáüÜý¼þrÿóÿ78õÿmÿ§þ©ýü6ûßù‰øH÷,öFõ§ô[ônôçôÊõ÷ÉøÚú=ýäÿ»¯¨ OÌò­í£ÇRE¤xζ G˜Ââüùkõ ò ïyìmêòèèÐç,è"é¦ê¬ì!ïðñõCø•ûßþ ÿ«ý è a dï®ô ä Ž  XŸêKÒ‡ÿÅþLþþ3þ‰þÿÍÿ \$É=sbRQqÿ¤ýªû”ùv÷bõnó®ñ4ðï\îîSîïPðòGôêöèù.ý¤5Å9 ykø –‹á•¨  ql q°æÿ,üŸøUõfòäïßíbìsëëDëûë.íÐîÍðóŒõ"ø¾úKýµÿèØx¾§2a<Ë<;+C“åÿñÿ@Ó¢¤ÍYšÂ¾ ~ ô  Ò +  ¦Ï¡(wþžûµøÑõ óxð2îLìØêçé‚é²ézê×ëÃí3ðó_öñù¶ý’l& ¨ Öœå£ÉQ:†<jlj 0 Øz1ÿü4ùªö‚ôÉò‡ñ¾ðnð’ð"ñòOóÎôyö>ø úÉûjýàþÇ.K"½$eÿ²þÝý ýŒü,ü ü6ü®üuý‹þéÿ†XNXb X & ¹ýã[]ßàbi ÿ 3¾Bý¹ù>öìòÛï%íÝêéáçEçJçñç5éëqíKð‡ó÷Çú–þ` } Y]2BÅÄLm:È - €×HæþÂüéúgùBø~÷÷÷X÷ê÷¶ø®ùÀúÝûòüðýÊþqÿÞÿ ñÿ•ÿøþ"þýøû¿úƒùVøJ÷oöÔõˆõ”õöÕöø©ùŸûæým$øÑš 9š¥Hq&£‹á®ç xÊùÿüTø·ôbñkîèëëé€è±ç‚çóçþè™ê·ìDï.ò\õµøü‚ÿÄÏò é lt´íË ^ ¹ ï9sÒc3ÿIþ©ýVýLý†ýûý þfÿ>ç—hq0¢Æž4ÿý½ûÎùÔ÷âõ ôgòñ÷ïMïïTïðPñ ó7õÍ÷»úðýRÎH¦ Ϫ ’q³SSº’êÕ j Àóÿ]ûÉ÷{ôŠñ ïíë«êYê˜êbë¬ìfîðãò}õ4øóú£ý/…•R³²P p  OgX5 óô €$Œ2 5d¥•O Ä è ±  ½ð–þNû…øÂõó§ð}î±ìTëwê$êcê7ëìîñëó1÷ÁúþW)Ú Q s,f(žs©J`ü1 ÃRÜ}þHûWø¼õ‡óÄñ{ð°ïcïŽï)ð(ñ|òôÜõÂ÷²ù—ûaýÿþc†_ê)ÑMœÏõÿÿWþ³ý?ýýýiý þûþ0¥Nè¿ p ë ð^XØÛb s  ZO ¤ü1ùÎõ“ò›ïüìËêéûçtççFèé‡ëùíáð+ô¾÷‚û[ÿ,ÝS u 0q,Vìí^H¸¾nÝ ! R‡ÖSþüú{ø?÷göóõßõ$ö·öŠ÷Žø²ùæúü6ý3þÿ™ÿïÿÐÿ]ÿ¯þÏýÊü®û‹úqùsøŸ÷÷·ö¼ö÷Ü÷ÿø€úYüþç}/çŽ RBÌàpsäÂÚ*  ¥ý3ÿ`û ÷ôÆðÝíië|é"èfçKçÐçñè¢ê×ì}ï~òÄõ5ù·ü0‡¦v æ é r~ ¬Ö¡ [ r st‡½%Íþ»ý÷üüYüyüØümý(þýþÚÿ®kfŒlKL ÿŽýäûúFøvö¾ô3óæñêðMðð_ðñUòô&ö­ø‰û©þöZ¼ Ô3xBoüëA S1 º 1UþŽúöö§ó¶ð8î<ìÍêóé¯éêÞê>ìîGðÉò‚õ[ø;û þ¹/]5® o ¸ ¡ 3 | ‰j1ïµ”™ÑDûÿõÿ2°eHK`w~d»‘ #Þ>L¥ýûiøÈõAóìðÝî+íåëëÙê&ëìqíhïÞñÄôø‘ûJÿÞƒ í ªÔprÔ•¶A@Åã± G¿4¿ýxúw÷ÎôŽòÃðwï¬îcî—î?ïPð»ñmóTõ[÷nùzûlý2ÿ¿ µ$ï|×6X‡ÿÒþHþôýàýþ‘þXÿd°1Ø—[ ¨ (ïSIÉÑ ` } 0†bÿü¹øoõNònïèìÏê6é+è¹çåç±èêì’î†ñÛôxøDü"ù­$ Fþ9ì “„â¶úÝ  &T±ýOû=ù‡÷6öMõÍô²ôõô‹õgöz÷²øþùMûŽü°ý§þgÿéÿ%ÕÿNÿ’þ­ý¬üŸû—ú¤ùÖø>øé÷â÷2øÞøçùLûý ÿPÃRçm Î ôÊ<;º®ê5üM 8 Ò2qþ©úööró8ð_íüê!éÚç1ç*çÄçúèÁê íÉïáò=öÄù[ýçQ€^ Ú är~ –¯dÇ ê à ¾š†”ÕÿUþý6üŸûZûbû®û5üéü»ý›þzÿFòp´·qã õþ¢ý üúÍø÷ƒõôØòëñYñ.ñrñ,ò]óõ÷ˆùOüXÿØ K Aê/þGûnµo­ EjŠýÀù'öÙòìïsíëêMéé|éoêæëÔí%ðÄòœõ”ø•û‡þRæ/ ¯ Õ á Í ^ Ÿ Ÿ nÀf þ Vâÿ±ÿÅÿ«mSPTM,à[t2‡¶¢ÿVýåúbøãõ}óFñTïºíŠìÓë ëøëÞìQîIð¾ò õÝø_ü Њ! {~.·¦ô ­" {ƒ; ¼ úü¤ù”öàó—ñÈïzî²ípí®ífî‹ï ñÚòàô ÷@ùrûŠýyÿ,œ¾Ž 4¯Ru°éÿFÿÔþŸþ®þÿ¢ÿ„§þ~¹R Í  & â >2µ à ] ‰ M¸ÙÅþûQø"õòVïéìéêgérèèSè/é¥ê­ì8ï7ò•õ9ù ýìÆzð Àôœ¯(QN–È Î¿´Äÿý…úZøŽö*õ3ô©ó‰óÌóhôOõröÀ÷'ù•úøûAý`þJÿ÷ÿ^_ÿÿeÿžþ·ý¿üÆûÜúúwùùùBù×ùÆú ü¦ý‰ÿ¨÷aÓ7 x <—ƒñÙ6Ol ^jµýûùWöäò»ïóì£êÚè§çççÎçéöêVí'ðTóÅö`ú þ§!]G Ë Ûkuöònu^c 9 ô«pXrÿÌýpügû²úRúDúúúú¨û{üaýLþ+ÿîÿ‡ìóŽâÿôþÊýqüöúgùØ÷YöþôÙóúòpòIòŒò@ófôýõý÷\ú ýüÿEq \êÍÿŸ¦ÞÇûÆ ? ¿üõø^õò,ï»ìÑêyéºè—è éê¥ë¬íðÕòÊõáøüÿø§  ´ é ®  ó € ¸ © d ú™P5T´ÿYÿEÿtÿáÿ‚N4'ð¥&f\þJ>Þ0@ÿýÍúoøöÎóµñßï^îCíìwìÙìÅí:ï3ñ¤ó€ö´ù+ýÌ€*± ùêotéÄþ•íö #uÆÿ0üÌø±õôò¦ðÔî‡íÄì‹ìÖìŸíØîrð\òôËö'ù~û½ýÒÿ«?ƒr K<æS’±ÀÑó5¦ÿNÿ7ÿdÿÙÿ‘‰·„€â   É  › ³ [ ˜qô.5þûù÷çôýñTïíë¯éÏè…èÕèÁéDëWííïóòWöÿùÓý·B ³ ËuŸ;@©uªRx/ŠŸ ‡[2&ÿJü²ùp÷‘õôó‰òfò¬òPóDôyõßöbøïùvûåü-þBÿ«÷ýÀGÿÎþèýüüüPû°úHú$úLúÈú™û¿ü6þôÿî\©ì øšß¸õKa- ˆ ‚0§ýXùÅõdòNïšì^ê©èŠç ç+çîçNé?ë³í˜ðØó[÷ûÁþmô; - ·ÊY_ÙÉ6)²àÇ } §Gþþ3ýµû‹úºùBù ùMù¿ùjú?û.ü'ýþöþ®ÿ3~ˆLËÿÿþ×üûú¥øA÷üõçôô‘ókóªóVôoõõöáø)û¿ý’‘¢± £ aÔ熡-"|=k< wµ×ÿöû/øœôXñyîì4êêè;è*è´èÒéyëší!ðùò ö?ù{ü§ÿªrì º ü Ê %— Ä ¤ J Æ,ŽþI=sÿîþ²þ¼þÿ‹ÿ<óÙ°hòAJn‚D»ñþðüÊú‘øXö4ô:òðïîxí^íÇí·î-ð"òô`÷ˆúòý„&¿2 fD´¤ËñtW¤f­ " Áÿaûò÷Ïô ò»ïêí ìäëµëìêì9îíïóñ7ô¤ö#ùŸûþ;:ñUahjÎæéèògìÿ­ÿ²ÿûÿˆV[Þ>œè ý ¦ û ð  £ \ ¬9´ý¸ú´÷Àôôñfï/í`ë êBé ékédêôëî­ð¹ó ÷Êúžþ€U l |:ȽÎî~Œ)ic /æ¢{þ†ûØø‚ö‘ôóònñKñ–ñCòGóôö®÷]ùûžüþMÿN «‘7¨ïÿÿ8þYýüèûsû<ûNû®û`ücýµþM!"Ak‹ Œ \äÜ/U"m? £ ©díÿXüÁøBõõñôîUì.êŽè„ççNç%è˜éœë"îñjôý÷¸û€ÿ8É  °=<¬êÉ:M « ! §xþ‹üìú¥ùºø,øù÷ø„ø.ùúû üý þãþŒÿþÿ/Èÿ/ÿYþPýüÕúƒù8ø÷ö8õºô’ôÌôlõvöè÷½ùìûfþûîÝ ± R©¡(.§‹Ö‹¯Mt 7 «é ÿ0ûo÷äó©ðÔízë©éoèÑçÓçqè¥édëí>ð2ó_ö®ùýIfEÓ Á á=%£   ÅO¶Hÿqþþôýþ‡þ"ÿâÿ¹™o,Â"AÓºW´þÛüÜúÈø³ö°ôÔò2ñßïêîbîRîÁî³ï&ñóxõ?øYû²þ2ÁE £ ÂŠä¾ ¼Í< Fö-þ Ð=þú÷ðó+ñÙî íÇëëñê[ëIì¯í}ïŸñô‘ö3ùÒû[þ·Ø°2Y!Š™UÊòãëwëÿ lë÷%fªßôØ { Ï Ê c • `ÇÒŠÿÿBýfú‚÷®ôòïrí½ë€êÊé£éêë²ìÖîxñ‡ôï÷˜ûiÿEº  ³ÃB&k”Š4 ÅcÆýºúø÷õ‘óòòðYð9ð‹ðEñYò¸óPõ÷ßø¯úlüþmÿ˜}ip4½Pwÿ›þÍýý™üMüEü‡üýøý#ÿ“@ ÷ « 8ð8U#t N ¾ÓŸ:ÿ¹û7øÎô˜ñ­î%ìê‰è•ç=ç‡çqèöé ì£îªñ õªørüCžó î |Œ oBŒU­¤P Ä d»5äýÕûú¶ø³÷÷ÏöæöM÷ø÷Ùøàùýúü1ý)þ÷þÿìÿÙÿkÿ¿þÝýÐü§ûqú=ùø'÷eöèõ¾õîõöy÷Öø‘ú£üÿ•T&õ © ,hFµ¦ àÊ瀤 f ÜFþpú·ö6óð>íòê1éè|ç‘çEèéeë·íqð}óÄö,úœýø,¾ ú Æ ñL/¢±k á % Kf‹É2Ôÿ·þâýZýý*ýxýýý®þ|ÿV.ô— A4Û5A‹þÚüûù"÷@õóùñ»ð×ï[ïSïÆï·ð%ò ôcöù$üjÿÕO¼  »ÿÃù•“ï­Õuœ_ ÕCrý¾ùBöóPðî7ìûêSê?êºê½ë:í"ïbñäó“öWùüÄþC…{X5 ® È Š ÿ48ðÆ®¸ï`;´hNZ}¨ÉϪI   ¢ G ‹këè}ÿáü&úd÷°ô!òÎïÌí/ì ëfêPêÌêÝë~í§ïLò[õÁøfü0Ìg ¼´9:¨z«<1”rÞë ² LÑ\ýçù÷œô’òýðæïNï2ïïUð|ñòò¥ô‚öuøjúNüþ¡ÿôÃ6]<ÜHŒ¸Ýÿ ÿLþ·ýTý1ýSýÁý{þÿÇJüÎ®Š N ç AKö5þMw ] Ûá‘þ&û¼÷kôLñzî ìê›è¼çxçÕçÒèhêŽì4ïHòµõaù2ý ÕrÉ ÅP\ÜÈãË æs È û%Z³ÿ@ýû:ù¾÷¦öóõ¤õ´õöÈö³÷Éøúù4ûfü€ýtþ5ÿ»ÿÿÿÿÿ»ÿ8ÿ|þ“ý‰ümûPúBùUø˜÷÷ëö÷“÷wø»ù[ûNý‹ÿÿ›Kù ñÕ- ^$Xû©Í ‘ S„ý·ù ö•òsï¹ì}êÍèµç=çfç/èé|ëåí¶ðÛó:÷¹ú?þ±øý¬ ô È!ùP+’4 · ¼´²É ‚ÿ=þBý–ü9ü)ü_üÒüuý;þÿñÿÀsüM^(¦ÛÉÿvþîü>ûuù§÷äõAôÒò§ñÒðað_ðÒðÀñ(óõL÷óùéümÎ# Q @رÑYBŒ9Rãý´ Y|¥üíøoõCòï5írë@ê¤é é.êFëÛìÝî:ñÛó©öŽùrü>ÿÝ>P^ L Ó ö » . [ R"ߘ_EU› êÿ÷ÿEÒ”†™¨¢unz.…}]T ÿ‘üúùZ÷ÇôXò"ð<î·ì¦ëëë–ë°ìVî‚ð&ó3ö”ù3ýôÁ{ P9­ø·ÕQ1}Eš‘ A Ã2ªÿAüù,ö©ó•ñüïãîMî8îžîuï°ð>òô ö ø:úEü/þèÿc—|VN}Ëû?vÿÌþQþþþZþíþÉÿçAÊu1ì’  V Oî&í> z m ý6,ôý¢úQ÷ôñ[îì êÃèùçÊç9èGéíê!íÔïôòköú÷ýÖ£B š “”u½o,Q · ËÓé"ÿüGúTøÁö–õÔô|ô†ôìô¡õ˜ö¿÷ù[ú­ûêüþîþŸÿ 8Äÿ-ÿfþzýxünûoúŠùÑøQøø0ø ømù–úüìýWÐ\è [ ¡£NYžX‚3Ê ñ º;ŒÈüùgõòïîFìê}èyççRç/è¥é¨ë'îñJô¾÷SûíþrÊÞ™ ê Å öHq]ë, 5  ìÄ´Ìÿ²ý“üÅûIûû?û û9üùüÔý·þ“ÿXøf—„*†žÿuþýŽûëù?øœöõ»ó£òÛñrñsñæñÎò,ôúõ1øÅú¤ý»÷>x Œ aßó‰“ݳ½APþ a•´ÿÙûø¢ôxñ¹îuì»ê•ééé¶éäê’ì®î'ñæóÔöÙùÜüÇÿ„.þg e ÷ æ U x _ ¾Yþ¾¦Ã»ÿžÿÅÿ*É•}l;Ú<T‡™Q¶ϪþTüáùd÷óô¤òŒðÀîTíWì×ëÝëoìí9ïeñô÷húýý³s Ô¬ë4ßèPRC$ ¿ -‰îþtû4øEõ¸òžðïéíWíKí¿í§î÷ïŸñ‹ó¨õà÷úPübþAã<DøXh/¶ <Xq•×ÿAÿàþ¾þáþLÿþÿò#„ :à * [ F Û Õ * | $t‚cý-ú÷öÛóñðRîìHêéMè1è²èÐé„ëÄí‚ð«ó)÷ãúÀþ¢p b VÖÒ<Gæòwƒ({ ’ ‡qg‚þÕûqùf÷¿õƒô¶óVó^óÇó„ôˆõÃö"ø“ùûgü©ý¼þ—ÿ0†•aðÿIÿyþŽý–ü£ûÅú ú‡ùDùLù§ù[úgûÉüzþoœñYÁ  :!³ß–Í|Ÿ8Lå  âmËÿübøÑô|ñ{îåëÍéCèRççTçFèÑééë}îzñÉôQøùû¤ÿ9 À … Ý»è2ø@Ž´ _ ‹}¨þýÕûçúOú úúlúûú¹û–üƒýnþHÿŒßò¿Fˆÿ‰þSýóûuúëøf÷øõ´ô¬óðòŽòòÿòßó0õîöùŽûUþRrž» ³ lÑËJ>žc‹’˜ > ÌêþûV÷Üó·ðÿíÄëêýè€èžèTé˜ê^ì–î*ñô÷5úVý^8Ïø r }  D q ˆ ^  ŒŠ#ãÖxÿ1ÿ1ÿrÿïÿpZJ1þ  2 ¿—[[þ+üÝù„÷5õó ñZïîí©ì¼ìVízî%ðNòëôê÷:ûÂþk¶ # H \%Yðå8î¯Ú§ / ‹Ö+þ£úW÷^ôËñ­ïîúìpìnìðìëíRïñóZõµ÷úpü¨þ­tðêdˆ_ñJzš¬Ô"¡ÿ[ÿWÿ˜ÿéð(†ûuã3 R 0 ½ î ·   ™S»åÿáüÇù¯ö°óâð^î9ì‡êWé¶è­è>éjê+ìvî<ñlôï÷¬ûŠÿl8Ò !…uÒ–¼H>«ž(_ Z 1ý××ýû“øsö»ôqóšò5ò=ò«òsó‡ôÖõN÷Þørúøûaýžþ¤ÿhçÁ9…ÿ¯þÇýÞüüJû½úlúaú¦ú>û+ükýøþÈÏþA† · ¿ ŠÂì’°H^ü 0 £ÿhûÈ÷Jôñî˜ë”éèBççmçsèê>ìåîõñVõðø¨übx¡ m ɨÍÅü¿&ð ‘ «O!þmü ûþùKùòøíø5ù¾ù{ú^ûVüRýBþÿÃÿ9rh…ÿ±þ¥ýküû©ùAøìö¼õÃôô±ó²óôðô2öÝ÷ëùOüûþÛÞëë Æ c¬ŽõÔ!ÔîqdÖÕ w Ó þGú“öóðSí#ë‚éxè è=èécêAì’îBñ:ôb÷¢úßýö¦ÿö ~ ” 4b$‚ Œ N Ü H£u ÔÚÿ"ÿ³þ‹þ©þÿ™ÿT,ò¾gݤñë–ùÿþüíù¹÷Œõ}ó ñðÇîïíí¨íIîoïñ<óÑõÆøü‚ÿ¸@ ™ ªY”HhëË ¬¼G_ ’ÞcýÏù{ö{óãðÃî(íì—ë¢ë4ìCíÁîðÅò"õ ÷'ú£üÿ*±ùæv®‘+‡³¾º¸ÆõQåÿ¹ÿÑÿ,̨¹ñCŸó- <  — Ç – ü ø ЏŠUÿoütùzö™óéð€îvìÛêÂé5é=éÞéëáì4ïò5õºøxüS3úŽ Õ¸$V“tÊ£/  Ê{: ý@ú¯÷}õµó`ò‚ññ%ñ›ñoò”óùôŒö;øñùžû.ý•þÄÿ²[ºÐ¢7šØÿþþþEý†üðûûpûšûüáüýýeÿîö5 D . ÞAEÝüœ·Pk  O8ß]þÈú;÷Òó¥ðÍí`ëqéèIç!çœç¶èhê¦ì_ï€òòõ›ùaý'ÕQ P®Œß¤Ø¥R•ƒ. ­ ©ÿ‹ýµû3ú ù@øÓ÷À÷þ÷ƒøBù-ú2ûAüJý<þ ÿ¥ÿ%˜ÿîþ þøüÂûyú-ùï÷Ñöäõ8õÛôØô9õö1÷Çø¼úý“ÿU8& à Cr:ŠU3@¸£ ª7Xý„ù×õkòYïµì“êéè­çòçÒèDê:ì¥înñôÄ÷ûvþ²¾‚ï õ ‰ §Kx3‡€ . £ ñ+e± ¾šÿºþ"þÕýÑýþˆþ0ÿùÿÓ°0µÄ1N©ÿöýüúøùõ ôHòÈðïÕî~î¢îFïkðò-ô·öŸùÑü8¾H» þ ù“·VaΛÆUSÍÕ é(X–üûøŸõ›òðäíMìDëÎêçê‹ë¯ìEî=ð‚òÿôŸ÷Iúéüjÿ·ÂãéŽÖÄd¿ååж©·ð]õÿ%šM6Iz¹ô å j œ r å ò™ßÌmÓþ ü2ùXö–óñ¹îÈìFëBêÈéàéŽêÒë¦íÿïÏòö‰ùDýõµ@ }T²†Åffɓғêì ± Sê‘ÿ_üjùÇö„ô°òSñpððð—ðyñ±ò.ôÞõ¬÷†ùXûý þùÿáfŸ‘Aº:_ÿ†þÁýý«üuü„üßüˆýþÀÿAùÚÒϾ Š l_é›¶Rt $ qi"´ý4ú½öjóTð“í<ëdéèfçSçáçéÒê íêïó™öOú þð§( \ -Šc°k’*:ÏùÊW µ üCŸ%ÿæüñúRùø0÷±ö‘öÈöL÷øùú=û`üqý`þ"ÿ¬ÿöÿüÿ¾ÿ?ÿ„þ—ý„üZû(úÿøñ÷÷gö ööVö÷*ø¨ù‚û®ý¿N « !Ð Áê€ðÖ>8 Ù8m•üÉø&õÅñ¾î(ìê“è¬çdç¾ç³è;êIìÌî¯ñÚô7øªûÿlŒdà ó ‘´Yƒ6}dü W † Ÿ´Ù•Gÿ>þ€ýýëü ýnýþ¿þ“ÿmAý’óð€Â¹kÿáý'üLúaøzö©ôóœñƒðÊï}ï§ïLðoñ ó õœ÷tú”ýçVÉ& Q4·ÅMBœTmëØB;Ú 7k“ÿÈû'øÈôÂñ*ïíë€êê?êöê0ìßíòïUòòô²÷úAýäÿR~XÖòª ÿ ö ™ òئ|i|ÁB TÞ  Ãçüð´8 o O Ðð®Ûaþ½ûùKö©ó6ñï1íÆëÖênê•êPëìvîÓð¤óØöYúþà±g æ à.ò­šçœÄm¬– C ÌLÞþ—ûøÜõŒó®ñJðeïïï¡ï”ðàñvóBõ1÷.ù&ûý¿þ@x!|‹Uâ?z¡ÆÿøþFþ¿ýoýaýšýþðþ`ð¨zT" Ò O ‡ièø­P | 9 –¡oý­ùOöóðmí.ëmé7èšçšç;èzéNë¬íƒðÀóK÷ ûåþ¼wü 1 Z.r 8¾º8Güj ¨ Îó-“þ4ü!úgø÷öŽõdõ–õöåöæ÷ ùGú†û·üÊý³þfÿÛÿ ùÿ£ÿÿIþWýJü0ûúùAøœ÷<÷*÷r÷øùú>üIþ–·a ~ ûQu2¼³þe a j¨ÿØûøô+ñ3î­ë«é:èeç2çŸçªèIêmìïòEõ¸øBüÈÿ/aI Ó ð •º^‚+c8¸ ÷  þîì Wâþ²ýÏü<üùûüKüÐüýPþ-ÿÐxñ/+ÞFfBÿàýOü›úÕø÷]õÒó€òyñÍðˆðµðYñwò ôö~øBûNþŠâ< ’[Ƽ.SùÿmK§• ) |¨ÉþúúV÷öóòð]îHìÀêÍéqé«évêÆëŽí½ï=òùôÚ÷Èú«ýmüD9Ï Ç ( % È  / Ó‡>õhÛÿûÿ[÷Ķ¿ÎÓ¾}@-ÀõÍKuWþûéøSöÒó}ñkï®í[ìë(ë\ë!ìtíRï°ñô¯÷+ûÙþŸe € ¡Z˜Jdß·ð 3[. Å8£!þÈú±÷ïô•ò°ðIïdîî#î»î¿ï"ñÒò¼ôËöìø ûýòþ›ëfqz»ã(fÿÉþ^þ0þFþ¥þNÿ<kÒbÅt  l ‘ eÛæ~  K ƒ QÀàÆÿ…ü6ùòõÑòíï]í6ëŒémèäçøçªèùéÜëHî+ñrôøÍû­ÿˆFË ÿ Ìê"ÃË>%Š€g † Œ‘«òývûHùv÷öõjô9ôiôñôÄõÓö øaù½úüGýXþ4ÿÔÿ/G¯ÿ ÿ:þHýFüBûMúyùÕøoøRøŠøùúOûìüÖþ]Ù`Þ ; c?½Ì^ièØ=… … 1æþ"ûn÷åó¡ð¹íDëTéöç5çç˜ç¸èlê§ìVïgòÀõHùæü~ø:/ Ä è‘·Xs9ø`ƒ t Gëájþýü\ûûúëú#û™ûBüýïýÔþ¬ÿgúWuMÞ&,ÿôý‹üþú]ù¸÷$ö²ôtó~òÜñžñÌñlò‚ó õ÷Zù üþþ!^žÆ ¾n¿øÃôˆ~Ý­þâ m ¹àþý-ú‰ö+ó*ðœíëê,éßè,é êrëTíï:òõø"û%þ±#Î  å N O ð = D  ¿Wî•[O{çÿ˜ÿŽÿÇÿ=é¾®ª¢…B˵ö“ßåÿ±ýUûãøoöôÚñäïAîí;ìòë3ìÿìXî7ð“ò_õˆøúûžÿXª Âî“ú¾âlhåø¶ 8˜ð]ýôùÐöô¢ñ¸ïPîníí>íåíýîvðAòIôzö¿øû1ý8ÿ•ÕÂZŸ”C¶ü"9Q{Çÿ?ÿðþáþÿ˜ÿ\bŸŽ"²* y U Ã Ë f E mñ))ÿüÏø¦õ¡òØïbíUëÂé¸èDèjè.é‹ê{ìòîßñ.õÈø”üvT” ÄŠÕ–ÂSJ©yÇ¢P Q 9Eý­úgøöþôìóIóóCóÐó®ôÍõ÷‹øúzûØüþÿáÿh©¥_Þÿ,ÿTþfýqü†û¶úú¡ùxùœùúçúüŒýSÿXçK¦ ã ì®’ñS5¢ ©]Õ*þuúÑöYó&ðQíïêéÈççç§çÛè¤êôì¸ïÝòJöåù•ý>Æ ² Û†ªDWæü¦õú Ë |#Õ¥¥ÿâýiüAûpúõùÎùõù`úûÏû¶ü¦ýþcÿŽÏψûÿ*ÿþÝüvûøùtøüö¢õxôóöò¼òèòƒóŽôöì÷1úÈü¢ÿªËîú Öj¢h¬b€ê<I$ ªò4ýcùÂõhònïèìæêuéèbèÂè¶é5ë/í”ïMòEõbøŽû®þ«rï Ð !  p r  T L  š‹ ­wxºÿAÿÿ!ÿtÿ¸’}jG”èô±+éXƒÿuý>ûñø¡öcôLòrðèîÀííÎìíêíEï#ñ{ó@ö`ùÇü\¯7 †ƒ/º¬þ®½3…„/ ží5“üùïõó´ðÈîaí„ì3ìjì!íMîßïÆñìó?ö§øûdý‘ÿ†7™¥Y´¼yô;]jr‡·ŸÿkÿzÿÐÿiDW™ûmÞ= x | 9 ¢ ª J } A š+~™þûyønõ…òØï}í‰ëêé¹èñèÄé.ë*íªïžòóõù^ý@×U ~<|0Nϳþ¸í®% Ó~ÿŒüÜù÷„õôóÖò+òòñ%òºò¥óÖô=öÆ÷`ùøú|üÝýÿ´B ¿)kÿþ¨ýÄüõûJûÑú˜ú¨úû¼ûÄüþ¿ÿž°á X u a YAµ©ÿbH » ÌŒwýÓùAöÜò½ïüì®êæè°çç!çÌçéòêTí,ðcóáöúMþ˜òù ›Çq‘#)©¬@t\ œ¬V1ÿJý¯ûgúyùæø¬øÄø&ùÅù”úƒûüýkþ7ÿÖÿ;bEãÿ=ÿZþBýü§úBùå÷¡öˆõ«ôôàó ô›ô™õ÷Òøþú|ý9$',  ÙRnJìøkE‹Gˆ^ á'LküŸøõ°ñ¿îCìMêëè#èúçmèwé ë!íŸïtòˆõÂø üEÿ\;Ï Ô 2 Ž%] E ì d Árê‹bzÿÖþ|þiþšþÿ¨ÿmI,Ç`Áá·;mNâ4ÿLý<ûùèöËôÔòñ£ïîçí¸í îàî;ðògô"÷6úŽý­B¶ ñÙX[Ѯ쇃åºÿ ™ ù8tÿÅûFøõ6òÍïáí~ì¨ëbë§ëpì²í]ï_ñ¥óö¤ø0û©ýûÿèj“`Ðè¯/v‘’ˆ†šÓ<âÿÈÿóÿaüS¥úAh _  z „ , j ? ¬¹pÞþ-û5øIõòîï¯íÔëpê‘éCé‹élêâëçímðfó¾ö]ú*þ á• ,ß¹Ç6=àý¥ëç ¯^ ÔþÊûù“ö†ôéòÂññÚðñ±ñªòïónõ÷Ïø‹ú6ü¿ýÿ7¦ïð¯4ŠÁÿäþþ5ýƒüýû²ûªûïû„üiýþÑ»Æàö ò  P‹bȳkW Ô ð¿VÎü=ù¿õoòfï»ìƒêÏè¯ç+çIçècéSëÇí°ð÷ó…÷?û ÿÍlÍ Ú ~ªPjòëZIÄÞ¨ 9 ¦oõ¬þ£üèúƒù{øÒ÷†÷’÷í÷‹ø^ùXúgûzüýlþ.ÿ»ÿ àÿeÿ«þ»ý¡ühû!úÞø®÷¥öÒõEõ õ-õ´õ¢öø÷°ùÂû#þÂŽrW % Æ#%ºÒ`\ÀŽË½ ‘ [„ÿ§ûà÷Lôñî®ëÇétè¾ç§ç/èOéüê(íÀï¯òÝõ2ù“üèÿ ´ü Ø @.¡Ÿ.Y. ¿  Y‹ÂŠ7%ÿZþØý¢ý³ýþþ@ÿëÅ‹.¡×Çj¾Ã~÷þ7ýNûLùD÷IõpóÌñpðnïÕî°îïßï8ñ óTõøûOþÁGÆ% J„qÑšÃK3ƒGk ö I|­þõúo÷3ôWñîîí¨ëÜê¢ê÷êÓë+íðîñsóöµøeûþu²¥E‰mð åh«¾°“wm„ÈEEËŒ€šÌ7M8 ç L \ Z BÆìÀM¦ýÛúø8õòðöí5ìèêêáé8ê$ë¤ì°î;ñ7ôŽ÷+ûôþΟK ¸ Ìr˜.+ˆDeñ÷†´• DÚoþÿú%ø£õ‰óáñ³ððËï ðµð¿ñó²ôvöRø2úü¶ý9ÿ…?­Ï¬I´÷#Hÿtþ¸ý$ýÄü£üÊü=ýþý ÿ_ð²–‹~ [  „«sβn d íù¤ÿ/ü´øNõò"ïŽìlêÏèÄçUç†çXèÆéÇëLîDñ™ô4øúûÐÿš?¥ ´ Y‚#4°š÷Ñ42ß P œÚƒþïûú•øu÷¹ö^ö`ö·öV÷1ø7ùXúƒû¦ü²ý˜þLÿÅÿýÿñÿ ÿÿHþRý:üûäùÈøÌ÷÷vö8öRöËö¨÷çø…ú{ü½þ<ç©m  žÞÆCFÁ­Éÿ°é ¾ B޽þèú+÷¡ódð‹í+ëSéèmçkçè=éëEíõïýòDö±ù+ý–Üå ô Û I:­¥)E À Þìþ&uúÿ¿þËý%ýÌü¿üöüiý þÒþªÿ„RˆÖã¦I,Îþ7ýuûšùµ÷Ûõô•òOñ^ðÑï´ïðæð:òôBöáøÔûÿdÔ< ƒ I›q»o„ùÏÂúÊ I ºãý$úšö\ó€ðî6ìáê êôéZêKëºì˜îÔðWó öÚø¬ûkþ]o*‡  B  › ÙáÃY0#A•'üÿp ×Ïã '³ 1 ïMJè+ËÿEýœúè÷<õ°ò\ðSî«ìtë¾ê‘êöêíëtí„ïò õbøúû½ÿŽV÷ V]ô yÃkwíÛSh2 ÉGÆaý-úB÷²ôŒòÝð«ïúîÈîïÈïåðUò ôëõé÷îùæûÀýmÿÝèy»³gã3e‰°ÿèþCþÌýý—ýçýƒþhÿ“û”Q!ò° H § »uǧû o p F:ûþû;øìôÌñòîvìlêæèðç•çÚç¾è=êMìàîåñFõëø»ü—hy ˆ*Nçí]6€CŽqR ~š¾vý.û9ù ÷köõ6õ1õ…õ(ö ÷!øVùšúÛû ýþñþ”ÿ÷ÿðÿ‰ÿèþþýüøúìùûø6ø«÷g÷v÷ß÷§øÎùPû(ýIÿ¥.Ío ý aƒQ·¥í9ö'Õ çpÃûý0úöóÓï íºêóèÄç3çDçöçBéëví>ð]ó»ö?úÎýN§Áˆ ê ÚM?®ž!Î, P M 8$%L©ÿFþ-ýcüéû¿ûÞû>üÔü‘ýgþGÿÞyá òâîÿ¸þJý±ûüù;øöâôpó>ò]ñÛðÃðñóñ?óÿô-÷»ùšü·ÿüR¡ Î Âcœ[-/‘W†,W ‘ÐóýUùÉõŒò³ïQíuë*êuéYéÒéØê_ìWî®ðOó#öùüäþšCŠ ” 4 n F È þ ùÈ}+á°§Ñ8âÿÑÿtôëôþøÒ|çÔF[uˆYÿõüqúß÷Uõêò³ðÆî7íìqëTëÄëÃìPîcððòçõ7ùÈü€H– çÞdhÛ²è|rÒ«  ¾ ?¨œüWù]öÁó“ñÞï«îüíÑí$îìîð¤ñtóuõ•÷¿ùÞûßý³ÿK R²Äq§ÈæXÿÉþoþUþþõþ²ÿ³ñbø£Rò p ¹ ½ jµ’ü ð o ~ (z…^þûÑ÷ô—ñ×îtì‚êé2èìçCè8éÆêäì„ï”òþõ«ù€ýb6àG S𠜕ö¾ó Ñš @ LHLqÿÇücúTø¤ö]õôôôZôõóõ÷døÂù"ûsü¥ýªþxÿNS™ÿèþþýüû2úpùâø–ø˜øîøŸù«úüÆýÅÿýaÝ\ É ÇðK`Eô 1 Ÿü?ýùÞõqòSïšì\ê©èŒçç5çûç\éLë¼íšðÎóA÷Úú|þx s Þ ÓI9¢ˆòëÆ Ì ¨ o6Eÿ¼ý~ü’ûûú¶ú¿úû˜ûPü'ý þñþÄÿuùDNÃÿ·þsýürúÔø:÷¶õ\ô<óiòïñÛñ6òóFôøõøŽúVýY…Áõ  ßf‡.LÖÅÌd Ñ )Kü‰øþôÄñðî•ìÃê„éÞèÓè_ézêì,îŸð]óOö^ùoünÿA× ‘ ª V • o ì   ¿[ë)øù5´ÿxÿ‚ÿÍÿR æÙÒÁ–A³à¾FuKÍøþ¹üYúë÷ƒõ9ó ñNï×íÊì7ì'ì¡ì§í6ïIñÓóÅö ú“ý?ù¥( hMÁ²ÕövW¢f²œ ; ¨þYÿÐû~øxõÓòŸðçîµí íèìHí!îfïñóòõW÷¤ùéûþ ÊAg8´Ü¸P°ç2c¹ÿ@ÿÿ ÿUÿèÿ¾ÓŠž! ‡ ¼ ° T š w æ ã o N¶ÚÎý¥úy÷aôvñÑîˆì®êVé‹èWèÀèÅéaë‹í5ðMó¾öqúIþ-© ©¼?+{1Qçÿ¬ åËÒþ üùh÷¥õMôeóìòàò7óéóåôö€÷ûø|úñûIýwþoÿ'œÉ²ZËÿ ÿ/þ@ýOünû­úúÄùµù÷ùŽú}ûÁüUþ.C‚Ù5  ¤ Ž(a*u<y,Z O 4Ð:‹üÝøJõïñãî=ìêsèkçç<çèŒé‘ëîñOôÖ÷€û4ÿÕL€ \ ÍÆ;'‰c½¢!K2 í ‘3çÀÐþ"ýÂû¶úú¤ùšùÚù[úûêûÙüÌý²þ~ÿŒ»§L¬ÿËþ°ýgüýúùøœöWõHô€ó óûòRóôLõîööøYûþð6 + èT[ëóiF‡/EÔì ¢ A`ÿûÁ÷:ôñ9îèë"êðèZèaèé3êêëî¤ðóö»ùêüó¤ š À t ·  '  § (™ 6 rÿ ÿîþÿyÿÕ´Ÿ…X¼®N™4ލþüUú øÇõó¢ñëï‹î’íí í‹í•î%ð5ò¹ô£÷ßúYþö ; ¬ Ùª ç2áîY&] E © K–þû¢÷”ôèñ±ïùíÊì'ìì}ìiíÄîðˆòÉô-÷Ÿù üXþwZô:)¾ûç‰î$:AIb›¡ÿÿ¢ÿ ¶ ¿kÙ@Ž ± ˜ 4 w W Í Ö r ¦{ý<LýAú2÷8ôjñáî²ìñê¯éùèØèQédê ì@îòðô†÷:ûÿöÇk É ÈS[ѭ쎙ªå Þ ¯q;'þHû³øwö£ô=óKòÎñÂñòÚòæó3õ®öGøéù‚ûýYþ|ÿ^üRa,ºPÿqþ‹ý®üëûQûíúÌú÷úrûBüdýÔþ‡vŽÀ÷ & ôušRN†8i l \ÿàûDøÅô}ñ…îôëÞéSè`ç çZçIèÒéêë‚î…ñßôvø0üóÿ¡#` B ·¯"`-vF¬ºƒ  žª^JþyüøúÎùùŒøpø¥ø ùÔù³ú¬û°ü­ý“þUÿæÿ;Oªÿóþþàüšû@úâø’÷aöaõ¢ô3ôôpô+õQöà÷Ñùü®þykld < Û,‘„ç³æ' Ù @v–þ»ú÷óSð‘íKë’épèëçè¹èêÑëî¿ðµóáö(úsý¨±xìþ £ Ô ŽÒ§( ð } ã3à^ óÿÿþIþLþþÿºÿ†eEËRž¦aÊâ«+lþzüfúBø öô9òœðQïjîõíúí‚îŽïñ&ó¢õ€ø¯ûÿ¥<à  7ô?<ÖÏ&ߡȎ WÎý.úÈö³óñËîíìëRëFëÅëÄì6î ð2ò“ô÷®ù=ü°þóù´"ÎÂ*\iaTSn²+âÿÛÿ™YPr³N†™ u N 3 ³ Ê yñO¬ÿÚüîùÿö#ôsñïòìJëê|éméõéëÇìïºñÜôSøüÞÿ¼ˆ% znîèOGÕÊ1’² ‘ GîžpýzúÐ÷ƒõ ó/ò7ñ·ð­ðñØñõòXôîõ¥÷iù(ûÏüPþœÿ¨oì  ¸.y¨ÿÊþðý)ý„üüÜûíûKüùü÷ýAÿΔ†’¥¬ “ E°ÁiT‰=r 2 ‰ˆAÌþAû¹÷Oôñ;îÀë¿éJèkç,çŽçè,êVìÿîò}õ"ùéü¶où< "˜ýÚ'äÕ#¿ 8 —ð[íÿ´ýÂû"úÝøö÷o÷E÷p÷æ÷œø‚ù‰ú ûµü¸ý›þPÿÎÿ ¼ÿ/ÿgþlýKüûÏù–øw÷„öÍõ_õHõ‘õ>öR÷Ëø£úÑüGÿóÅ¥~ 7 ¹îÂ"Q 3ÄÈJY r«ÏýúùFöÏò­ï÷ì¿êéè‘ç¾çˆèçéÍë,îîðÿóD÷¦ú þWwSÚ û « ä¡ä³Í B Š ºärö´ÿµþÿý”ýtýšýþý•þRÿ&Ø“(‡§ E3ÛÿCþyüŒúøŽö¥ôäò_ñ*ðTïêî÷î‚ïŽðòôŠöZùyüÐÿIË< ‚ ƒ)^0µšÞ„—#:ñ ` Íý[ùïõÖò&ðïí>ìëêê ë4ì¾í®ïññrô÷Ñùƒüÿ§€$äD I ùauR61Q£0ÿÿgþÍÊéNrvI Ü ! ™ Á…èò­*ÿyü®ùßö#ô’ñBïHí¸ë¢êêêªêÔëíÐï‹ò­õ#ùÔü¥~BÕ ycºsŒå5em 2 Ï\öÿ±ü¦ùêöôžò%ñ(ð¨ï¢ïðåðòóAõ÷ÿøãú²ü[þÐÿô—îúÁM©ä 1ÿdþ³ý/ýâü×üý¡ýzþÿŸiN>$ ì „ Ø×rP…<y D ©¸ƒ$þ®ú=÷êóÏðî ë¶éWèçbçØçíèšêÔìï¯ò&ö×ù©ý?Ï üpcÉ܉¬OƒYå > {²ûjÿýÿúCùä÷èöOöö<ö±ök÷[øqùœúËûíüóýÎþtÿÜÿâÿ€ÿàþ þ ýóûËú¨ù™ø±÷þöösö°öN÷Mø®ùkû{ýÑÿ] ̃  šTžh§Upù÷v… 7£á ý@ù–õ+òïnìFê­è­çMççnèâéàëVî1ñZô¸÷2û®þE3É ÷ °î¬ì³ ü™ ô  ,2CqÌbÿ:þ^ýÐüü˜üäüiýþæþÂÿš`z´ªW·Íÿ.þüÇúíø÷Gõ¢ó5òñLðíïðŒð”ñóõq÷1ú<ý~áK¤ Ò ¼Ig ~O€•žI ¬â6üˆøõòRïíuë]êÚéìéê¸ë[ífïÇñfô/÷úÜü“ÿaWò+ þ l x , ‘ ¶ª}AâÞk÷ÿ"6#@RJ¨ñ炾™>¸þ)ü€ùÓö8ôÆñ“ï´í<ì;ë¾êÎêpë£ìcî§ðcóƒöõù ýj9òy µñ˶»é#Û%  G¾BÿêûÍøö—óžñ ð!ï£î¥îïðGñÚò¨ôžö¨ø²ú¨üzþu‹RÊóÔtà#Np›ÿÜþCþÞýµýÒý9þëþåÿ –7ö‡ 2 ± ð Þn’By7 ~ V Ìîφý(úÐö–ó”ðâí–ëÄézèÆç¯ç7è]éëdí*ðXóÚö”únþJ¡ è Í=)†N~(´Îˆö / Kb‰Øþ_ü1úZøäöÕõ.õíô õ‚õBö>÷fø§ùòú3ü\ý^þ-ÿÀÿäÿmÿ½þáýãüÕûÅúÄùäø5øÄ÷Ÿ÷Î÷YøBùˆú(üþKµBÞt í 30Ò¼ëž!š « aÔPüøòô”ñî÷ëàéXèkççuçjèôéì•î‡ñÇô;øËû\ÿÒ ¹ ð °ð­è¤ìÌR’ ž ŠlV\ýþ¯ý®üýûžûûÃû7üÜü¤ýþ`ÿ3êwÍä´;ysÿ.þµüûaù¨÷ýõrôó òRñûðñœñŸòôöUøû÷ý!k½ü ßTZÞÔ0÷ô • ï>ÿhû¹÷Jô2ñˆî\ì»ê®é9é]éêSëí4ï±ñpôX÷QúEýÃ&7ê6  ’ ¥ Y º Ô ¸w!ÊWY“ ÈÿÉÿ ŽD$&(ÝpÁÃpÁ¶Q˜–WþìûfùÜöcôòúï6îÕìèë|ë™ëEì~íBï‡ñ@ô]÷Çújþ)ì—  <VOâÓ#×ûžÑª B ²†þûð÷õ¤ò¤ð!ï#îªí´í:î1ï‹ð8ò#ô:ögø–ú³ü­þqö1²÷ï¢d­ËüÿNÿÍþ…þþÀþJÿ,wñŠ1Öe Ì ÷ × ]|-i / ƒ lõ-&öü²ùtöUónðÖí£ëçé´èèè«èáé­ëîÔð ô–÷Xû6ÿÜn ³ ”ýá3í •Ž¡ñ ÿ8þ¢ûYùk÷àõÀô ôÅóáóZô#õ-öh÷Âø)úŒûÙüþûþ¸ÿ3j[ €ÿÃþâýëüìûøúúoùùøÉøèø^ù.úWû×ü¥þµûcÜO ¨ ϱ:Xýµ¿>8¸ Î ‹Yÿ›ûç÷Zô ñî’ëŽéè@ççsç|èêEìèîïñDõÍøpüšïú § æ©ê£Ö‡¾Šø  ÒT4?†þýïûû¢úyú›úûûcüCý,þÿÚÿô-#Ò9]ÿAþòüzûêùRøÅöTõôódòò+ò²ò­óõôö3ùÉû§þ¸çA 9îJ7¤„ÌyˆÿæK? × ,WtþœúîöónðÊí§ëêé¬èâè­éë×ìï²ñô”÷­ú¿ý´wõæ D 4 ¶ Ì  Ù ç ¹ aðy ½–¥óÿ…ÿ]ÿyÿÖÿi+öÛ¡8‘£cÍÞ˜" þÂûaùúö£ôpòwðÌî‚í¨ìKìtì'íeî*ðnò"õ7ø˜û/ÿá•1 ˜ ³j§\zøÕ°¿Lk0 ´bÂýJú÷.ô³ñ¯ï,î1í¿ìÔìhírîãïªñ³óëõ;øúÓüòþ݈æñ¥ÓU¤ÎäõK®ÿFÿÿ5ÿ•ÿ;#E– އ × ñ Ä B _  U ' Š †%u‰ÿsüLù+ö(ó\ðßíÅë"êézèˆè3éwêPì±î‹ñËôZø üà¦5 uO°‰Íx†ûÞ;!¤Ø Õ ´w‹ýÛúzøvöÙô«óîò¡ò¾ò<óô)õyöí÷rù÷újü»ýÝþÅÿkËåºRµÿîþ þý2ü\û«ú-úïùüù[úûüxý#ÿ-qÅ M VŽ˜,AÏÔQMÒ ï¶>žþïúL÷Ðó•ð´íAëPéðç+çç†ç¤èYê–ìMïhòÏõkùýÑhÉÞ ’ Ö›ÙŒµX~4‰ ]  Ÿ>÷Þÿÿýhü"û3úù]ùoùÈù_ú%û üÿüòýÕþ—ÿ*‡£{ [ÿjþCýóû‡úùŸ÷Göõ'ôó4óJóÌó¼ôöá÷ ú‰üLÿASls Nè)ýSTïïY6’  dŒ©ýÔù)öÁòµïíëxé‡è4è|è\éÉê¶ìïÇñ¿ôã÷ûHþY7Í æ S N Õ í œ í í ¬ ; ®†¿£Çÿ.ÿÝþÓþ ÿÿ&òÔ½cÿe‡^âízÁÿÌý¬ûpù.÷øôäòñvïBîyí*í]íîWïñYóöùfüîÿ3¼ »ä„øÀçrnèó¦ e§ùüuù2öHóÈðÂîAíKìâëì¨ìÆíOï1ñXó±õ$øúýKÿ[)©Ò¢7‘â=€öÿ¥ÿ–ÿÍÿHý't×>˜Ó Ý ¦  ; ó @ •§^Èùþü÷øôõó_ðýíýërêkéôèéÍéëílïMò’õ$ùêüʨjó ,ýSUïëL]*’« Œ N ÚÿÓü ú”÷}õÑó—òÓñ„ñ£ñ)ò ó4ô›õ*÷Ïøvúü‰ýÔþçÿ¶@{3²5ÿSþpýœüçû^ûû ûNûåûÏü þÿSMj™Æ Ý È uÏÆLVÝß\\ é äzëýNú¾öVó/ðbíë)éÝç-çç±çâèªêûìÄïðòiöú×ý–9£À y¾‚»g„+Êð $ š©jÿhý¯ûJú?ùø=ø?øø#ùêùØúÚûáüÜý¼þrÿóÿ78õÿmÿ§þ©ýü6ûßù‰øH÷,öFõ§ô[ônôçôÊõ÷ÉøÚú=ýäÿ»¯¨ OÌò­í£ÇRE¤xζ G˜Ââüùkõ ò ïyìmêòèèÐç,è"é¦ê¬ì!ïðñõCø•ûßþ ÿ«ý è a dï®ô ä Ž  XŸêKÒ‡ÿÅþLþþ3þ‰þÿÍÿ \$É=sbRQqÿ¤ýªû”ùv÷bõnó®ñ4ðï\îîSîïPðòGôêöèù.ý¤5Å9 ykø –‹á•¨  ql q°æÿ,üŸøUõfòäïßíbìsëëDëûë.íÐîÍðóŒõ"ø¾úKýµÿèØx¾§2a<Ë<;+C“åÿñÿ@Ó¢¤ÍYšÂ¾ ~ ô  Ò +  ¦Ï¡(wþžûµøÑõ óxð2îLìØêçé‚é²ézê×ëÃí3ðó_öñù¶ý’l& ¨ Öœå£ÉQ:†<jlj 0 Øz1ÿü4ùªö‚ôÉò‡ñ¾ðnð’ð"ñòOóÎôyö>ø úÉûjýàþÇ.K"½$eÿ²þÝý ýŒü,ü ü6ü®üuý‹þéÿ†XNXb X & ¹ýã[]ßàbi ÿ 3¾Bý¹ù>öìòÛï%íÝêéáçEçJçñç5éëqíKð‡ó÷Çú–þ` } Y]2BÅÄLm:È - €×HæþÂüéúgùBø~÷÷÷X÷ê÷¶ø®ùÀúÝûòüðýÊþqÿÞÿ ñÿ•ÿøþ"þýøû¿úƒùVøJ÷oöÔõˆõ”õöÕöø©ùŸûæým$øÑš 9š¥Hq&£‹á®ç xÊùÿüTø·ôbñkîèëëé€è±ç‚çóçþè™ê·ìDï.ò\õµøü‚ÿÄÏò é lt´íË ^ ¹ ï9sÒc3ÿIþ©ýVýLý†ýûý þfÿ>ç—hq0¢Æž4ÿý½ûÎùÔ÷âõ ôgòñ÷ïMïïTïðPñ ó7õÍ÷»úðýRÎH¦ Ϫ ’q³SSº’êÕ j Àóÿ]ûÉ÷{ôŠñ ïíë«êYê˜êbë¬ìfîðãò}õ4øóú£ý/…•R³²P p  OgX5 óô €$Œ2 5d¥•O Ä è ±  ½ð–þNû…øÂõó§ð}î±ìTëwê$êcê7ëìîñëó1÷ÁúþW)Ú Q s,f(žs©J`ü1 ÃRÜ}þHûWø¼õ‡óÄñ{ð°ïcïŽï)ð(ñ|òôÜõÂ÷²ù—ûaýÿþc†_ê)ÑMœÏõÿÿWþ³ý?ýýýiý þûþ0¥Nè¿ p ë ð^XØÛb s  ZO ¤ü1ùÎõ“ò›ïüìËêéûçtççFèé‡ëùíáð+ô¾÷‚û[ÿ,ÝS u 0q,Vìí^H¸¾nÝ ! R‡ÖSþüú{ø?÷göóõßõ$ö·öŠ÷Žø²ùæúü6ý3þÿ™ÿïÿÐÿ]ÿ¯þÏýÊü®û‹úqùsøŸ÷÷·ö¼ö÷Ü÷ÿø€úYüþç}/çŽ RBÌàpsäÂÚ*  ¥ý3ÿ`û ÷ôÆðÝíië|é"èfçKçÐçñè¢ê×ì}ï~òÄõ5ù·ü0‡¦v æ é r~ ¬Ö¡ [ r st‡½%Íþ»ý÷üüYüyüØümý(þýþÚÿ®kfŒlKL ÿŽýäûúFøvö¾ô3óæñêðMðð_ðñUòô&ö­ø‰û©þöZ¼ Ô3xBoüëA S1 º 1UþŽúöö§ó¶ð8î<ìÍêóé¯éêÞê>ìîGðÉò‚õ[ø;û þ¹/]5® o ¸ ¡ 3 | ‰j1ïµ”™ÑDûÿõÿ2°eHK`w~d»‘ #Þ>L¥ýûiøÈõAóìðÝî+íåëëÙê&ëìqíhïÞñÄôø‘ûJÿÞƒ í ªÔprÔ•¶A@Åã± G¿4¿ýxúw÷ÎôŽòÃðwï¬îcî—î?ïPð»ñmóTõ[÷nùzûlý2ÿ¿ µ$ï|×6X‡ÿÒþHþôýàýþ‘þXÿd°1Ø—[ ¨ (ïSIÉÑ ` } 0†bÿü¹øoõNònïèìÏê6é+è¹çåç±èêì’î†ñÛôxøDü"ù­$ Fþ9ì “„â¶úÝ  &T±ýOû=ù‡÷6öMõÍô²ôõô‹õgöz÷²øþùMûŽü°ý§þgÿéÿ%ÕÿNÿ’þ­ý¬üŸû—ú¤ùÖø>øé÷â÷2øÞøçùLûý ÿPÃRçm Î ôÊ<;º®ê5üM 8 Ò2qþ©úööró8ð_íüê!éÚç1ç*çÄçúèÁê íÉïáò=öÄù[ýçQ€^ Ú är~ –¯dÇ ê à ¾š†”ÕÿUþý6üŸûZûbû®û5üéü»ý›þzÿFòp´·qã õþ¢ý üúÍø÷ƒõôØòëñYñ.ñrñ,ò]óõ÷ˆùOüXÿØ K Aê/þGûnµo­ EjŠýÀù'öÙòìïsíëêMéé|éoêæëÔí%ðÄòœõ”ø•û‡þRæ/ ¯ Õ á Í ^ Ÿ Ÿ nÀf þ Vâÿ±ÿÅÿ«mSPTM,à[t2‡¶¢ÿVýåúbøãõ}óFñTïºíŠìÓë ëøëÞìQîIð¾ò õÝø_ü Њ! {~.·¦ô ­" {ƒ; ¼ úü¤ù”öàó—ñÈïzî²ípí®ífî‹ï ñÚòàô ÷@ùrûŠýyÿ,œ¾Ž 4¯Ru°éÿFÿÔþŸþ®þÿ¢ÿ„§þ~¹R Í  & â >2µ à ] ‰ M¸ÙÅþûQø"õòVïéìéêgérèèSè/é¥ê­ì8ï7ò•õ9ù ýìÆzð Àôœ¯(QN–È Î¿´Äÿý…úZøŽö*õ3ô©ó‰óÌóhôOõröÀ÷'ù•úøûAý`þJÿ÷ÿ^_ÿÿeÿžþ·ý¿üÆûÜúúwùùùBù×ùÆú ü¦ý‰ÿ¨÷aÓ7 x <—ƒñÙ6Ol ^jµýûùWöäò»ïóì£êÚè§çççÎçéöêVí'ðTóÅö`ú þ§!]G Ë Ûkuöònu^c 9 ô«pXrÿÌýpügû²úRúDúúúú¨û{üaýLþ+ÿîÿ‡ìóŽâÿôþÊýqüöúgùØ÷YöþôÙóúòpòIòŒò@ófôýõý÷\ú ýüÿEq \êÍÿŸ¦ÞÇûÆ ? ¿üõø^õò,ï»ìÑêyéºè—è éê¥ë¬íðÕòÊõáøüÿø§  ´ é ®  ó € ¸ © d ú™P5T´ÿYÿEÿtÿáÿ‚N4'ð¥&f\þJ>Þ0@ÿýÍúoøöÎóµñßï^îCíìwìÙìÅí:ï3ñ¤ó€ö´ù+ýÌ€*± ùêotéÄþ•íö #uÆÿ0üÌø±õôò¦ðÔî‡íÄì‹ìÖìŸíØîrð\òôËö'ù~û½ýÒÿ«?ƒr K<æS’±ÀÑó5¦ÿNÿ7ÿdÿÙÿ‘‰·„€â   É  › ³ [ ˜qô.5þûù÷çôýñTïíë¯éÏè…èÕèÁéDëWííïóòWöÿùÓý·B ³ ËuŸ;@©uªRx/ŠŸ ‡[2&ÿJü²ùp÷‘õôó‰òfò¬òPóDôyõßöbøïùvûåü-þBÿ«÷ýÀGÿÎþèýüüüPû°úHú$úLúÈú™û¿ü6þôÿî\©ì øšß¸õKa- ˆ ‚0§ýXùÅõdòNïšì^ê©èŠç ç+çîçNé?ë³í˜ðØó[÷ûÁþmô; - ·ÊY_ÙÉ6)²àÇ } §Gþþ3ýµû‹úºùBù ùMù¿ùjú?û.ü'ýþöþ®ÿ3~ˆLËÿÿþ×üûú¥øA÷üõçôô‘ókóªóVôoõõöáø)û¿ý’‘¢± £ aÔ熡-"|=k< wµ×ÿöû/øœôXñyîì4êêè;è*è´èÒéyëší!ðùò ö?ù{ü§ÿªrì º ü Ê %— Ä ¤ J Æ,ŽþI=sÿîþ²þ¼þÿ‹ÿ<óÙ°hòAJn‚D»ñþðüÊú‘øXö4ô:òðïîxí^íÇí·î-ð"òô`÷ˆúòý„&¿2 fD´¤ËñtW¤f­ " Áÿaûò÷Ïô ò»ïêí ìäëµëìêì9îíïóñ7ô¤ö#ùŸûþ;:ñUahjÎæéèògìÿ­ÿ²ÿûÿˆV[Þ>œè ý ¦ û ð  £ \ ¬9´ý¸ú´÷Àôôñfï/í`ë êBé ékédêôëî­ð¹ó ÷Êúžþ€U l |:ȽÎî~Œ)ic /æ¢{þ†ûØø‚ö‘ôóònñKñ–ñCòGóôö®÷]ùûžüþMÿN «‘7¨ïÿÿ8þYýüèûsû<ûNû®û`ücýµþM!"Ak‹ Œ \äÜ/U"m? £ ©díÿXüÁøBõõñôîUì.êŽè„ççNç%è˜éœë"îñjôý÷¸û€ÿ8É  °=<¬êÉ:M « ! §xþ‹üìú¥ùºø,øù÷ø„ø.ùúû üý þãþŒÿþÿ/Èÿ/ÿYþPýüÕúƒù8ø÷ö8õºô’ôÌôlõvöè÷½ùìûfþûîÝ ± R©¡(.§‹Ö‹¯Mt 7 «é ÿ0ûo÷äó©ðÔízë©éoèÑçÓçqè¥édëí>ð2ó_ö®ùýIfEÓ Á á=%£   ÅO¶Hÿqþþôýþ‡þ"ÿâÿ¹™o,Â"AÓºW´þÛüÜúÈø³ö°ôÔò2ñßïêîbîRîÁî³ï&ñóxõ?øYû²þ2ÁE £ ÂŠä¾ ¼Í< Fö-þ Ð=þú÷ðó+ñÙî íÇëëñê[ëIì¯í}ïŸñô‘ö3ùÒû[þ·Ø°2Y!Š™UÊòãëwëÿ lë÷%fªßôØ { Ï Ê c • `ÇÒŠÿÿBýfú‚÷®ôòïrí½ë€êÊé£éêë²ìÖîxñ‡ôï÷˜ûiÿEº  ³ÃB&k”Š4 ÅcÆýºúø÷õ‘óòòðYð9ð‹ðEñYò¸óPõ÷ßø¯úlüþmÿ˜}ip4½Pwÿ›þÍýý™üMüEü‡üýøý#ÿ“@ ÷ « 8ð8U#t N ¾ÓŸ:ÿ¹û7øÎô˜ñ­î%ìê‰è•ç=ç‡çqèöé ì£îªñ õªørüCžó î |Œ oBŒU­¤P Ä d»5äýÕûú¶ø³÷÷ÏöæöM÷ø÷Ùøàùýúü1ý)þ÷þÿìÿÙÿkÿ¿þÝýÐü§ûqú=ùø'÷eöèõ¾õîõöy÷Öø‘ú£üÿ•T&õ © ,hFµ¦ àÊ瀤 f ÜFþpú·ö6óð>íòê1éè|ç‘çEèéeë·íqð}óÄö,úœýø,¾ ú Æ ñL/¢±k á % Kf‹É2Ôÿ·þâýZýý*ýxýýý®þ|ÿV.ô— A4Û5A‹þÚüûù"÷@õóùñ»ð×ï[ïSïÆï·ð%ò ôcöù$üjÿÕO¼  »ÿÃù•“ï­Õuœ_ ÕCrý¾ùBöóPðî7ìûêSê?êºê½ë:í"ïbñäó“öWùüÄþC…{X5 ® È Š ÿ48ðÆ®¸ï`;´hNZ}¨ÉϪI   ¢ G ‹këè}ÿáü&úd÷°ô!òÎïÌí/ì ëfêPêÌêÝë~í§ïLò[õÁøfü0Ìg ¼´9:¨z«<1”rÞë ² LÑ\ýçù÷œô’òýðæïNï2ïïUð|ñòò¥ô‚öuøjúNüþ¡ÿôÃ6]<ÜHŒ¸Ýÿ ÿLþ·ýTý1ýSýÁý{þÿÇJüÎ®Š N ç AKö5þMw ] Ûá‘þ&û¼÷kôLñzî ìê›è¼çxçÕçÒèhêŽì4ïHòµõaù2ý ÕrÉ ÅP\ÜÈãË æs È û%Z³ÿ@ýû:ù¾÷¦öóõ¤õ´õöÈö³÷Éøúù4ûfü€ýtþ5ÿ»ÿÿÿÿÿ»ÿ8ÿ|þ“ý‰ümûPúBùUø˜÷÷ëö÷“÷wø»ù[ûNý‹ÿÿ›Kù ñÕ- ^$Xû©Í ‘ S„ý·ù ö•òsï¹ì}êÍèµç=çfç/èé|ëåí¶ðÛó:÷¹ú?þ±øý¬ ô È!ùP+’4 · ¼´²É ‚ÿ=þBý–ü9ü)ü_üÒüuý;þÿñÿÀsüM^(¦ÛÉÿvþîü>ûuù§÷äõAôÒò§ñÒðað_ðÒðÀñ(óõL÷óùéümÎ# Q @رÑYBŒ9Rãý´ Y|¥üíøoõCòï5írë@ê¤é é.êFëÛìÝî:ñÛó©öŽùrü>ÿÝ>P^ L Ó ö » . [ R"ߘ_EU› êÿ÷ÿEÒ”†™¨¢unz.…}]T ÿ‘üúùZ÷ÇôXò"ð<î·ì¦ëëë–ë°ìVî‚ð&ó3ö”ù3ýôÁ{ P9­ø·ÕQ1}Eš‘ A Ã2ªÿAüù,ö©ó•ñüïãîMî8îžîuï°ð>òô ö ø:úEü/þèÿc—|VN}Ëû?vÿÌþQþþþZþíþÉÿçAÊu1ì’  V Oî&í> z m ý6,ôý¢úQ÷ôñ[îì êÃèùçÊç9èGéíê!íÔïôòköú÷ýÖ£B š “”u½o,Q · ËÓé"ÿüGúTøÁö–õÔô|ô†ôìô¡õ˜ö¿÷ù[ú­ûêüþîþŸÿ 8Äÿ-ÿfþzýxünûoúŠùÑøQøø0ø ømù–úüìýWÐ\è [ ¡£NYžX‚3Ê ñ º;ŒÈüùgõòïîFìê}èyççRç/è¥é¨ë'îñJô¾÷SûíþrÊÞ™ ê Å öHq]ë, 5  ìÄ´Ìÿ²ý“üÅûIûû?û û9üùüÔý·þ“ÿXøf—„*†žÿuþýŽûëù?øœöõ»ó£òÛñrñsñæñÎò,ôúõ1øÅú¤ý»÷>x Œ aßó‰“ݳ½APþ a•´ÿÙûø¢ôxñ¹îuì»ê•ééé¶éäê’ì®î'ñæóÔöÙùÜüÇÿ„.þg e ÷ æ U x _ ¾Yþ¾¦Ã»ÿžÿÅÿ*É•}l;Ú<T‡™Q¶ϪþTüáùd÷óô¤òŒðÀîTíWì×ëÝëoìí9ïeñô÷húýý³s Ô¬ë4ßèPRC$ ¿ -‰îþtû4øEõ¸òžðïéíWíKí¿í§î÷ïŸñ‹ó¨õà÷úPübþAã<DøXh/¶ <Xq•×ÿAÿàþ¾þáþLÿþÿò#„ :à * [ F Û Õ * | $t‚cý-ú÷öÛóñðRîìHêéMè1è²èÐé„ëÄí‚ð«ó)÷ãúÀþ¢p b VÖÒ<Gæòwƒ({ ’ ‡qg‚þÕûqùf÷¿õƒô¶óVó^óÇó„ôˆõÃö"ø“ùûgü©ý¼þ—ÿ0†•aðÿIÿyþŽý–ü£ûÅú ú‡ùDùLù§ù[úgûÉüzþoœñYÁ  :!³ß–Í|Ÿ8Lå  âmËÿübøÑô|ñ{îåëÍéCèRççTçFèÑééë}îzñÉôQøùû¤ÿ9 À … Ý»è2ø@Ž´ _ ‹}¨þýÕûçúOú úúlúûú¹û–üƒýnþHÿŒßò¿Fˆÿ‰þSýóûuúëøf÷øõ´ô¬óðòŽòòÿòßó0õîöùŽûUþRrž» ³ lÑËJ>žc‹’˜ > ÌêþûV÷Üó·ðÿíÄëêýè€èžèTé˜ê^ì–î*ñô÷5úVý^8Ïø r }  D q ˆ ^  ŒŠ#ãÖxÿ1ÿ1ÿrÿïÿpZJ1þ  2 ¿—[[þ+üÝù„÷5õó ñZïîí©ì¼ìVízî%ðNòëôê÷:ûÂþk¶ # H \%Yðå8î¯Ú§ / ‹Ö+þ£úW÷^ôËñ­ïîúìpìnìðìëíRïñóZõµ÷úpü¨þ­tðêdˆ_ñJzš¬Ô"¡ÿ[ÿWÿ˜ÿéð(†ûuã3 R 0 ½ î ·   ™S»åÿáüÇù¯ö°óâð^î9ì‡êWé¶è­è>éjê+ìvî<ñlôï÷¬ûŠÿl8Ò !…uÒ–¼H>«ž(_ Z 1ý××ýû“øsö»ôqóšò5ò=ò«òsó‡ôÖõN÷Þørúøûaýžþ¤ÿhçÁ9…ÿ¯þÇýÞüüJû½úlúaú¦ú>û+ükýøþÈÏþA† · ¿ ŠÂì’°H^ü 0 £ÿhûÈ÷Jôñî˜ë”éèBççmçsèê>ìåîõñVõðø¨übx¡ m ɨÍÅü¿&ð ‘ «O!þmü ûþùKùòøíø5ù¾ù{ú^ûVüRýBþÿÃÿ9rh…ÿ±þ¥ýküû©ùAøìö¼õÃôô±ó²óôðô2öÝ÷ëùOüûþÛÞëë Æ c¬ŽõÔ!ÔîqdÖÕ w Ó þGú“öóðSí#ë‚éxè è=èécêAì’îBñ:ôb÷¢úßýö¦ÿö ~ ” 4b$‚ Œ N Ü H£u ÔÚÿ"ÿ³þ‹þ©þÿ™ÿT,ò¾gݤñë–ùÿþüíù¹÷Œõ}ó ñðÇîïíí¨íIîoïñ<óÑõÆøü‚ÿ¸@ ™ ªY”HhëË ¬¼G_ ’ÞcýÏù{ö{óãðÃî(íì—ë¢ë4ìCíÁîðÅò"õ ÷'ú£üÿ*±ùæv®‘+‡³¾º¸ÆõQåÿ¹ÿÑÿ,̨¹ñCŸó- <  — Ç – ü ø ЏŠUÿoütùzö™óéð€îvìÛêÂé5é=éÞéëáì4ïò5õºøxüS3úŽ Õ¸$V“tÊ£/  Ê{: ý@ú¯÷}õµó`ò‚ññ%ñ›ñoò”óùôŒö;øñùžû.ý•þÄÿ²[ºÐ¢7šØÿþþþEý†üðûûpûšûüáüýýeÿîö5 D . ÞAEÝüœ·Pk  O8ß]þÈú;÷Òó¥ðÍí`ëqéèIç!çœç¶èhê¦ì_ï€òòõ›ùaý'ÕQ P®Œß¤Ø¥R•ƒ. ­ ©ÿ‹ýµû3ú ù@øÓ÷À÷þ÷ƒøBù-ú2ûAüJý<þ ÿ¥ÿ%˜ÿîþ þøüÂûyú-ùï÷Ñöäõ8õÛôØô9õö1÷Çø¼úý“ÿU8& à Cr:ŠU3@¸£ ª7Xý„ù×õkòYïµì“êéè­çòçÒèDê:ì¥înñôÄ÷ûvþ²¾‚ï õ ‰ §Kx3‡€ . £ ñ+e± ¾šÿºþ"þÕýÑýþˆþ0ÿùÿÓ°0µÄ1N©ÿöýüúøùõ ôHòÈðïÕî~î¢îFïkðò-ô·öŸùÑü8¾H» þ ù“·VaΛÆUSÍÕ é(X–üûøŸõ›òðäíMìDëÎêçê‹ë¯ìEî=ð‚òÿôŸ÷Iúéüjÿ·ÂãéŽÖÄd¿ååж©·ð]õÿ%šM6Iz¹ô å j œ r å ò™ßÌmÓþ ü2ùXö–óñ¹îÈìFëBêÈéàéŽêÒë¦íÿïÏòö‰ùDýõµ@ }T²†Åffɓғêì ± Sê‘ÿ_üjùÇö„ô°òSñpððð—ðyñ±ò.ôÞõ¬÷†ùXûý þùÿáfŸ‘Aº:_ÿ†þÁýý«üuü„üßüˆýþÀÿAùÚÒϾ Š l_é›¶Rt $ qi"´ý4ú½öjóTð“í<ëdéèfçSçáçéÒê íêïó™öOú þð§( \ -Šc°k’*:ÏùÊW µ üCŸ%ÿæüñúRùø0÷±ö‘öÈöL÷øùú=û`üqý`þ"ÿ¬ÿöÿüÿ¾ÿ?ÿ„þ—ý„üZû(úÿøñ÷÷gö ööVö÷*ø¨ù‚û®ý¿N « !Ð Áê€ðÖ>8 Ù8m•üÉø&õÅñ¾î(ìê“è¬çdç¾ç³è;êIìÌî¯ñÚô7øªûÿlŒdà ó ‘´Yƒ6}dü W † Ÿ´Ù•Gÿ>þ€ýýëü ýnýþ¿þ“ÿmAý’óð€Â¹kÿáý'üLúaøzö©ôóœñƒðÊï}ï§ïLðoñ ó õœ÷tú”ýçVÉ& Q4·ÅMBœTmëØB;Ú 7k“ÿÈû'øÈôÂñ*ïíë€êê?êöê0ìßíòïUòòô²÷úAýäÿR~XÖòª ÿ ö ™ òئ|i|ÁB TÞ  Ãçüð´8 o O Ðð®Ûaþ½ûùKö©ó6ñï1íÆëÖênê•êPëìvîÓð¤óØöYúþà±g æ à.ò­šçœÄm¬– C ÌLÞþ—ûøÜõŒó®ñJðeïïï¡ï”ðàñvóBõ1÷.ù&ûý¿þ@x!|‹Uâ?z¡ÆÿøþFþ¿ýoýaýšýþðþ`ð¨zT" Ò O ‡ièø­P | 9 –¡oý­ùOöóðmí.ëmé7èšçšç;èzéNë¬íƒðÀóK÷ ûåþ¼wü 1 Z.r 8¾º8Güj ¨ Îó-“þ4ü!úgø÷öŽõdõ–õöåöæ÷ ùGú†û·üÊý³þfÿÛÿ ùÿ£ÿÿIþWýJü0ûúùAøœ÷<÷*÷r÷øùú>üIþ–·a ~ ûQu2¼³þe a j¨ÿØûøô+ñ3î­ë«é:èeç2çŸçªèIêmìïòEõ¸øBüÈÿ/aI Ó ð •º^‚+c8¸ ÷  þîì Wâþ²ýÏü<üùûüKüÐüýPþ-ÿÐxñ/+ÞFfBÿàýOü›úÕø÷]õÒó€òyñÍðˆðµðYñwò ôö~øBûNþŠâ< ’[Ƽ.SùÿmK§• ) |¨ÉþúúV÷öóòð]îHìÀêÍéqé«évêÆëŽí½ï=òùôÚ÷Èú«ýmüD9Ï Ç ( % È  / Ó‡>õhÛÿûÿ[÷Ķ¿ÎÓ¾}@-ÀõÍKuWþûéøSöÒó}ñkï®í[ìë(ë\ë!ìtíRï°ñô¯÷+ûÙþŸe € ¡Z˜Jdß·ð 3[. Å8£!þÈú±÷ïô•ò°ðIïdîî#î»î¿ï"ñÒò¼ôËöìø ûýòþ›ëfqz»ã(fÿÉþ^þ0þFþ¥þNÿ<kÒbÅt  l ‘ eÛæ~  K ƒ QÀàÆÿ…ü6ùòõÑòíï]í6ëŒémèäçøçªèùéÜëHî+ñrôøÍû­ÿˆFË ÿ Ìê"ÃË>%Š€g † Œ‘«òývûHùv÷öõjô9ôiôñôÄõÓö øaù½úüGýXþ4ÿÔÿ/G¯ÿ ÿ:þHýFüBûMúyùÕøoøRøŠøùúOûìüÖþ]Ù`Þ ; c?½Ì^ièØ=… … 1æþ"ûn÷åó¡ð¹íDëTéöç5çç˜ç¸èlê§ìVïgòÀõHùæü~ø:/ Ä è‘·Xs9ø`ƒ t Gëájþýü\ûûúëú#û™ûBüýïýÔþ¬ÿgúWuMÞ&,ÿôý‹üþú]ù¸÷$ö²ôtó~òÜñžñÌñlò‚ó õ÷Zù üþþ!^žÆ ¾n¿øÃôˆ~Ý­þâ m ¹àþý-ú‰ö+ó*ðœíëê,éßè,é êrëTíï:òõø"û%þ±#Î  å N O ð = D  ¿Wî•[O{çÿ˜ÿŽÿÇÿ=é¾®ª¢…B˵ö“ßåÿ±ýUûãøoöôÚñäïAîí;ìòë3ìÿìXî7ð“ò_õˆøúûžÿXª Âî“ú¾âlhåø¶ 8˜ð]ýôùÐöô¢ñ¸ïPîníí>íåíýîvðAòIôzö¿øû1ý8ÿ•ÕÂZŸ”C¶ü"9Q{Çÿ?ÿðþáþÿ˜ÿ\bŸŽ"²* y U Ã Ë f E mñ))ÿüÏø¦õ¡òØïbíUëÂé¸èDèjè.é‹ê{ìòîßñ.õÈø”üvT” ÄŠÕ–ÂSJ©yÇ¢P Q 9Eý­úgøöþôìóIóóCóÐó®ôÍõ÷‹øúzûØüþÿáÿh©¥_Þÿ,ÿTþfýqü†û¶úú¡ùxùœùúçúüŒýSÿXçK¦ ã ì®’ñS5¢ ©]Õ*þuúÑöYó&ðQíïêéÈççç§çÛè¤êôì¸ïÝòJöåù•ý>Æ ² Û†ªDWæü¦õú Ë |#Õ¥¥ÿâýiüAûpúõùÎùõù`úûÏû¶ü¦ýþcÿŽÏψûÿ*ÿþÝübaresip-1.0.0/share/sound9.wav000066400000000000000000001047741372575704200162300ustar00rootroot00000000000000RIFFô‰WAVEfmt D¬ˆXdataЉÔ (ü;Ô½óyZ¤oÓì Ú¼°Óÿ=ýû8ùã÷ ÷«öÀö<÷ø#ùbú³ûþü,þ&ÿÜÿ>Fðÿ<ÿ3þàüWû«ùô÷LöÍôó«ò4ò:òÈòâóˆõ²÷SúYý©,¿D ˜3B²vÓn]±‚ê õþûY÷ô/ñâî2í'ìÂëìÙì9î ð:ò§ô7÷ÌùJü˜þŸO›zí÷¢ü ìÕÿÛþþ“ýhýý7þ6ÿ’C7Z“Ç Û ³6KßâKGç  µ>þTúxöÌòrïˆì)êjè[ççlç‹èVê½ì¨ïýòœöcú3þæa…; n ”xÔ¹= w ‚ xtâ|mÿ½þoþ‚þîþ¥ÿ—±ÛýÿÊKp,xR¾Æyþêû2ùkö´ó)ñèî í°ëäê¹ê7ëaì2î¡ð›ó ÷ÒúÔþîýß q–20ÿ.´¤Þ x ¶™ýÊúbøpöõô³óÎó\ôJõ…öõ÷€ù û„üÏýÚþ–ÿùÿÿÿ§ÿùþþýÈüjûûù’øJ÷:özõõ/õ¿õÑöcønúçüºÿÏX Œ ‹7s&<¦[[©Si @=üønô1ñwîSìÕêêäémê•ëJívïÿñÉô´÷£úxýlbì ÌŽôùÅŒgk®ÿ>ÿ&ÿnÿnÌ«‰ L Ù ðQ*t+ R óægÿ½ûøjôñöí^ëTéîç:ç@çèxé˜ëOî…ñõ÷øòüé½Lz .TàËÂà¶ Q íMC…ÿ þý†üVü†ü ý×ýÓþêÿ ã~Dz6Q]ÿcý+ûÎøcöôØñïïhîYíÖììì£íýîôð~ó‰öþùÁý²±œ N ©á’Ó\0[ð½ 0 ‚ÔHþùúøõ~ó ò%ñÒð ñ¼ñÛòOôöÕ÷²ù~û!ý‡þ ÿ_¿ÀeºÿÌþ®ývü<ûú!ùoøøøœøùùúÓüÿŸkZN * ÏÿY0™RcÖÀ 9 \L+ýù=õ¶ñ¡îì0êõèoèžè|éüê í”ïyòœõÝøüAÿ&ºæœÔ Š Ã † â ê³Tè…E;y úÿEìå#“ ²0 € ‹ 9 z > ~ 6 i"mbý¬ù<öêòÖïíßê1é&èÍç+èAéësímðßó©÷­ûÇÿÓ°> _üa"Š[©‰ n ®óYûÿëý;üöú"ú¿ùÇù.úåúÙûóüþ;ÿ8‚­yâëÿ™þúüûù÷ õ/ó–ñXð‹ïAïˆïeðÛñãósöyùÞü…R#Õ HZðòKïØS”]Ê ý9ÿ…ûøõ‹òŽð(ï_î2î˜î„ïäð¡ò¡ôÊöÿø&û&ýèþ[s(weúDUCÿ"þ ýüaûóúáú6ûøû'ý½þ°ïfü•  ^TÞåW)S׺ Ý HibþSúaö¬òWï}ì7ê˜è­ç{çè;éë‚ícðžó÷£ú*þЧg¶ „ É ± ` {  vņ% ?ÒÿÂÿ °›¿\¥Ê´M ƒ H “b·šNþIû)ø õòTïøìëÁéé é¹éë%íËïøò“ö}ú–þ¹Ä–  ~Nqá ¶1%ªÜ Ø ¿¯ÄþÆûÛùcøf÷äö×ö5÷ï÷ðø#úoû»üðýùþÁÿ9X}ÿ‡þEýÅûúbø¯öõÆóÂò&òòfòUóÑôÕöUù@ü€ÿùŽ Š ®n­TR›*&«¤, `bU\ü—ø&õ%ò«ïÈíˆìîëùëŸìÓí‚ï’ñëónöÿø‚ûÝýøÿ¿&#´ÚŸ:7üþ%þýMýhýçýÌþ¯–²ë( N @ã ஫ ×  é\’ÿ§ûÁ÷ô†ðsíãêíè¢çç8çè®éãë¥îØñ`õùêü¦4tM © z¶[lòý  ò _çÂÿùþ‘þŒþáþ‡ÿk~§ÏÞ½U–qÝ×a‚IÿÇüúJ÷†ôåñ†ï…íúëüê›êáêÔëqí¯ïòÌõ|ùpý†ž“ D [Žñy6Vîñ ˜.Ò¤þ¾û6ù!÷ŠõxôìóáóLôõAö ÷#ù®ú*ü€ýœþlÿæÿÃÿ)ÿ?þý½ûMúÜø…÷`öƒõõóô]õHöµ÷Ÿùûû·þ¿øFˆ  mÓ¶¦˜ÓZ7{; “  †hýhù§õFò`ï íUëMêóéEê:ëÂìÇî2ñæóÆö²ùü<ÿ¥¶_•V£ƒ4*þÆ›“Æÿ@ÿÿ@ÿÐÿ¼ÿŠI( à „ à ÝfkãÇ  á ,ŸýüDù˜õòêî&ìêéLè\ç$ç¨çäèÎêUídðÞó¥÷—û‘ÿrf B –SrïÍà9: ÿ ¤Eþæ–þzýÆüzü‘üýºýªþ¼ÿ×åÎ|Þã„»Šøÿþäû‹ù÷´ôoòið¾î„íÑì´ì7í^î$ð‚ògõ¿ønüVWM “¢(JÌ’ ÇÛ c ¿zÿüù`ö5ô“òƒñññœñ™òóóõY÷2ùû®ü#þPÿ&Ÿ¸sÜÿüþèý³ütûEú>ùtøý÷è÷Cøù]úü=þ¹ze` K z„ Rôæ,Ðã } ¸´”þyúˆöáò¥ïììÎêYé˜èŒè1é}ê^ìÀî†ñ•ôÌ÷ û7þ.Ú%þ[ 8 • { ö  ò 8ÓŠrñÿ$µœË2¾UßC g 6 › ‡ ð Ð * mw;þÒú\÷ùóÊðîíƒë¢é_èÊçëçÆèTê‹ìYï¦òWöKú`þsb R RèÔ³´,0Ø B ‹Ð.¿šþÏümûyú÷ùáù.úÏú³ûÃüéý ÿë€Ã¨+Kÿ‚ý²ûµù¢÷“õ¥óðñ‘ðœï&ï=ïëï1ñ óvõ[ø§û@ÿÜŸ ,c&[îÏö`| Ih†ÅüCùökóAñ«ï±îRîŠîLï‡ð&òô+öZø„úü_þçÿæPV^|qÿQþ6ý7üjûåú¸úïú’û¤ü þüÿ*˜,Ì [ ½Ô†»`fÇ” ÄÅÿ³û²÷åómðgíîêéðççÌçËèrê¯ìkï‰òìõsùüühšvèÝ L 0 ‰ _ ¿ º g Û2…í€StïÿÇÿüÿ‰e}ÀhQ § ÿòikIÿNü/ùöúò$ð£í“ë ê#éåèYéêVìÌîÐñKõù,ýOfN å ¯µ¼´®ÎvÃ Ñ À®¹þþ‘ü†úíøÌ÷&÷øö7÷Ö÷Ãøçù,ûxü´ýÈþ¡ÿ.e>¹ÿØþ§ý3üúÔø÷uõôäò$òÙñòÔò&ôö`ø.ûZþÇZóq ³˜ã l~Ý•¹d ± Á¶µýÝùOö)óƒðoîúì+ììvì}íïõð5óªõ5øºúýKÿ(ªÄs¶•X`J,!ÿ<þ“ý9ý9ýýgþ–ÿöA„ ¹  „æÒ40Á¹ $ Ÿâýüù<õ¦ñmî®ëƒéþç-çç¾çéë¯í¾ð,ôØ÷¡ûdÿZS × Ô ?R5ø d ‘ ™˜§àV:ÿ¹þ›þÙþlÿBKrŸ¹¨X´®:Tü8£ý÷ú,ø^õ«ò0ð îUì&ëêžêYëÀìÌîpñ˜ô,øü;@ {sÚž± ±¥ø¼ ü ³ Oðµÿ¸üúÜ÷öåô1ôôGôúôöR÷ÉøPúÐû/ýZþ=ÿÎÿÙÿUÿ~þaýü¡ú+ùÆ÷ö–õøôÃôõËõ÷Øøû¹ý°á0} ª –#5¶“À7ø gÝ ïÐþÂúêöhóXðÒíèë§êê/êðêHì%îoð óÜõÃø¡û\þØÉ po QX5ÿпáÿHÿÿÿÿe”Å¢l % ¼mžCUÔ Ä 31Õ=þ…úÎö:óëïÿì“ê¾è’ççcçcèêkìOï¨òXö>ú8þ!ÜG H È·¸ÉC5±Î § X ü¯‹¦ÿÝý ý¥ü¡üúü¡ý…þÿª¿´uí ʺþœüIúÙ÷gõóïð!ï¾íÝìŽìÜìÏícï“ñQôˆ÷ ûûþùù× q§]|ñ¯³ý—Žøï øM®;ýúI÷øô,óîñBñ#ñˆñcòŸó'õáö´ø„ú9ü¼ýüþéÿyª}úÿ*ÿ þðü¯ûwú`ù€øî÷»÷ô÷£øÊùfûpý×ÿ‰nld 7Èù±Ù`<gãºù· þÿÝûÛ÷ô¶ðÐí~ëÑéÔèèøèêÀëøížð•ó¿öüù,ý2ô[VØÚ ] g  < ,ç†!ѬÆ-íÿ ƒVuÒYóˆý : ' ° à U ^ à ßfˆ[ÿùû€øõÉñÌî7ì%ê«èÛçÀç^è²é´ëRîyñ õíøúüÐ8 +’\€ùËþ¢Ê‘ d ¬ˆOÿkýëûÙú7úú4ú¿ú‘û–ü·ýÛþìÿÒzÓÒn¨ƒÿþDüMú9ø"ö"ôVòÖð»ïïï€ï–ðEò„ôF÷vúüýº’a  ]K²}šÿ§–ÖvŽ7 ¹× þsú.÷Wôò=ðï‚î‹î!ï6ðµñ‡ó‘õ¹÷âùòûÒýnÿ´"Bu¡ŸÿþaýWüyûÞú–ú°ú5û(üˆýMÿhÉYþš G€W’)_ ) Ð&ý ù(õñaî·ë©éGè›ç©çmèÞéëë~î}ñÊôFøÎûCÿ†}+ Ã Ñ T R Ö ð µ ; œòUÞ ­Ñÿïÿg1=xÎ'j}L Á Ë _ w3èASý7ú ÷îóþð[î"ìkêKéÓè éúé˜ëÛí´ð ôÇ÷Åûæÿþ² Ñ žƒ¶:h6¡Ä ¾­±åÿbý;ûù=øs÷"÷B÷Æ÷œø°ùìú6üvý•þ~ÿm^ñÿ&ÿþ üûIù…÷ÔõPôó.ò¼ñÊñaòˆó;õt÷$ú7ý–$ÃP ¬µO^Ï‘šénÁ‘ú ÿ)û‚÷:ôiñ&ï}íyìì\ì5í“îbðˆòëôm÷óù_üšþŒ'^*Š„"r‡wZHÿVþ›ý*ýýZý þÿ‘W_”Ü : Ÿ´EC¥h$ 6 Ý2TþbúöÑòuïŠì+êmè`ç çvç–èaêÇì°ïóšöZú þÉ8Pù ¸»)`FÎ  # '4bÉyÿçþ¯þ×þTÿ=lŽSÊâŽÉèÜ|þÛûù=öyóåðžî¿ì`ë–ênêðê ìùínðoóäö²ú¸þÕæÈ Y{]õÕŠ{ïÿ É nǹýûú¢øÀö_õƒô*ôMôàôÐõ ÷søõùuûÝüþ ÿ±ÿýÿëÿ}ÿ¸þ«ýcü÷ú}ù øÂö²õõôžô¼ôYõyöø8úÁü¥ÿÊl « ²d£WmÕ‡ƒÎs† YV7"ü5ø•ô^ñªîŒìëIê,ê·êÞë‘í¸ï9òøôÖ÷¶úzýI+¢¦4R h€i8íTÿ÷þõþTÿ,–Bò ¾ P gÃ•Õ › / L}ÿÇû ødôøðçíLëBéÝç+ç3çöçoé‘ëHî}ñõéøÞüΙC í q´^{XH  ±b4>•ÿFþZý×ü¹üùüýaþdÿ}–—hö0 z€aÿRýû™ø ö¹ó€ñ‘ïîøìxì“ìPí²î³ðFóZöØù£ý› Ž C ž‚Õƒ~ÀGEÜ÷² - ˆåeþ$û=øÇõÑóhòñDññ7òUóÅôoö9øúÃûRý£þ¦ÿM—‚UÿXþ-ýíû­úˆù”øè÷—÷¯÷;ø@ù¼ú¨üùþšwuv ] `Dž\qÖŠ”ç Z zgEý4ùYõÕñÄî?ì[ê$é¡èÓè²é1ë>íÁïò·õìøü2ÿ‰¤Iq  G  Y `*ÒoéòEîÿóÿV"sô,°   ¹ ò ­ à ‹ ¯W”y!ý¨ù-öÒò·ïûì¹ê éè©ç è#éíê[íWðÊó”÷–û­ÿ´Œ -¿ÉÑ7Y?Õ 9 †ÜT þqü@ûú,úBúµútûkü†ýªþÂÿ´nÞõ¬þñÿ‰þÕüçúÔø¶ö¨ôÅò'ñçïï×î$ï ðŠñžó:öLù¼ünDÕ KaøùQóÙ}P“^Ï 'Sÿ©ûJøPõÑòÞð‚ïÂî›îïñïOñóþô÷AùVûBýðþMNí(‡ÄËÿ²þý{üŽûÝú{úyúßú´û÷ü¢þ©ü…+Ò ] ®ª6=­yžõ>  l‡{þhúsö¾òiï‘ìNê²èÉçšç#è\é7ëŸí|ð°ó÷¡úþn|-m - e  9 â  û • \½=ðê7àÿçÿIþ1…â0W> Ð ý µ ò±ôÆ5WþBûøéôäñ!ïÀìÚê†éÕèÓè†éìêûì¦ïØòvöbú{þ§u è âN7¤`vòêu¯ · «ªÐ9þ÷ûú·øË÷W÷V÷½÷{ø~ù¯úôû7ý_þWÿ ox"oÿcþ ýyûÀùø÷;ö¢ôHóEò¬ññüñ÷ò€ô’ö!ùühÿíŽ( š ćÈpl³?6º²; qwn{ü¾øVõ^òìïîØìEìSìüì/îÚïäñ3ôªö,ùžûåýìÿžðÙWl#‡«£ˆqÿtþ©ý"ýðüý²ý­þ¼·å/z ª £KˆGv ÿV O }ªÿ¸ûÌ÷ôŠðvíæêñè¨ççBç&èºéïë¯îßñaõùÚüB ^ #Uñü‰. † © ´Àç?ÜÍÿÿÊþÙþBÿøÿê6aoHØ Ù4’ŸSÿ¾üúù!÷Pô¥ñ?ï8í¬ë®êOêšê’ë6ízïQò¥õZùSým‡| + u=nõÉåM ,È÷Ø Š,Þ¿þéûrùl÷äõàô`ô^ôÏô¤õÇö!ø›ùû‰üÍýÔþÿòÿøÿ ÿðþòý¶üOûÓùZøþö×õþô…ô}ôóôìõh÷cùÏûœþ³ûV£ ׿3ÕÄû~X˜V ¬ ¹ …ýˆùÍõqò‘ïBí“ëê;êê…ë í ïpñôíöËù•ü2ÿˆ†@ï-x¤™o="eÿòþØþÿÄÿÈ ¿‘€r N ø WSÙØF f ! _4¹ ýIù•õòÜîìÚé<èMçççÜèÇêOí]ðÕó˜÷…ûyÿQî2  Nj³|Øá ° bÞÚµþ¯ýýÖüÿü}ýBþ:ÿOkuVùLAÎñªþÇû\ùÞöiôòð^î$ísìZìãìîàïGò6õ–øNü<C> ‡–9¸|‰ë±ôÍ \ Á’ÿ=ü:ù¡ö„ôïòéñsñ†ñòókôöÁ÷ùLûæüGþ^ÿ(}ÿþký,üçú¶ù°øë÷|÷t÷Ý÷¿øúèûþ­zƒ z @¹ÇRE“1^ý Ÿ ÖЮþ”ú¤öóÆïíøêˆéÊèÁèhé³ê’ìïî¯ñ´ôà÷û.þ¯è±þÌ  ú n Œh»c)#bõÿâÿ-ÕÑŽ(Ê] Å ê ¶  ø V ) u @™“HþÒúQ÷åó¯ðÎí_ë|é:è¦çÊç¨è9êsìCï’òBö5úGþV?ã ! ⡈Å_`Úã“  ^³"Ƶþÿü°ûÐú_úXú±ú[ûDüVýyþ–ÿ“^ããPYÿdý€ûqùO÷5õ=óƒñ!ð-ïºîØîïÞðÅò:õ*ø‚û%ÿõÓœ .g,aóÒ÷_Š{ QwžæüoùTö­óŽñðïºîöîºïôðŽòqô€ö¢øºú±ünþáÿú³û•ãöÿâþ¿ý£ü¨ûãúiúJú’úHûmüýýïÿ0°U Ÿ 'ܵ¸ÄÒG6 ¶ãßÿÊûÆ÷øó€ð|íë0é è çíçíè“êÎì†ïžòùõuùóüQtA¤‹ ì à  â > 9 è dÅ%žD,cõÿäÿ0ÓÁê:šò)' Ö $ b F¬œ$XÿMüùëõÓòôïmíZëÓéêè®è&éRê+ì¦î¯ñ-õùý4I. Á åØtÀm>“ « §¤¿ÿ»üÃú<ù,ø•÷s÷¼÷bøQùuúµûøü(þ-ÿôÿlO³ÿ¼þuýíû9únø§öýôŠógò©ñdñ¥ñsòÑó»õ'øû=þ·Vù~ ư ý4¸‚‘í£Çr À ÓÍÒýú|ö_óÂð¶îIíì[ìÓìÚí_ïJñ‚óëõhøÜú/ýFÿ{N—Ëζœÿ–þ»ý ýÕüéüaýAþ…ÿ#5~Ñ  "êN9˜_‡ü ] BÄþýùEõ¬ñqî²ë‡éè6ç#çÊç&é'ëºíÇð0ôÕ÷•ûOÿà, à«ã¿„ õ * =Kl¸CTÿêþáþ4ÿ×ÿ¼Ñ0J6Þ/—Ÿ4\% ýãú ø-õoòìïÁíìØêDêVêëƒì–îAñoô øñû#(ò `Vºz‰â„xÌ“åà ¡ HöÊÿÞüJú#øuöJõ¢ô{ôÉô€õ‹öÕ÷EùÂú4ü‚ý™þhÿáÿÿÿ¾ÿ$ÿ7þý§û+ú«øA÷öõvôJô™ôjõÀö–øäú™ýŸß;” Ê ½OdåÂì_,œ‚ö ëþáú÷‘óˆðî%ìêê\êzê;ë“ìlî°ðCóöáø°ûYþÂٌСÿñ‚ÃǤtNIzÿóþÁþíþ{ÿh­=ôí× — 3á ©±$  i[óPþúÎö4óàïñìƒê®è„ççYç[èêfìIï¡òMö.ú"þµ  „h±YeÝÎMq S  ĉx¨*ÿ þOýûü ýrý%þÿ!>P?öaq[0 ¸þ†ü!ú¡÷!õ¿ò–ðÃî_í~ì2ì‡ì€íïVñô]÷ýúàþäèÉ d›Pmß›æ~wãÞ… ÷UÂ\ý@ú†÷Bõ„óRò°ñ˜ñòßòôõN÷ùÕúxüèýÿèÿa{9¡ÿÁþ¨ýlü$ûéùÑøö÷k÷C÷‰÷Hø€ù/ûKýÅÿˆ~ŠŽ l:ô¢z è"Û ,6øûö÷6ô×ðõí¨ëÿééÂè0éFêöë*îÊð¹ó×öú)ýÏ%s é è z ²¡`¬jVƒÖÿ ›„¸(¾e ~ ½ ¨ , 7 ¾ ¼ / —©nÿþûyøÿô±ñ®îìê‡è¸çŸç@è—éœë=îeñøôØøãüõí© ôT4¨v¨N{HÐ 2 ‰òˆcÿ”ý(ü)û™úuú´úIû!ü)ýIþhÿoIâ)›¾‚ÿñýüúí÷Èõ¾óêñgðLï­î›î ï@ðùñDô÷MúÞý¥†\  `P·ÿ¦“Òr‹7 • Åë(þ›úb÷–ôLò’ðpïéîöîï¤ð òëóëõøúüéýoÿŸráížþÿïýÎüÆûïú]ú#úLúãúêû_ý8ÿgÛ|0 Ù [—s׬äv^žBX ø<B.ý ù;õ£ñvîÎëÃécèºçËçèê ìœî•ñÛôLøÉû1ÿfMÐÝ g h à Ö V n 4 À*Œÿšq”æÿ©†£îO¯õ Ó @ A È ÐZkUWý,úóöËóÒð)îëë2êéèÙèÊémëµí’ðîó«÷«ûËÿçß Ú¤ØfFuøØ(ûmš Ÿ±÷ÿ†ýqûÊù—øÝ÷š÷Ä÷Pø*ù?úwû¹üîýÿþ×ÿdœwóÿÿÜýaü³úèø÷_õÕó”ò³ñFñ[ñýñ/óïô6÷ôùýÄZ ¼Êgx訯û‘|Ξ --,ÿLû­÷mô¦ñkïËíÎìtìºì“íðîºðÙò1õ¦÷úvüþz"Ú(¡çöãÈÿºþÑý#ýÁüºüýÜýÿj…Ë# p — }ª£þ¸Õ_ h Pjþrú‹öØòzïì0êtèiççƒç¤èpêÕì»ïó™öRúþ¬¶ Ð ]V¼”êÑ \ ¤ ÃÕò3®u“ÿÿïþ*ÿºÿœÈü ÜISðÎó€þÍûôøöAó¤ðWîtìëJê%ê­êâëÁí=ðEóÀö’úþ¼Î¯ ?^ôë5ʨÔ\PÈß ² b×Ùý+ûãø÷¿õðô¢ôÎôeõWöŽ÷óøkúßû6ý[þ=ÿÌÿØÿSÿzþXýü†úùŠ÷;ö,õsô#ôKôôô"öÔ÷ú›üŽÿÃ Ç ÖІš°¨ï‘¡8 qoR?üXø½ôŒñßîÈìVëêvêë+ìÚíüïuò)õú÷Êú}ýùÿ&õYJÈØ„Ûðتr”ÿùþ°þÃþ8ÿ =¾}gcY - Ä Û2ý4Õ ã j z)“ÿÓû ø`ôïðÚí>ë4éÐçç)çïçiéŒëCîwñ õÛøÊü³vò « ¾8Qø·ø ð º r48¥ÿkþ•ý&ýýlý þìþõÿ)$íoša¾¯9fÿCýæúgøßõló*ñ6ï©íšìì<ìíjîsðó,ö²ù…ýƒ 5 ‘tÅqj©.,Åä¥ ( õþNûuø ö%ôÈòúñ¸ñúñ´òÑó=õàöžø_ú ü…ýÁþ­ÿ=pEÂÿñþäý®üdû úùøøc÷÷@÷Û÷ðø~ú}üàþ“Žœ Cž…௿Ä, { —ƒ_ýPùwõõñèîiì‰êVé×è éëéiësíðïÅòÔõýø"ü$ÿèYbö © Ë ~ ÏÔ¡Nõ­¨Ðÿìÿf:]ÂSü£/ † 6 i  B Þ ôº+ý¦ù!ö½òœïÛì—êçèÞçˆçìç éÖêFíDð¶ó€÷€û“ÿ•fæ ø †{Îy|à³ó’  ]ÃN/þ§üŠûÛúšú¾ú;ûüþüþ:ÿI1Ü:>àøÿ{þ²ü°úøaöHô\òºðyï¯înîÂî±ï<ñ[óö ù›üV5Ò MdüüSó×xK]Ò 8mÿÎûzø‹õó1ñßï'ïïsïað¼ñmó\õm÷„ùˆûaýùþ@+´Ú¡DAÿ!þüüéûûYúúú‡úoûÆü†þ¡¢X ¢ ûü‹’ÿÇæ[/p 2 ¤”þ~úˆöÒò~ï¨ìgêÎèéç½çGèéZë¿í—ðÄó'÷ úþRQó# Õ ÿ ¡ ¿ b š y  ŒòaòºÉ-îÿ „O_¡gºâÆ S v " Q ÿ1ñO`þ<ûøÊô»ññî‹ì£êNéŸè èVéÀêÔìƒï¹òYöGú`þˆS Á ¶âûc2°¬= ” –¤ÜVþ(üaú ù0øÊ÷Õ÷Eø ù ú<û{ü´ýÏþ¶ÿX§™,bÿ@þÓü.ûeù÷Èõ)ôÌòÉñ5ññ”ñšò0ôPöìøôûOÿà‹. ¨ ×àˆƒÈR#DÆ¿H Ї›üæø‡õ˜ò/ð]î,ížì±ì\íŽî5ð8ò}ôèö[ù»ûïýáÿ~»úÿ¦ÿõÿáþìý,ý³ü“üÔü}ýþÿÿÇÖpÉ  °ï¬ÖdQŸU ƒ >žÃÿÊûØ÷ôð|íìêøè±ç#çPç5èÊéþë»îçñdõùÌütêÏ  Ì ó†Š º  E \w°ÐØÿ<ÿÿ&ÿ¢ÿghÅòþÓZƒA‹`ý]ÿ·üâùúöôhñúîïìaëcêêVêSëýìHï%òõ9ù6ýSnc  XJΞ¸ÛþžÔ½ y(éÚþü­ù¸÷?öIõÕôÝôTõ+öN÷¤øúŠûèüþÿ²ÿþÿíÿ~ÿ¸þ¦ýXüâúZùÙ÷xöQõzôôôŠôõ÷&ù£ûþ§ýd¼ ä¾,_ì  v³o Ä Ñº¢ý©ùóõžòÄï|íÔëÖê…êÜêÒëVíSï¯ñPô÷åùŸü)ÿlVØê‰¸îà´²ÿÿ¤þŸþúþ¸ÿÒ@ó×ÖÕ º j ÌÈJC¨w² ` ‘ZÓýPù”õ òÒî ìÌé/èBçç–çÖèÃêLíXðÎó÷tûaÿ0Äþ Å °½-Ku… _ ß¼Ì$ÓþãýXý3ýlýùýÉþÉÿâÿÞv»Ÿ'Ìÿý¬û0ù¢ö!ôÈñµïîÆììì‘ìÆížïòõnø-ü".-ü zˆ ï$¡coИ޽ S Â)ªÿbünùãöÔôLóRòåñÿñ“ò’óæôwö,øêù™û ýmþmÿ`LÞÿÿþïü¦û[ú'ù"øc÷ýö÷x÷iøÕù¶ûþ ƒŽ¤ ¦ vô“†ÑlT(0Á ôëÉþ¯úÁö óêï;í%ëºééúè¢éíêÊì!ïÚñÖôö÷û&þü…¬c _ ¤ w åÝ”=ðÆÒ%ÎÿÓÿ5ô]è>Ù E l 5 Ž i » ¾ zİWþÔúH÷Óó–ð°í>ëZéè†ç­çè"ê^ì0ïò/ö ú/þ9¸ ï ¨ÏW8q …“K Ë /“ÌÐþ.ýóû&ûÆúÏú4ûèûÖüêý ÿ ÑEbuiÿHýQû0ùÿöØôØòñ³ïÀîQîtî2ïŒð~òþôú÷]û ÿãÉ— -i/dôÒô[ …x W…´ý›ùŒöñóÝñ\ðtï$ïdï*ðcñùòÓôØöëøóúÖüþÛÿÞÀ (goÿTþ,ýüû\úíùÜù4úüú5üÚýàÿ5Ç|9 à Tw0f\ zb ÛúÿáûÛ÷ ô•ð“íëMé,èÃçèé¸êñì¤ïµòöyùêü:O _7 ‹ V › c ¼ ¶ h êVÄMQúÿbU²z´± [   q Æ ™ïÎDgÿLüùÑõ®òÇï;í$ëœé´è{èöè&êìƒîñõèø÷ü, › ºPKœ>1{*O` ƒ Œ˜Å-ÿåüû‹ùŒøøï÷Bøîøáùû>üyýœþ’ÿF«¶a®ÿ þDý©ûãù ø8ö†ôóìñ1ññð:ñò}ótõî÷Ùúþ¥Pü‰ ×Å6JÌ”¡û¯Ò~ Ï åäðý'ú«ö—óñï›íÙì¹ì3í:î¼ï¡ñÑó.öœøû@ýCÿ÷N?Ææ¦>;" ÿ þ9ý¬ürü˜ü$ýþsÿ'(`º f €M´žù»ÛZ>” pè%ý+ùOõ³ñwî¹ëéèBç1çÚç7é7ëÉíÒð5ôÓ÷‹û:ÿ¿ÿÞH , BrH „ Á àü//!nÿÿ'ÿÿA6VŒÀÚÂc©‡ôêk€6ŸýÑúç÷þô5òªïyí¾ëŽêûéêÖêIìbîñHôç÷Óûêÿ Ø D6—S^´THg¿Á Œ @üßÿý€úiøËö¯õõ÷ôMõö÷ZøÃù6û™ü×ýÚþ“ÿöÿýÿ¥ÿôþóý°ü?û¶ù-ø½öõ‹ôöóÒó,ô õnöUø³úxýÜE© è áwì…?K·› 0!ÿû3÷¼ó¹ðAîdì/ë¦êÇêŠëàì¶îôð~ó7öùÀûWþ­°O@Žsú45èËÓÿÿžþ€þÂþgÿjÅjGEK @  ‡§Sy s K  …cþ—úÐö/ó×ïæìwê¢èzççRçWè êcìFï›òDö ú þæŽæÒ =Wùÿtfè þ ÇŠ`d¨Aÿ6þ‘ýQýqýéý©þŸÿ´ÒâÊwÕÕm™Y´·þrüúùj÷Ýôpò@ðhîí"ìÚë3ì4íÙîñêó2÷ÚúÄþÍÖ¹ VŒ@ZÊ„ƒÊc\ÌËy ó]Õ}ýoúÃ÷ŽõÝó·òòòò]ó–ôö½÷wù(û¹üþ)ÿèÿJNöÿJÿXþ1ýêûšú[ùDøl÷éöËö÷í÷6ù÷ú%ý²ÿ†Œ¦· ž=x4\àµ×IIý KR3üøVôûðîÔë0ê<éûèkéê/ì_îùðÞóòöú&ý «îÆ& s g ó&ׄ5ÿ?Òÿ¿ÿ ²±ù{"Õ| ý > ( ¦ ª '  ~ ^ÇË‚ÿüuøñô›ñ“îöëàéfè™ç‚ç%è€é‡ë*îSñæôÄøÌüÙÌÚ ¼ÏåTP÷(ü ýcÞ‡vÿ»ýdüyûûúçú3ûÒû²ü¼ýÛþöÿôÂK€VÈÕƒÿÜýñûÕù¢÷põ\ó‚ñûïßîCî6îÂîëï¯ñôÞö$úÀýxU  aR¹‚œü¡ŒÊl†6 ™ ÐþEþÃú–÷×ô˜òéðÑïQïdïðñòQôHöUø^úJüþrÿ‹G¡™7‡œÿ†þ^ý;ü6ûeúÝù°ùéù’ú¬û4ý"ÿeìž`  ¡åÅ*þ4À¢Ûw‡  ]^Fý5ùPõ¹ñîèëßéƒèÝçðç·è(ê1ì½î°ñíôUøÅû ÿF‘Ž þ l Z Ó ê ² D·%¨UAz ûÿFêÛ bÎ5’ Y ¿ µ 0 ) £¢4j\ý#úÝö©ó¨ðùí·ëüéÝèiè©èžéEë‘írðÑó÷û°ÿÊ¿k °t¢+2²“å½6m Œ°©ý¨ûúòøHøøHøÛø¹ùÎúü>ýhþjÿ0«Í‘öÿýþ²ý#üdúŠø®öëô\óò:ñÑðîð™ñ×ò¤ôùöÅùôülÄb ËÝ|ý¼Á žˆÙ© =AGÿnûØ÷¢ôäñ²ïî%íÑìíõíOïñ,óyõà÷FúŽü¡þiÚæŠÅŸ!]eO5ÿ,þLýªüXücüÓü­ýíþ‹{ªh  ò Þj€ Tš ˜ +nþ‚ú—öáò‚ï–ì9ê~èvç'ç“ç¶è‚êåìÈïó›öKúýýåãr  ïLrY è 7 a€®“o¥ÿ9ÿ-ÿ}ÿR‹±«dÇÅSj > …þÁûØøçõ ófðî,ìÊêêàélê§ëŒíðóœötúþ¢µ• #?ÑÅ œw£+"Ÿ¼ ™ Uçøý[û$ùb÷ö^õõPõìõàöøtùãúJü‘ý¤þpÿéÿÇÿ+ÿ<þýžûú†ø÷µõ¦ôñó¨óÚóôÌõ÷Êùtüxÿº" á ø´ú°Ä)ÕʬºO ˆ†l^ü{øæô¼ñïíšëÚêÄêSëzì&îBð³ò\õ øàúýêÿ¿î\^ÿN^Fú÷ÿ'ÿþgþþÿNã¶±½¾ š 6yM d’'* ¥ ¨Kªÿàûø^ôéðÑí3ë)éÆçç#çëçgéŠëAîsñõÏø¸ü™RÄÓ g pá´ìªO– – l 2ý1´ÿþÐýuý}ýßýþwÿ…¥»²rç¹ßTlÿ6ýÆú6ø õ"ó×ðÝîMí?ìÃëçë²ì#î5ðÚòÿõùgýkyn & c³\Rã¬Ï– ! þxû®øTözô*ógò.òvò2óOô·õR÷ù¸úQüºýàþµÿ/J qÿþrý/üÝú“ùlø}÷ÞöŸöÑöz÷ ø@úQüÆþ‹‰¥À ¼ yÚÄ ÛêGññT. š ´žzýlù–õòï”ìºêŒééGé'ê¤ë«í"ðïòóõù%üÿÊ(£«8 N øDGÉy?/]Ûÿ°ÿãÿt_˜±h ¬   ² Þ † ¢ 1 8 Ãá©6ý¥ùöªòƒï¾ìxêÇè¿çlçÒçñèÁê3í2ð¥óm÷jûyÿv@¸ à G5&%‡Z±¤L Ç 2¨F!OþÝüÔû8ûû9ûÂû‘ü‘ý¬þÉÿÑ­K˜ˆ;mþü|úHøöéóöñOð ïEîîcîZïîðóËõôøyü>% Î LeýüQïÒúpCˆYÔ H‡ÿóûªøÈõaó„ñ=ðïsïäïÒð+ò×ó½õÁ÷Êù¼û€ýÿ4{ŒA¤Æÿ¸þ‘ýiüXûuúÖùŒù§ù0ú*û•üiþ˜½ƒD å FLÝäN+™f  [ ±Á­þ•úöèò–ïÂì„êîè èâçoè¨éëâíµðÚó4÷¡úþ7'¹Ù| ™ 0 D á  ö ˜†§‚§"úÿ.½œ¾}ëCl N Ô î Ž ® Mnjkþ8ûî÷­ô•ñÄîYìoêélèpè*é—ê°ìcï›ò>ö-úFþei/ ˜ ˆè§» ØìkkP o ~æsþWü£úaù•ø>øUøÎø—ùúÉûý2þ@ÿ¥ß»7Vÿþüåú ù)÷Xõ³óSòPñ¿ð°ð.ñ?òáóö¹øÎû5ÿÓˆ3 ³ ç±õœ—Úa/OÐÉS  ¼üù¸õÓòtð«î‚íúìí¾íðî“ðòÊô(÷ŒùÚûûýØÿ_‡Gž‘*xŒ|aÿQþcý®üDü5ü‰üFýlþôÿÑôF° Z bS4¼¡æ’ · h¿ÜÿÝûæ÷ô™ð„íõêé¾ç2çaçHèÝéìËîòñiõ ù¿ü[ÅÞ Æ r Ž‘™ D § Þ-yúÂáÿ]ÿ8ÿrÿ×åSƒŽ]Ûù¨â¥õÛiÿ°üËùÕöëó-ñ¸î©ìëêÁéêëÆìïûñZõùý9TI õ :û$£p‡ë¨Îr®  g#òóþ>üèùø›ö³õKõ\õÚõ´öÖ÷(ù‘úúûIýjþHÿ×ÿ äÿ^ÿ‚þ\ýüûwúãøY÷ôõÌô÷óŠó•ó!ô5õÐöêøwûeþšýpÒ âS=‰(C¿’̆ Ú èÓ¾ýËùöÌòúï¹íìëÓê-ë#ì¤íïòñˆôB÷úªü"ÿQ'•”"BýbƒuP*?ÿ¡þUþdþÖþªÿÚ^%*5 $ Û ?:¹« Íü Ÿ Àî+ýXù•õòÊîìÂé&è:ç ç“çÕèÃêKíVðÉóƒ÷dûIÿ™È „ º[`Éšà«' ت™¾+ðþþ ýŽýÙýuþPÿXv’”fó*ýe_îøý“ûùiöÛóyñ_ï¨íkì¾ë­ëAì~í^ïÖñÖôGø üë iwøÚ †FQ³}Æ« I À3Áÿˆü¡ù%÷$õªó¼òXòyòóôbõíö˜øIúçû\ý“þ}ÿB•ÿÃþ²ýuü"ûÐùšø–÷Üö~öö÷ø‘ù„ûàý’† à Р¨-CÑÄ £‡½PTá äþËúßöBóðfíUëîé9é5éßé*ëíWïòùô ø$û þä[pAò+ ô[sQ ¾}b€éÿ§ÿÂÿ;8¤@÷±S Ä ë ² ×  Ø  µðÍgþØúA÷Ãóð•í!ë<éúçjç“çvè êLìïnòö úþø ¼ l‹ 殯.A Œ ýrÑéþ\ý6ü|û.ûFû¸ûtühý}þœÿ«•E©³Zœyûþ.ý#ûñø±ö~ôuò¯ðHïUîêíîØî<ð9òÄôË÷8ûïþн‘ *i/còÎîS |r \’Ê(ýÇùÄö6ô.ò¸ðÙïïÕïœðÔñeó8õ1÷7ù-ûýü‘þ×ÿÃPzE¼îÿéþÆýšüû‹úÕùqùnùÖù±úýû¶ýÐÿ8Ü¢l  ›Å€·WS£GF¬Œ ÿ!øûñ÷#ô¬ð¬í;ëméOèéç:è;éàêíÄïÏòöùãü%*Øã ( ç # ã 8 1 æoåaúÇÙ=þÿ”au¿)= 9 Þ  á ( í2exÿMüù¸õ‹òï íòêié‚èJèÉèýéßëbîrñõôÏøÝüýët ^ûë3ã Å+ Y o‹ÈCÿý=ûÚùìøtøløÉø|ùqú“ûÉüûýÿùÿšëàuªÿ†þýfûù©÷Ëõô—òrñºð€ðÑð´ñ*ó.õµ÷®úþ”Hþ’ åÖJ(]Ý¢­¸Ûˆ Û öû þMúÙöÏóEñLïïí4íí–íîðüñ"ôsöÓø&ûRýAÿß!ýp~.±©ÿxþý¸ü8üüFüçüñýaÿ*>Šôc º Ü®X-£~Ë œ 5:ý;ù[õ½ñîÂëšéèQçCçîçKéKëÚíßð=ôÔ÷û%ÿžÑ£ÿ Ö Öÿ¢Î –  V ¬ðd"†ÿIÿkÿåÿ«®ÚPjNç#ôP5¤¦HŸýÀúÇ÷Òôþñkï5íwëGê¶éÏé™êì1îèð"ôÆ÷¶ûÏÿðõ½ &q(0‚!k8–  u 6óÿ'ý¶ú°ø"÷ö‡õtõÒõö÷àøBúªûý-þÿÀÿ ûÿÿÅþ¯ýZüÙúCù°÷:öúôôxó\óÀó«ôöøúVý{×M» ·::§]fб$ F9"ÿ!ûY÷éóíð|î¦ìwëóêëÜë1íï:ñºógö#ùÑûVþ™ˆ1Þôq¤¢‚\G[ÿ«þHþ>þ–þQÿkÜ–…“§ ¦ u øÂãpeÁ Ö®/wþ¢úÓö-óÑïÝìnêšèrççOçVè êcìEï˜ò=öúøýÉg´• õ Åü–— û€° ¦ |N6M§VÿaþÑý¦ýÙý`þ-ÿ+FfsUøI9¿×ƒɸþ_üÖù6÷œô%òíïî¨ìÉë„ëãëéì–îàð¸ó ÷¸ú¨þ¶Â¨ Ez-E²if«D?±¶j îcèýžúøÚõ7ôóò‰òýòÝóõö-øÛù}ûüüCþAÿéÿ4!´ÿôþðý»üiûúÎø·÷ãögöTöµö’÷ìø¿úÿüÿƒ˜ÁÜ Ís²q™ì w>n hmN/ü1øwô ñGîìdêué7é©éÀêlì—î*ñô÷#ú&ýúÿ‡¸~Í¢ýçj™ˆM½—¦ûÿ£ÿ¦ÿÇÜ9Í„Cô z ½ ¥ Ž s Ë žøí–ÿ üqøäô‡ñzîÚëÃéIè}çhçèkéuëîCñÕô±ø¶ü¾ªW¨ ‚Ñ„”þÅõÓ® K Æ<É…‰ÿâý üÉû]ûYû³û\üBýPþnÿ‚y:´×šöí…ÿÉýÊûœùY÷õýòñ‘ïuîÛíÓígî™ïgñÇó«öüù¡ý{jL þ _Q¸€—ö˜‚Àb2 › ÙbþìúË÷õæòBñ3ð»ïÔïsð‡ñüòºô¦ö¦øŸúxüþuÿyaEÑÿûýÍü©û¦úÜù^ù=ù†ù@úmû ý ÿaû½Ž P å0zN€ã«³ E }z_ýLùgõÐñ¦îìÿé§èèèáèQêXìàîÍñõ_øÃûÿ&îQ? « “ õ Û P e / ÅB½O^ p).nÔKº  Þ = ) — ‚ ëÚ[€cýúÈöŠóðÌí†ëÊé«è9è|èuéëpíUðµóv÷wû•ÿ­žE „BjíÃëjKŸ|ý > ]x­ÌýÞû[úLù³ø‹øËøfùIú_ûüÄýãþ×ÿ‹òÿ¬úÿëþŠýèûú-øEözôåò¡ñÃð_ð‚ð7ñ€ò[ô¼ö•ùÒüVÃh Ö펠ÌϨᲠKUbÿ‘ûø×ô#òüïmî~í1í}íYî²ïrñóÄõørú§ü¦þY´«;c,¡ÒÓ¼ÿ¢þžýÇü1üîû üü}ýÓþ†‹Í5«  J<ÌákZ¨Q\Ó È RŒ˜þ”ú¥öìòŒï ìDêŒè†ç9ç¨çËè—êøìØïóžöEúìýs¼¬- - ¢ †Û§ø ß r É ý*iÑvhµÿ`ÿjÿÏÿƒyžÛA9ëD6µ»Kj$Œþ¶û½ø¿õÙò*ðÐíæë„ê½éé.ênëYíâïõòzöUúfþˆšz ¬›ÝjCn÷ñr˜ ~ Fõþ‹ûeù´÷öÍõ–õÓõuöj÷øöù\û¶üíýíþ¥ÿ ¶ÿÿþ·ü=û§ù øˆö2õ#ôqó/ókó,ôwõG÷“ùMü`ÿ±&ž ù Ø ØëM÷é)ÅÑd žž†|üŸøõîñOïFíáë&ëë¥ëÌìvîŒðôò’õHøøú‡ýÝÿâ‰Æ“ðäyÀ̳s{ÿ¹þ@þþ\þþþ]îú !  ¦ë½ Éîyp Þ ÖmÁÿïûø^ôäðÊí+ë!é¿çç çêçhéŒëBîrñýôÅø¦ü~.•™ " ‡S„#=å1 :  ðÔà)Áÿ´þ þÃýÞýPþ ÿ8N?ö`mHptÿ*ý¨úødõÚò‡ð‡îõìæëmë–ëfìßíøï¦òÔõiùIýRd[  pPC7qòÃñ·…  ‘¹þ¢ûçøœöÐôóÕò¥òóò²óÏô3öÆ÷oùûšüðýÿ¿ÿ!&Ïÿ"ÿ-þý±ûVúùß÷óöZö%öbö÷Pøú%ü¬þ‚ºá ç ¬ÿ["{ yP ¸ и–ý‰ù¶õ<ò9ïÃìíêÄéLé…égêãëåíWðóö#ù*ü ÿ¬ùÝOGÆÐq¸¹ŠCýÏФÿÿÚÿ‚ƒÐ[Ò ' „ -Rð  ƒ | øÂBý¦ù öšòlï¤ì\ê«è¤çRç»çÝè¯ê#í#ð–ó\÷Vû`ÿVŠ ‹ í1ÐË+ÿYR ‹ Œ<,oþýü”ûtûµûIü ý$þ?ÿXY+ºõÒJ[ bþpüIúø½õó’ñçï£îÜí¤íîï£ðØò•õÈøWü&È HcûùLèÉïd8SÓ W ÿüÛøöªóÚñðöïâïWðFñòCô öøúñû¢ýÿ)çC?á3Hÿ0þý×ûÇúéùRùù>ùØùåúdüKþŽ×¬z %Ž™,3›[n֛Πƒ ÓßÇþ¬ú´öó¯ïÞì¤êé3è è™èÓéªëîÕðóóB÷¤ú÷ýý~# 2 ¼ È ^ q œ¥ZI„Põé~÷nËô Ô T e ù ›¬J†wþ5ûÞ÷’ôqñšî+ì>êèè<èBèérêŽìEï€ò%öú,þIJ n W±jyÙ¢#'Æ G e”ïþ‡üæú¶ùûø³øÖøXù&ú.ûXüŒý±þ±ÿwóßDLÿþýhüú´øÅöêô>óÛñÙðKðBðÉðåñ“óÍõ…ø§ûÿă6 ½ õÁ­§çl9W×Ð] œ¯¸Üü8ùëõó»ðûîÚíYítí#îTïóðèòõj÷¾ùûûþÐÿASÿB$¯ðýêÿÎþÁýÛü1üÕûÖû>üýJþèÿÙtî` ¯ ¾s´mï+Î é ‘àöÿñûõ÷&ô¤ðíëéÎçDçuç^èóé%ìÝîòoõ ù³üC ¬O x  (©  Ë 5 u¦â?Õ´éÿ|ÿnÿ¼ÿ]Ebàæ\n9ê'úvÿ¬ü¶ù²ö¼óõðyîeìÓêÖééÕéÝê’ìêîÓñ7õúøþü:. Ø Öúv>R¶s›C† Sû ÿhü$úPøøööÃõÝõbö?÷`ø­ùûkü¬ýºþ…ÿþÿÜÿ?ÿMþý¡û úmøÛöqõHôvóó"óºóÛô…ö®øKûHþŒü{æ xc¯M4aڪ㛠ï ÿìÛýíùCöüò1ð÷í]ìkë#ë€ëvìöíéï7òÂôo÷ú·üÿ7øR>»Ë{×òã¿ žÿÌþ>þþ)þ°þ›ÿá{V^|” Œ H¯ª%g"F Ü õ¦ =ýaù˜õòÅîùë»é è6çç“çÖèÅêMíVðÆó{÷Vû2ÿïn’ C mb/s?¨ Ç ¶ ‘rt­0 ÿGþçýéýEþðþ×ÿæ %$îp˜[°—+óý{ûÜø1ö—ó,ñ ïQíìgëZëõë8í ï ñ¨ô!øíûïÿÙ WcãÁñh&0’^¬– < ¾<Øÿ¬üÕùh÷võ ô'óÍòõò’ó’ôàõd÷ù©ú7ü™ý¼þÿ %åÿLÿgþFýûûžúGùø ÷Vööö­ö¿÷MùRû¿ýƒ‡°à ø Øc| þDØ·èwwÿ -"ÿþèúÿöeó9ð“íˆë&êuétéêjëAíŽï8òõ&ø/ûþÍ14Çã„°oÐåÄ„= ý-ªÿ~ÿ°ÿA-jé–\! Ì A i -{E / P ïëwþÝú<÷¶ólð}íë éßçQç|çbèûé<ìï`ò öùùþþÔ` ‡ .E½‘ÀRRÓìµ K ÊPöÕÿŠýxüÒû–û½û;üýûýÿ,6¹ —Ê÷þýöú³øeö&ôòIðßîíí…í´íîîïõñŠôœ÷ûÓþ½°‰ %f,`íÆäGöþqj _àHýôùýö|ô€òñ?ðþïHðñGòÔóŸõ÷„ùiû&ý¤þÕÿª4ìQtÿdþ9ý üíúýùOùõøùyùeúÅû‘ý¿ÿ:ðÅ [ àΤœç…}ܶ #@.ü ø;ôÆðÈí[ëévèèeèhé ë>íèïëò+ö†ùÝü£ÕŽ Å w © b ² « cósü¦‡®)5ħÎ(Ÿ‡Å À ` • P Š @ t2‡‰ÿOüøø¡õkòuïßìÃê9éSèèŸè×é½ëCîVñÜô¶øÄüâïÈK ^èÖµ¡é™Å…ó - P|ËXÿ7ýyû)úMùäøéøPù úû#üTý~þ‰ÿ_ð, ‰¨ÿnþçü%û>ùI÷aõ ó òûðFððjðWñØòéô~÷ƒúãý@þ™ ñåZ8lë­¶ ¾â æ *þsú ÷ ô‰ñ™ïEî‘í{íûíïðXòvô»ö ùMûfý@ÿÉõ»· $úþçýóü6üÃû©ûôû©üÈýMÿ+T±,© 5 v_´k|ë¼ È/QPýLùiõÉñŒîÏë¨é,èdçXçèbébëïíïðGôÕ÷yûÿ~£gµ  ¼ jŠ)S  › é Z°8"ÿwÿ¯ÿ<&]£ßùÙkœ`¬€ÜË[ ý±ú©÷§ôÊñ/ïôì3ëêséé_êÝëî¾ðþó¦÷™û´ÿÕÚŸ ðHûÿNêÝ5j} ] *Kýëú÷øz÷{öúõòõXö÷'øhùÃú ühý„þ`ÿîÿ#üÿvÿ˜þmýüuúÒø5÷¹õwô†óûòæòUóLôÍõÓ÷Pú4ýhÒSÌ !ÀÜ_8\ÆyçÆ8 [Q=ÿAû÷ô"ñ¹îëìÂëCëkë0ì„íRï‚ñùóšöGùäûWþ†`×â}«uèðÏÃÿãþBþñýûýiþ:ÿjñ¿Áà à h‰0KѼΠØN‹þ®úØö-óÍïØìhê•èoççPçXèêgìGï—ò7öúäý¬@W « qž0,›L K . 6¥jÿŒþþúý?þ×þ°ÿ·Øùày¼­ß¹þNü³ù÷]ôÛñœï»íQìsë1ë•ë¢ìVî¨ðˆóàö–úŒþŸ®• 2f,–JE‰"”žZ çgù½ýÍú?ø(ö’ô†óóó}ó^ô”õ÷Ÿø@úÓû@ýsþ[ÿìÿ÷ÿsÿŸþŠýFüèúŠùCø,÷[öæõÝõKö7÷¢ø†úÙüˆÿ~£Ù ú¦êªÒS!;£e‘= …ˆiKüOø™ôGñtî5ìœê°éwéêéë«ìÒî^ñ1ô-÷3ú&ýéÿdƒ6t9†eá ùÂ}D-LµÿrÿŒÿÛxä°i õ : !—‹ô Í  Ü(«ÿüpøÚôvñdîÁë©é/èdçRçûçZéfë î5ñÆô ø ü£ˆ.v G8@¤h—A{^  ±‚šÿ þÛüü¿ûËû3üçüÓýäþþ³/Þ%‰ÿ·ý¤ûeù÷ÇôŸò·ð)ï îvísí îHï ñ‹óyöÔùƒýdZB ÷ [M´zìŒu²Uu, › â"þûøZõ4óœñ˜ð(ðGðèðüñnó$õ÷ùøáú¨ü6þzÿgö#òlžÿ˜þpý=üûúSùÞøÊø#ùîù.ûÞüóþ]Û» ˆ 'x`ÇšÉM"NÝÞ j –xýdùõêñÂî#ì"êÍè-èEèé~êƒìïíñõjøÂûÿ¿ïL & ~ [ Ë Þ ªFËSõÇÜB˜g€ÑFÈ> ¢ a º › ý Ú 3‚—jýú¶önó]ð¢íYë›é}è èRèNéýêQí9ðœó^÷^û{ÿ| W/­~¢ÿV8Á 9cª%îýü¤ú§ùùùPùòùÚúðûýJþ^ÿCç:2ÉÚþdý­ûÊùÒ÷Þõ ôqò*ñNðîïð×ð+òô€öfù¯ü?ú¿l àú¯ÙÚ¯•æ¸) Yi}ÿ´û1øõeòGðÁîÚí“íãí¿îðÒñÙóö\ø úÂü­þKqìº!HB(ÿþýBü¸û„û²ûJüMý¸þ€™îhì ]  ˜*AȲù› ö x«°þ§ú´öùò˜ï­ìSêè™çOç¿çãè¯êíêï'ó¤öAúÝýW’uç Ú C h.| d ú X —Ò"W`Äÿ†ÿ¦ÿæìd§ÐÅqÁ¦ Š–=“þ¬û¥ø™õ¨òñï‘í¤ëAê{é^éóé8ë)í·ïÏòYö8úJþm] å ú„n¬6 6À¼Dq a 5 5þºû¦ùøâö=ööWöþöö÷'ùzúÖû#ýKþ8ÿÛÿ&¨ÿÞþÅýiüÞú:ù•÷ ö¯ô¡óóò¸òüòÊó"õ÷]ù&üHÿ§(«  3øCüoBÛåx ²´ ›üÄø=õ!òŠï‰í+ìvëhëûë!íÈîØð8óÊõrøûýÑÿÂT}7„ió2: þìÿþþJþãýÔý'þßþøÿk*#Ai n Z+u,GÈ´  Ùÿþûø`ôãðÆí&ëé¼çç!çíçléëEîrñúô¼ø–üe f^ Ü Ï,ï¶ÏyÊ Û È¬¢ÁÍÿÖþBþþ?þÂþŒÿ‰¦ËàÌ{ÙÖjB}ÿýŒúÛ÷)õ”ò9ð4îŸìëëFëìí¾ïsò©õEù+ý9OG  [:„(PРÎoœq ‘ÓþËû ùäö'õñóEóóró4ôPõ±ö<øÙùoûåü'þ"ÿÊÿ•ÿÔþÍý‘ü5ûÑù~øT÷jö×õ«õôõ»öøÃùøû‘þw•Í ÜG7”MW«MCp Õ ëÓ±ý§ù×õbòdïôì$ëÿéŒéÇé©ê$ì#îŽðIó8ö9ù1üÿÉ›ûãSQé+*ý¼€_pÅÿkÿmÿÏÿŽ¥¥h:   ¥ÄY_ Ô ¿ -/ÛPý¨ùö‹òYïìCê’èŒç<ç¨çÌè êíðˆóL÷BûGÿ7òZ R Å¢ßwnÌ¡ÿþ ¹ M Õn26ŽþEýeüïûáû0üÐü¯ý¸þÓÿèâ¨)T€|WþQüúÃ÷nõ4ó1ñï<îwíCíªí²îYð˜ò`õø6ü ô¿ B^öóDÞ¼áU*sKÐ #e¹ÿ<ü ùCöõó1òþðaðSðÌð¼ñó±ô„öpøZú(üÄýÿÆ ó‚ÄÿÊþ¨ýtüFû7ú^ùÐøžøÖø€ù ú1ü-þ‚!ïÓ® cÓãx~å¡®Ïû © ôüáþÅúÍöóËïýìÆê8é]è8èÈèê×ë1îøð ôS÷¨úíýÓDDÈ Ê H J Ú ê•!©E _ p,4zëoïQ { X Ó Ú d h èév¢„þ3ûÐ÷yôPñrîÿëê»èèèÚèOêoì)ïgò öüùþ-)å B %x+4BUØà†æ  JŠ÷ªþ¶ü(û úaù(ùWùâù¶úÀûèüþ1ÿ#ÙCSQCÿßý5üXú^øbö}ôËòeñcðÙï×ïfðŒñFóõRøûÿ´|8 Ä Ï»³òt?\ÛÕd §¿ÐüüaùöNóñMï4îºíÚíŠîºïUñDókõ®÷òùüþÉÿ%!·ç¸3imVÿ:þ1ýRü³ûfûwûòûØü(þÚÿà* ) ¨ ÐÊée;n ºüø4ô±ðœíë"éâç[çŽçwè ê=ìòîòxõ ù¨ü,{y ) ¼ Á 8(› ¢ Q Á I”¯¤ðÿšÿ¢ÿº³Ý"l¡©oÜãv/Yƒÿ¨ü£ù‘öó¿ð=î%ì‘ê•é?éšé¦êaì¾î¬ñõÜøâü ¸ õ®ÎE |:d[` >$ÿ‘ü_úøU÷Šö;ö_öêöÊ÷êø4úûÞüþ ÿÂÿ$+Õÿ!ÿþËüHû¤ùù÷_öñôÆó÷ò•ò±òTó‚ô:ösøû*þ|ú„ø 8"š†ÑnR}óÀ÷®  øýúmö-ókð9î¦ìºëvëÖëÍìJî8ð~òÿôž÷?úÅüÿÊéTUøKaO.ÿXþÛý´ýìýŠþ‹ÿç–…ŸÌð ò ´vÃu  &Ë$OýkùœõòÂîöë¸éè5çç–çÛèÊêRíYðÅóu÷HûÿÏC[ «ŸùÂÑ> d ^ G9Nœ5'ÿxþ.þCþ±þjÿ\u›¸³víºýÏ6;ïýeûµøüõVóáð»îüì¾ëë ëªëôìãîlñ{ôû÷ÎûÔÿìóÅ CMʦÒF n<Ž - ºDîÿÑü ú¬÷Éõjô”óDósóôõ`öÞ÷uù û‰üØýåþ¢ÿ ³ÿÿ þÛüƒûú¾øƒ÷‚öÑõ„õ¨õIöj÷ ùûžýs‡¾û  –³C5y ä›— I<ÿû÷ŠócðÃí¾ëaê´é·écê­ëíÉïjòGõBø;ûþ¶øy„5êDV5ú¼“—ÚÿjÿTÿÿEGš,ëÀ B ¼ å ¦ï°â „ ˜ )G ‰þãú8÷ªóZðgíïêéÈç;çiçQèíé/ìïSòÿõçùéýá¯3 P ïül9dóów”f  •+ä×ÿ¶ýºü'üýû4ü¿üŽýþ¥ÿ¾Â˜.qVÕëôþýüÌúxøöÑó¶ñåïyîˆí#íWí,î¢ï²ñRôn÷îú·þ¨¡ `&Yä»×9æîc_þ a¨ôiý!ú7÷ÃôÔòtñ¨ðnð½ðˆñ½òEôöê÷Óù§ûPý¹þÓÿ‘ðï“èÿûþßý¬üxû\úpùÉøzø’øùúŒûlý­ÿ;æÌ • "WQíâ(À² Þ E^I*ü"øTôâðçí}ë¶é è?è”è—é:ëjíð ó?öùØüýÿán9 a  - ß + # Þuÿ–QEMóë%› L E á  ¾ ë ’ ·d¨›ÿSüîøŒõMòQïµì—ê é'èôçxè´éžë'î=ñÄôžø«üÇУ! -°—ØlU›L|B¹ þ 0kÌmÿ_ý´ûwú­ùTùfùØù˜ú“û³üàýÿÇFn8Ÿ§ÿVþ»üæúîøëöøô0ó¬ñ†ðÓï¤ïðûðˆò¥ôF÷XúÄým6üž úñgExôµ»Âæ• ï %Hþ™ú:÷DôÎñéïžîñíáícîkïäð·òËô÷Fùvû|ýAÿ´Ê{Ư@‡—…ÿfþUýhüµûOûEû¡ûjüžý8ÿ+g×bì Y ‹gÔ¼¿Ê0ù3 óRmfý^ùxõ×ñšîÞëºé@è{çqçè}é{ëîñSôÙ÷rûÿþ^u+k ' X û ­ Õ   $ {¾n ë!³ÿ¤ÿñÿ’|à-m‡dî Ë Ëòo£ý£ú÷ô—ñõî¶ìóêÂé4éTé'êªëÔí–ðÛó‡÷|û™ÿº¾€ ãÉËʱ£ýÒ<W B oý û>ùÒ÷âöoöqößö¦÷³øñùEû˜üÑýÜþ¥ÿ<ýÿ`ÿlþ,ý²ûúbø¼ö:õöóóòsòëòïó~õ’÷úýTËXÚ 2>àýXzá’•úÙK ohYÿbû§÷FôZñøî2íì–ëÁëˆìÚí¤ïÎñ;ôÏömùùûXþs9œ“:ö_„|^A>ÿjþØý™ý¸ý;þ"ÿhèü*Y m IÔö›±0Y ? m¡þ»úßö/óÌïÕìeê“èoççTç]èêmìLï˜ò3öüùÑýN a >É¿+© æ ï ßÐÝ¢}ÿµþPþMþ¥þMÿ2CiŒ”jú0dUØö¼þ>ü’ùÔö ô”ñNïiíýë ëáêIë]ìîrðYó¸öuúpþ†˜€ Pþw(!düút„H ßk Ýýûú~øuöîôïówó€óþóâôö„÷ù¨ú+ü†ý¤þvÿðÿ Ìÿ3ÿLþ%ýÒûjúù¹÷¡öÕõgõhõãõÝöYøNú²ürÿy¬ï! $×à ‡RhÌŠ±Z  ¢ƒgüoø½ôpñ¢îjìÖêïé¹é/êFëíìï”ñ]ôM÷Eú(ýÙÿAMîÏâV}j6øÊÁòÿnÿ@ÿqÿî.´mB Ý n µ › ùY& d  Y2Áÿ üpøÒôhñQî¬ë’éèOç?çêçLéYëî*ñ¹ôø‹üˆfB FéêH 6â  ½ Sè™}ªÿ.þýgü ü=ü²üqýdþxÿ“Ÿ„-ˆˆ#U ÿ§ý€û/ùÍöuôDòVðÅî¨ííí¶íùîÛðOóHö­ùdýMJ6 ï TF¬q„Þ|d¡Eh$ ™ è3›þ=û6øõ„ó÷ñþð–ð»ð`ñsòáó‘õi÷Mù&ûÙüRþÿWÏæ )ÿþæü®û‡ú‰ùÊø_øXøÀøœùïú²üÚþW÷ä ¾ e½©ã_…  Ž ¼²’ý}ù™õòáîEìHê÷èZètè?é®ê±ì/ïò2õxøÂûòþèÑží ¹  Ú D V #ÅSèš~¨$ûÿ/¿¤Ð2¶BÀ ( ä 5 b 1 {I©¯sýú¥öTó;ðzí.ëpéRèãç+è+éÝê5íð„óF÷FûaÿrYõ 'Øòi5Uб òƒ Ù M¤3þHüíúú‰ù}ùÕùúkûü¬ýÑþÚÿ±DƒfçËþ?ýuû€ùy÷zõóþñ¶ðÛïï±ïyðØñÊóEö8ùü(í»n ç©»)âá$²˜è¼0 e{—ÿØû^øFõ§ò“ðï9î÷íKî)ï~ð4ò3ô_öœøÏúßüµþ=l8ž¡I¢¾³ÿ”þ|ý‚ü¼û?ûûYûüý›þy¦ ˜* ¨ óñ†"HâÜA $ ÉÈþ»úÅöó§ï½ìeê±è°çhçÚçÿèÊê(íð6ó«ö>úÏý;i=¡ † â ° ó ´ þ æ € æ0yÙh7WÒÿ«ÿáÿnH^œë4^Q÷>  x]ÉÃXœþ¥ûŽøuõzò»ïUíeëê<é"é»éëûìŽï«ò9öú/þRc> à ÔY>wþÒû……G B #RþêûçùYøE÷­öŽöÜö‰÷‚ø±ùÿúRü’ý©þ„ÿGšÿºþ‹ýü€úÎø÷Œõ/ô!óvòAòòióÎô»ö&ùÿû/ÿ›(µ " Lc.2Xï÷Š ÅɺºüéøjõVòÇïÎíwìÈë¾ëSìyíï'ñ}óöø-û—ýÅÿ¢ 5Üîm¤§ncÿ€þÛý…ýŠýòý¿þïÿwKW†¼ ß Ô Ç–ÜŒ ÷ O 0²òÿü)øeôãðÄí$ëé¼çç&çóçsé˜ëKîvñùô´ø†üLæ7# • |ÏŠ®F^ ` z tgn Øÿøþyþ]þžþ2ÿ 6^qYÿQ@ÂÓt«†ÿýqú°÷ñôQòîïäíLì>ëÉêúê×ë]í†ïCòõ"ùý 82 ì E!h ö+©y©M[ *îþõûYù-÷õWô¶ó˜óóó¸ôÔõ0÷´øFúÍû2ý_þEÿÖÿ áÿ]ÿ‡þmý"üºúMùõ÷ÉöâõUõ2õ‡õ\ö²÷…ùËûuþl™ß 7 zlɈÙvh¾ ð íÍýÆùúõŠò‘ï'í]ë>êÎé êïêhìcîÈð{ó]öQù9üøþtšZ§~àÒašo4îwÿ2ÿJÿÂÿ˜Æ=îÁ p  z ƒ4À» $  bVõ^ý¬ùö€òHïyì-ê|èxç*ç—ç¾è•ê í ð|ó>÷/û.ÿÊ)  UŠk@¢§ l ¤O%>¬þyý­üKüMü¬üWý>þKÿfyk&™³i·!Nþ4üèù„÷!õÜòÒðï×ííäìQíaîðZò,õrøüôÿïæµ :Vîé8ЬÏCd@Ì 'rÑÿ`ü=ù‚öAô‰òbñÍðÆðCñ5ò†ó!õëöÊø¤ú`üèý*ÿ§×¨#UÿMþ ýæûµú¨ùÓøMø'ømø(ùZúÿû þv&÷ß ž*ÁÇ+ãìG&Î ûþÞúæö5óéïíìêaéŠèhèùè3êì]îñ*ôe÷­úäýëª ùm ` Ó Ë U € b¥9ä»Ó9ùÿa~ÖVænÕ  Û P O Í Ä 5 &£¿‘þ3ûÄ÷cô1ñNî×ëæéèççòç¶è/êSìïOòöõåùùý¾  ñ<éìCóŠ—D® ò.~þÅþäüjû`úÇùùÙùlúGûRüxýŸþ±ÿ–<“)`;ÿÁýüú øöô[òòððïjïmïð5ñûòNõøZûæþ£t7 É ÙżøyB]ÝØi ±Ïçý‹ùSöóMñ¡ïîîBîôî#ð»ñ¢ó¾õô÷(úAü%þÃÿ ïpK¸ãàÿÃþ¦ý¡üÊû5ûöúû¥û üþÌÿæCËc î Qn*n$?µ„¯AJ á!)üøDôÁð¬í"ë6éùçtç©ç”è*êXì ï!òƒõ ùžüWFÍÙ _ X Æ ®  # Õ K ŸêEȇ’öÿ·ÿÖÿN W§÷/6ö\ W ÜætŒ;’ÿ¦ü‘ùröeóŒðîèëRêVééaésê2ì”îˆñôô¿øÆüèó— ЄŸÒà@þ+Ü.< & ;ÿºüšúêø²÷öö´öâöt÷Wøwù»ú üQýtþ^ÿM=Ïÿÿèý…üðú>ù‡÷åõrôFóyòòAòïò*ôðõ7øòú þlö‹ N=¸¥ñ‹m• Ô¿  (þ3ú˜ö`ó¦ð|îñì ìÌë/ì&í¡îŠðÈò>õÐ÷`úÔüÿÏ”íßu¿Ï¼Šÿ›þãývýbý¯ýbþyÿì°³Þ K U ‰ƒøÙÆÔ T Vñ@býwù¢õòÂîõë·éè8ç ççãèÓêYí^ðÆóp÷;ûÿ¯# ¼ Ï Q;ŽR’`Ò  ûþ'‰8@ÿ¨þsþþÿäÿâ-JAýivI[LìýPûøÉõóšðmî«ìlëÃê¾êbë³ì©î9ñPôÖ÷¯ûºÿÔݰ ,4®‡°!ÛãFnf  ´Kõü=úð÷öËôô¼óòó˜ô™õâöYøæùoûÜüþÿ¶ÿñÿ‚ÿ¿þ´ýrü û›ù7øùöùõMõõ7õæõ÷Åøìú}ýb…Ë @ 0Ææxhª76½µ8 cV6ÿ#ûA÷°óðõíöëŸêöéüéªêóëÄíðŸòrõ_øIûþ¡à½+$§¹d¸Æ¦o:/„ÿ)ÿ)ÿ‰ÿGaÈn?!ý · 5 _aB× Þ bs'›þêú7÷¡óLðUíÚêôè´ç)çYçDèâé%ìûîIòòõÖùÓýÄŠ  ­²ß‘‘:  ^ÑØ/ÿâýûü|üdüªüBýþÿ8PN£Ö©±òþçü£ú>øÓõ}óZñ„ïî%íÃìýìÙíWïqñô@÷Êú›þ“‘s WOØ­Ç&ÓÛSR÷ a±‰ýNúr÷ õ(óÔññàð4ñò5ó¸ôröJø#úæû{ýÏþÓÿz¬<ÿ‚þ\ý üèúÌùäøDøø%ø¾øÎùSûFýšÿ:ù Ì aœ`™4%fùä7 g|dCü;øoôÿðî¢ëßéÍèoèÆèÊélë˜í6ð*óVö™ùÔüêÿ½9Jãü • ± [ £ šXõŠ/ûSýÿe!-zõ†Ž Ñ É ` … + L ä ù–Ë®ÿXüæøyõ2ò/ïìnêâèþçÍçUè”éëî%ñ­ôˆø“ü¬°~õ úvVJü0ü| Í YÌ€ÿ†ýðûÆú úÅùäù`ú'û&üEýmþ†ÿx0±eµ§ÿ@þü¨ú øö‘ôÂò:ñðcï8ï¡ï¡ð9òbô÷.ú¦ýY+ù  úqN€û¹¾Âç™ ÷ !:dþÀúk÷€ôò:ðøîSîHîÎîÕïKñó#õP÷ƒù¡û’ýBÿŸŸ;rIÊ óþÓýÄüÜû3ûÚúàúOû+ütý"ÿ)yü–. ¥ ßÀ.es4f  u‰}ýqù‰õçñ«îðëÎéWè•çç=è›é˜ë îñaôÞ÷mûíþ>Gî Î ó ‹ œ 0 V " « Y±+ÛÒÈÿÐÿ2èãa¶úíq 6 dN„§ý—ús÷Yôhñ¿îzìµê„éøèéóé{ëªíqð¹ói÷aûÿŸ ` ¾ î˜“ÛsfÁš / & (’ýVû…ù*øJ÷äöòög÷2ø@ùzúÈûý<þ5ÿëÿMUKÿAþíüaû°ùô÷Dö½ôvóˆòòòƒò“ó/õR÷íùïü?Ã[ç FWüŸu•ú§¨ é\ ‚~tÿƒûÏ÷vô’ñ9ï{í`ììëìâì3îùïò~ô÷•ùü[þbaD»ÉwÕôéË´ÿ¹þðýnýAýsý þ ÿe5s¯ Ì °?aŒe£M s *Œ·þÊúèö3óÎïÕìeê”èrçç[çfè êvìSï›ò1öóù¿ýsð×  ÃÝ`P¹«: ~ ‘ ޝÿÝþþ þ ÿÂÿ´Îú$ôz¤e¶• Áþ/üsù¦öæóPñïí¬ëÐê“êëìÜí=ð,ó’öTúTþnj 7âòUù;ÓÓQg3 Õmüý*û¼øÄöKõYôìóýóôgõšöøˆùû„üÍýÖþ’ÿõÿûÿ£ÿôþùýÁü`ûìù~ø0÷öOõèôóô{õ„öøúŠü\ÿr´ @ KP;¸“ó¬Ðv º¼ž„üøâô›ñÓî¡ìë1êÿévêë2íPïÍñŒôp÷Yú+ýËÿ¦Áe—_ËíÚ©sOT—ÿ&ÿ ÿTÿüÿÿV𺞃 O å .€f»~ ¯ X ‰U×ÿ+ürøÌô[ñ@î™ë~éè>ç0çÝçAéPëøí ñ®ôøwünDØ Ë þ˜’ê§Ó€Ã¶ s ¼w¹ÿRþPýµüü¯ü2ýûýõþ &- §óáh…;“ÿ˜ý^ûûøŠö&ôìñ÷ïbîEí³ì¹ìaí­î—ðóö†ùEý68( ä J=¢duÍiP3X – îC·þfûløàõÕóUòeññ1ñÙñíòWôöÍ÷¤ùkû ýpþˆÿG¨ªO¥ÿ¶þ—ý]üûöùûøCøá÷æ÷]øJù¯ú…üÁþP ñ ¡ÿïY*SΘ¸:0 ± Ûͬý—ù´õ"òïjìqê$é‹è§èséáêáì[ï3òMõ‡øÄûäþÊ`‘M K Œ X ½ Ì›BÚ{=4róÿ>æà“$¼@ ™ ¬ d ¯ } Ç ‡ ÃÑÇ|ý ú—ö<óðVíëGé*è½çè éÁêíðnó1÷/ûGÿT6Ë ÷  ³#é~_»©B £ ê5ž?/þ}ü5û]úõù÷ùZú ûýûý:þYÿV¡Î›¼þý>û8ù"÷õ2óŽñDðjïïKïð…ñƒó ö ùjüß´n ì ±Ä0èå&²—è¾6 oŒ°ÿûûŒøõëòâðpï™î^î¶î”ïçð™òô°öÞøûýü¾þ1IQA×#4"ÿþêüôû7ûÅú¯úû¾ûêü~þp±+Æg ð DHàöy[•(u P ÂçáþÏú×öó¸ïÐìyêÈèÊç…çùçééêDíðGó´ö=úÁý!@Z 1 € C } 7  g  qÇ1MßÿÎÿ½©ÎqÀëÛ| ¹ † Ø®ðs¦þžûyøTõNò‡ïí)ëÄéééè†éÕêÐìhï‰òöÿùþ7G Ÿ ¬+ @Ô¼HKÞ ! oþü)ú«ø¨÷÷ ÷b÷øù=ú…ûÎüþ ÿÑÿIi*ÿ—þSýÑû$údø«öõ°ó¢òûñÍñ$ò ó{ôwöðø×ûÿ'¾ 2 c1€:K§J3jš ×ÞÓÙüù˜õòðîÆììì®ìÓítïxñÆó@öËøIû¡ý»ÿƒìí«sæúßÿÚþþký&ý>ý»ýŸþäÿ‚kŠÉ < 8ç1ÿAëöc9 † \Ô ü3økôæðÆí&ëéÀçç.çýç~é¢ëTî{ñùô®øwü3Âç L (p"@Óê™ ô  8~âÿÿ°þ©þþþ¢ÿ‡šÅðåƒÉª¦Ê‘ÿýWúˆ÷¼ôò¦ï–íüëîê{ê±ê“ë íPïòWõùðü  Õ ,JçÑO€'_B ò5ÿü“ùw÷Øõ½ô(ôôuô=õYö±÷-ù´ú,ü€ý™þiÿãÿÀÿ&ÿ;þý´û@úËøm÷@ö\õÔôºôõþõc÷GùžûYþ`œî9 [5©žü²¶‹Ý© éýåùö³òÁï]í™ëêêTê8ë°ì§îñ®ó…öjùBüïþYlSlRØ á«‚{­ÿ'ÿ÷þ&ÿµÿ¢år5 ß Œ ó û¢&s D –}mý±ùþõvò9ïgìêjègçç‹ç´èŒêíðró1÷ûÿ÷¢÷ Ü <3¿­ÝBN  Êq.FÉþ«ýõü¦üºü'ýÞýÍþÞÿú ô¥ ¶ïÀ.Fþü»ùF÷Öô‡òvð½îví´ì‡ìûìîËïòøôHøóûÚÿÜש 0LâÜ)¾˜º.R3Å (~èÿ„üoùÁöŽôãòÇñ;ñ<ñ½ñ¯òþó“õT÷&ùðúšüþ:ÿ‰¢_ÇÿçþÑýšüYû&úùIøÌ÷±÷øÑøúÌûíýh*  ÖUn o#&|/Oò 55ÿøú÷Ró ðCíëŽéºè›è.éhê9ì‹îEñIôy÷´úÜýӀϮ ö \ K Î öØ‹(Çj–éÿ®•Æ0¿\ìX … ] Ì Â 5  cÐÝ þ5û¹÷Nôñ,î±ë¿éièÁçÏç–èê9ìøî9òàõÎùáýóæ– æ ºÿ¤¡ô¡³:Kt ÄqÞþý¬û´ú-úúZúøú×ûåüþ*ÿ1  äËOp5ÿ¥ýÓûÑù¹÷£õ«óíñðïüîï¦ïàð±òõí÷4ûÊþ‘k5 Ë á'ÌÁüzA\ÜØm ¹Þþ<ýµù‰öÎó™ñ÷ïïîƒî¬î`ïð"òôö<ø`úfü6þ¾ÿî¾*2à=\Qÿ0þýüAû¸ú†ú¹úYûgüàý¼ÿëZóš 2 žÂ‚Æ{“Ëîxy AC1ü+øVôÓð¿í7ëNéè‘çÉçµèJêvì#ï6òõù•ü2‹ˆ î R 3 ¢ W Ô1‰õŠ^€ûÿÒÿ•q‹Ð*»Â} Û Ê B <¹À\¢ÿ¥ü‚ùUö>ó\ðÍí®ëêéÊè,éBêìmîeñÕô¢ø«üÍçÔt ©XmÚ—¢¿î¥þ  ÿ RÿãüÕú7ùøc÷-÷f÷þ÷åøúDûüÆýÙþ²ÿ?vPËÿêþ·ýAüšúÙø÷lõôóÈòýñ§ñÓñŒòÓó¦õü÷Æúîý[ñ cVÓ ¥…«äÎ % ;32þWúÃö”óãðÁî>í_ì%ìŠì‚íûîßðóõø„úåüÿíp?†iò2=( ÿþþnýýýqý:þgÿðÈÞf £ ¶ „óì]9vŽ †\vý„ùªõ òÅî÷ëºé#è>çç§çïèßêdífðÉóm÷0ûñþëëw ~ õÕ!àí c ™ ©®Âýu:YÿØþ¸þõþ‡ÿ]g¾ÜЄæåw–A€]ëý=ûmø˜õÛòUð"î]ìëvêtêëtìqîñ&ô²÷ûŸÿ¼Æ˜ eŠù°¸ðKJ ¬Qýqú4øpö-õpô5ôsôõöe÷ÕøXúÓû0ýYþ<ÿÌÿØÿSÿ{þ]ý ü–úù±÷pörõÊôôÇôƒõÂö‚ø¹ú[ýPƒÖ* ` Xó©˜Øb5YÜÑR |pQÿAûc÷Øó½ð*î1ìßê;êEêôê<ì îGð×òžõ~øXûþŒ¸‚ÝÅ8=Þ*6ä·¦Èÿ.ÿçþýþsÿIxõ¯h ) ¬ Ö“Ñ‚¡* $ ›žF®þóú7÷šó?ðFíÉêãè¤ççMçbaresip-1.0.0/share/soundroute.wav000066400000000000000000001047741372575704200172160ustar00rootroot00000000000000RIFFô‰WAVEfmt D¬ˆXdataЉHkE µŸê†fˆî£·@X ³7ÊŽý›ú øîõTôBóºò·ò-óôEõ½ö]ø ú±û8ý‹þšÿZÆÛžUÿgþaýYüfûúúØùûùƒúvûÑüŽþžóu š  /ýV%[íÖÂ Ü ÆÐÿ½û³÷ÕóGð(í—êªèuççUçkè<êµìÀïAó÷!û9ÿ<{ | òÎv¾x¸• + —õa÷Íþôü{ûjúÅù‰ù®ù(úåúÒûÚüçýâþ¸ÿT«²dÁÿÌþ’ý ü‰úäøH÷Íõôžóóþòjó^ôÚõØ÷Mú'ýN«‡ Ä ¶=>£ZX˜îÄ ûâžTü(ø?ô¹ð¶íNë“é’èQèÍèýéÓë9îñJô·÷;û¶þ½÷ ° ß „ ¡ ? o B Î ,uÁ(½“¶ÿ-ÿûþÿÿ< ê„ÔÊ]ˆJ«µÿwýû~øöõ‹ó[ñ‚ïî0íàì1í(îÅïÿñÉôø´ûÿ§±• /`døÅκÄR „ |_QýuùëõÐò<ðBîììAì?ìÞìîÂïÜñCôÜöˆù,ü«þîãz¨jÀ²K›´­š”®ûÿ‹ÿhÿ™ÿøvü–.© ñ î Œ ¸ g ‘ 4 Tü<(ÝüuùöÑò×ïAí+ë­éÙè½è]é¹êÉì}ïÁòxö…úÄþC: ÓïtMnÐr]ŸL|N áVÎlþJû‚ø+öTôóDò òXòó9ô§õI÷ùÉútüöý:ÿ3Ú(!Ê.^ÿjþhýnü’ûéú…úwúÈúû ü#þÿÿ$ü| ä ýyuß«ÓV: aÏôóüìøõ^ñî]ë;éÉçç(çè–éÜë½îòãõçùþ ª Þ ¨çdóO ³ þL¸\ÿLý˜ûLúnùüøóøFùèùÆúÌûâüóýéþ±ÿ9wcúÿ=ÿ6þïü{ûíù\øàö’õ‰ôÚó–óÍó†ôÅõ‡÷ÂùhüdÿžúY ™ š>gýì(§kzá¶  ÚýUùPõ¥ñqîÑëÙé˜èèUèMéóê3íôïó‡öúªýW8¬ ¢  î @ _ K ä B ~±ô]ÿêÿ'ÿ»þ¦þåþkÿ+ ð§C pnH<þôûˆù÷¬ôuò‡ðüîëíhíí9î–ï“ñ$ô6÷³ú}þuxc d8tÖä,´‰¿nµ ¶”uþzúÆöyó¬ðtîàì÷ëºë%ì+í¼îÀðó¼õyø9ûàýS~O¹µBd%’¾¼£‰…©°ÿ¨ÿôÿ“°’•é ý ½  ø \ ; ˜zï ãý”ú=÷þóöðGî ì^êTéûè[éwêJìÅîØñiõZù‰ýÒ" ß )åû[ýÞvK™{  }à\ÿüùƒönôãòæñyñ”ñ-ò3ó’ô2öú÷ÑùžûJýÁþóÿÒ\Œh÷HlÿuþzýüÍûEû û'û¦ûŠüÒýwÿjøcÄ ý óŒ°LQµw™% . Ç"þ$ú7ö€ò ï8ìãé7èEçç®çéëÊíñ´ô­øÐüöþÄ) h%0AÃËr Ö F¾ýÑûIú/ù†øJøtøöøÀù¼ú×ûøü þøþ°ÿ"G–ÿÃþ¬ý^üíúlùõ÷žö€õ±ôDôHôÉôËõP÷Pù¿ûŒþŸà.l w2~AfÝœ íŽ• 8Ìþ‰úoö¡òAïlì8ê¸èöçöç´è&ê;ìÝîðñUõìø’ü%ˆ›H z % ?ÉÇBL ÷ Z ¯Ó„8;ÿ•þHþRþ«þHÿî¼T¥¡>wLÄëþÏü…ú&øËõ’ó•ñïï¹îîæídîƒïBñ—ótöÃùjýIA. ì YTÁ‰šèp6C©~à ïΡÿûµ÷9ô6ñÂîîìÆëMëëXìÂí¬ïüñ˜ô`÷8úý¡ÿÿ ¯æ¬ï~Á˱‰klžÑÿãÿHÿþ6˜Ú Þ _ r ( ÁߌØÚþ©ûdø+õòXïüì$ëæéRétéPêäë%îñhô9øTü•ÛþÚ O>Ž.09;«¤D ¬þ\èü¼ùôö¤ôÛò¡ñûðäðRñ8ò‚óõæöÎø·úŠü0þ—ÿ±uÞï®%dÿ‡þ•ý¾üü±ûûåûüœýÿÆËT¦ ß á ’Ú£Ý}|ݦ å ®JÿYûm÷ªó1ð%í ê¾èç çwç’èhêéìÿïŽóv÷•ûÆÿäÍ^ |HàÉ µÛ”ü 0 NuÀIþ#ü`ú ù(ø·÷³÷øÀø¯ùÈúôûý,þÿµÿÔÿ9ÿTþ0ýàûvúù¯÷ö—õõÙô$õìõ4÷øø/ûÉý±Ñ @ P †rÉyu¹F#` SEÂû˜÷®ó&ðí²êóèñç±ç2èméTëÑíËð$ô»÷oûÿ¤çÊ8  w;mB s ¦ ¸ÂÝ! jÿ‰þþÖýþýsþ$ÿòæÅ{óòev'„ÿ—ýsû0ùæö±ô«òïð—ï¹îeî©î‹ï ñ$óÈõæøeü'÷¿ A_ùöCÑšŸæ€€ $ Õ®ü¶øõØñ)ïí°ëùêóê—ë×ì¡îÝðqó?ö)ùüÚþi©ŠþþЦ]¼×Á‘_@I‹ìÿ–am¬ pÈûñ • Ö ¥ ú Ð*‘¿ÿ±ü„ùUöEórðüíýëŽêÃé¨éDê˜ëœíCðyó$÷%û[ÿ ÐÇ a€åhç°Åt Þ%lÔý|ú~÷ôôíòwñ•ðHðˆðHñxòôÍõÁ÷Âù·û‰ý#ÿts_PòR•ÿ þºýøümü+ü=ü®ü€ý±þ9 OÁ É ôæS+g … e‰ü¤øÚôNñ!îsë\éòçEç[ç7èÑéìïqòDöZúþ¾Ä Ï ™ÉQ'K™á°" S bm’ìþü“úùã÷;÷÷:÷Ê÷¥ø·ùéú#üPýZþ0ÿÂÿøÿ–ÿåþðýÅüvûúÁøŠ÷ŠöÕõ€õ˜õ'ö3÷»ø·úýÖÿÐð & þ€ü5¸„Ÿ÷ a nAþüÉøÇôñçíDëIéè†çÉçÊè~êÒì®ïõòˆöDúþ¯3Ú ÿ ••þ×* ‰ À ɾºÓ!´ÿ˜þ×ýrýgý¯ý<þÿæÿÙÅ“.†8„pJþQü/úú÷ÎõÄóùñ…ðïûîï­ïïðÊò5õøpûÿáÁŒ [LÒŸ©írCrS DÙýÅùøõ‘ò«ï\íµë¿ê}êêêûë¡íÄïKòõøûþý»0Jú6úJ , ¬ÝÑŸ^$pFÛ¸Îc¶ïù¼ % & ² ÄZ|3«ýšú|÷oô“ñïæìLëKêõéSêgë-íšïòöú$þcœ§ c­j‚ä…b~å¨Ý¡  TˆÒþPû!ø^õófñHðÂïÐïgðxñîò²ô¬ö¿øÒúÌü–þV5·Ü¬2|ž®ÿ¾þæý:ýÎü®üçüýuþÅÿeGW¥ ®  ²À8X >u²ýÙùötò-ïWìêoè„çZçõçQédëîbñõ ùTý® x>TµdlÚÆG{ €tw¥ÿýßúù¸÷Öölötöàö£÷¨øÙùûdü’ý“þYÿÕÿÙÿ_ÿ›þšýjü!ûÓù˜ø‡÷·ö:ö"ö{öM÷˜øYú…üÿßßóü Ú pŸNhÚœ¨±É ^ u;þúíõ"òÄîîë¹é8èvçzç?è½éãë›îËñTõùæü©>…c Ä ˜Õx…š Û á ǧ›¹ÂþÆý'ýæüþüdý þÞþÍÿ¾ŸYÙòxŸlçþýûùçöàô óñWð¦ï~ïêïîð‹òºôl÷Žú þ¾ŽW ö I0ISœ"åïQ y {J ÿâúóö_óEð»íÕë ê êSê2ë®ì³î(ñðóïöúýøÿžñÜTS Ø é Ûß°eÙÃåMm ]¥à÷Ôb Q pͽM“þ¤ûœø˜õ¹òðßíìëê\ê|êQëØì ïÖñ)õèøóü(b} U ǵ¦‡¤þœŽéÇF ˆ¯ßÿ8üÛøâõcóqñðTï,ï–ï‚ðàñ˜ó‘õ±÷Ýùûûòý¯ÿ9õRSm£ºÇÿßþþ…ý7ý:ý˜ýSþjÿÔ†ozŽ’ k 8ý>îŠ z åÛuÐþ ûC÷ óDðMíÚêéÝçtçÎçëèÃêGíbðøóë÷üY‹‰1 f fð+ÅÒh¤ ¤ ‡mr³ýFû=ù§÷ŠöéõÀõö©öœ÷Çøúlû¸üâý×þŠÿïÿÁÿ1ÿ]þRý"üâú©ùø¥÷÷Ãöèö÷øúü]þÝØÔ ³ W u½ge°I6…J Ÿ¢uÿ;û÷7ó³ï®ìBêƒè‚çEçÌçéë–í©ð!ôÞ÷»û–ÿMÀÓ o €ûÚÌó¤ô ý Ù¢uh’ÿÏýöü}üaüœü ýÝýÀþ³ÿ¡t}“Q³ºlÿÓýÿûúû÷ûõ ôƒò>ñeð ð@ðñgòXôÑöÁùý¥a#Ç -2º©ìu;>„” ­†C üþ÷Bôöð4îì›êÜéÔé}êËë¬í ðÇòÇõëøüÿõ}£W’ O ’ c Ð èÂs»r¥$õÿIAb˜ÏîßåØ\j.ôiÿŸü²ù¾öàó9ñäîþì ëÛêÀêVëì‘î%ñGôÞ÷Ìûðÿ'L: ÏêqMnÌe=cçäv ¾Ýø3ýªù~öÆó–ñüïÿîŸî×î›ïÚð€òtôœöÛøû9ý&ÿÎ"¯äÁP¡ÅÓáÿÿOþÕý¦ýÌýMþ)ÿ[Ú˜~x T ÷ I4¥Œá¡ Î s žeãÿ3üwøÑôeñRî·ë¯éPè©çÃç è:ê‡ìrïãò¼öÜúÿ^wE ©‡È]<cÖ ÒƒÍ Î ¥rThþÆû„ù±÷Xö~õ!õ9õ»õ–öµ÷ùiúÎûý?þ%ÿÃÿ¯ÿ ÿ)þýìû¹ú˜ùŸøã÷w÷m÷Î÷£øëù¤ûÁý4éDzŒ 7•‹ÿÜžv¡*# ¢ÄªwüOøWô³ðƒíâêéè¨ç*çrç{è;êŸì‘ïôò§ö‰úvþJæ+ ÿ M# ‚Ó¥  ò ª`,'eÿôýßü,üÛûçûDüäü·ý¦þœÿ‚FÔ­îÙÿsþÍüöúù÷9õó2ò6ñ°ð®ð<ñ^òôOöù*ü›ÿ<ñ• 'Ôóm39|Ñÿ¢ Ø À;ýù8õ¾ñÅîfì±ê²éléÝéúê³ìóî ñœôÉ÷û5þ5ñO@· ® ' & ¸ ê Ò†¬M]ôÿÞÿ¥rr’¿ááª'IJ…ƒ)Šý½úÝ÷õZòôïðíhìrëëuë}ì3îŒðyóãö°ú¾þë Ç ÅÛ:Ù±Ç#Ö÷¡ ô =þŽú1÷BôÖñþïÃî(î+îÃîßïnñWó€õÎ÷%úkü†þcð"ò_m$”Ìáéûÿ)ÿˆþ*þþaþÿûÿEÔ–xb: ç O [÷   é KBæSý§ùöòcï¥ìpêÛèøçÒçnèËéÝë•îÜñ—õ¥ùâý)WG × éf9Y¾khÄ•òú Ê„G2ÿ_üäùÖ÷Aö+õ—ôôÚô˜õ§öñ÷^ù×úEü‘ý¨þ}ÿ5¥ÿïþþîüÈû§ú¡ùÍø>øø4øÐøÝùYû>ýÿ–f  ’-;ªqˆò·æ “ ÚØ±ýˆù‚õÂñkîšëhéêç+ç2çþç…éºë…îÍñrõSùLý9ùlv ÿ ÷Q "£™7  ¼ZÒÜÿ3þãüöûmûFûxû÷û³ü˜ý‘þ‡ÿeŒ¶‹+ýþ‡ýÙûú'øRö£ô2óòhñ5ñŠñoòåóæõhøWûŸþ"Äc Ý Ý(×× doÒ¡÷ õ¼sþ<ú>öšòoïÕìãê£ééTé<êÈëæí}ðpó¡öîù9ýaLâ Á õ ¥ Ö ‘ ã ß ™*©-Ο° ¾ÿÂÿµ•²ÑÛ¹X¤!ÂúÔcþºûôø+öó ñïîCíì”ë°ëyìïí ðÁòûõ¡ù”ý³Ûæ ² OìËä8ͲüÃ' ILTÿ„ûû÷×ô1òð¡îÊí•íüíñîcð<òaô¸ö$ùŠûÐýàÿ¤ÁçzËîöúNÿÄþ€þþöþµÿÇ$½~S" Ò J s 5€E~ ' D à ÙgþÐú6÷»óð£íEë}é`èüçXèuéKëÍíæð}ôsø¦üð-9 ð 4éûZÿè§›& õ ¢Jý^úøDöòô%ôÙó ô¥ôõÝöMøÕù]ûÎüþÿÜÿIa'¢ÿÜþåýÒü·ûªúÃùù¶ø³øùéù*ûÔüßþ7Í…E ï fJ„(*)+“ r áýèþÃú³öÝòdïfìÿéEèGç çšçæèçê‡í¯ðAôøüû˜Õ ˜ Íf[­`€Q/ Ö aì“kŒþýÙûûºú¾úû¸ûŽüƒýƒþvÿHçCPdnÿ+þ©üúú2ùi÷¹õ;ôó2òÑñññ›òÔó˜õß÷šú´ýž2® ðÙJ)b婬õŽ #÷¯ÿkûS÷‰ó/ð^í/ë°éëèãè“éïêæìaïEòtõÌø/ü{ÿ‘[Á± ! r Z Ð å ¬ =¯š?A¸ÿ‚ÿ¡ÿ ¾£¬ÂϾyë¼äWh(ÿ¨üúJ÷£ô)òùï-îßì!ìììÆí¥ï ò&õ¡øuü ²‘ ,¬„¡û`{òÜV €wŠüÙø„õ¦òSðšî…ííIíîcï%ñAó›õø™úýDÿ>å+ ƒ˜SÁö$sÿÿþØþÿ‰ÿb‹ö’L » > } b Ù Ó E + … \½ºnÿñûeøëô£ñ®î,ì5êâèAè]è9éÑêíðqóJ÷lû´ÿûø iT¢@%L¹w•)O# Ç[ÔýñúpøaöÓôËóIóIó¿óœôÌõ8÷Êøgúùûiý¤þ›ÿA”’>¥ÿÑþÕýÅü¸ûÃúüùxùGùwùúû„üVþ}è*Ë F XºÉ\D…(< Øýûê÷ômðGí®êºè}ççOç_è(êšìïóãöäúôþí°  ‡_“  WdO õ sågÿþ;ý×ûÚúFúúGúÈúˆûuüxý|þkÿ/¹ûêƒÇÿ¹þfýÞû3ú|øÐöJõô ó‚òoòáòÞódõo÷óùÝü‚} É È[gÕ“–Úb7i G /ë¡ütøŠôñÿí•ë×éÒè‹èé(êôëOîñEô£÷û‚þÁ¼Y† 3 Y ÷  ¯ â » R ¾xô¡Ìÿ\ÿBÿ{ÿÿÿ¿­µÁ»Œ fPÓëšäØÿ„ýÿúaøÆõJó ñ&ï²íÅìqìÀì¸íXï—ñgô´÷bûTÿgzg Bó]øÌÛ/Öç} · ¸¤ŸýËùHö4ó¥ð®î[í°ì«ìDínîð"òzô÷™ù(ü’þ¿ž ;ë3¬ø 4•ÿ9ÿ.ÿxÿ C¶Qþ¥- } €  I ò  ¬ ¿XˆdýùöÌòÅï"íë{é è}èérêì2ïtò+ö8úwþÂ÷𠊧/ 0—@36sR óx®þœûäøšöÎôŠóÏòœòèò¤ó¿ô#ö¸÷fùûªüþ?ÿ­äÆZ®ÿÎþÏýÆüÊûïúKúñùïùPúûOüçýÚÿ‡« % hYÞáPEĤð ¼">3ý#ù1õƒñ9îrëHéÏçç çñç€é¿ë˜îóñ¯õ«ùÃýÒ¶N | (=±{œol Ž ìNЊÿýðû·úêù‡ù‰ùäùŠúiûjüyý~þdÿ´‡/ÿþ±ü(û‡ùæ÷]öõ÷óFóó@óôKõ÷dùü'ÿrßN ­]‘1(iíµÆ/_ _'Ûý ùšõíñ·îìêÔèMè…èvéëHíþïóuööùyýÝÙ@ * d ² ~ Ó Å h Óe½=øüÿQÿýþÿRÿëÿº®²±”E³Ì†ØÂGpMþîûmùãölô&ò*ð•î}íõì íÅí&ï(ñ¿óÙö^ú2þ3A5 î H$hÿÙî=˧ä›ê òØÀþÍú!÷ÚóñÝîKíbì#ì‰ìˆíïñWóãõø9ûÊý(=ùP;¹Ðˆñ ý>³ÿqÿÿçÿŸ¥ìc÷‘ u Q © ‡ â ·  Ú?Iþ°úI÷ùóäð'îáë*êé·èé,êüëwî‰ñõ ù<ý†ÇÙ ˜ 䢼!ȯÛW6 # ž›ÿ]üqùíöåôcónòò"ò¹ò¹óõ¢ö[øú×ûlýËþäÿ«5üy¼ÿÓþÔýÕüìû-û®ú~úªú;û4ü’ýMÿW  L PóÀÇ*éŒ Œ Zdþ\úeö¤ò;ïJìíé:è@ç çœçïèøê¤íÛð€ôqøŒü«¬lË ®³¼Íåp„; ® ýE¡,ýý$ü¯ú§ù ùÝøù—ùaú[ûnü…ýˆþdÿdp(Œÿ¡þrýüˆú÷ør÷öíôô¯ó¸ó@ôMõßöîønûLþqÂ"p ŠRªw¤"åí<Þåi ‡`ÿÓú·öçò…ï­ìvêñè*è$èÚèDêOìæîìñDõÌødüèÿ;@ß ¦ º ?:¸ Ç z ê .`˜ïxDaÿÒþœþ»þ'ÿÔÿ®¦¤“\í2«ÐñÿÍünúú÷õCó9ñˆïIî‘íoíííïÓð/óölùý  È >B¸ˆ õ„PdЬ +ìÿÞû ø–ô˜ñ'ïVí.ì³ëâë³ìîòï5òÀôv÷:úïüzÿøKq'qTß ,ûëýDÎÿ¥ÿÑÿO6…û‚g ” t õ  — ¨ 5 Dà ÿÈûrø'õ ò7ïÐìíê¦é é)éê“ëÓí±ðôé÷üI‘¶• þRöÞk(£§U Ë+™3ýú[÷õWó%ò„ñnñÛñ¼òþóŠõH÷ùôú°ü?þÿŽ9Œˆ3šÎÿßþãýðüü}û#ûûvû4üVýØþ®Ê~ä - >úKVöóN G iÿ’ûœ÷ÎóKð5í¨ê½è‡ççbçwèFêÁìÐïXó:÷Rû}ÿ”w ª›â|i±d•\Ó  J…åƒþrüÂú~ù«øGøLø¯øaùMú`û‚üžýœþlÿûÿ?1Ïÿÿþäüûú†ø"÷íõÿômôFô˜ôjõ¿ö‘øÙú…ý±üB b =³© À ˜v³d ¤“T üß÷òógð\íìê)é"èÛçVè‰éfëØíÇðô÷Cûãþ[eÇ ¥ õ ´ä¾ ˆ  C f„µ¨‹ÿÂþRþ;þwþüþ¹ÿž–‹g„¡c½Xÿ™ý_ûù©öbôNò†ð&ïAîëí.îï˜ð·òdõ‹øüãÿÔÈ› (OòøLá±¼ ª°8 ` Kýü ùiõ6ò‹ï|íì\ëRëïë'íæîñšóWö.ùü¶þ1]*Œ}ü¿8(ÝÎëBäÿÕÿ±•¸ {ñU ‰ . k 3 ~ G “i×óÿÓü”ùTö3óQðÎíÄëLêzéYéòéDëGíïï&óÒöÖúÿVŠƒ !CбØ?ãͩɅ üQ¦þÑúá÷bõfó÷ññÐðñÌñôòsô1öøúàû›ýÿV<ÉüÙj½äÿñþúýý[üÛû¦ûÊûNü6ý}þ .wË & öf_ϧá{{ ë Ýi«ÄüÓøþôgñ1îxëYéèç3çCçè¬éñëÔî;òöúGþpq& r 9gîÆîkJœxù : \z³"ÿÚüðúpùaøÇ÷›÷Ö÷iøDùPúyû¦üÃýºþzÿõÿøÿ|ÿ³þ§ýgüû—ù5øööñõ<õéôõ¡õ¹öPø]úÓü¡ÿ­ß 8 ®ÊYF… ÚõjL ³ ¾ŽHýù õ[ñ"î{ë|é4è®çêçãèŽêØì©ïäòjöúÏýhÉÓn ‰ xQ¨Ž  \ u~Ž¿$ÐÿÌþ"þÓýÜý4þÐþžÿ‰i0 ›Ñ¦"PþAüúÀ÷õhóñðï~îŠî1ïxðZòÍôÀ÷ûÊþ¦‘h LP޲Øo£O †V&þúOöìò ð¼íìëÙê@ëJìåíüïuò3õøûÞý‡èï¹q¶‘?8Ù¯¦Ï;ôÿÿÿ\ ÿ+~âB„’ V ½ ¸ : ? ÇØ}ÈÏý¬ú|÷^ôsñØî¬ìëÿé¤éýéëÕìCïGòËõ°ùÖýVe $s4Q¸_Cg֢Ⱡ/ ~Àÿ¢û€øÈõóâñÊðGðUðèðóñ_óõ÷ùÿúâü•þ%ìXj( àüÿÿþGý¥üFü7üƒü0ý=þ¥ÿ\V|¹ñ é s’1@µŽË v žX½îý ú2öò:ï[ì êbèoç>çÓç*é7ëêí*ñÜôÞø ýB\7 ± ¯ßö[—Ža w~”×ÿ[ý8û|ù2ø^÷ÿö ÷~÷@øAùjú¥ûÛüõýâþÿôÿÄÿ2ÿVþ?ýüû¢úHùøíöö¡õõñõÏö(øúù9üÕþ¹Ìò û žÚ“µ.ó[ !³ ßÃ…þGú.ö`òýî"ìèébè›ç—çUèËéèë–î»ñ7õéø¯üfí(û R UõƒŠ) v Œ ƒx‚¸-ñþ þƒýWý€ýõý¦þÿqc>ïcŠYÉÚòþýüúÍøœö„ô ò ñÛï&ïýîjïsðòNô ÷8ú¿ý€]3 Þ <,“XiºE…Y· ¾’Xÿ3ûH÷¸ó ðî2ìüêxê§êëñìêîRñ ôøöûùôüÈÿ[štÜÍG P ó?Fߟtr«,þÿ!˜Z[Û0t‘p ü % Ý  á. ‰»þ¸ûøˆõ™òíï£íÖëœêê#êõê|ì®î}ñÓô•ø¥üÝ<  ‚Ø}eˆé‹ïØb °ä ‡ü6ùHöÓóéñ“ðÕï®ïðüðQòýóçõö÷úüöýšÿòõ›ãÓsÒ"ÿ?þ€ýúü»üÒüDýþEÿÆ‘±Øí Õ u´~Àp…è H 3Áÿ;ûh÷¹óQðPíÓêôèÅçUç©çÁè“êí(ðºó¨÷Ðû ;5Û ±µ ¯àƒ›>‰ š ‡ õýšû£ùø÷xöWö öE÷4øYù›úåûý4þÿ­ÿùÿòÿ˜ÿðþþæü¦ûXúùò÷÷kö,öZöþöø±ù·ûþÖÆÕã Ó …ܼ ½¿ §“ࢠóñÀÿû[÷sóêïßìnêªè£ç_çßçéëí˜ðôµ÷†ûUÿÿgo  ZNz3 ¦ “pXc¥1ÿþNýéüàü*ý¹ý~þeÿXB ¥úþ§óâ|ÿÊýßûÏù²÷¡õ·óòÁðãïˆï½ï‰ðïñéólögùÄüe/þ¯ 0º•bj¶RSÓ ñÎZüQø˜ôNñîjìóê1ê$êÇê ìãí4ðãòÓõåøùûóþ¶+?ã  ý É 4 P0ìšS*4?ËŸªÝ"c‰}* } h àài4”ÿ·ü¶ù¯öÁó ñ¨î·ìOë„êdê÷ê>ì3îÉðîó‰÷|û¥ÿá ÿ ™ºF(O³S3aïö“ æ8ýúàö2ô òvð}ïïTïðKñæòÌôâöù6û@ýÿ¦ãÃDh5¸ .@ÿiþÀýVý9ýtý þÿþIà¶µÆÒ ½ l Ǹ*b@ Ú ú´#füøêôqñSî®ëé5è‡çšçrèêOì6ï£òyö•úÔþ%ñ R/pé_œY±  ªŠ~¥þüåù#øØö ö´õÒõUö.÷GøŒùäú8ürýþNÿÒÿåÿsÿ¸þÁýžücû&úýøøE÷ÞöÛöH÷*øƒùNûýÐÁ¿« fÒÓP5rþ׈} øõ½üø’ôèð²í ë éÆçBç‚ç„è;ê—ìï×ò€öVú7þË• Û Ž¦"\5¤ à ª v@#5Šÿ0þ2ý”üVüqüÛü„ý[þKÿ=ÖUŠkñíÿoþ±üÄú¿øºöÐôó´ñ²ð)ð(ðºðáñžóæõ«øÚûXÿÊ| ü &ÞŠVc¬5 <ã  Ê‰ýhù‹õòï¼ìëêºé%ê9ëéìï¼ñ©ôÅ÷ðú þú£ðÐ9 % •  S @ý @õÓìKüÿUöØêR|€IÂ܊ʼnÝÇY¦ýÄúÑ÷éô,ò·ï§íìë¾êëìÑí,ðóŒö]úrþ¥ÔÚ “ݸâ¿#ß ¾  D\†þâú÷«ôGòtð=ï¤î¦î9ïOðÓñ¯óÈõøFúvü{þ?¶ÑŒæäõ(<F_ÿ˜þþ¸ý½ýþÓþåÿGîǾº¢ \ Î à™$~ T ª”)ˆýÎùö™òcï›ì\ê¾èÓç¦ç=è”é£ëWî›ñRõ]ù—ýÜõ ƒ •æq$)kÖí ΙnlÿªüAúCø¼ö³õ'õõrõ/ö9÷zøÛùDûžüÕýÕþ‘ÿþÿÞÿVÿ‹þŠýgü5û úù-ø¢÷r÷ª÷SøpùÿúøüMÿ꺢„ B ¾Ü€– ÕíVD ì -%øýÈù¼õöñ˜îÁë‰éè?ç?çè„é¯ërî°ñKõ!ùýñ¦ ‘ ‚Ù©-+´ß Æ …7öÛýÿkþ2ýYüãûÌû ü•üWý>þ4ÿ#÷œÿÕ9DþþoýªûÂùÏ÷êõ.ô³ò‘ñÞð«ðñïñmóyõøûYþëœI Ð é=õþIÓ›«ä= =ÀþŒúöìòÁï(í4ëòéié™éyêýëî™ð~óžöÛùý)‡¢H o  B ù M M ¬;ÒˆpšÚÿ÷ÿcDl{Zõ;B‚þÄûêøöQóÎð¥îîìÂë1ëJëì‰í¨ïbò¡õLùFýkš­  îÝ0Ó¸Ø3нáO {ˆ›ÿÕûWø<õžòðïCî îpî_ïÈð”òªôðöHù™ûÉýÁÿnÅ»M~UÞ)HR]~ÿÈþNþþDþÂþšÿÄ:êÁ©‰ G Ê ù À Ρ ³ C` ŸþùúQ÷Çó~ð—í.ë]é8èÍç$è;é ëŒí¢ð7ô+ø[ü£ßé  ã˜« µ¤ßssö ÷ ´oEVý·úø»öuõ±ômôŸô;õ/ög÷ËøDúºûýEþ6ÿÜÿ/.ÝÿAÿhþaýAüû ú"ùwøø%ø–øxùËúŠü©þÁ`  £ØŸâŒ‘èô Î 7L0ÿûíöóï‹ìê]èXçççâèÛêsí‘ðôê÷ßûÖÿ«>r - \ñä7íºø å ;ܘˆ¿þLý8ü‰û=ûOû³ûZü2ý'þ!ÿ Ð_§ž=‚tÿþ~ü¸úÝø÷Dõ»óò§ñEñgñòXó'õz÷BúkýÚt¡ ñåaJ‹ßç4ÒÓR lBûÿ¹û¢÷Ùóð®í|ëûé2é%éÎé!ëí}ïSòsõ»ø üFÿLZ<   à Å ; S " ¾@¾P ?Ïÿ²ÿéÿk0&<\o`…–?zE¤¡Kÿµüøù/÷vôìñ®ï×í€ì¼ë›ë%ì]í>ï½ñÉôJø%ü7_y_ ïn’ófˆú} ²»¼Ùü2ùæõóÁð ïûí‹í»íîÆï}ñ‹óÕõ>ø«úý*ÿ Ï› ¸ Qacpœÿúþ™þ‡þÌþiÿ[œÒ s0 ¾  ï g^Ë © ù èÿüøøô¢ñ¡îìê·èè%èýè‘êÖì¼ï)ó÷!ûhÿ­Ðª Uöß €EmA$ Ø}3þFûÔøÔöRõTôÙóÜóSô,õUö¸÷;ùÇúEüžýÁþŸÿ,fLãÿ4ÿOþEý+üû ú\ùÝø¶øòøšù²ú5üþXØ…C÷ ƒ ɯö3Ȱ 0g`>ü#ø5ô—ðiíÉêÏè‹ç çPçXèêƒì~ïîò²öªú¯þŸY½ ° î ­˜ì¶  » KÑi+-ÿ€ý1üHûÅú¥úàúhû,üýþÿõÿ©!M%¦Ðÿªþ?ý ûàùø\öÊôyó€òóñâñYò^óïô÷˜ù‘üÙÿVèp Ê ÕtŠÆÐ¤|°Y ‘ z7îüÂøØôQñLîßëêéÊè9éYêìjî-ñEô“÷÷úPþj÷ ¶ Ò h ~  Q 2 ÓM·*½‚‰ßÿˆÿ†ÿÖÿl?<Oa^-½ú×KQì!ÿÿ•ýúúHøšõóÁðÏîQí]ììRìKííî1ñôZ÷û ÿ&A5 à!ØïQòÍä>î¥ è òçìý ú¦ö™óñïÌí!íí¯íÑîmðmòµô*÷¯ù(ü|þ’[ÈÏn¨ƒ Tnom¸ÿ+ÿäþðþRÿ hò¢b ­   ¯ × | – # * µÕ¡5ý¬ù)öÌò·ï íÝêMékèBèÙè.ê8ìéî*òàõìù*þvª£ >]æÅîZ YeR  —0ïþíûDù ÷Iõô\ó-ózó3ôHõ£ö+øÈùcûãü5þIÿ„¢mîÿ/ÿ@þ7ý&ü&ûLú®ù\ùfù×ù³úûû¨ý°ÿŠ/Õ ` ³±@J½´1 R  u‰vý\ùbõ¬ñZî‹ëZéÙçççççoé¦ëxîÊñ~õqù€ý†bò ¿ÐA .³¥!Ü d ÕLä´ÿÏýFü ûeúúú‚ú-û ü ýþ ÿâÿ„äô¯%ÿìýwüØú$ùs÷Þõ}ôhóµòtòµò~óÒô¬öùÊûèþCÁ? ž »w¶_^¦/úyO« ¬t(þìùæõ8òï\ì^êé‰è»è¤é8ëbí ðógöØùKýŸ¸{Ó± Ú # í E < è _»‚ìxÿ<ÿVÿ½ÿgFFRU7äIWBˆ›bþíûWùºö1ôÛñÓï3îí‡ìšìTí¸î¾ð[ó|ö úæýð Æ ( Xö×óHÞÁÄ , ÿ û{÷;ôyñIï¹íÐììñìéífïRñ“óö¥ø<û¸ýÿ¦éÂ1;ëOy}soˆÒÿZÿ/ÿWÿÖÿ§Æ%²Y˜ ÿ  ä :  h 3 w <‘ŠAþÐúX÷úóÖð îºëúéßèyèÐèåé²ë+î<ñÍô¾øïü:|Ž N œ]yâz®3‚~ 1 »=ÙÿªüÍùX÷\õäó÷ò“ò±òFóBôõ÷¿øqúü“ýÙþÙÿ†ßá“þÿ1ÿ<þ5ý1üHûŽúúòù-úÏúÛûNýÿ@Ÿ&¹> — ¨VŠ09Yrò ë s¨¨þ–ú–öÌòZïaìüéAèAçççÛèÝê‚í±ðNô8øKüb[k I—GO­f…:þ ƒ ä@±R8þuüûú“ùpù«ù8úûûûýþ ÿÔÿb©;†ÿ‚þ;ýÁû(ú†øóöˆõ]ôˆóó(ó¸óÏômöŠøû þ?¢o ˜mѨÝa*5‡+3¸ Õ­eÿû÷0óÌïñì·ê/écèVèégêhìóîíñ7õ°ø8ü­ÿðæw‘ ' 3 ² ¬ + > ú u È ZÇhM‚ÿ ÿîþ"ÿ¡ÿ\DEH7ý†ÁŸ+Õ ÿÐüZúÒ÷Sõùòàð$ïÝííúìxíîeðÇò³õùÎüÁÎÏ¡ ,ª ý“f€ó×G dR3/üdøõôûñïÀí™ììHìíjî=ðqòìô÷AúáüVÿŠjèü£àº?~Œ~kiŒçÿ‡ÿvÿºÿS<jÐZó‚ð % ‰ • ! ( © ©6_>ÿêûƒø(õûñï¨ì»êléËèâè·éFë„íbðÈóš÷¸ûþÿFmN Ç»º§ÓAû–§b æVÓ|ýnúÁ÷‰õÔóªòòûñhòDó~ôÿõ®÷sù4ûÚüQþ‡ÿn=#»9ÿ@þ?ýLü{ûâú“ú›úûÖûý¦þ“Æ)¥ w –^·ŒÌlg¾z © `¹ÓÿÍûÍ÷õóiðJíµêÂè…ççRç`è)êì¥ï&ó÷û4ÿD ¦ º D2ySK¦ ýB’ºþ¾ü"ûðù-ùÖøåøNùúíúûûý!þÿËÿDpIÎÿÿëý›ü!û“ùø˜ö\õjô×ó³ó ôèôIö*øú>ýJŽêA p XÛÜE VçÆ´ óá¡Wü(ø9ô«ðží*ëcéWè èè©é}ëåíÇðô‚÷ûªþ9W * r +X6  ÜB‰ü¬¨ÿ÷þŸþžþíþ‚ÿM<90 ²%Ö"»ÿ ýOûâøqöôõñ"ð¸îÍísí·íî&ðLòõ1øÄûœÿ˜—s ;æôPìÃÔ)ÏÜj š ŒeKý_ùÄõ–òïïâí|ìÂëµëLì|í0ïSñÈótö8ù÷û—þüÍýox!{˜pXY‰øÿ°ÿºÿÉÅÿhénÞ!  Å ÿ Á  À ý )øü§ùVö%ó5ð¥íëê5éé¤éóêõìïÔò‚ö‡úÂþ A> Þ“x¥¼­òžÉ‘  yÝbþ&ûCøÐõÞóxò¢ñZñ™ñRòtóèô˜öjøDúü²ýÿ< œeå*GÿNþUýtü¾ûHû!ûUûìûèüGþþÿ<š W ~ [ÕÔG!Yïè P 9»óýù%õ„ñDîƒë[éâç&ç/çþçŒéËë§îòÍõ×ùÿý"Í  ׉aŒöR;Ë  QƒÑTÿ!ýKûÝùßøRø1øsø ùãùëú ü,ý9þÿÈÿ*=üÿgÿ…þbý ü˜úù¬÷döZõ¤ôTôxôõ?öã÷úˆühÿ‡Ë E ;×þ—ŒÐ[,I¾Ÿ  Û“ýXùOõñaî¶ë³éfèÚçèé¤êäì©ïØòQöòù™ý$vr  — ŒïÈ" ¢ ô 9^¦#çÿüþjþ1þNþ¸þbÿ9,% ÏW”zÿ ßD[þ4üæù‰÷8õó*ñ£ïîîî¸îðëñeôb÷Êúþh_A ê 9OåÀØ)º–ÑƒÊ Æsþkú¨öIójðîzìë9ë›ëì.î9ð£òQõ$øþúÂýV£—">ç"õo {R8AÔÿøÿo6B„ê^Ê * ï T I  ¼ 66Ê÷ýÁú€÷QôWñ¯îwìÈê¸éWé¬é»êìíîóñxõ`ù‰ýÏ! ã 6ûˆ4J˜⾠I ¥ôZÿóûÞø2öô`òMñÎðÜðmñqòÕóõY÷Gù0ûýü˜þðÿ÷§üù¦DYÿbþuý¨üü¼û¾ûüÞüþ€ÿO`î9 b Nã ¬¼1<ß þ­-þ<úZö©òMïdì êYè_ç(ç¶çéë»íöð¡ôøÆüö àU P¸}•ü¶ÌNQî B j„¯žýûåù«øå÷‘÷§÷øßøÜùýú-üTý\þ4ÿËÿ´ÿÿþèü’û'ú¿øq÷Uöõ õüôgõPö¸÷™ùêû™þµî ÈÔý|FW²av 0ÐþŽúrö ò9ïZìê‘èÄçºçqèÞéñë•î®ñõÃø|ü$žÌ“ ß ¢ Óo{ÿ ´ 2 <Ee³@ÿOþÝýÅýþ„þ@ÿ"Þ‡îµÿýÝú™øUö-ô;òšðcïªîîíîúï¤ñãó©öáùtýA* Á *%•bzÒd3HµŽò þØ£ÿ„ûž÷ôýðwî“ì[ëÕêÿêÐë9í'ïñ*ô÷öùÜü›ÿF eH·¸V¡«‹V$ nòÿ/¿™±öU¸* – º i ž T\ÇæþÑû£ø}õ}òÃïmí•ëSê·éÏéžê#ìVî&ñ~ôCøVü’ÕùÙ TK¦P=gÏ~‚ñä{ ÖaÕüù®öDôbòñYð3ð˜ðzñÆòfôBö?øBú4üýý‰ÿÉ´CwTå9`pÿ}þžýèümü>üfüîüÖýÿµ—®ã D : å-û@îvU ¬ ŒOÿoû÷ÕóbðWíÑêéè³ç;ç‰çšègêáìòï~óg÷ŠûÃÿëá‚ ±SW®SG<^j ‹ “žË4þìûú’ø’÷÷îö<÷ã÷Ïøíù%ûaü‰ýŠþSÿÕÿçÿsÿ³þ²ýü,ûÑù‚øY÷löÐõ–õÌõ|ö§÷LùdûÞý©­Îî ï °þXfí8ø FA ÉûŸ÷²ó$ðíŸêÖèÉççøç-éëí‹ðìó÷Tûÿ³ ’ ’ ØÌý¿ & K I:8Y³WÿOþ£ýSý\ý¶ýRþÿ ýã§4yk6 ÿÆýÄûžùm÷JõRóžñGðdïï<ï ðxñyóö ùuü$úÕ’ *ÅDZƒ’ã„‹ 2 Ù©ü¤øïô¨ñéîÇìOë‹êzêëSìîbðóâõâøäûÊþyÛÝq5 g . ˜µœaçÒòU aðU¨õ" Æ  ø e WÐÖvÃÿÒü¿ù¥ö¦óßðpîtìë1ê êœêâë×íoð–ó5÷+ûYÿ™ÈÁ `…ý*•;$Zò« BvÉýYúC÷Ÿô€òòðýï ïÔïð¿ñOó'õ-÷FùXûLý ÿ‚§qÝí«!`{‰ÿþÎý0ýÕüÉüýÅýÑþ3ãÏä ( " Ý A8­“á”± B VfœüÆøõ‚ñYîªëé èjçwçHèÙéìþîfò7öOúŠþÁÓ› ú Õ¬‘À?a*‘ ² ¬¥àþdüEú“øW÷”öHölöñöÈ÷Üøúbû¦üÌýÃþzÿåÿÿÿÅÿ;ÿiþ]ý(üÝú”ùdøc÷¨öEöIöÁö±÷ùöú;ýÖÿ³¸ÈÅ  ‰Ë[5_äÖ M fBýÒøÐô!ñåí:ë6ééç^ç˜ç’èAê“ìqï¿ò[ö&úúý¶;j* g (¢†áÁ; g _ =>¬ÿjþƒýúüÎüúüpý#þÿñÿàºhØüÉ9Koþ™ü–ú|øeölôªò9ñ1ð¥ï¤ï9ðfñ*ó}õMøˆûÿÑ¡_ ë !ã¡uˆ×e?u!^ N×ýºùàõjòtïí_ë[ê êqê~ë#íKïÜñºôÅ÷ÞúæýÁW’b¼œ  ö ƒ ¹¬q!Òš½6‹D:_Ÿãæ] o  @õ6ŒÄýÏúÉ÷ÏôòïcíÇëÂêcêµê»ëqíÏïÂò5ö ú%þ]’ [«p‘ý¨Ž²ãÖ ? t—Îþ6ûï÷õ¸òíðºï#ï$ï³ïÂð<ò ôö>ølú…üsþ „)p]úW„–¤ÿÂþþýEý]ýÐý þÊÿEôÿ  Î Ib§˜ó ¿ çoÀýøù;öªòhï•ìLê¥è³ç€çècélëî\ñõùNý·¢ . >º³!ÙæU=µÛ ͪ’£ÿôüú¯ø7÷:ö¸õ­õ öÈöÍ÷ùZú´ûüüþÿ©ÿüÿüÿªÿ ÿ*þýãû¥úsùdø÷÷Ýö÷Ö÷ù£ú¯üÿÉ®© l ÷!Ïíh5N·x  D €s@þ úøõ,òÉîìë¯é$èXçRçè‡éªëcî—ñ'õòøÔüªT²© " ^,´¸J‚ y JåáŸþ}ýºüWüQüŸü2ýúýãþØÿÁ‹"ux!naÿ[ýû‚ù|÷‡õ¼ó7òñXð$ððpñöò õ¥÷¯úþ²p+ À ðNrÏãM#€ „Q ÿÛúáö@óð~í‰ëEê¹éãé¼ê6ì=îºðó öËùñüõÿ».9Ïê ˆ ¬ ` ´ ¹„,És>=óÿ(­wxžÔù’Ѩÿ}Ž?¥þÒûäøöõ'ó–ð`îžìjëÓêéê¯ë&íGïòGõøøøü#Xp I ¾³ µ Ç)ÎÄúr ©Âáÿ&ü²ø¡õ óñ‘ï¾î‰îéîÑï1ññòøô,÷qù¬ûÅý¦ÿ<|\ÛûÄB†£®¿ÿèþ@þ×ýºýõýŠþzÿ¾Lûì ¸ F }G“T # §¶iÙþ%ûo÷ØóƒðíëBéè¤çôçéÔêOíbðóóä÷üV˜M DX¼h\ž;EÕ õ Ãy›ýûæø1÷øõ?õõ7õÓõÃöó÷Lù·úübýzþRÿßÿ–ÿäþ÷ýßü²ûƒúlù‚øÙ÷†÷–÷øùjú<üpþò±’x E Üð;ëôMõóS( Œ›yÿFû)÷Eó¿ï´ì@êyènç'ç¥çãèÓêbíxðöó»÷¦û’ÿ\å  êzk½v¢R› — ` Çš ïþ’ý”üùû¾ûßûNüüüØýËþÀÿ¡ZØïw¤}ÿþWü{ú‹ø öÓô?óûññ»ðßð”ñÝòµô÷êù!ýŸGø íítg°@o— ³ŒFüò÷+ôÑðîÎëKê~éléêYë;ížïfòvõ­øíûÿ¯ôÈ õ M . ¤ À –=Ì\Ôâ9ãÿßÿ-ÆŸ§Êô·&Ãï¨ôÜqÿÇüõù÷Nô´ñhï†í&ì[ë6ë¾ëöìÙî\ñmôô÷Ôûîÿ=* ÀànS}å†f‘¡ àôÿ'ýŠùGöxó2ñƒïsîî1îïî.ðÚñÚóöiøÂúýÿßYu-ƒ{­¼ÃÙÿÿ~þ0þ4þþDÿO©D ðÔ  ; Š yòèP& l + pQæÿKü ø õ¦ñ™îìöé‘èâçòçÄèTê–ìyïãò¸ö×úÿ`€Y ʵ©•ÆAAí.! å›bZþ™û8ùF÷ÑõÝôjôrôéôÀõâö:ø¯ù+û”üØýãþ¨ÿ< ŠÿÇþÐý¸ü“ûyúù»øBø$ølø$ùLúãûßý0ŇY » uXš0Tïù ˆ¹«ü_øjôÄðíéêèèžççUçVèêqìcïÊò„öqúmþS] H ¬{ª6$|O¯µ | ¹f?YÿÂý‰ü³ûBû1ûxûüÑü½ý¸þ«ÿ'Œ£dÌÞÿŸþýfû’ù¶÷ìõMôóòõñfñWñÓñÞòyôœö;ùCü›ÿ'È^ Æ Þˆ©(õSâ½õŸ Ú Åƒ;ýù'õ¡ñ›î.ìkê_éévéŽêFìŠî?ñIô‡÷Ûú"þ?–¥9 J Ù ê † ¿ ¥ P×RÙ^~íÿ°ÿÆÿ,ؽÈæÿÎYŽ_Ĺ@a(ªýúú4øsõÖò{ð|îõìúëëèëáì…îÌð§ó÷½ú¿þâ ³ûº×@èÉçI"Ê  *)7þuú÷ÿó}ñïAî–ííî8ïÊð¼òôôW÷Èù,üiþisfóìm±ÊÎÔòÿ9ÿ¾þŒþ¯þ)ÿûÿ‰*ðˆ ) Œ š <d › – %âfýÍù;öÐò®ïôì¾ê%é;è èèîéõë£îâñ—õ¡ùÞý)\U ð ™{§ÍÐ.üRN  ³]-ÿ;ü£ùv÷Äõ•ôêóÀóôÆôÕõ&÷¡ø.úµû ý[þVÿ^d„ÿ³þµý üˆû„ú«ùùÇøÜø\ùIú¤ûfý„ÿë‰Bü ˜ ù¯'ù ›r³ r ÉÕºý˜ù–õØñî©ëpééç!ççâçcé’ë\î¥ñPõ:ù?ý<–µ TaΗ¼E?»Ò œ 5 ºFôÛÿ þ˜ü‡ûÞú™ú³ú ûÐû°ü«ý«þšÿbó>8Ú%ÿÍýAüŒúÅø÷aõöóÛò%òæñ*òúòXô?ö¤øyû¦þŸ- ™ Ä׉Þl;RÀ˜õ ÷Àuþ9ú3ö…òMï§ì¦êZéÊèöè×ébëíðó\ö¾ù ýbkh8 † N ’ Z ³ ° e èTÀCñÝ›ÿxÿ¨ÿ$âÐÜð÷Úƒàã¯rÌÊzþðûEù”öúó”ñïÕí®ìì,ìçìLîVðøò öµù™ý¬ÊÑ š ðCèÏòOëÖ"éI cZTÿrûÖ÷ôâñ·ï*îBíí]íOîÂï¡ñÔó=öÁøDûªýÜÿÄV…Kª¨N¬ÕÜØßaÿþþèþ)ÿÁÿ«ãYü¶q … ¬ t Ê   î ¯ ç žäÍtþóúk÷þóÌðöí™ëÏé¬è@è‘è¢élëãíòð‚ôrø£üí/B  Q2žNA| þpy ; Ôgõü(úÁ÷Òõfôó"óCó×óÎôö÷'ùÇúUü½ýëþÑÿf¦‘-†ÿ¨þ§ý—üû¥úîù~ùdù­ù`ú€ûýîþ%š6Ýt Ý ûµñœ¨ ÇÜW I ÊöîþÓúÊö÷ò~ï}ìêNèGçç‡çÌèÇêdí‹ð ôø ü ¹ â ,Øß>û ¾ê½ R Ç7½tqþÃüvû’úúúGúÙú§ûü£ý¥þÿFÁñÍS…ÿgþ ýyûÌùøwöõÏóöò‹ò›ò1óQôûõ&øÅúÄý }þj ¢„óÔœkzÏu~ "ú±ÿkûM÷{óð9íüêqé èŽè6éê†ìïòñ-õ˜øütÿ¦ ¨ ª $  › ³ w þ_µ›TR ÿCÿ<ÿ†ÿäÙâêÛž P!ŠˆT6ÿÖüKú¯÷õ³òŒðÅîuí²ìŠìí-îùï`òTõ¼øü{‘›u ý—vœœv—ýu ›‘{ü¼øTõ`òùï-îíŠì²ìuíÅîŒð³òõ¯÷KúÖü6ÿTˆŠ!P žÛêâÙä†ÿ<ÿCÿ ÿRT›µ_þw ³ ›  $ ª ¨  ¦tÿü˜ø-õòñï†ìê6éŽè èqéüê9íð{óM÷kû±ÿú" ~uÏzkœÔó„¢j þ} ÄýÅú&øûõQô1ó›ò‹òöòÏóõwöøÌùyû ýgþ…ÿSÍñÁFÿ¥þ£ýü§ûÙúGúúú’úvûÃüqþt½7ÇR ½ ê¾ û>ߨ,â ¹  üø ô‹ðdíÇêÌè‡ççGçNèê}ì~ï÷òÊöÓúîþöÊI W ÜÇ ¨œñµûÝ t Ý6š%îþý€û`ú­ùdù~ùîù¥úû—ü§ý¨þ†ÿ-‘¦fÑÿëþ½ýUüÇú'ù÷öÎô×óCó"óófôÒõÁ÷(úõügÔ; y pþ |ANž2Q B /í£ürø‚ôòðãílë¢é‘è@è¬èÏé™ëöíÌðþók÷óútþÍäžç ¯ î   Ê t ¬ …  q¶üYã«Áÿ)ÿèþþþaÿߨÜÕ¬N¨ªK…VÄÜÿªýDûÁø=öÔó¡ñÂïOî]ííBí*î·ïâñôÖ÷rûTÿZcI é"ÖëOòÏèCðš Ñ Ê¬™ýµù öøòVðLîçì,ìì®ìÕíï”ñúó”öEùðûzþÊÌr¯ãàƒÚ÷ðÜÐâ$¨ÿxÿ›ÿÝñCÀTèe ° ³ Z ’ N † 8 hkb ý¾ù\öóðíbë×éöèÊèZé¦ê§ìMï…ò3ö9úuþÀ÷õ ˜ÀR;lÞ‰×Ä™ - Ÿ¦þyû¤ø?öXôúò*òæñ%òÛòöóaõ÷ÅøŒúAüÍýÿ%Ú8>óbšÿ«þ«ý°üÐû û³ú™úÞú‡û˜ü þÛÿôFº5 œ Ò »?E¼—ÎaTµ –<?ý:ùPõ¥ñ\î’ëcéâçç!çéçpé©ëîØñ–õ˜ùºýÕÉr ³ r› ù'¯ù˜ ü B‰ë„ÿfý¤ûIú\ùÜøÇøù«ù„úˆû üµý³þ„ÿd^Vÿ[þ ýµû.ú¡ø&÷ÕõÆôôÀóêó•ôÄõv÷£ù;ü-ÿ]³ N Rü.Ðͧ{™ð U \)Þý¡ù—õâñ£îõëîéè è;è%é¾êôì®ïÐò;öÍùfýâ%– ›  d<š Œ ) ˆ Âð*‰ûÿ)ÿ¯þŒþ¾þ9ÿòÿÔÎʱmìófsiiþ,üÈùW÷ôô¼òÊð8ïîí–íAîï}ñÿó÷uú7þ)* Ê "IçÉè@׺û³ â¿þ½ú÷§óÌð…îáìèëëúëõì|î{ðÖòsõ4øúúªý(a@¹Ä_ŽYÎÿæÈ½Ø,Æÿ°ÿíÿ~^ÙR×P¥ ¿ † ê Ù J 9 ¥–?"þÛú‡÷Iô?ñŠîFìŽêvéé_ékê.ì›î¡ñ'õù;ýƒÅÚ Ÿ õ½âSõ(©ˆÞÆ ^ È'›ÿCü;ùœöyôÞòÓñWñfñõñóòMôìõ¶÷’ùfûýŸþÞÿÌd£Œ'«ÿ¸þ½ýÑüüxû1ûBû³û‰üÂýYÿ?f¹| µ ¯O|$6ª{¬H ] Smþqú„öÊòcïqìêVèUççžçèèéêíÄðjô_øü«¹ˆù ïT0šXu»  Y‡Å0ßýãûLú$ùlø$øBø»øùyú“û¸üÐýÇþŠÿ <¨ÿãþØý”ü+û¯ù:øâöÀõéôrôjôÝôÑõF÷8ù™ûZþb›å! .íAAÆ•©µÊY €`ÿ×ú¸öãòyï–ìTêÄèòçâç‘èöéì™î¦ñ õ øKüæÿQp+ l & PèòyŠ ;   Ôð D©ODÿþ4þ0þ~þÿÙÿü­{ƒ-uYßÿýÂúiøöÚóÚñ.ðïî1îîsîƒï2ñxóGöŠù'ýÿôà¡ ‘f†å}SnàÀ* =îÿÔûô÷mô\ñÙîöì¾ë6ë[ë&ì†íhï´ñNô÷õùÇüqÿÜô¨ïÃ&·ôʧŸÆ-ßÿãÿ9âÔ\Ì=–À ¤ . M õ  Èô¯ÿíû­øvõfòžï;íYëêlé~éKêÎëîÑð+ôò÷üFŒ³— o@°gtíí øGŸ!ýêù÷µôÝò”ñßð»ðñûñ?óÓô ö‹ø{úWüþ}ÿ¤wïØZ¡ÀÿËþØýüüNüßû¾ûùû”ü’ýïþ šÇ` — › R¢v½kzê  å\’ÿ¦û»÷öóxðbíÓêãè¥ç'çnçyè@ê´ì¿ïEó)÷Fûyÿ›Œ( SóõMôë;ðÜE x ’±òpþ<üjúùø–÷†÷Ù÷‚ølùƒú²ûßü÷ýäþ–ÿßÿRÿzþbýü·úLùó÷ÃöÓõ7õõ?õøõ1÷æøû›ýyÃõ  ÕE;ž\h¼XDM ˜Vüä÷óóbðOíÔêéôç¤çèBéëíƒðØóo÷%ûÙþi¶§#  T“G}F ¸ ì ûL¾zÿŠþõýºý×ý@þèþ¿ÿ®£†BÄûÛ\|<¦ÿÅý¬ûqù,÷øôñò1ñÑïéî‰î¾î‘ïñ ó¡õ²ø&üáÿ©r úÄÎ)Ç µ ³¾I p X#øüøøGõòGï&í¯ëéêÓêjëžì`î–ð'óöõäøÒû¥þ?Ž}ÿ¨Ñ’ùÔžxw­(óÿ=>sÉ,„¹´ ` ¬ ˆ ê Ï9.»õÿñüËù öóºð=î6ì¼êãé¹éEê‰ë~íð@óáöÛú ÿQ„€ #MãÏrNð À + p²þ¯ú¥÷ õöòpñð$ðXðñ7ò¼ó‡õ|÷‚ùû[ýÿan!xu"‹ÁØÿãþúý2ýŸüQüWüºü}ýŸþáåJy ‚ J¸´,^ " © ²TªÔüòø'õ—ñcîªë‡éèRçXç$è¯éìëÉî,òøõ ú@þs€D   x·N5híÏ!÷l ©®Éÿ¯ü£úùÖ÷÷Ýö÷÷døsù¥úãûý*þ ÿªÿüÿüÿ©ÿÿþüü´ûZúùÍ÷Èö ö­õ¸õ:ö7÷¯øúôü£ÿ’ªÍÛ µ=UæÙ!³º>. ¢ ·Nýùõ\ñîlëcéè€ç³ç¥èLê•ìhïªò;öøùÀýoç ¿ ó ˜§bIÎ   ÿôEÊÿ þÐý]ýEýýþÂþ¤ÿ–„Wú]p)„ sþ…ülú>øö ô<òÂð³ï$ï#ïºïíð¸òõï÷6ûÎþ—t? Ö ã²Ž¨ý‘p«[ ’]%þ ú5öÂòÏïqí»ëµêcêÂêÇëcíïòÏôÉ÷ÏúÄýŒ6õ@ o ] æãŸ_:D‹6½šÒ!q¬¹ƒ ö  œ ¼b’WÁæýÞúÅ÷ºôÜñKï#í~ëqê ê[ê_ëítïjòàõºù×ýN^ !u?e׈u¡ã!ë _ ¡ÑÿˆûMø}õ*ófñ9ð¤ï¥ï1ð9ñªòlôeö|ø–ú™üoþK9ÉüØhºàñÿÿ#þpýúüÎüúüƒýjþ¬ÿ>=_ g ; Áᆢ(g * j;¶úý&ú[ö¿òqï“ìAê’è˜ç^çéç6é:ëåí!ñÐôÒøýBfM Ö ä_5[ˉ Šȸ³Öÿ;ýöúù±÷ÁöIöEö¨öc÷dø”ùÝú(ü]ýiþ;ÿÅÿÿÿåÿzÿÃþÌý¦übûúÜøÈ÷ñölöHö”öW÷“øEúdüàþ¥¬² ‘ *a?À‘¬Õú › ÓÁŠþOú7öfòþîìÙéHèwçjç èéªëYî‚ñõÆøœüfVB ± ”á“­8AÝ " ( äÏã3ÑþÅýýÉüÕü0ýÎýþ‰ÿ{`!«íÝq§‚ ÿLýXûFù-÷'õOó¿ñðÔï ïýïòð€òŸôC÷YúÉývB « òZ$;•*ý…`Á È™Yÿ+û5÷–óoð×íâëœê ê1êëtìpîßð¦ó¥ö¿ùÒüÃÿvÖÐWe ø  Æ  "õ¨Uða UòÒçaœµ˜. g 5 qÝÛyÊþäûâøâõóbðîSìëzê‹êOëÇìéî¨ñïô¤ø©üÙ2  ‹„ã’ƒ±ÇÅ*’ Õú$uü ùöyóxñ ð<ïïdïGðžñRóJõm÷žùÄûÆýÿ 6ky4§ãý ÿRþ¶ý\ýSý£ýOþWÿ³Y8:IK & ¿ ýÌØ’ ’ ³ÿTû÷ìó‹ðíë-éøççÉçÖèŸêí$ð²óŸ÷Éû AFø 8ífXþ°ï î έ©ÞýdûLù§÷|öÌõ–õÐõlöY÷‚øÑù,ûü²ý³þsÿçÿÕÿSÿŠþ‰ýaü%ûíùÏøã÷<÷îö÷’÷’øúìû4þËž“‹ j ^<GS®WS±‚ áëÃÿŠûg÷~óòïáìgêšè‰ç;ç³çéèÑêWíbðÕó÷oûOÿŒ¬ U vî@û-å: D  ã®—µÿÖýîüfü>ümüèüžý}þpÿ`9åTwC´ɉÿýý4üBú?øBöfôÆòzñ˜ð3ðYðñbòDô®öùÕüaÖ{ äñ‚~Ïg=P¦KTÙ ùÕ’VüCø~ô&ñVî#ìžêÏé·éSê•ëmíÃï}ò}õ£øÑûæþÇ\Tž i º – * ¸Uö±™¿/òÿn $V‹«¡V¸·He F›ÿÜüöù÷*ôñ'ï9íÐëÿêÕê[ë“ìwîýðôž÷„û£ÿØþò ޵H3dÒzb•%*Á *Atýáù©öãó¤ñúïíîîªîcïšð;ò-ôUö™øÝúýÿµÂî‡Þ"@ÿ„þþÅýÝýOþÿ@³eE<2 ´ ÿ{oÓ¢ ß “ Ìž$|üÃøõ®ñ•îñëÞéqèºçÄç‘èêZì9ï òröŽúÐþ0 va²WF|ýÔÈ îµ™þêû™ù¸÷Pögõüô õõUöq÷¿ø'ú’ûèüþÿ´ÿËÿ4ÿ\þTý-üýúÜùßøø§÷‘÷å÷«øåùûžý¯„jB î QN̶ü•}¸PU à öÆüø¡ôöð»íëé¶ç(ç_çYè êdìMï©òZö<ú-þ­þß <1¼¬ ãNb 9 î`O€ÿþÞüü¾û¼ûü¨üuýbþYÿD¦ùü§÷ðÿ˜þýü0ûGùY÷õÕóqòmñÜðÎðMñ`òô2öÞøóûZÿô¥I ¾ â˜ÂJ4ˆû6ã ! ωý`ùxõóñíîì»ê¬éWé¸éÈêwì¯îWñQô€÷Áú÷ýÊ66¼  I T ï *  Ê^ê„B6oøÿÔÿA8R{ oõ"ç>"—£VÂýþú$øQõ£ò9ð.îì›ë9ëëzìîjðIó¨ökúsþÆÊ ƒÑ–º)ØÀåO9ê A _hþÊúb÷eôëñð¸îîîî£ï*ñó8õ‰÷æù4ü[þDß ÿz”WÏ %,9bÿ¸þNþ1þjþüþçÿ#¦^9ô ¢  "È   rv$™ýòùQöØò©ïäì¤êéèÚçfè³é¶ëaîñOõXù“ýÛ Ÿ ¾I,[ÐŒ—þ×;E  ˇhÿˆüúã÷?öõxôTô¤ôZõdö¬÷ù˜ú übý…þgÿüÿ=*Èÿÿ9þ,ý üëúãù ùsø1øRøßøÝùKû!ýTÿуQ Ë ;RöŒa‰× Í "ÿý×ùÍõò§îËëŒéþç/ç&çâç[éƒëDî„ñ%õùýó»9P è ïY!GÔÕ[~ W  š<þÿGþèüìûUû!ûHû¾ûtüUýNþGÿ*åeœ <ÿ²ýüDújø˜öèôtóRò™ñZñ¢ñxòÞóÐõCø&ûbþÝy ‘ Éžò­¼¥x“Þ> A Âþ‡ú‚öÔòïõìóê¤éé5éêë¥í5ð%óVö§ùøü) ÂýÀ  Á ÿ Å  ! ÞnéhÿÅɺÿ°ÿøÿ‰YXp˜{!xoýÍü—þ÷û8ùtöÈóSñ0ï|íLìµëÂë|ìâíïï–òÄõ_ùKýeŒš j ÜÏ)ÔÃìPôæ; s —˜œÿÄû1øõLò&ðî·ísíÍí¸î"ðõñôqöâøOû ý»ÿ"Ö%² 09<M‚ÿíþžþŸþ÷þ¨ÿ¬ü‰BÜ  6 X+r * W 9ªþû‚÷ôÇðåí}ë©éè èWècé*ëží«ð9ô(øWü¡áó´ ÆçV EÜÛXp A êŽJ>ýú*øIöèô ô³ó×ójô\õ˜öø“ù!û›üëýÿÎÿIpDËÿÿ!þýûûíúúNùåøÖø-ùðù"û¾üºþ’Bý¦ KSy2Dº ¦ D4ÿû÷&ó¥ïì)ê`èRçç…çÂèµêJíiðõóÍ÷ÍûÓÿ¹`© z ¾glÌŒ·^–w  ¥)Æ“¦þýÖûû›ú“úâú{ûLü?ý@þ9ÿ»#=n‡ÿQþÚü4ûsù®÷ÿõ~ôDóhòûñòªòÔó‰õÁ÷nú|ýÓVæb §–ûAÓ§º»ÇN mFþÿ¸ûš÷Èóbð„íFë·éâèËèlé»ê¨ìïûñ(õƒøêû>ÿ_6©© ( ! • ‰ % ð ‚óZÐj<Sºÿvÿ‡ÿçÿŒik~Œ~?ºà£üèjŠVÿáüAú÷ìôqò=ðjîíHìì™ìÀíïûñõôdø/ü3RdG ×ó€f“ý ª, ¡ ÏÎÁÎüù³õÇòeðîxíúìíÝí$ïàðùòSõÒ÷ZúÐüÿ Õ+ŸÁ†ý7HED\¡ÿ"ÿîþ ÿ‚ÿMhÇZ Èu ú > + ¬ ² 3 ' ‘ wæð­ÿ8ü°ø7õíñóîhìgêéVècè/é·êñìÌï0ó÷ûeÿ­Õ¸ 3+‡5*aݨÑm˜o ¢? þûŠømöÏô¸ó(óóˆó]ôˆõóö†ø(úÁû;ý‚þ†ÿ;©bÔÿ ÿþýûûû8ú«ùpù“ùúûuü8þR±@äƒ þ :…f­OG—Ik [bKü8øNô±ð‚íÝêÛèççAçAèüéaìZïÌò–ö–ú¨þ¨së ò rY90ŠV¨— > ¹&Ÿ@ÿNýÛûÏú-úòùúŽúHû1ü5ý<þ1ÿþÿ“á߆ÙÿÙþ“ýüqú¿ø÷õBôFó±ò“ò÷òäó\õX÷ÍùªüÙÿ=»1 ~ ‚3®zây]œN Ž |:ïü¾øÍô<ñ+î²ëåéÐèyèßèúéºë îÖðúóX÷ÐúAþŠ‘<w 3 h  : ä  ÿ ˜ Y²%ƧÖÿWÿ/ÿZÿÒÿˆos}yOë;1Âé¦ÿ¸ý<û¥øö“óRñfïéíñììÐì¹íIïyñ;ô{÷ û ÿ, ÄÁÞHó×öX (Æ  ðæý ú|ö[ó¾ð¸îTíšì‡ìí3îÓïÛñ1ôºöWùíûbþ›ˆBWIä7URFFg½ÿVÿ<ÿxÿì‚»_è < E í # Ú ± Ó{¸ŸKýØùgöó ðbí8ë¤é»è‰èé^ê\ìï8òæõìù(þt¬« Oyú/¦^_¶w»ž ? ÁCèþÊûù¬öÒô~óµòtòµòhó}ôÞõs÷$ùØúwüìý%ÿ¯ôä„âÿ ÿþ ý ü-û‚úúúeú ûFüÏý´ÿäLÕd Ü !¥³. Aп òb†€ýqù~õÊñxî¦ëoéççççÙçZé‹ëZî¬ñbõ\ùvý‰u R 1´½J@±³` Õ /аÿ¨ýûû³ú×ùfù\ù®ùLú&û&ü7ý@þ/ÿîÿm¢„Iÿ5þãücûÈù+ø£öHõ3ôzó-ó\óôIõ ÷Dùíûïþ0— R eY ZîÅæ]>£ ªv*þìùàõ*òéî8ì.êÙèBèkèMéÝê í·ïÌò)ö¬ù5ý¡Õµ* # – | × ¯   ­  b¢òh Rÿðþäþ+ÿ¸ÿmonT ƒ¨nÏÈ[’|þ(ü¯ù*÷µômòmðÑî¯íí!íÌíïñ™ó¦ö úìýçòè ¥ î>äÍòQïØ!à5 A& ÿûZ÷ô1ñíîKíRìì]ìQíÏîÁðóšõHøúú•ýÿÿ!ìQK×ú½-^aO<?lÖÿ†ÿˆÿßÿ‰‚½*·MÓ2 Q  ~ h Ò ¶  ÷jPþ÷ú“÷Eô-ñjîìYê9éÊèéêßëLîQñØôÂøîü7z‘ Y °|¤ÐÆŠtÕÊ p èVÙÿ‘ü˜ù÷ïô^óYòâñóñ€òyóÊô\öøàù û?ýªþÐÿ¦%M!©õÿÿþý,ühûàú¥úÅúHû1ü€ý-ÿ+iÑK»  ¶ì˜­ î° ½ YŸ¯þªú²öîò~ïƒìêXèPç ç‹çÏèÉêií—ð5ô#ø>ü`g0› Œî°È3ö¯Éƒ ÷ C…ØXþ5ü²úšùòø¶øÝø\ù úû+üEýOþ4ÿãÿLf,ŸÿÁþžýEüÇú;ù¸÷Uö,õSôÜóÙóTôRõÔöÔøFûþ3}Ø$ AmE€ ßöUª Эhÿ!û÷)ó¼ïÖì‘êýè%èè·èêì¡î¢ñøôøü¨ÿÃù © Ë ^gï  ¾ 0 s Òœ[iÿÌþ‡þ™þúþœÿpcaQ ¸ ›Ï *ÿý«ú>øÕõ‹ó}ñÆïî»í‹íûí ïÁðóæõ2ùÙü¼»²} úˆfó’nï_ y_7%üJøÉô½ñ>ï]í%ì›ë¼ë€ì×í®ïìñvô/÷øùµüKÿ¡¤Ez?–…`o\<&0kéÿ²ÿÏÿ? P¾?¾" S ; Å à   < ZLFÿ ü»øsõSò}ïí!ëÎé%é2éûé|ë®íðÙó¢÷¹ûûÿBlR ÓÒ4çß‹Jaåñ¡ tÚkýBúz÷'õXóògñEñ§ñò»óDõ÷Ýø¸ú~üþtÿ‚=ž§_Ð !ÿ'þ2ýZü³ûOû=û‰û8üLý¿þˆ˜Ü; å ø ºí7äñ\- r >«Öÿßûê÷ô‘ðsíÛêâèççXç]èê‹ìïóíöû0ÿL7Î ô è‘ŒâŸØ£ ` Á©þŠüËúxù–ø%øøwø"ù úûAüaýhþAÿÝÿ./Üÿ6ÿEþýºûDúËøg÷/ö;õŸômô±ôuõ»öø·úVýEo´÷  össߤµ «˜ã  éߣ[ü+ø7ô¢ðŒí ë;é$èÍç8è]é.ë—í~ðÇóQ÷ùúŸþ `C³ ¡ Î Àù Ê G ‰ ©Áê:ÄšÿÂþDþþNþÈþ~ÿ]RH)ÞU~M»ÅnÁÿÉý™ûHùðöªô”òÈð_ïpî îCîïðžò<õWøÕû›ÿˆ{O á½Ð3ظÓ0Ýî ­ škFýLù¡õbò¨ï‰íìJë1ëÂëîì¥îÎðQóöêøÄû‚þB;õZ{lDc÷ÿÚÿšpˆÒ;¬M M ù B  o H ¢‡)ýÛùžö~ó™ðîýëyê™éiéòé4ë(íÁïìòöŒúÀþ== ä«›ÓIþõ=éÐ I œëYþûøyõmóïññ«ðÞð‘ñ³ò.ôêõÏ÷ÂùªûoýþþD9Õÿœ÷#4ÿ>þWý•ü üÌûãûYü2ýkþýÿÛö7…Æ ß ´+-©Ù‚‘  ¦ñý!ùKõ°ñrî¯ë„éè?ç?çè‰éÁë˜îöñ¼õÈùøý%-ì D VíÕ –€Ü¾B „ ¢ºêMÿøüÿúpùSøª÷r÷¢÷-øù ú5ûgüŠý‹þVÿÞÿþÿ‘ÿÕþÕýžüDûÛùzø9÷/örõõ'õ³õ¼öCøAúªülÿn™Îí Ök)$q敃 õ Ü—ý]ùRõ›ñWî£ë”é=è¦çÓç¾è\ê›ìcï™òöÎùˆý)”ªT ~ $™àÎ \ ¢ º¾ÇîGåÿÓþþ½ý¸ýþ˜þ_ÿF<(õäæŒÑ¶?{þvüFúøÈõ¯óÓñOð9ï¦î¤î=ïtðGò«ô÷âú†þ\D ¾ ß#¿¢Ã¸Ý“Ú Ô¥rþ]úŒöó,ðÑíìë¾êëì§í·ï,òéôÑ÷Äú¦ýYÇ݉ŊÜÂI€|RêØöUüÿKìÓõ@ ý@S  • % 9 Ðð£ú þðúÅ÷©ô¼ñïéì9ë%êºéêë¼ìïò‹õhù‰ýÊ ã < 5¬cVŠÞ&ü | ÊXÿÚû«øæõžóáñºð(ð)ð²ð´ñóÐôºö¿øÄú±üoþíÿñkŠUÖ=Kÿ[þ„ýÛüqüVü”ü2ý0þŠÿ5#@vª à ¤ 5\"¦ŽÛ • Ë7þVú€ö×òï—ì;ê„è‚çBçÆç é ë²íèð’ôø½üõø} ˆ×þr5PÓÒf« ¿ÁÐýNûƒù*øH÷ÛöÞöE÷øýø&úcûžüÁý¸þsÿåÿÒÿNÿþrý8üäúŒùGø.÷UöÒõ´õ öØö#øåùü¥þ~Šª ± Yœ_ép/Rñ %Ôþ•úyö£ò6ïOìêrèšç‡ç5èé®ëSîqñêôøfü#´úÚ @ b*¸Çl ½ Ò Æµ¶àIÿþ þtý9ýVýÀýiþ@ÿ. ¸5hDÃã¦ÿ@ý6ûùâöÌôæòKñðTïï}ïvð ò2ôàöúý8æ“ öïa3S³O(Fº™ÿ á¥ÿ|û‰÷îóÉð3î>ì÷êdê„êOë·ì¨î ñÁó¯ö¶ù·ü”ÿ4iààh } * }‰c"ݪŸË?4*Sšì0P4 É ý   ã?+¶óþùûåøÓõãò4ðãí ìÇê$ê1êóêjìîNñ˜ôQøZüÎñÓ SR¶jb•ºÂ0 ¯ þ/eÄügùlöéóïñ‰ð½ïˆïãïÁðò·ó¡õ²÷ÏùßûÊý|ÿâó§þú¥ BXeÿ~þ¹ý*ýàüéüNýþ1ÿ¥cXp“¦ 3zNZ  o gÿUÿ†ûµ÷ô˜ðíëéßç_ç£çªènêßìêïsó[÷ûÀÿñó¢ à“§ ¿½ ¼Ü…Ó ã ÕÆÖþ·û±ùøþöZö,ökö÷ò÷ùXú¦ûæüþðþ˜ÿòÿùÿ­ÿÿ4þýåû›úYù4øE÷ öWöxö÷ø£ùšûõý ‡š ‰ >›ƒà¯ µ± Û 5; Ðû¨÷ºó(ðí“êÁè©çUçÅçôèÓêPíQð¹óh÷;ûÿÁ3H è …pÀ~´uÕ í Ø±‘ÆEÿþDýÒü»üúü€ý?þ"ÿÒsÓã›õòšÿöýüúö÷çõýóQòüðð®ïÕï“ðéñÓóHö6ù‡ü ä°b Øï‹éˆe}Ø‚ < Ý¥ü•øÓô}ñ®î|ìõê#êêœêÖë£ííï™òˆõø¸û»þ‰ .á Ý % ü p ‘t0Û[Z˜!þÿ,«rtŸßF?óP G ÍÜtš[Èÿôüûùøö ôRñêîñìë§êxêüê2ìî ð¸óH÷3ûXÿ’¾· Y…EºiX“,<Þ 3 ]€¿ý8ú ÷Nôòsðjïýî&ïÛï ñ ò„ôœöÍøüúýòþÚÉYŠcï>cqÿ¦þõý€ýWýƒý þñþ-¸‚xƒŒ v ) ŠƒõUR û (íf¯üéø7õ»ñ–îèëËéUè—ç›çbèèé"ìýî`ò.öGú…þÃß³ ! [ó.µ“Úžû ò̹Õþ9üúù(øÏöñõõ¡õöíöøHù¢úüû?ýVþ2ÿÄÿôÿÿâþõýÛü¥ûjúAù@ø~÷ ÷ÿö^÷2ø|ù8û[ý×ÿ”~wa Ž—[ö߯± 7 \B ýÞøÜô*ñêí7ë*éÓç>çoçbè ê[ì:ïò2ö úîý½Xžv Ë Žµ@1’sé ñ ¹|V\¥ÿ=þ0ýƒü7üFü¥üGýþÿüÿà (jXì%•þâüÿúù÷õ_óóñèðUðGðÊðâñóÈõ€ø¢ûÿÀ~/ ± â¢ÖgC_¸Q4s$e VÖý°ùËõGòCïÕìëýé¤éÿéë¬ìØîsñ^ô|÷¬úÏýÈ}ØÇ? : ¸ ½ V ’ „Bâ~+ÿ \ÿÿôÿ;Ϧ¯Ù8?‘¶q¹ïè‡Þýûø3õuòüïåíJì@ëÙêëì¼í ðìòOöú&þV† O£o˜Ã²ÞPLh ‘¦ÊþûÀ÷ÍôZòxð1ïŠî~îïðñhóõÀ÷úAüPþ"¦Ñ› Â0i‰žÿÐþ4þÜýÓý"þÌþÐÿ$¿Ž~u\  Ž ¨Qx‰ n ÓÉhÏýújöäò©ïØìŽêãèêç®ç4è|é{ë"î[ñ õùHý޾³ L jõÚ …FYÊ®8  ß­¡ÿÓü]úPø¹ö¡õõéô<õñõöö5ø—ùûgü§ý³þ|ÿøÿõÿzÿºþÃý¦üyûPúDùiøÖ÷›÷Ç÷aøpùðúÚü"ÿ³z\: ù xœJkîÆîg9r & qpGþúö;òÔîñë¬éèCç3çèçYéxë1îgñþôÓøÄü«iÝë { {á§Ï_fö&  Ëw. }þ6ýNüÊû¦ûÛû[üýúýñþäÿ½jÙüÉ<Vÿ›ýàûúø1ösôôòÌññÐðñ÷ñfóbõá÷Ñúþ¦Qü… É©Íã?رÐC!ƒ ŠVÿÖúÒö&óïïGíDëòéYézéLêÄëÎíQð3óTö”ùÓüóÿ×i“G ~ 3 k . ‰ Uñ{ ¸•±ÕÿäÿBëÎÝ(8¿ü}Œ*]1¶þü.ùWöšóñæî'íïëRë\ëì|í‹ï6òiõ ùýüK` 8 °ª ¼±áLøòO(› ÈÔãÿü‹ødõ·ò˜ðï.îëíAî&ï†ðNòbô©öù_û™ýÿX½Âc¡„g‹–ž¹ÿüþwþ;þRþÂþ‹ÿ¨µ„fC  ˆ ¾ ä´õ ¥ Ç e[ãþCû÷ôÇðØífë‰éVèÛç"è)éìê\ígðòóß÷ üT“¤d ³v˜ ÂÀ ©³=b B ü±…ýÙú‘ø¿öjõ˜ôFômôÿôíõ"÷†øúûäüþÿÏÿ1?ûÿlÿœþžý‚ü`ûMúaù¯øLøGø«ø~ùÂúrüƒþå…J Ó \•d±i|⛪ w”}ÿRû:÷XóÐïÁìFêwèbçç‡ç½è¨ê5íKðÎóœ÷’ûÿiG  NóöVKú>- ä ~Ê®ØþVý4übaresip-1.0.0/share/soundstar.wav000066400000000000000000001047741372575704200170310ustar00rootroot00000000000000RIFFô‰WAVEfmt D¬ˆXdataЉÐˆ U?¾Â?-†J{Aì1# Õ\ÐHþØú–÷–ôéñ ïÆíeìƒë#ëDëãëùìzî\ðòõ¦÷eú/ýðÿ—XW  \ V ð , “ Ì À x  lÂgÎUÿþÚüçû,ûªú`úLújú³ú"û¬ûKüóüý?þÑþMÿ«ÿèÿôÿÂÿoÿþþtþÙý4ýŽüñûdûóú¤úúŠúÉú@ûïûÕüïý8ÿ¦4Ö€&º/ x ˆ U Õ ÿ Ï A T i x@Í/wý³úö÷Uõàò©ðÁî7íìnë?ë‘ëeì·íƒï¿ñ_ôU÷Žú÷ýz}Î á£ëT1|2Säî{œa Þ)[ŠüÎø?õóñþîtìbê×èÚçqçŸç_è®éëÌíðˆóÓöKúÙýfÝ(2 ë B*™Š÷ãPEÌðÁ O ¬éQ¡ýûÉø¾öõžó—òðñ©ñÀñ0òðòùó>õ³öLøûù³ûfýÿí ætÈåÏ‹!˜ùN ÷\Øo&(p×YíŒ/ËXÍ!NKª- ä€ÿüýcüÀú ù÷öÑô½óêòcò/òTòÖò¶óòô†öjø–úýü’ÿC¹Z Ð ÷‰²h£^™U˜iÕ ë»ZÛþTûÜ÷ˆôpñ§î?ìJêÕèêççËç›èûéäëJîñQôÍ÷}ûJÿÛo Ä ÂYx•wă»{ÐÌ … ~íþpûøõCòßïèíkìlëðê÷ê~ëìïíÄïïñ_ô÷Èùœülÿ%·, õ g { .€s R O — ûHŠÏ$”ÿ(þéüÝû ûpúúëùùù7úú$ûÃûpü#ýÒýtþÿvÿÊÿúÿìÿ¯ÿRÿÚþMþ³ýýyüëûsûûçúáú ûmûüÒüÓýÿ[Õeœ)œ ç þ Ö e ¢ ‡  >  ‰ ±’6¬þKû–øøõóDñQï¸í†ìÅë}ë´ëkì íPïqñøó×öýùWýÐTÌ! >ùb5u#Iï%ü ‡Ü?ý}ùãõ‡ò~ïÜì°êéîçgçvçèNé ë@íâïàò$ö™ù*ý¿Bž¾ Ž ÿ'-²½U‡aó O ‡¯Øþzûùíöõ—óvò¶ñXñZñ¸ñkòjóªôö¼÷tù7ûúü¯þJÁ %ªD>¥ ‚Òg¼%§H õÿ3†õ{ªCÑL©ãñÏzî-8ÈÿYþÒü>û¨ùø®öbõHôkóÕòòŸò óÐóñôjö5øHú˜üÿ¹j· . nfBb8hÇ´: f J÷„ÿüŒø5õò=ïÄìºê,é%è¯çÌç}èÀéëÙí˜ð¸ó%÷Ìú”þf+Ê . @í&Üœ›ß0kt 4 À.–ÿ ü©øõ£ò%ðîxì]ëÄê°êë ìhí/ïPñ»ó^ö(ùüãþ­TÇùÝ i ˜ eÏ×‚Ö Ü Ÿ + Ò>€ÛÿWþýÛûïú>úÉùŽùŒù½ùúœú:ûëû¥ü`ýþ²þ:ÿ¥ÿíÿèÿ ÿ:ÿ½þ.þ˜ýýrüöû”ûTû>ûVû¡û!üÖü¾ýÖþ|ù…š V r T ñ ? : Û !   ãݘ"Šþàû4ùšö#ôáñäï=îøì"ìÂëÞëyì’í$ï*ñ—ó_öqù»ü)¦t ™ v÷ ¦º?1[œ\©“ - ŒÆõý.úŠöóðKíëBé èdçUçÜçõè—ê¸ìIï9òuõçøzü¤B * µÕ~¨Op/Úÿ˜ ô )Gd’þàûbù#÷2õ˜ó\ò‚ñ ñùðEñéñÝòôŠõ*÷èø·ú‰üPþŽò#ÙYž©'¨ XšÛ"yæqîÿäÿÿÿ;˜ •'¼JÈ.s’ƒBÎ%I=¯þ;ý·û.ú¬ø?÷óõÔôîóKóôòðòCóñóøôWöøú:ü¥þ4Ø~ Ñ ÑÌ­ ~sî÷— Û Ó‘)°ü<ùãõ»òØïNí/ë‰éhèÕçÔçgèŒé=ëoíð#óöúßý°y" “ ·{͟暸@5Ÿ‰â rß@­ü:ùýõ ósðFîŽìUë êqêÆêšëåìœî²ðó¹õ†økûTþ/êt¾½ d ® •5óWh 2 Á _‹²â'ŽþýáûÛúú†ù8ù$ùFù™ùú±údû%üêü©ý[þøþxÿØÿ)èÿ•ÿ(ÿ§þþ‡ýúüzüüÆû û¦ûÜûEüâü±ý±þÛÿ)“‘xÄ å Ï y Ø æ ü  °  ó’ ÿpüÏù:÷Äô~òzðÆîpí…ì ììŽì‹íïêð=óíõëø$ü†ÿúlÆ ñ Úk”Ft%¡‹èÃ(& Ð :{«þáú4÷¼óðÀíbë‚é-èjç<ç¦ç£è,ê6ì´î–ñÈô5øÈûiÿ{Á ¿ cžd¬o¬dœ[¬œ; š ÌäôÿNü¸ùb÷Võ¡óJòVñÇðžðÖðkñSò…óõô•öYø2úüëý¯ÿTÐ,˜òô§/”àSŒÒ,¡5ïÿÍÿÐÿøÿ@¤§6ÂC°-0¦R_@þþžý+ü¯ú7ùÐ÷„öbõtôÅó^óFó„óôõKöá÷Áùâû8þ´Iåvë 2 ;õRHËÖdv3í I V&Ë\ýëù‘öcóvðÝíªëíé²èèäçZèaéôê í›ï“òáõpù+ýúÆvô *mZ¾‘Ír„ ”»Ž $‘îQýÐùöyóÉð€î¬ìVë„ê8êsê/ëfì îðsòõá÷ÍúÂý«y|• X ¼ ¾YŽ_Óò Ä V µ ï+J|ÌþDýîûÏúíùKùçøÀøÓøùŽù'úÛú¡ûpü<ýÿý®þDÿ»ÿ<D(êÿŽÿÿ˜þ þ‚ýýü;üüüûüpüõü¬ý“þ¦ÿÝ3„é3 W H ý l Œ Z Ð ï ¸ 0\Gü‰ÿüüfúÙ÷eõóñRïìíîì_ìHì¬ì‹íåî²ðëò‚õjø‘ûåþP½ H :ÚÞ&䪲-# ³ n å.aÿ•ûà÷]ôñ<îÅëËéYèwç,çwçWèÆé¹ë$îöðô„÷û»þ[ã: N `B§ˆá´×97Þ A qƒ‰™ÿÁüú§÷‚õ²ó?ò1ñ‰ðHðlðïðÊñóò_ôÿõÈ÷ªù–ûýXÿ¦ 4"Ñ?pe$´i¡Ïü2yØV÷ÿ½ÿ©ÿ»ÿïÿA¬*±;½/‰Ä׿wþSyrFÿûý™ü,û¿ù^ø÷ñõüôBôÌó£óËóHôõGöÂ÷‰ù’ûÑý:¿OÙK ” ¢gÔÜv™Cq&g< ± Ô¶jþšú@÷ ôñoî*ìWêé8èýçTè=é´ê°ì&ïòDõÆøyüDÈR —„ÚËjƒ#Y8 ÕDžùýkú ÷îó%ñÂîÑì^ëoêê'êËêìëí}ïÑñlô;÷,ú+ý"¸3e C à ß”àÇMyU ì L ‚œª¹×ÿrýüËúÐùùœøbøeøŸø ùžùRúûòûËüœý_þ ÿ—ÿHhb8ïÿ‹ÿÿþ þ†ýý³üsüWüfü£üý¯ý}þxÿ˜Ù1—þ[£È ¿ ~ û -  Õ ¸ J‘”_„ýúúuøö¼ó«ñáïmî\í·ì‡ìÐì”íÑî‚ð òõð÷ûHþ¨i ˜F”qÒªô¬Òj|; àJüøõ´ñ½î/ìêŒèç#çPçègéBë˜íYðsóÓöbú þ²F®Ö ª›™ýeOÃÎ€è  %"#;ý{úõ÷¶õËó=òñQðùïðxðEñcòÉóhõ4÷ùûýùþÉtð4;‡ËÑž8§ô(Np—Ì~µÿ‰ÿ„ÿ£ÿãÿ>¯/´6­VytBàM‹ˆÿQþý¥ûDúëø¥÷€ö†õÂô?ôôôô:õJö«÷XùHûqýÇÿ:½>« ô ×QkWd6“ƒ  KA«þFûî÷¸ôºñï°ìÈê[éuèèVè!ézê[ì¸îƒñ¬ô øÈûÿ\¬ ™»XfßÀ Æ÷¬ôà … øO¤þ ûš÷iô‰ñ ïÿìoëbêÝéâémêxëúìçî0ñÅó”ö‰ùü–ÿ†Pâ. &  ùÈ-)Áýä ‚ ä  *--9^ÿ¨ý üÏú»ùèøWø øú÷&ø‡øùÇù”úqûTü5ýþÈþlÿïÿL„•€J÷ÿŒÿÿþ þ•ý/ýãü¸ü´üÜü2ý¹ýoþQÿZ†Ë {Ð9 5 ü † É ¿ c ´ ± ]½Ú¼qþ‹ûù¤ö[ôEòrðñîÏííÍìýì¥íÅîZð\òÁô{÷|ú°ýdºò ô ® þwjЦêŸÍ}½ž 2ËÿüAù¨õMòDï ìrêÇèªç"ç1ç×çéÑêíÀïÍò$ö¯ùXý¥X CÍ熢5>ÀÁIc Ž À Ê¿³»ýçúIøñõëóBòýð!ð°ï¨ïðÃðÖñ4óÐôžöøú—ü”þy;Ï-M-É!9¹/~±Ñè%\­µÿqÿTÿ^ÿŠÿÖÿ9®.¯)’ä#º?•¿Âÿ¡þfýüÅúuù4ø÷öFõ¶ôkôkô¼ô_õVö÷/ùûýYÿº/¥ U m DËö¹ ëP>·à k ¼Ç›Nÿñûœøeõ_ò ï:í=ëºé¹èDè`è éIê ìPîñô}÷ûÛþ¦f e w&`DÜÜEe1‹… 4 «Qÿ­û.øêôóñ\ï4í‡ë]ê»é¤éêëvìSî‘ðóìõãøòûÿáŠï  ¹ õs†2}q | ® ¼´¦¡²ÿäýDüÚú¬ùÁøø¶÷”÷±÷øø<ù úíúÚûÈü¬ýþ9ÿÓÿH˜Á ]‘ÿÿ•þþ­ýWýýýý\ýËýhþ2ÿ$9k¯üH…©© x ` i # ‹ ¢ hâÜ„þü¦ùA÷úôáòñyïFîyíí0í½íÁî:ð òkô ÷ùùýbº E N €†"¥˜úÍâ:/ Ó<µýóùSöêòÐïíÏê éÏç)çç¢ç¾èfêì+ï)òvõüø¤üX†Ô Õ x®j£Sy.Êõ¾4 i q_G@þYû¥ø4öôOòîð÷ïmïNï˜ïDðJñ ò8ôöû÷úü)þ"ú§XPrˆ8¶ ;Veq„¨ä>¼ÿ`ÿ,ÿÿ8ÿqÿÇÿ1ª(£n®ÌÂ)˜ÛõÿêþÃýˆüAûüùÁøž÷žöËõ0õÖôÄôõŒõiö–÷ùÌúÆüñþ@¥q· Ñ ¯A|S½´4>Óû ½ ' F,íÿšüIùöó=ðÈí¹ëêétèrèéêÇëïí‹ð‹óÞöoú(þð³W Å è¬ÿÒÑïvhͰ(á ^¶TüÇøpõdòµïqí§ë`ê¡éméÃéžê÷ëÃíôïzòCõ<øPûmþ|l+¨ Ö ¨ ²Ýúûª  F P?% )þpüíú¦ù¡øâ÷h÷4÷@÷‰÷ø²øùfú\ûVüJý0þþþ°ÿ=¥åþð¿q ˜ÿÿ þ.þÎýˆýbýbýýäýiþÿõÿôC‚Âù ñ ‘ ò Ü \ ‹ kOaAüþžü9úÜ÷˜õ}óñðÃîãíníjíÝíÅî"ðìñô¦ö|ùüÆÿ`˜ ¦ tð­Ór‚óZ?°º p æ1kþ§ú÷Œóað“í4ëSéýç8ç çuçtèêì›î‰ñÊôIøðû¨ÿXëJ a mFœj¬d”FƒZØ  àÊþÑûù~öCôdòçðÕï1ïúî/ïÉïÁð ò ómõe÷yùšû¸ýÅÿ³w[l8¼û÷´;”ÆÞååéú!eËÿWÿ ÿçþëþÿXÿ·ÿ'¡‘õBoxX “î-ÿþñüºûúLù,ø+÷Sö®õFõ#õJõ¿õƒö–÷õø™ú{üþË Ø 4 µþçfv6è+ ‹ À¹‡@ýõù¾ö¯óÜðZî9ì‰êVé«èŒèýèþéˆë•íðóCöÆùvý;ÿ©" U-—…ê½úŸ®.)¬Æ‹ j±ýüdùýõÜòð¶íÐëjêŽé=éxé:ê~ë7íZïÖñšô’÷¬úÒýïñÅZ ¢ 9ê-s‚<¬ à æÎ¨‚ltþ¤üû§ù‰ø±÷!÷ØöÔö÷ƒ÷'øôøÝùÚúßûâüÚý½þ…ÿ*«29Þ…¢ÿ'ÿ±þIþöýÁý¯ýÄýþrþ ÿÎÿµ½Ý @oŽi  € ¬ % m g~¨Ÿnÿ!ýÉútø5öô4ò“ðCïQîÇí¬íîÑîðÀñÕóFöùü-ÿn¶ìý Ó\…?~7d”– @ â ÿ\û¯÷0ôöðî ë¥é2èOççOç1è£éœëîìð ô˜÷<ûöþ­L» æ º%xØ«õ½ ò|» ç}ZÿOüqùÐö{ô€òèð»ïüî­îËîRï;ð|ñóÓôÎöéøûBýaÿd@èV€e T a - ¿Rhh^SSf“âÿVÿñþ·þ¤þ¸þîþ@ÿ§ÿ– yÑ )è‡úChÿkþTý-üûÕùºø¸÷Üö/öºõ‡õšõùõ¥öŸ÷ãønú7ü5þ\ ñ@~ ˜ € %{v 1æ&ôSL è 4@ãýŸúj÷Xô~ñðî¾ìúê¯ééè®èéäéQëBí«ïò­õ!ùÇü†Jù| ½¨(0±¢ýÁí‰5a4 ÁdªýúŽöYózðîì}êƒéé4éÝé ë¯ìÂî3ññóèöú3ý]pX f n OxeçÌD z  a0üÓÆþßü*û°ùxø‡÷àö‚ökö—ö÷ž÷gøSùVúeûuü~ýuþSÿ¨_|rEú˜&®ÿ5ÿÆþiþ%þþþ-þ‚þÿ­ÿ}o|›Âçß F < è G Z#¥èöÚÿŸýTû ùÐö¶ôÍò#ñÇïÅî&îôí3îäî ð›ñ•óíõ•ø~û—þÍ @S 0ÄýÌ"õ>ù&Çå‰À œ 0Ôÿü`øØôñîìýénènçç2çöçMé,ë‰íSðyóçö‡úBþÿ©' f PÕåvüëP/“ˆc m OîÿÓüàù)÷»ô¥òñð¨ïÎîeîmîàî¸ïìðqò8ô4öUø‹úÆü÷þÂI‹> § Ç £ @ ¦ßóîÚò±É\ÿßþþeþdþ‰þÌþ)ÿ˜ÿˆú\§Óܼsþ`œÿµþ²ýœü|û[úFùFøf÷²ö2öïõðõ9öÎö¯÷ÙøJúúûáýôÿ%g¬ãü æ ”ö¨æ³ùtˆ = ¡Â±‚þGûøõ"ò‰ïHípëê.é×èéÒé"ëöìEïòõ€øüÔÿ•GÓ !´ÔqùÚ%Ü ¹øÙ p ÓYþªú$÷ÝóçðVî8ì˜ê€éõè÷è†éšê,ì.î“ðIó=ö]ù’üÈÿéå¨# F _F¼ÀWˆZÚ   ö¼zAÿ"ýTûÁùoøe÷¦ö2öö$ö€ö÷Û÷ÇøÎùæúüý'þÿîÿž'…¹Ã¨lª3»ÿFÿàþþZþHþ\þšþÿ•ÿM)!/HcutT ‘ Û ã ¤  G)Å!F>þÜûùi÷Rõgó¶ñNð=ï‹îCîhîïðñ]ó›õ+øÿúþ/f•¨ ‹ )rSÀ¬é4ó-ë:+ Ï;…Æüùƒõ.ò*ï‰ì\ê²è•ç ççÃçýèÂêí¿ïÖò9öÓùýOß à}©W~$£›½  ùÀ…\ýWúˆ÷õÑòñï¨î%îîsî:ï`ðÛñó™õ¾÷ýùEü†þ±º”4“©u ô (  ¿ . k€v[7%jÿÕþkþ,þþ(þ]þ®þÿ‰ÿyä;x“‰WûtÈÿøþ þýôûßúÐùÓøò÷7÷­ö\öLö€öþöÆ÷×ø.úÅû”ý‘ÿ¯âK` M m†@”zðõ¼ Œ >?ÿíûÀø­õÈò%ðÖíëëtê{éé"éÉéûê²ìçî‹ñôã÷pû"ÿà”' Ž9q)TììT(p7Š{  ‡Í ÿSû¿÷fô[ñ±îwì»ê…éÜèÂè5é1ê­ëíõï¢ò’õ²øíû-ÿ^lEØ  ófiùÂåp° µ ŽLþ´ÿký†ûÙùnøJ÷röèõªõ´õööO÷:øDùdúûµüÑýÙþÅÿŒ-¤îÙŽ,º@ÈÿZÿüþ¸þ“þ“þºþ ÿ„ÿ$êÍÈÒáìçɆ l … Z ç+'ÝRž‰þ^ü,úøíõôJòÙð¹ïõî—î¥î"ïðjñ-óPõÈ÷†ú|ý•Áëþ å ŒâÕW]ÝÑ9mF®´ jä6{ýÅù0öÐò»ïíÂêþèÄççç—ç´è_êŒì/ï5òõ ùØüXòT if1u-Vñ‘©Y± à ¤g"êýÓúï÷Põóñ™ïˆîëíÂí î¿îÖïFñóýô%÷kù¿ûþNm_À¥ ; „ ‚ : ´ ÷ ß°\ISÿÒþPþúýÏýÎýòý6þ”þÿ}ÿ÷ÿhËEP4ï‚íÿ4ÿ[þiýgü^ûXú_ù}ø¾÷+÷Îö¬öÎö5÷å÷Ýøú˜ûOý5ÿ?bŽµÆ ³ k áÔ<:Êêè Ó g´È¶ÿüiùXöoóÃðgîlìßêÎéAé=éÇéÛêvìîñ ôJ÷Éúrþ+áy Þ ú¹Ú!×õ|mÐ¯È 9ƒ½ÿþû^øôôÕñï¿ìæê’éËè”èëèÎé3ëíYïüñçôøEûþÍíÛ† Þ Öe„/d'}mJ R ) ߆-æÿ¼ý¿ûùùtø7÷Fö¤õQõIõŠõ öÄö¬÷¹øÞùûHüvý’þ”ÿs,»R^B¬?ÇL×ÿnÿÿåþÐþàþÿ{ÿ±gace\=þ”ø! ­ í|ÑööþÜü·ú•ø†öšôàòfñ9ðeïòîèîLïð]ñó õl÷úöü CS = ìOR顲71¥š8  ‰å/þyúÞöuóRðŠí/ëPéûç6ç çsçsèêì¤î™ñãônø#üêÿ«PÂ ì ºd:€7b4óVo PÂ}þUû]ø¦õAó;ñžïqî¹íví¨íHîPï´ðiò`ô‰öÖø4û”ýæÿ!ô†ÐÎ { Ú ê ² 7 ‚ ›Že-ñº”ˆÿ×þ=þÏýŽýxý‹ýÂýþ~þöþrÿëÿW±ð ܇ hÿ¥þÇýÖüÚûÝúéù ùGø¬÷C÷÷!÷s÷ øêøúrûýàþÖç"-  Õ S†bÞóœØ¦  À#KI/ýú÷ôdñüîñìPë'ê€éaéÍéÄêBì?î°ðˆó¶ö&úÄýx-Ê8 b3™„çº÷œ«)! ´p ê8p¬üùˆõUò|ï íë¨éÃènè©èqé¿ê‰ìÁîXñ<ôZ÷œúíý7hj, ž ²]˜^­‡ñò”ä ï Å v¬Rþü!ú‚ø+÷!ögõþôãôõˆõ9ö÷+øVù“úÖûýDþ[ÿR#ÊD°¦w)ÄNÑUäÿ„ÿ<ÿÿÿ0ÿyÿêÿ€8 õéáÒ±u¹´lß õž H]ÿTý>û'ù÷4õwóõñ½ðØïSï2ï}ï5ðXñäòÑô÷§ùuüoÿ‚ª• K¸Ëu©]Š-EÖç‚¶ ’ *’áþ.û÷ôìðî¢ëªé9èWç çWç9è­é¨ëîñ=ô¾÷nû5ÿü«, i NÉÌK?£v»yºŠù ýºeÿÝûÑøö…ócñªïaîí1íKí×íÍî$ðÐñÂóìõ>ø¦úývÿ½ÝÈtØï µ * N & ¸ ) ï®eæÄÂÿäþ1þ«ýSý)ý*ýQý™ýûýoþìþjÿáÿF–ÈØÂ… –ÿéþþ@ýRü`ûrú”ùÐø/ø¼÷}÷y÷·÷9øÿø úTûÚü’þsq€’— =  ì{¦h½§) J  ŒÉØËýµúª÷¿ôò•ïzíÇë‡êÇéŒéÛéµêìöíMðó'ö‡ùýÆx ƨ#&¥•ñ´à{#J ší&]ý¨ù öÚòëïcíSëÅéÂèOènèéPêì,î¶ð’ó¬öðùHýÞóÌ W …M¤…ïá`s#|Œ c £/ÄsþHüQú˜ø'÷ö0õ°ô‚ô¡ô õ±õö÷Ëøú_û­üïýÿ)ÒdÇüå¤FÕW×\ñÿ™ÿ^ÿCÿNÿÿØÿVø·Žt`J&ëŽLX$®ôö¸?’½ÿÇýÀûµù´÷Íõô‡òCñQð¸ïƒïµïSð[ñËòôÉöBùúûãþèùí § @üF\Pþ,â-  Ç;“ÿâûAøÆôŠñŸîì ê~è€ççCçè^é?ëžímð™ó÷¹ú€þJ’ á Ûo*<½­å;š ª f ±ÿjüKùgöÐó”ñ¾ïYîjíóìôìjíNî–ï8ñ%óNõ£÷úüÿ[‘•ZÙ è t ­ – 6 “ · «{3Þ‰>îÿøþ-þý ýàüÎüåü ýyýèýeþçþfÿØÿ6{  {.¼ÿ&ÿqþ¤ýÅüßûùúúZùµø8øì÷Ø÷ømøù ú>û«üKþç ¦ 0 xrS,œ¡> z [ ïAacþWûRøgõ«ò/ðîBìíêê¿éñé­êðëµíñï™òõìøqüÅfä &§Ã\iâÄÆó Û· G ¡ÛþRú½öfóaðÀí•ëêéÉè8è:èËèèé†ë›íðêòÿõCù üNvd  Q5¨¦*5Êð¯*  «7¸=Ùþ—üˆú¶ø*÷ìõõiô&ô3ôŒô)õö ÷>øŠùãú@ü”ýÕþúÿûÒ}÷B^OÇ[Þ[Ùaüÿ®ÿÿsÿÿÎÿ4¿i-ãÄœa‰Û÷×vÔïÊjÖ5þ>ü?úGødö¦ôóÍñÍð#ðÙïôïxðfñºòqô‚öãø†û\þRY[E  ‚±~ÝÂ%Ti:Ÿ ¥ `âA•üóøsõ+ò1ï˜ìrêËè°ç(ç7çÞçéÝê$íÞïùòcöúÊý—XóS bH0ÐÝZJ·¬7j X µPüüËùÒö"ôÌñÚïYîMí»ì£ìíÓí ï¢ðˆò¯ô÷}ùü…þò>Z9Ñ  ¸   ±  D ; »\øœQ!ÿ0þzýóüžüwü}ü«üúücýÞýbþèþeÿÒÿ'`wi4Úÿ[ÿ¼þþ4ýZü~û©úåù;ù¶ø^ø;øRø¨ø?ùú0ûƒü þÁÿ—…}pP  í ô¥ùêr’K ¢ ž J²æ÷þ÷ûøøöPóÍð˜îÂìYëhêùéê®êÓë{íœï+òõVøÌûhÿ´6 ƒ „&X 5ÌÌ5 QhU ò T‘Ãþÿú^÷öóÝð%îÞëêØè*è èƒè…é ëí{ïCòRõ•øöû_ÿºóö² ¥¾^ƒ/i8¨Æ ¡ I ÏD»DÿîüÇúÛø5÷ÝõØô)ôÐóÊóô¥ôvõ}ö¯÷ùdúÎû3ýˆþÃÿÛËŽ ²µŽEßfáXÖbÂÿ ÿ£ÿËÿ!Ñ—iAÖ g‘ƒ8¬àÕŽhœþ¶üÆúØøûö=õ­óYòMñ“ð5ð:ð¥ðxñ±òMôDö‹øûÚýÀ»¶ ^ äüokèßO8ŸŒ & ô…îHý¦ù!öÐòÈïíßêéèçCç3ç»çØè‚ê°ìTï]òºõSùýã©PÀ ã§úÐÛŸª.7Ò Ã`ó’ýQúC÷|ô òþï`î8í‹ìYì¡ì]í…îðìñôhöäøtûþƒäÂ' 9 õ Y i ( Ð Ë ™EÞm¢\8ÿ<þmýÎübü'üü9ü}üßüWýÜýgþîþhÿÏÿGP3ñÿŠÿÿZþžýÒüü1ûoúÃù8ùÕø£ø¨øêøjù*ú)ûcüÓýqÿ3ùá»w  ` r3š¡B|P  ٠že‡ÿ’üœù¶öõólñ,ïGíËëÃê:ê4ê¶ê¾ëIíOïÄñ›ôÄ÷+û¼þ`‡ Ý ì è´ù­ÌSE©ˆïï š Gxÿ®ûøŒô_ñî/ìKêïè#èéçAè)é™ê†ìâîñ¦ôæ÷Iûºþ!j‚U Ò í™Ï‹ÉŽÝ½;bA è iÖ>¶ÿKý ûùI÷Öõ·ôïóóeóžó"ôëôíõ÷tøàùWûËü3þ„ÿ³¼—BºÿþÁcígÚOÏ` ÔÿÀÿÐÿbà|0ôÀŒLù‡î'*ó~ÊØªF´ýþ)ýHûeù÷ÔõBôçòÐññ—ð†ðÙð’ñ°ò0ô ö;ø°ú^ý3!÷¸ Dˆuû £¶CIÍÕm¡ ƒ#™ùýYúÑöwóbð¥íSëzé(èeç8ç¡ç è.êBìÏîÆñõ£ø^ü-ùª( ^9¦—Þ'ÝŸ½i´° r š-þÜú»÷ÝôRò*ðpî+íbììEìëìî}ïQñoóÇõHøáú~ý„ÍÞ«+ W + § Ë ›  Z [ ) ÓcçjùžcÿOþgý°ü-üÜû½ûÌûü\üÐüUýäýsþùþpÿÏÿ/*±ÿ>ÿ¬þþEýü·ûøúLú»ùOùùù2ùœùDú*ûKü¢ý)ÿÕŸyV(á s Ñ í ½6R _N Û ë‚Þ+ý=ú\÷›ô òÄïÐíAì$ëêaêÆê²ëí ïdñ#ô8÷úþ¯N×4 OrV¶‡Ãiyùóq„? µü-`ü«ø&õæñï‡ìˆêé$èÌçèÔè+êìMîûðúó7÷›úþ„Ýð ‡ ½…ذ çK?Ëüá ‰ jÇ-¯ýZû=ùc÷×õô¼ó5óó-ó£óaô^õŽöæ÷YùÛú_üÙý>ÿ„¥™\ëGpi9ätï^Ì?ÂZäÿÝÿüÿ?¦-΃CÃps¸Ì¨I¬Ó¾søWÿ—ýÅûïù!øjö×ôwóVò€ñþðØðñ³ñ·òôÝõò÷Oúçü¬ÿ‹sQ ¢ ðꂪX†.RóÊ ¾@¨þ û÷!ôñ3îÌëÛénèçDççpèáéÛëPî3ñpôõ÷ªûxÿGŒ Ô ÄJWßÙ@T >üV[ ! ¼CÌþlû8øDõ¡ò^ð‡î&í@ìÙëïëì‚íîî¸ðÏò&õª÷Júóü•ÿ|¦Œ& m [ î ( œ ã ê » bìeÚWç–ÿiþiýšüþû˜ûeûcûŒûÜûIüÍü_ýõý‡þ ÿ|ÿÒÿÐÿtÿøþaþ´ýúü;üûÕú@úÌùùeù€ùÕùeú3û:üyýèþ~4þΗL Þ @ e BÌýÍ:C ì 8 0ßQ–¿ýÜúøAõ¯ò]ð]î½ì‹ëÐê•êßê­ëýìÊî ñ²ó±ööùnýœ&‰ °…õñkY³w¦CVíà b°ãýVùÄõsòyïæìÌê6é-è·çÕç†èÃé„ë»í[ðPó‡öìùgýãJ†… 5 …jÚÎC9µ¼X”€ + ¦T«þ¯ûzù†÷ßõ‹ôóñò¬òÀò'óÙóÏôüõV÷Ïø[úìûxýñþN†“oˆÅЮdùwäK´)°Pñÿøÿ#särÊ„;æ}ôEhW ‡ÆË™6«ÿÿý>ütú°øþölõôßòýñjñ0ñUñÜñÅòôµõ°÷õùwü)ÿùÖ®m U\@NSR„ TäVÿ½û3øÍô¡ñÅîKìCê¼èÁçXç…çGèœézë×í¥ðÑóI÷öúÂþ“Tì D Iç´ÌQAŸoºŒô Ð lïoÿü¼ø³õ÷òšð§î)í'ì¤ë ëìícî ð0ò„ô ÷°ùdüÿ¯$ef { ƒ /  u  i x M óxçO»8ÐÿŒþsý‹ü×ûZûûþúû]ûÄûFüÙütýþ¢þ#ÿÿÙÿèÿ¤ÿ=ÿ¹þþrý½ü ü^ûÇúLúõùËùÔùúŽúCû2üWý®þ.ЈJ ¹I ¯ Û Ä ^¢ˆ 1 ô \ n6¾Oþwû£øæõRóùðíî=í÷ë%ëÑêþê°ëãì“î¹ðGó0öbùËüUêuÝ ðt†#›}Ê„³c } cšÈýúföó÷ïMíëeé>èªçªç>èaé ë.í¾ï¨òÙõ<ùºü>² Û FGÓäu…4á+Í G žå.‹þ ü¾ù±÷ïõ€ôló³òXòXò®òTóAôjõÄöBøÖùuûýžþ`†z:Â2á~þkÍ-• ˜B üÿG£¯T´^ötÏÊ[²Ð·l÷ÿ`þ±üöú<ù‘÷ö›ôjó|òÛñŽññ òÛò ô•õv÷¢ùü¬þk< È ] ¹ÊÑ®ïL'…nì  å„nüäøzõEò[ïÏì±êéúçtç‚ç'è^é!ëeíð6ó öDú þÞ¥G ° È~À¶ZhãÍ0« ~ ›üEù'öTóÝðÎî3íìuëWë¸ë’ìÜí‹ï’ñáógöùÑûþ;Å7 ‚ ¤ i Ð Ú Œ í  ß † mÉ%¶þ„ýƒü·û#ûÆúŸúªúâúAû¾ûQüñü•ý4þÅþAÿ¢ÿãÿøÿÌÿ|ÿ ÿ‚þåý;ýŽüçûNûÎúnú6ú.úZú¾ú[û1ü=ý|þæÿrË'µ  O B ë A=Ú  õ x ¥…%‘ÚþüDùŠöõó–ñ€ïÁíiìëë&ëºëÑìeînðãòµõÔø-ü¬ÿ:Ã/ h XíÁæ{|æ¾ Ò& ³ O}þ´ú ÷œózð¹íjë›éWè¥ç‡çþçé—ê¦ì%ïò+õ‹ø ü—ÿtœ z ÿÄòŸËv¨g¾¼p ê =z¶ÿmü úã÷ö}ôNó}ò òõñ:òÒòµóØô1ö²÷Nùùú¤üDþÌÿ3p}Vö^ŒZ†óQªlç|0#hÍMã‡0ÕnñU“£(—ÍÍš<»þýsûÅù!ø•ö-õ÷óÿòPòññëñBòøò ô}õC÷Vù«û4þâ¦m$ ¹ 5û]OÉÄ=5°´M † r!¨ý–ù)öìòõïXí&ëmé;è˜çˆçè(éÎêøì™ï òûõ”ùVý(ó  BiF™[ˆ% œ'P, ÎL¾:ýÔù¢ö¹ó'ñýîFí ìNëë]ë!ìXíùîõð?óÄõsø:ûþÁ_Ïë ¾ œ :ÿ n ‘ q  —÷G•ìYçþý„üŸûóú€úEú?újú¿ú7ûÉûlüýÁýaþïþeÿ¼ÿñÿìÿ³ÿYÿâþTþ·ýýoüÖûQûéú¥úú¦úôúzû7ü+ýQþ¤ÿ­Pø˜" ‰ Á ¾ t Û ë   ö ï Œ ÓÍ„`ÿ£üâù-÷˜ô5òðJîßìâë]ëTëÍëÇì>î+ð†ò@õJø“ûÿŒ€ À ¼bžb¢SrûðX;§ª W Ã3ÿfûµ÷8ôñ-îÅëÚéxè§çlçÆç²è*ê#ìî^ñ~ôÚ÷[ûíþvã  ±è®øÂ ÎèOX Ž ÞC~ÿÖü[úø&ö‚ô8óMòÂñ˜ñÊñRò*óGôõ ÷Ãøxú2üãý€ÿýSyj#¡æôÑ |Ø)zÓ<½Zþÿ4„ñv ­NælØ"B2îtÂÛÁ{ÿ‡ýìûJú¯ø'÷Àõ†ô…óÉòZò?ò€òóômõ÷ùOûÃý_Ñ‚ { žqãë|‘'<Óó¦ ø ø¸LÊýFúØö•ó“ðæíŸëÐéƒèÃç–çþçùèƒê“ìïòYõæø¡üq@õy ¶— tTŸTu ºòØ ýiÛýgú#÷$ôyñ4ï`íì/ëÛêëµëÙìiî[ðò õÑ÷ŸúuýAóyÄÇ x Ð È _•mì   ­ * „Ê P¨ ÿ¾ýŒüŽûÊú@úñùÙùõù?ú°ú@ûåû–üJýøý—þ ÿŽÿÚÿãÿŸÿ;ÿ¾þ.þ“ýöü^ü×ûgûûñúøú1û ûFü!ý.þiÿÉHÚu ÷ 2 7 ú p ” _ Î à ˜ úÝtáÿ3ý|úÎ÷;õÕò®ðÖî[íJì­ë‹ëçëÄìîðï0òÒôÇ÷ýúbþàaÐ Ò"ýV$`Ÿ!9÷ o¸êÿüaø×ô’ñ¦î&ì ê¡è²çXç•çeèÃé¥ëþí¾ðÓó)÷ªú@þÒMš¤ [­÷Þ@eÝò´ 3 €°ÔFýµú^øNöô*ó$òñ@ñ^ñ×ñ¢ò¶ó õŒö5øóùºû|ý-ÿÁ.mwHÝ7XDÿ’_«ó?—Œ5òÿAš˜-È^æY­ÛÝ­J°âá²]ÿèý_üËú:ù¸÷Söõ ôEóÇòšòÄòIó*ôeõõöÕøùúXýáÿ†7ât Ú ãf€)X:î+ø c yLîvþöúˆ÷@ô4ñxîì8êÒè÷ç¬çöçÓè@ê4ì¤î‚ñ»ô;øîû¼ÿŒHØ %§ºGE®¿n˜J‘‚ / ¯þûª÷•ôÓñsïƒí ìë§êºêOë^ìÞíÂïüñ{ô.÷úâü½ÿ€~œ h Ú í êÖf¡ ’ B ¾ Q„¹ÿ`ÿçý›ü…û¨úú¢ùxù„ùÃù+ú·ú]ûüÏüŠý9þÖþXÿ»ÿûÿ Þÿÿ#ÿ¢þþ{ýæü]üèûûZûPûuûÎû\üýþ5ÿéjöd ¢ ® {  7  Ÿ Ê  G/Ü\¿ýûmøÝõvóHñeïÛí·ììÈë ìÊìî¼ïáñjôI÷múÃý6² k {> ‘íF =ßù•Ó kŸÎüùzõ%ò%ïìmêÒèÅçMçkçèbé,ëqí ð*óyöøù‘ý+³0 þ kiîñpjâÞgŠUØ % Oi‡»ýû§ø}ö£ô#óòGñîðøð_ñò'ótôøõ£÷jù=ûýÔþ}Z}fƒ·³{è0o¯øRÅW åÿãÿJ¬&°CÖ`×5p‚f—áøâ¤ÿDþÍüHûÂùHøåö¦õ˜ôÅó8óùòó|óCôdõÚöŸø«úóüiÿý¢DÒ : jRäÏã0ZCÇ ôÚ‹ÿ¥û8øìô×ñï£ì§ê(é1èÊçõçµèêÜë3îúð!ô”÷=ûÿ×™3 ™<i.¶¦ÌÔ-* ß aÈ*ÿœû7ø õ3ò¹ï­íìë{êsêïêèëVí+ï\ñÖóˆö`ùJü3ÿ¸2h O Ý Ô9:Ü& Ö S ¦Ü)[¨ÿþ³üƒûŽúÕùZùùùIù¨ù/úÓúûQüýÖý„þÿ•ÿíÿ-Üÿƒÿÿþþýnýäüjü üÇû­û¿ûüyü#ýÿý ÿ;‘ÿ{ûrÓ # ú Ž Õ Ê h ­ š 1 xy=ÑEþ¨û ùöôäñ÷ï_î)í`ì ì3ì×ìøí‘ïšñ ôÑöáù(ýq¾ Ö ¦ª¯%XMG* ¿T„ýÀù!ö½òªïüìÂê éàçJçJçàçé¹êèì‡ïƒòÊõEùàüµ š !;Üý™®?Qíô} Ë ñ7þ}û÷ø´öÀô%óêññ¢ð–ðëðšñšòàóbõ÷Þø¼úütþ2Î>{}BÈó™q·ï$^§ßÿÅÿÑÿO¹7ÁOØT¹"àvØ ãÿ™þ5ýÀûGúÔøv÷7ö$õHô®ó^ó_ó¶ódôkõÇörøeú•üöþy¨1 ™ Î ¿^œpж ‚‡$ h c%ÃÿRüçø™õ}ò¨ï,íë…ésèïçýçžèÐéŒëÉíyðŒóïöŽúQþ!ç‹ õ ËÖµÄ<"~ZÅÏ yÕÿ=üÈø‹õšòðßí/ìëVê3ê•êxëÒì˜î½ð1óâõ½ø¯û¤þ‰MÞ. / Ø !˜M§¬ i ê : j†ž¾öÿNþÒüŠû{ú©ùùÅø¯øÒø'ù§ùJúûÐû ümý-þØþhÿ×ÿ!GF"Ýÿ|ÿÿþôýkýîü…ü9üüü>üžü/ýóýåþ?šxæC – v  n w + ˆ @ ¢¼—AÇþ7ü¤ù÷·ôòŒðçî íÂìWìdìíìñímïZñ°ó`ö[ù‘üìÿXÁ 0 ¨JiûüjG™jƽ b É :þrúËöYó5ðqíëKéèNç0ç©çµèMêeìñîßñõ“ø.üÕÿqí3 / Ïú땿o°‘! r • ¥¸þëûNùóöäô.ó×ñæð]ð:ð{ðñòMóËô{öNø7ú&üþáÿ“qŒjdƒhœû?rÉL²7àÿ¯ÿ¤ÿ½ÿùÿQÁAÉQÏ;¾Æ¢MÈ+çþ—ý3üÇú_ùøÇö±õÍô'ôÈóµóöóôzõ»öLø%ú>üŠþú‚“ø 0 )Ô# ‚¢Â{ × æ¹dýü–ùGö%óEðºí–ëèé½èè èè£éCëeíýïüòNöáùýk4àW „S²’è¬ÚprçÚXr: Æ,‚âü^ùö ó\ðîMìë9êúéBê ëRìî!ðò;õøûþ܃ë Ë /-Ãñº$7ü € Ð û(Kþùü—ûoú…ùÜøuøLø_ø©ø!ùÀù|úLû&üÿüÏýŽþ3ÿ¹ÿYpb0áÿxÿþþyþóýtýý®üwüfü€üÉüDýîýÈþÌÿô:•ú^´ñ ï ›   ç \ | H Ä÷ëªCÿÃü;ú¼÷Xõó"ñrïî*í¨ìœì íñíQï#ñ]óõõÛøþûLÿ¯b ‡ lþ+äÊéupßÊ>K  t¼ðþ&ûw÷úóÅðëíë“é.è[ççyçièæéèë`î>ñpôá÷{û&ÿËU­ ¾ wÇ¢ýÓ å'ì?,Å  ;@:?ÿ_ü­ù9÷õ>óÍñÁððäïðŸð…ñ»ò4ôäõ¼÷­ù©û¡ýˆÿPñ_”Š?²äÙ–"…É÷:bšêXêÿ ÿ}ÿÿ¨ÿïÿOÄEÊI»Tm\°DL/ÿóý¡üDûæù“øW÷?öUõ¤ô6ôô=ô¼ôõ·ö.øîùîû$þù{öY ’ ‘G¦ -Få ºöÉ > cI¥ýCúõöÎóäðLîìRê éQè$è‰èéëíˆïqò²õ7ùëüµ2µ òÕLGºœç›ºJUçå xß2‰ýùù™ö}ó¸ð[îrìë#êÈéõé§ê×ë|í‡ïêñ“ôq÷oúzý|e!¢× ¶ 5OÿD"ž¾  h Ž™——§Ôþ(ý­ûkúiù¨ø*øî÷ð÷-øœø6ùòùÅú§ûŒülý=þ÷þ”ÿd“›~Aèÿyÿüþzþúý†ý'ýãüÁüÉüüü_ýòý²þŸÿ°â*€Ø'az g  ‘ ¾ ) b H Þ+7 ¹ÿJýÎúWø÷õ½ó»ñð›î—íÿìÛì.íúí=ïòðó‘õ`øqû°þf´Ý Ëj©wÈ’Íw#±Ó › n¦ÿÛû&øžôYñlîêëâéaèpççRç$è‡épëÓí¡ðÆó0÷Çúuþ"¸ F xñäN/‰dÉÅgÀ ããÔËÿÙüú†÷DõWóÊñ£ðæï•ï¬ï'ðÿð+òžóLõ'÷ ù'û/ý)ÿ¾E“£pù?E¦T™¯Èî)ûÿ™ÿ^ÿKÿ]ÿ‘ÿãÿJÃCÂ8œæè UuoÿHþ ý»ûiúùç÷ÍöÞõ$õ¨ôsôŠôóô®õ»öø¾ù¥ûÄýuê\º ô ø ¸$0Ò½ÿÊ# Ÿ ÚÔKþðú¢÷yô‡ñáîšìÁêdéèCèŠècéÈê³ìïëñõø:üÊ‚ [Qßôƒƒí¿û§Êq­Ž ( “ä4þ˜ú(÷øóñ¤îŸìëêé¯éHêbëóìïîHñìóÉöËùÞüîÿç¹P  ™ 4i3‘…C­ $ (  !ÿ^ýÊûoúSùzøå÷•÷†÷´÷ø­øgù=ú%ûüýæý´þhÿûÿg®ÍÆœRñÿ~ÿÿþ þ¢ýSý"ýý6ý‚ýýý¥þyÿsÅ VÒëÜ ›  Z M ï A @ ñX|i)Ìý^ûðø•ö[ôUò‘ðï î]í!íYí î1ïÊðÏò4õì÷éúþd»2 'Ó"nRªr©RuU1 ÂZü×øEõòñòîZì8ê›èçç2ççç.éþêKíðó€öúÂýuÈ °4GÝîuqå×P[h Œ ˆqZYý~úÛ÷õxóÏñð¶ïKïLï´ï|ðœñó³ôöø¡ú¸üÃþ¶…$Œ´š:•­‡(—ß(3Hp±šÿGÿÿÿ9ÿzÿÕÿC½;´t«¿ªjû_—©ÿ˜þlý.üéú¨ùuø\÷iö§õõÚôÞô0õÓõÇö ø•ùdûlý¡ÿö\Ä V ^ %ž»rºŽëÒGP ø KY3íþšûPø$õ,òzï#í6ëÂéÐèjè”èNé–êdì°îkñ†ôí÷ŒûLÿÐg À ÉlšEbëÛ5ü9öD3 Ø G—âþ;û¼÷yô†ñõîÔì0ëê{épéïéòêoì[î¨ðEó ö$ù?ü[ÿeJø` u +{`×â„Ä«C ™ ¼ º£†ruÿ›ýïû{úFùTø§÷B÷ ÷?÷˜÷%øÜø³ù¡úšû–ü‰ýkþ4ÿÞÿcÂùñ¹eüÿ…ÿÿþ!þÇýˆýlýwý¬ýþŸþ[ÿ=CešØE]Q  ¤ ñ ÷ ¯  1 û|º¾“Hþéû†ù1÷ùôðò$ñ¦ïîÀímíŒí"î-ïªð“òÞô÷fú„ýÃZ† 8—  d¹€ÀÒ cÊFý‰ùïõò~ïÐì•êÝè±ççç±çÜè’êÉìrï{òÑõ`ùýÇrøD BàÁð”­;DÑî§ 5 /ðßýðú7øÂõ óÜñ~ðŒïïñîEïýïñsòô÷õü÷ú;üWþ^Cû|¾½uæ ú§j“£¥£¨½é3¢ÿ7ÿõþÛþçþÿcÿÆÿ9´.ŸþChg<åa²ÛÿàþÈýœüeû.úùê÷õö,ö™õEõ7õtõÿõÚöøtù*ûý:ÿ|Ó0‚¸ à ‘B jWÏÒcˆ J ¶ÙÄŒÿBüüøÐõÒòð±í±ë%êé™è¥èBélêìOîòðøóN÷áú™þ_» ! ;ó9ÿ:àïgJ¡v×Ö … úK’ÿâûUøõ÷ñMïíPëê_é9éé‡êïëÊí ðŸòvõ|øûÄþÜÔ™ I ††9ðB6× 2 U O0áÐÿàýüú@ù4øp÷ôö¿öÎö÷ž÷Pø(ùúû#ü&ýþùþºÿWÎB@Õwÿÿ¢þ?þóýÆý¾ýÞý)þ¡þDÿÿ /^¹ÏÅ‘ ) „ › h è  þ™ð ÷¿þpüúË÷–õ‹óºñ0ðüî)îÀíÆíAî0ï‘ð_òô÷êùõü&k®Ú Ú š¦¾MO§ßIM tÀûý<ú›ö/óðLíùê&éÞç(ç çƒç‘è-êLìáîÚñ%õ­øZüÉ]» Î …Ξé«àЬO}D´ ß Ùµ‰jþiûšø öÐóññwðjïÌîîÛîï†ðßñó]õe÷‰ù¹ûæýûËeÁÙ©0 o i # ¤õ+%'[²ÿ/ÿÔþ¤þ›þ·þôþLÿ¸ÿ.¨„Ö Ç[Ä!ÿþýÝû±úŒùxø‚÷³öö´õ•õ¾õ2öõöø\ùøúÐüÙþOŸé ' û ‰Ä¡¬Ëx¹ •  RP&çü§ù|özó¶ðBî0ìêléÏè¿è=éIêßëôíðoó³ö8úèýªj  ¨tÒ² Îû‘‘ðfu0 ¬BŒüòøŒõnò¬ïUíwëêLééQé"êuë=íoïúñÌôÒ÷øú)þOY2Ë  ‰¥P‹W»¾jË ð 翊U1,þPüªúAùø@÷­ödöaö ö÷Æ÷›øù™ú¬û½üÄý·þŽÿCÒ9u‰vAð‰›ÿ%ÿ¹þbþ&þ þþKþ«þ5ÿéÿÁ¹Éé0A8 ª  :  ± ûù®SU0ÿñü¨úbø2ö'ôPò¾ð|ï—îîîhî<ïð2òHô¸ösùlüŽÿÇ. 2 útŽ9i2ÂÅ>6¹Ô ˜ p°þñúJ÷Ôó£ðÍídëwéè>çç]çNèÎéÕëTî=ñ{ôû÷¦ûdÿ¾, T "†rÛ» ÒÇÝX‰ ƒ[&úþçûù_öôòxðOï–îOîwî ïÿïMñèòÂôÍö÷ø2ûnýœÿ«“F»íÖt È Ô œ ( «µ©’yjmŠÊÿ.ÿ¼þtþUþ^þ‹þÕþ7ÿ©ÿ!™e¨ÌË¢NÏ'[ÿnþgýOü0ûúùø<÷—ö(öùõömö÷ øJùÍúŒüþ™ÏS€ ‹ d ûC0¹Ö‚¼…á Ù v Æ×½ŠýQú'÷#ôWñ×îµìÿêÄé éàèAé/ê§ë¡íðëòö“ù9ýöµ^Ù ðd^ѳ³Ñ^dðÙ ^µö9ý“ùöëòð¡í§ë/êAéàè éÄéÿêµì×îWñ#ô'÷QúŠý½×Æv Ù á …¼‚Ö¹0Cûd ‹ € SÏ™þŒüÍúJù ø÷mööùõ(ö—ö<÷øùú0ûOügýnþ[ÿ'ÏN¢Ę̈e™!©ÿ7ÿÕþ‹þ^þUþtþ¼þ.ÿÊÿŠmjy’©µ«( œ Ô È t Öí»F“«œÿný2û÷øÍöÂôèòMñÿï ïwîOî–îOïxðòô_öùçûúþ&[ƒ‰ XÝÇÒ »Ûr†"T , ¾dÿ¦ûû÷{ô=ñTîÕëÎéNè]çç>çèwédëÍí£ðÔóJ÷ñú°þp˜ Ô ¹6>ÅÂ2i9Žtú2 . ÇŽÿlüsù¸öHô2òð<ïhîîî—î|ï¾ðPò'ô2öbø¨úñü0ÿUS®ùû±  :  ª 8A0éɹÁéÿ5ÿ«þKþþ þ&þbþ¹þ%ÿ›ÿ‰ðAv‰u9ÒCŽÿ·þÄý½ü¬û™úù›øÆ÷÷ öaödö­ö@÷øAùªúPü,þ1UŠ¿çð Ë j¾»W‹P¥‰ Ë 2YO)þøúÒ÷Ìôúñoï=íuë"êQééLéêwëUí¬ïnòŒõòøŒüB¬0 ufð‘‘ûÎ ²Òt¨ jªèý8ú³öoóðôíßëIê=é¿èÏèléê0ìBî¶ðzó|ö§ùçü&PR • ¹ xˬ¡Ä‰û '  éŸOÙþÐüøú\ùøõö2ö¾õ•õ´õö³ö‚÷xøŒù±úÝûýþ!ÿÄ[Ç Ö„¨.¸ÿLÿôþ·þ›þ¤þÔþ/ÿ²ÿ['%+õ¤# i o 0 ©ÙÁeËûæý¹û‰ùe÷]õóßñ†ðïÛîîÌîjïwðññÐó öšøiûjþ‰µÙß ´ D}O¬Šà«éžÎ…Î » ]ÉZü­ø%õÚñáîLì-ê‘èƒç ç(çÞç&éùêLíð/ó›ö<úûýÀt M Iß§ÂOM¾¦šÚ Ú ®k&õüêù÷ô_ò‘ð0ïAîÆíÀí)îüî0ðºñ‹ó–õË÷úpü¿þ÷ ð™þ è h › „ ) ‘ ÅϹ^/ ÿDÿ¡þ)þÞý¾ýÆýóý?þ¢þÿÿwÕ@BÎWºÿùþþ&ý#üûú(ùPøž÷÷Îö¿öôöp÷4ø@ùúüàýÐÿá0OU 2 × 6Bð9††I  ™ÔÜÄþû|øvõŸò ðÊíïë‡êé9é_éêPëíMï÷ñõUøâû’ÿKú… Ö ×v¡Jgïà:ÿ9ó;! » _™þáúN÷øóòðOîìlêBé¥è™èé%ê±ë±íðÒòÐõüøBüŒÿÄÙ¶J ˆ cÒÏWj B‘à ¸ ‚0Ó|:ÿý*ûtùøÚöÿõtõ7õEõ™õ,öõöê÷ù.úeûœüÈýàþÛÿ²aå<ghCþŸ.´9ÆÿcÿÿçþÛþõþ7ÿ¢ÿ3齨£¥£“j§ú æu½¾|ûC^Wþ;üúü÷÷õôsòñýïEïñîïŒï~ðÜñ óÂõ7øðúßýð/5  §îÑD;­”ðÁàBD ørÇý`ùÑõ{òrïÉì’êÜè±ççç±çÝè•êÐì~ïòïõ‰ùFýÊc ÒÀ€¹d  —8 † ZÄýfú÷Þô“òªð-ï"îŒímíÀíî¦ï$ñðòùô1÷†ùéûHþ“¾º|û1  ¯ ÷ ñ ¤  Q ]EØšeC=[ÿŸþþ¬ýwýlýˆýÇý!þþÿ…ÿüÿe¹ñùÂcÞÿ4ÿkþ‰ý–üšû¡ú³ùÜø%ø˜÷?÷ ÷B÷§÷TøFù{úïû›ýuÿr†£º¼ ™ C «Ä„â×`{+u ` øJe[ÿ?ü$ù öEó¨ð[îoìòêïépé{éê0ëÔìõî†ñyô¼÷;ûâþ—GØ 3 Dö9ü5ÛëbEšlÉÀ g ÐLÿŒûí÷†ôkñ°îdì–êNé”èjèÐèÂé6ë#ízï,ò$õPøšûíþ3YKø P GÒ뎺r»ž%^ V  Ä\ö¡ÿlýdû•ù øÇöÓõ0õÞôÚôõ§õiö\÷uø¨ùéú.ülý˜þ©ÿ—_ûjª¿«t´;½CÕÿzÿ9ÿÿÿGÿšÿ±pH3(ß—(‡­•:š´Œ$…¶Ãþ¸ü¡úøö³ôóœñ|ð´ïLïKï¶ïðÏñxóõÛ÷~úYýZqˆŒ h [P×åquîÝG4°È uÂýú€öóðKíþê.éçç2ççç›è8êZìòîòñEõ×øüZÂ1 UuR©rªRn"Ó'2 »dþéúì÷4õÏòÊð1ï îYí!í]í îï‘ðUò[ô•öðø^ûÌý)i|Xñ@ A ï M Z  › Ü ëÒV Åsyÿ¥þýý‚ý6ýý"ýSý¢ý þþÿ~ÿñÿRœÆÍ®gûÿhÿ´þæýýü%û=úgù­øø´÷†÷•÷å÷zøSùoúÊû^ý!ÿ  ($ ­ C…‘3i4™   P¹çîÿÞüËùÉöìóHñïîóìbëHê¯ééêëŸì¤îñøó(÷˜ú4þä“( Ž ­qʧû¿íƒƒôßQ[ ‚Ê:üøõëñï³ìÈêcéŠèCèèdéÁêšìáî‡ñyô¢÷ðúKþÔÚŸ  #Êÿ½Ò0$¸ø ô º \êuÄý¥û¾ùø»ö®õóôŠôsô¨ô$õÞõÍöç÷ùiú»û ýHþoÿuU èæœ8ÂCÃJãÿ‘ÿ]ÿKÿ^ÿ™ÿûÿ)îȯ™T¦E?ùp£“E¾)ÿ/ý'û ù'÷Lõžó+òÿð'ð¬ï•ïæï£ðÊñWóDõ†÷úÙüËÿÔããÀ gÅÉd‰/NäñxF ¸"uþÇú0÷Æó¡ðÓípë‡é$èRççpçaèâéêëlîYñžô&øÛû¦ÿn› Ó ±#wÍ’Èw©jËÝ ´f°þqû`ø‘õóòð=ïúí.íÛìÿì—í›îð»ñ½ó÷õWøÎúJý¹ÿ 7+ÞH b ) ¾ ‘  g z a'Ø€*â°Ÿÿ²þòý_ýüüÉüÁüãü'ý†ýúýzþüþyÿèÿA~›“d”ÿ÷þ=þlýŒü§ûÅúòù6ùœø-øð÷î÷*ø¨øiùkú­û(ýÔþ§——™Žh  ¾ž"DÿO5¶ × ¢!e|zýoúq÷“ôêñ‡ï|í×ë§êõéÈé#êërì[î¸ð}ó™öùù‰ý2ßxå çUJº›çœºGLÕòµ 2µëü7ù²õqòˆïíëé‰è$èQè éRêìLîäðÎóõöCú¥ýIc> É öº åF- ¦G‘’ Y ö{ù$þîûîù.ø·öõ¼ô=ôô6ô¤ôUõ?öW÷“øæùDû¡üóý/ÿLD°\mT»IÊEÄOïÿ¨ÿÿ}ÿ ÿêÿXêšb:÷É…"–Ùä²?Š”_ñPˆÿ¡ý©û­ù¼÷äõ4ô»ò…ñŸððäïðÁðÍñ>óõ9÷­ù_ü?ÿ:@; Å ,?ì'å Óý¢Çw¾ ­ UË&ÿ{ûá÷pô>ñ`îèëæéièyçç[ç.è“éëëíÅðúów÷&ûðþ¼t K >ÊßpuéÊä+þl‡ b ¯LÿþûÛøõõ]ó#ñQïñí íœì¨ì*íîrï"ñóXõ¼÷;úÃüCÿªë÷ÄH | \ ç   › ï  ñ´^ú•:ôÌÿÈþîýDýÉü€üfüwü®üýtýóýyþþþxÿáÿ0bpY¹ÿ3ÿŽþÏýÿü&üLû|úÀù!ù©ø_øLøuøÜø…ùoú—ûùüþK(ûÐ € ü 7$ºñÃ-/Ë  ëƒÜþûø;õò!ðîRì ëBêúé9êëMìî\ð óö^ùâü‚,Æ: rXÚçrpڬ蒲S„W à4kýáùNöüòýïeíCë£éè èè½èèé–ëºíEð%óGö–ùýüd¹æ× { ¢‚ #Ô)0 ø “‚úŠþ>ü%úLø»özõôöóµóÈó'ôÍô±õÇöø_ùÇú3ü—ýçþ+ÈM¢Æ¾;ÏQÉAÁQùÿ½ÿ¤ÿ¯ÿàÿ7²LÉr?ûœhƒdjŒq“áÿþ&ü7úNø{öËôMóòñ{ð:ð]ðæð×ñ.óäôóöNùëû¸þ¥ •r ! ‘°o¿•ëºÃÏ/ 3 íqÕÿ.ü“øõßññîeìMêµè©ç0çNçèKéëqí5ðYóËörú:þ Éb ½ Æj™GjüûiJ¨ 0  ÁXìÿ‘ü[ù`ö°óZñmïñííìdìWìÂì íçîŒðò·ô÷¤ù7üÇþA—¼¢@ ˆ + w n  v – Cæxš?åþóý/ýžü>üüü9ü…üîükýôýþÿ|ÿÝÿ"FG!×ÿhÿØþ-þmý üÐûûJú§ù'ùÒø¯øÅøù©ù{úŠûÒüNþöÿ¾ž†j: ê i ¬ §M˜!Ø / . ÞM‰¤þ¯û½øâõ1ó½ð˜îÒìxë•ê3êVêë/ìßíðšò‹õÈø=üÕÿy Ï ÅZ~"<ĵÖËõ ‹ ç!QþŽúïöŒóyðÉíŒëÐéžèýçïçsè…éë,í¨ï}ò™õçøRüÃÿ%ch $ ‡‚ ¶Ðpœ^¿Î ™ 1 ¨yöþ•üeúrøÇökõdô¶ó_ó^ó®óHô$õ7öv÷ÔøGúÀû5ý™þãÿ Øvà"¹TØOÁ7¹OÑÿÅÿßÿ§^$ï·q™óÈB}{>Î2tþü¼úÞø÷bõàóšòšñëð–ð¢ðñêñ%óÀô´ö÷ø}û7þñË } ôíQ?®™ýÜ;!š µ àüEùÊõƒò‡ïèì¹êéàçJçJçàç éÂêüìªï½ò!öÀù„ýT¿* GMX%¯ª¦Ö ¾ q(ýáùÑö ôšñ‘ïøí×ì3ì ì`ì)í_î÷ïäñôö ù¨ûEþÑ=yx1 š ­ h Ê Õ Ž ú #  Órû{ÿ‘; ÿÿý#ýyüü¿û­ûÇû üjüäünýþýþÿƒÿÜÿ-íÿ•ÿÿ„þÖýýQüûÓú/ú¨ùIùùùZùÕùŽúƒû³üþ¨ÿ[)ܦS Ö &Ü:9Ô Ý O h 2¸3ÿJü`ùˆöÖó\ñ+ïVíèëïêsê{êëì­í¹ï3ò õ7øœû*ÿÈaß * -Ô̦¶.i<™ 3 ™×ÿ=û”÷!ôúð3îÜëêµèõçÊç1è(é§ê£ìï×ñìô8ø¥ûÿ‹ÚôÇ CZ0ãÏäRj: Ò D¢ýiÿóü«úŸøÚödõCô|óóùò8óÅó˜ô¦õåöHøÂùHûÍüDþ¤ÿâøá—f‚p5×`ÖC°&¬Jãÿåÿ WÅRø¯o0è{³·ƒf}Z}Ôþý=ûjù£÷øõtô'óò_ñøðîðGñò#ó£ô}ö§øû»ý‡iO% Ø UŠgÞâjpñîikþ 0 ³+‘ýøùyö*ó ðqí,ëbéèkçMçÅçÒèmêì%ï%òzõùÎüŸk“ Õùß= Fí‘ >{k ²6ÃýmúI÷jôáñ¼ïîÊì ìÈëì·ìÛíeïHñvóÝõmøû¿ý\Ü/G Ê Ÿ  7  { ® ¢ d öjé5ÿþý\üÎûuûPûZûûèû]üæü{ýþ¢þ#ÿÿÞÿ ûÿ»ÿXÿÖþ9þŠýÏüü]û·ú+úÃù„ùxù¢ùú¨ú…û›üçý`ÿÿ¹„Q¾ B ’ ¡ fÖêí Ú h œ ~€½ÿâüú.÷{ôüñÂïÞí^ìOëºê§êë ìƒísïÓñ•ôª÷ûþ¯/ ‚ ‘J˜n¿®EGº§%Ø HŒ¼ÿîû;ø»ô‚ñ¤î4ì@êÓèöç¬ç÷çÒè8êìxî4ñ@ôˆ÷öúvþîLyc ø +î:X)€fãÚ t â7†áÿXýùúÕøõöeõ*ôIóÄòšòÇòEó ôõSö¸÷:ùËú_üèý]ÿ²áâ°J­ÝÛ­Yæ^È-˜šAòÿ5Œ—?ó«_’ÿDX7ÝHwm.Á-ÿ|ýºûóù5øŒö õ¶ó¢ò×ñ^ñ@ññ$ò*óôNö^øµúFýÔ°€3 ´ òÝe@Þ÷­[¤ šMÒ@þªú)÷Óó¾ðþí¥ëÃéeè•çXç²ç¡è ê&ì¦î’ñ×ôaøüêÿ¸o÷ 9!Ÿ`$Vý"Ò ÐaàbþýúÇ÷Òô0òðïîÄìçë‹ë­ëJì[íÖî®ðÕò;õÎ÷|ú3ýáÿtÝú˜ à Î _ ” p ú 7 2 ÷  uÚHÉiÿ.þ!ýFü û1ûøúñúûgû×û^üöü“ý.þ¾þ;ÿŸÿãÿÚÿŽÿ ÿ—þøýJý–üåû@û°ú?úõùÙùñù@úÊúŽûŒü¾ý ÿ¨P Ê„* ­   ì m•_È Ð x Ç ÄyóAuýŸúÑ÷ õò[ðiîÙìµëëÛê/ëì`í4ïyñ$ô#÷gúÛýiýØ òº uTŸTt —¶y õ@q¡üæøYõòï“ìƒêùèþç–çÃçƒèÐéŸëæí“ð•óØöFúÊýL¸øø ¦ óÓ<'‘|ëãqž{  ‚Ñ_ÃýOûù÷mõôó€ò?òZòÉò…ó†ôÀõ'÷¯øJúìû‡ýÿ{ÁÛÂtî2B"ØlæN­ vñ„4þÿZ½<Óz)Ø| Ñôæ¡#jySý€ÿãý2üxúÃø ÷õGô*óRòÊñ˜ñÂñMò8ó‚ô&öø[úÖü~ÿCÞŽ  XOèÎ Âø®è±  ãvíþ[ûÚ÷~ô^ñî#ì*ê²èÆçlç§çxèÚéÅë-îñ8ôµ÷fû3ÿÃW ª §;XðûrS¢bžb¼À € Œÿ“ûJø@õ†ò+ð>îÇìÍëTë]ëâëßìJîð5ò˜ô-÷âù£ü`ÿ„ÍÓŒ ï ö   ë Û t ¾ Á ‰ " ˜øP­¤ÿQþ+ý7üzûôú¦úú¥úéúQûÖûoüý·ýTþâþYÿ³ÿìÿñÿ¼ÿeÿïþaþÁýýlüÉû7û¿újú?úEú€úóúŸû„üýçþYì•G÷— q ‘ n ÿ :œ ¾ ë Ï_Áþ:ûsøÄõ?óõðùîXí!ì]ëëNë ìFíýî'ñ¹ó¢öÔù:ý¾LÎ, P'œ %ˆ[™FiB  ó(Vý”ùûõ ò™ïøìÎê(éèˆç˜ç;èmé&ëXíõïìò)ö–ùý¨!r† M ´°5=ÄÉO]û5¹ $ m¦â4þ«ûVùC÷}õ ôøòBòëñññPòÿò÷ó-õ•ö!øÅùsûý»þ<šÍÍ—(£“UñnÕ0‡ãMÍh#0|çlªQó†ZŒ^öV}p3ÌÿDþ¤üùúNù²÷1öØôµóÒò:òõñ ò}òNó}ôöã÷ úmüÿ¶z=ê p ¼¾g¨vËŸòÄÿz œ t—ÿ ü‹ø+õò%ï¦ì—êéþç‡ç¥çWè›éjë¹ízðœó ÷´ú}þO³  &Ò ¾æ|{æÁíXh / Ã:¬ÿ-üÔøµõãònðeîÑìºë&ëëëiìÁí€ï–ñõóŠöDùüÚþ‘%…¥x õ  Ú =Aë B O  µ 'Ëræÿ|þ=ý1ü[û¾úZú.ú6únúÎúNûçûŽü;ýåý‚þ ÿ|ÿÌÿøÿãÿ¢ÿAÿÅþ4þ•ýñüQü¾ûAûâúªúŸúÆú#û·ûƒü„ý¶þ%Ém† ß  í Œ Ú Ð i ¤ ‚  7Å;þÑûùgöáó’ñ‹ïÜí’ì¸ëWëuëì3íÎîÝðTó'öEù›ü~ « 0ÍãhZ¶À~Ȱ G ¥Þ þDú ö6óðeí!ë^é'è‚çtçúçé±êÏì[ïEòzõäønü„å ì n…'Lï®Ñʹ] È <k¬þü¢ùv÷•õ ôÛò òñŽñÛñ|òjó›ôö‘÷<ùöú±ü`þ÷ÿl·Ð²[ÊÏtö^´T¯£Güÿ B˜ •-Íkþ~á2Â:z†`žþýuûÖùBøÄöjõAôTó®òXòXò³òló€ôïõ±÷¾ù ü‹þ.åžG Í +á4…uäÓGFÛ  ²>ºü<ùÙõ¨ò¾ï.í ëaé>èªçªç>èeéëMí÷ïóföúÈýšc }  c³„Ê}›#†tð Ý uêUËübù0öGó¹ð“îãì°ëþêÑê%ë÷ë=ííîùðRóæõ£øwûOþ¾6n\ ô 1 ˆ¢^Ä Û ¯ I ¹ JˆÐ.®þWý2üCûŽúúÔùËùõùLúÇú^û ü½ürýþ¹þ=ÿ¤ÿèÿÙÿÿ#ÿ¢þþtýÙüFüÄû]ûûþúûZû×û‹üsýŒþÐÿ8»OçxóM x i  u  / ƒ {  fe$¯ÿdü°ù ÷„ô0ò ðcîíì ë¤ë'ì)í§îšð÷ò³õ¼øüoÿïlÐ  ôŒºoŸAQÌ´çID ì T“ÂþöúI÷Ñó¥ð×ízëœéGè…çXçÁç¼èCêKìÅî¡ñÍô3ø½ûVÿäT „ RSN@\U m ®Öù)ÿwüõù°÷µõôÅòÜñUñ0ñjñýñßòôlõþö°øtú>üÿý«ÿ6™ËƇ WhEô}æ;„Êräs#øÿñÿP°)´Käwùd®Ðňo“†Nñþxýìû[úÏøV÷üõÏôÙó'óÀò¬òñòó‹ôßõ†÷zù¯ûþ«T¦+ € ”X¼µ9CÎÚj…5 … †Jãgýìù‡öPó[ð»í„ëÃé†èÕç·ç-è6éÌêæìyïsòÄõVùýã°bà íVC¦w³Ykñõ…°‰ &œnýöù±ö²ó ñÊîýì­ëßê•êÐê‹ë½ì]î]ð¯òAõøÜú¿ý–Qß08 ì C :ÍýÌBe @ Þ L —Îþ4~èþyý:ü3ûeúÕù€ùeùùÌù@úÕúû;üúü´ýaþøþtÿÐÿÒÿ|ÿ ÿ‡þõý_ýÍüIüÜûŒûcûeû˜ûþûšüiýiþ–ÿçWÚeìb» ê ã œ ( î [ m & Œ¦|•ÿóüJúª÷&õÏò¸ðîî‚íìïëÙë@ì&í‡î^ð¡òDõ8ølûÌþC¼! [ Vü> T@ÙßWJÄÔ Œ Gxÿªûõ÷pô3ñPîÛëáépèçDççnèÛéÌë3îñ!ô÷ û¨þ@¾  ÊóR.†Xª‚êð¢  Qs‹¬ÿçüOúò÷Ýõô·ò³ññØðþð€ñVòwó×ôjö!øïùÅû—ýWÿøs¾Ó¬I¨Ì¸spÃCƒÎ-¦?üÿÝÿäÿZÂ?Ì^ïtä9ipGë\™¥„>ÿÙý_üÛúYùæ÷Žö^õaô£ó-óó5ó¼óô×õc÷=ùZû¯ý-Çj‰ á üË?Kç °Ø…½‡ ð Ý„þ›ú7÷úóûðMîì+êÔèèÌç$èéˆê‡ìïæñ&õ«ø`ü-üµ? „qóùyiǶVrO4 ×N¯þú8÷#ôdñ ïí²ëÆêaêê$ëAìÐíÄï ò›ô\÷=ú+ýÞ‚ë Û N _ R6½í Ñ s á (VyŸÕ)ÿ¢ýKü*ûDúœù2ùùùOù»ùLúøú·ûüEýþ¬þ>ÿ±ÿ*/ÏÿpÿùþsþäýUýÐü\üüÌû½ûÜû-ü°ügýOþcÿžùjçcÓ) [ Z  › Ë § + W + «ÞÍ„~ýáúHøÇõoóQñ}ïîëìEììbì+ípî*ðRòÝô»÷Üú-þš r° ´i½ŸÝ'Þ—¦9^( ªù-^ü£øõÆñÏîBì.ê è¡ç8çeç(èzéSë¥íbðwóÑöYúùý™#ƒ¡ mÕÍIC¶£ ûuˆD¸ ÷!3^ý°ú;ø ö0ô°ò’ñÙð†ð—ðñÐñçòBôÔõ÷eùHû)ýýþ´FªØÊ~ó*'î‡ùLŒÀô0|àbÐÿÀÿÔÿ `ÏOÚgícÁþÿºB—¼³„ÿ3þËüWûàùtø÷íõëô"ôžóeóóïó·ôÖõI÷ù ûKý¶ÿ>Öiè A b;½ÝŽÉ‹Ï™íÒ U ‚j!ºþIûæ÷¦ôñâî†ì™ê)éAèéç#èïèKê/ìî_ñŒôø®ûxÿGš ï ESÌ­ù´è ìÝ ‡ `¼þ+ûÄ÷›ôÄñOïIí¾ë¶ê4ê:êÃêËëGí,ïlñõó¶öœù’ü‡ÿežÙ  P |B¡š3r`  w »áù3qÿÓýcü)û*újùêø¨ø£øÕø8ùÃùoú1ûüÒüžýZþÿŠÿñÿ3PGÏÿhÿîþgþÜýWýßü}ü9üü'übüÎümý<þ8ÿ\¢mÞE™Ë Ð ( i Y õ 9 ' Âäƒþtûäøhöôìñð…î]í¡ìYì‹ì8í`îþï ò|ôC÷Qú’ýó`à Ò7.ªŸÛÐú§ãÀ P©ãýSùºõ]òTï°ì‚êØè»ç3çCçèçéßêíÈïÐò!ö¦ùHýî…ô& ŒŸ8Oßèkoüä^ ¶»ÀÚýû‹øDöMô±òxñ¥ð:ð5ð“ðMñYò­ó=õûöØøÆú¶üœþhŽÕà¬8ƒ‘g ÖAi—Ñ!Ëÿ£ÿ ÿÂÿbÖXáfßE޵² ŽËÛÃÿˆþ3ýÎûdúù¯÷}övõ¥ôôÊóÐó)ôØôÝõ5÷ÛøÇúîüDÿ»DÏI ¡ Æ ¨8i/ƒ^¾¥² öóº_ÿöû•øRõCò{ïí ë…éƒè è*èØèêÞë%îÝðöó^÷ÿúÃþ‘Tò U hQ 5ÌÌ5 X&„ƒ 6 ´hÿÌûVøõ+òœï{íÓë®êêùéhêYëÂì˜îÍðPóöøø÷û÷þæ²Jž ¢ K ’rêù¥ôí  P p}…—Áÿ þƒü0ûú?ù¨øRø;ø^ø¶ø;ùåù©ú~ûZü4ýþ¼þ[ÿÚÿ4iw`'ÒÿeÿèþbþÞýcýúü«ü}üwüžüóüzý0þÿ!Qœø\» ; D  ±   ¸   Ñ9Z>ò…þü}ù÷¯ôˆò¢ð ïÓíí£ì»ìMíYîÚïÌñ"ôÒöËùüüPµX j 7¬·JZÝÐ0HbS óX—ÊýúcöùòÞï$íÝêéÞç7ç(ç°çËèrê˜ì1ï+òsõóø•üAâ`¥ Ÿ :iT%ÂÝ~±‚ E [YR\þ†ûãø‚öqôºòfñxðôïÙï#ðÍðÍñó¦ôdöGø?ú>ü5þÖjÊïÔv×÷Û‰aœÄã-i¿4Îÿÿsÿÿ®ÿüÿaÙ[Þ[ÇO^B÷}ÒûúÿÕþ”ý@üãúŠù>ø ÷ö)õŒô3ô&ôiôõìõ*÷¶øˆú—üÙþ=¸7« * ¯ðÊ5*¦¨5Q d vN üCùÿõêòð›í†ëèéËè:è8èÉèêé•ëÀíaðfó½öRúþÛ¡G · Û óÆÄâi\ç&ä fÅqüìøõ™òñïµíðë­êñé¿éêíêBìî/ð«ògõRøWûcþaAï[ z > ¡œ,Srx0 ¦ ç Kþ«ü>û úùmøøØ÷ì÷8øµøZùúùúßûÅü¤ýqþ&ÿ¼ÿ.{  {6Øÿfÿçþeþèýyý ýåüÎüàü ýý-þøþîÿ>‰Þ3{«· “ 6 – ­ t è ÙZ•‘[ÿüú£÷Nõ%ó8ñ–ïNîjíôìóìjíYî¾ï”ñÐógöKùjü±ÿ fª  š;å­½<*oÛá ’ J€þ¹ú÷™ómðží?ë^éèCçç€ç~è êìŸîŠñÆôAøâû“ÿ;Ç - â,þP\Fü@§ í ùèãþúûBùÉöôËò[ñSðµïƒï¸ïQðCñ‡òôÍõ´÷µùÀûÇý½ÿ’?¸öô®$XLŽë&J`tŽ·øVØÿÿNÿCÿ^ÿ™ÿñÿ\×WÕF¤åüÇdÒ)ÿïý­ü_ûúËø÷ö±õ õ¡ô‚ô°ô0õö'÷˜øQúHüsþÄ/£c Œ |#s`áï…¤M…W Ì óÞHýðù¬ö’ó¶ð,îìPêénèOèÂèÅéSëcíëïÚò ö¨ù]ý&íš J#{à´ñ•¥&#¨Æ xÆý‡ù'öóMðöíìµêÛéŒéÇé‡êÇëzí•ïò¿ôª÷µúËýØÉŒ J ) §½h¦{ì =  —’€qs’þÚüTû úÿø9ø·÷y÷}÷¼÷/øÐø”ùrú`ûRü@ýþéþ–ÿ …ÂØÈ–Fáÿjÿìþoþûý™ýQý*ý)ýSý«ý1þäþÂÿÄæe®ï) ¸ & N * µ ï ØtÈݽvÿý¦ú>øìõÂóÐñ$ðÍî×íKí1ííaîªïcñ…óöÑøÝûÿeºý ùŠºy»v£?KÌÉNi , «ü5ÿnû¾÷=ôñî¨ë­é9èWç çWç9èªé¢ëîìðô÷.ûáþ’*’ ¶ ‚çÖE-Š]©u˸K• ª‚oÿuü§ù÷ÑôäòXñ5ð}ï2ïSïØï½ðõñwó4õ÷'ù>ûTý]ÿH žõ ßl´¹u±Òáéõ 8€êÿyÿ0ÿÿÿ<ÿ„ÿäÿUÑNÄ)w¦°DÊ#R[ÿDþýÖû“úVù+ø÷9öˆõõãôþôgõ!ö+÷‚ø!úüþR¬vÅ ï ä ”òñ‡­^˜]²ž , jh7íýœúZ÷<ôXñÁî‰ì¿êqé©ènèÃè¨éë í|ïUòˆõù¬üp8êp ´ !)«œ÷ºç„™3b8 Ê-xÄý&ú¶öˆó°ð?îBìÄêÍéaé€é'êPëñìüîdñô÷ú/ýIK#À ¦ØœóÞb†SÕ  - "çÖàþýrûúêø øs÷!÷÷C÷¬÷Gø ùéùÝúÚûÖüÇý¥þhÿ ‡Ü ð±Wëÿrÿöþ~þþÂý‹ýxýŽýÏý=þ×þÿˆ”ºñ-eŽ›‚ 7 ² ê Ú { ΠІô!æÿ”ý4ûÖø‰ö`ôiò´ðPïHî¨íví¹íqîžï;ñAó¦õ]øUû}þÂPo Vó4b7€:dºì  P«êÿ#ünøãô™ñ¤îìêsèsç ç6çûçPé/ëŠíRðuóÞöyú/þå‰ 8 š¥17²¡éROì= S C baresip-1.0.0/src/000077500000000000000000000000001372575704200137405ustar00rootroot00000000000000baresip-1.0.0/src/account.c000066400000000000000000000677401372575704200155560ustar00rootroot00000000000000/** * @file src/account.c User-Agent account * * Copyright (C) 2010 Creytiv.com */ #include #include #include #include "core.h" enum { REG_INTERVAL = 3600, }; static void destructor(void *arg) { struct account *acc = arg; size_t i; list_clear(&acc->aucodecl); list_clear(&acc->vidcodecl); mem_deref(acc->auth_user); mem_deref(acc->auth_pass); for (i=0; ioutboundv); i++) mem_deref(acc->outboundv[i]); mem_deref(acc->regq); mem_deref(acc->sipnat); mem_deref(acc->stun_user); mem_deref(acc->stun_pass); mem_deref(acc->stun_host); mem_deref(acc->mnatid); mem_deref(acc->mencid); mem_deref(acc->aor); mem_deref(acc->dispname); mem_deref(acc->buf); mem_deref(acc->ausrc_mod); mem_deref(acc->ausrc_dev); mem_deref(acc->auplay_mod); mem_deref(acc->auplay_dev); mem_deref(acc->extra); } static int param_dstr(char **dstr, const struct pl *params, const char *name) { struct pl pl; if (msg_param_decode(params, name, &pl)) return 0; return pl_strdup(dstr, &pl); } static int param_u32(uint32_t *v, const struct pl *params, const char *name) { struct pl pl; if (msg_param_decode(params, name, &pl)) return 0; *v = pl_u32(&pl); return 0; } /* * Decode STUN parameters, inspired by RFC 7064 * * See RFC 3986: * * Use of the format "user:password" in the userinfo field is * deprecated. * */ static int stunsrv_decode(struct account *acc, const struct sip_addr *aor) { struct pl srv, tmp; int err; if (!acc || !aor) return EINVAL; if (0 == msg_param_decode(&aor->params, "stunserver", &srv)) { info("using stunserver: '%r'\n", &srv); err = stunuri_decode(&acc->stun_host, &srv); if (err) { warning("account: decode '%r' failed: %m\n", &srv, err); } } err = 0; if (0 == msg_param_exists(&aor->params, "stunuser", &tmp)) err |= param_dstr(&acc->stun_user, &aor->params, "stunuser"); else err |= pl_strdup(&acc->stun_user, &aor->uri.user); if (0 == msg_param_exists(&aor->params, "stunpass", &tmp)) err |= param_dstr(&acc->stun_pass, &aor->params, "stunpass"); else if (acc->auth_pass) err |= str_dup(&acc->stun_pass, acc->auth_pass); return err; } /* Decode media parameters */ static int media_decode(struct account *acc, const struct pl *prm) { int err = 0; if (!acc || !prm) return EINVAL; err |= param_dstr(&acc->mencid, prm, "mediaenc"); err |= param_dstr(&acc->mnatid, prm, "medianat"); err |= param_u32(&acc->ptime, prm, "ptime" ); return err; } /* Decode extra parameter */ static int extra_decode(struct account *acc, const struct pl *prm) { int err = 0; if (!acc || !prm) return EINVAL; err |= param_dstr(&acc->extra, prm, "extra"); return err; } static int decode_pair(char **val1, char **val2, const struct pl *params, const char *name) { struct pl val, pl1, pl2; int err = 0; if (0 == msg_param_decode(params, name, &val)) { /* note: second value may be quoted */ err = re_regex(val.p, val.l, "[^,]+,[~]*", &pl1, &pl2); if (err) return err; err = pl_strdup(val1, &pl1); err |= pl_strdup(val2, &pl2); if (err) return err; } return 0; } /* Decode answermode parameter */ static void answermode_decode(struct account *prm, const struct pl *pl) { struct pl amode; prm->answermode = ANSWERMODE_MANUAL; if (0 == msg_param_decode(pl, "answermode", &amode)) { if (0 == pl_strcasecmp(&amode, "manual")) { prm->answermode = ANSWERMODE_MANUAL; } else if (0 == pl_strcasecmp(&amode, "early")) { prm->answermode = ANSWERMODE_EARLY; } else if (0 == pl_strcasecmp(&amode, "auto")) { prm->answermode = ANSWERMODE_AUTO; } else { warning("account: answermode unknown (%r)\n", &amode); } } } static int csl_parse(struct pl *pl, char *str, size_t sz) { struct pl ws = PL_INIT, val, ws2 = PL_INIT, cma = PL_INIT; int err; err = re_regex(pl->p, pl->l, "[ \t]*[^, \t]+[ \t]*[,]*", &ws, &val, &ws2, &cma); if (err) return err; pl_advance(pl, ws.l + val.l + ws2.l + cma.l); (void)pl_strcpy(&val, str, sz); return 0; } static int audio_codecs_decode(struct account *acc, const struct pl *prm) { struct list *aucodecl = baresip_aucodecl(); struct pl tmp; if (!acc || !prm) return EINVAL; list_init(&acc->aucodecl); if (0 == msg_param_exists(prm, "audio_codecs", &tmp)) { struct pl acs; char cname[64]; unsigned i = 0; if (msg_param_decode(prm, "audio_codecs", &acs)) return 0; while (0 == csl_parse(&acs, cname, sizeof(cname))) { struct aucodec *ac; struct pl pl_cname, pl_srate, pl_ch = PL_INIT; uint32_t srate = 8000; uint8_t ch = 1; /* Format: "codec/srate/ch" */ if (0 == re_regex(cname, str_len(cname), "[^/]+/[0-9]+[/]*[0-9]*", &pl_cname, &pl_srate, NULL, &pl_ch)) { (void)pl_strcpy(&pl_cname, cname, sizeof(cname)); srate = pl_u32(&pl_srate); if (pl_isset(&pl_ch)) ch = pl_u32(&pl_ch); } ac = (struct aucodec *)aucodec_find(aucodecl, cname, srate, ch); if (!ac) { warning("account: audio codec not found:" " %s/%u/%d\n", cname, srate, ch); continue; } /* NOTE: static list with references to aucodec */ list_append(&acc->aucodecl, &acc->acv[i++], ac); if (i >= ARRAY_SIZE(acc->acv)) break; } } return 0; } static int video_codecs_decode(struct account *acc, const struct pl *prm) { struct list *vidcodecl = baresip_vidcodecl(); struct pl tmp; if (!acc || !prm) return EINVAL; list_init(&acc->vidcodecl); if (0 == msg_param_exists(prm, "video_codecs", &tmp)) { struct pl vcs; char cname[64]; unsigned i = 0; if (msg_param_decode(prm, "video_codecs", &vcs)) return 0; while (0 == csl_parse(&vcs, cname, sizeof(cname))) { struct vidcodec *vc; vc = (struct vidcodec *)vidcodec_find(vidcodecl, cname, NULL); if (!vc) { warning("account: video codec not found: %s\n", cname); continue; } /* NOTE: static list with references to vidcodec */ list_append(&acc->vidcodecl, &acc->vcv[i++], vc); if (i >= ARRAY_SIZE(acc->vcv)) break; } } return 0; } static int sip_params_decode(struct account *acc, const struct sip_addr *aor) { struct pl auth_user, tmp; size_t i; int err = 0; if (!acc || !aor) return EINVAL; acc->regint = REG_INTERVAL + (rand_u32()&0xff); err |= param_u32(&acc->regint, &aor->params, "regint"); err |= param_u32(&acc->rwait, &aor->params, "rwait"); if (acc->rwait > 95) acc->rwait = 95; if (acc->rwait && acc->rwait < 5) acc->rwait = 5; acc->pubint = 0; err |= param_u32(&acc->pubint, &aor->params, "pubint"); err |= param_dstr(&acc->regq, &aor->params, "regq"); for (i=0; ioutboundv); i++) { char expr[16] = "outbound"; expr[8] = (char)(i + 1 + 0x30); expr[9] = '\0'; err |= param_dstr(&acc->outboundv[i], &aor->params, expr); } /* backwards compat */ if (!acc->outboundv[0]) { err |= param_dstr(&acc->outboundv[0], &aor->params, "outbound"); } err |= param_dstr(&acc->sipnat, &aor->params, "sipnat"); if (0 == msg_param_decode(&aor->params, "auth_user", &auth_user)) err |= pl_strdup(&acc->auth_user, &auth_user); if (pl_isset(&aor->dname)) err |= pl_strdup(&acc->dispname, &aor->dname); if (0 != msg_param_decode(&aor->params, "mwi", &tmp)) acc->mwi = true; else acc->mwi = pl_strcasecmp(&tmp, "no") != 0; if (0 != msg_param_decode(&aor->params, "call_transfer", &tmp)) acc->refer = true; else acc->refer = pl_strcasecmp(&tmp, "no") != 0; return err; } static int encode_uri_user(struct re_printf *pf, const struct uri *uri) { struct uri uuri = *uri; uuri.password = uuri.params = uuri.headers = pl_null; return uri_encode(pf, &uuri); } /** * Create a SIP account from a sip address string * * @param accp Pointer to allocated SIP account object * @param sipaddr SIP address with parameters * * @return 0 if success, otherwise errorcode */ int account_alloc(struct account **accp, const char *sipaddr) { struct account *acc; struct pl pl; int err = 0; if (!accp || !sipaddr) return EINVAL; acc = mem_zalloc(sizeof(*acc), destructor); if (!acc) return ENOMEM; err = str_dup(&acc->buf, sipaddr); if (err) goto out; pl_set_str(&pl, acc->buf); err = sip_addr_decode(&acc->laddr, &pl); if (err) { warning("account: error parsing SIP address: '%r'\n", &pl); goto out; } acc->luri = acc->laddr.uri; acc->luri.password = pl_null; err = re_sdprintf(&acc->aor, "%H", encode_uri_user, &acc->luri); if (err) goto out; /* Decode parameters */ acc->ptime = 20; err |= sip_params_decode(acc, &acc->laddr); answermode_decode(acc, &acc->laddr.params); err |= audio_codecs_decode(acc, &acc->laddr.params); err |= video_codecs_decode(acc, &acc->laddr.params); err |= media_decode(acc, &acc->laddr.params); if (err) goto out; err = decode_pair(&acc->ausrc_mod, &acc->ausrc_dev, &acc->laddr.params, "audio_source"); err |= decode_pair(&acc->auplay_mod, &acc->auplay_dev, &acc->laddr.params, "audio_player"); if (err) { warning("account: audio_source/player parse error\n"); goto out; } /* optional password prompt */ if (0 == msg_param_decode(&acc->laddr.params, "auth_pass", &pl)) { err = pl_strdup(&acc->auth_pass, &pl); if (err) goto out; } err = stunsrv_decode(acc, &acc->laddr); if (err) goto out; if (acc->mnatid) { acc->mnat = mnat_find(baresip_mnatl(), acc->mnatid); if (!acc->mnat) { warning("account: medianat not found: '%s'\n", acc->mnatid); } } if (acc->mencid) { acc->menc = menc_find(baresip_mencl(), acc->mencid); if (!acc->menc) { warning("account: mediaenc not found: '%s'\n", acc->mencid); } } err |= extra_decode(acc, &acc->laddr.params); out: if (err) mem_deref(acc); else *accp = acc; return err; } /** * Set the authentication user for a SIP account * * @param acc User-Agent account * @param user Authentication username (NULL to reset) * * @return 0 if success, otherwise errorcode */ int account_set_auth_user(struct account *acc, const char *user) { if (!acc) return EINVAL; acc->auth_user = mem_deref(acc->auth_user); if (user) return str_dup(&acc->auth_user, user); return 0; } /** * Set the authentication password for a SIP account * * @param acc User-Agent account * @param pass Authentication password (NULL to reset) * * @return 0 if success, otherwise errorcode */ int account_set_auth_pass(struct account *acc, const char *pass) { if (!acc) return EINVAL; acc->auth_pass = mem_deref(acc->auth_pass); if (pass) return str_dup(&acc->auth_pass, pass); return 0; } /** * Set an outbound proxy for a SIP account * * @param acc User-Agent account * @param ob Outbound proxy * @param ix Index of outbound proxy * * @return 0 if success, otherwise errorcode */ int account_set_outbound(struct account *acc, const char *ob, unsigned ix) { if (!acc || ix >= ARRAY_SIZE(acc->outboundv)) return EINVAL; acc->outboundv[ix] = mem_deref(acc->outboundv[ix]); if (ob) return str_dup(&(acc->outboundv[ix]), ob); return 0; } /** * Set the SIP nat protocol for a SIP account * * @param acc User-Agent account * @param sipnat SIP nat protocol * * @return 0 if success, otherwise errorcode */ int account_set_sipnat(struct account *acc, const char *sipnat) { if (!acc) return EINVAL; acc->sipnat = mem_deref(acc->sipnat); if (sipnat) return str_dup(&acc->sipnat, sipnat); return 0; } /** * Set the SIP registration interval for a SIP account * * @param acc User-Agent account * @param regint Registration interval in [seconds] * * @return 0 if success, otherwise errorcode */ int account_set_regint(struct account *acc, uint32_t regint) { if (!acc) return EINVAL; acc->regint = regint; return 0; } /** * Set the STUN server URI for a SIP account * * @param acc User-Agent account * @param uri STUN server URI (NULL to reset) * * @return 0 if success, otherwise errorcode */ int account_set_stun_uri(struct account *acc, const char *uri) { struct pl pl; int err; if (!acc) return EINVAL; acc->stun_host = mem_deref(acc->stun_host); if (!uri) return 0; pl_set_str(&pl, uri); err = stunuri_decode(&acc->stun_host, &pl); if (err) warning("account: decode '%r' failed: %m\n", &pl, err); return err; } /** * Set the stun host for a SIP account * * @param acc User-Agent account * @param host Stun host (NULL to reset) * * @return 0 if success, otherwise errorcode */ int account_set_stun_host(struct account *acc, const char *host) { if (!acc) return EINVAL; if (acc->stun_host) return stunuri_set_host(acc->stun_host, host); return 0; } /** * Set the port of the STUN host of a SIP account * * @param acc User-Agent account * @param port Port number * * @return 0 if success, otherwise errorcode */ int account_set_stun_port(struct account *acc, uint16_t port) { if (!acc) return EINVAL; if (acc->stun_host) return stunuri_set_port(acc->stun_host, port); return 0; } /** * Set the STUN user for a SIP account * * @param acc User-Agent account * @param user STUN username (NULL to reset) * * @return 0 if success, otherwise errorcode */ int account_set_stun_user(struct account *acc, const char *user) { if (!acc) return EINVAL; acc->stun_user = mem_deref(acc->stun_user); if (user) return str_dup(&acc->stun_user, user); return 0; } /** * Set the STUN password for a SIP account * * @param acc User-Agent account * @param pass STUN password (NULL to reset) * * @return 0 if success, otherwise errorcode */ int account_set_stun_pass(struct account *acc, const char *pass) { if (!acc) return EINVAL; acc->stun_pass = mem_deref(acc->stun_pass); if (pass) return str_dup(&acc->stun_pass, pass); return 0; } /** * Set the media encryption for a SIP account * * @param acc User-Agent account * @param mencid Media encryption id * * @return 0 if success, otherwise errorcode */ int account_set_mediaenc(struct account *acc, const char *mencid) { const struct menc *menc = NULL; if (!acc) return EINVAL; if (mencid) { menc = menc_find(baresip_mencl(), mencid); if (!menc) { warning("account: mediaenc not found: `%s'\n", mencid); return EINVAL; } } acc->mencid = mem_deref(acc->mencid); acc->menc = NULL; if (mencid) { acc->menc = menc; return str_dup(&acc->mencid, mencid); } return 0; } /** * Set the media NAT handling for a SIP account * * @param acc User-Agent account * @param mnatid Media NAT handling id * * @return 0 if success, otherwise errorcode */ int account_set_medianat(struct account *acc, const char *mnatid) { const struct mnat *mnat = NULL; if (!acc) return EINVAL; if (mnatid) { mnat = mnat_find(baresip_mnatl(), mnatid); if (!mnat) { warning("account: medianat not found: `%s'\n", mnatid); return EINVAL; } } acc->mnatid = mem_deref(acc->mnatid); acc->mnat = NULL; if (mnatid) { acc->mnat = mnat; return str_dup(&acc->mnatid, mnatid); } return 0; } /** * Sets audio codecs * * @param acc User-Agent account * @param codecs Comma separated list of audio codecs (NULL to disable) * * @return 0 if success, otherwise errorcode */ int account_set_audio_codecs(struct account *acc, const char *codecs) { char buf[256]; struct pl pl; if (!acc) return EINVAL; list_clear(&acc->aucodecl); if (codecs) { re_snprintf(buf, sizeof(buf), ";audio_codecs=%s", codecs); pl_set_str(&pl, buf); return audio_codecs_decode(acc, &pl); } return 0; } /** * Sets video codecs * * @param acc User-Agent account * @param codecs Comma separated list of video codecs (NULL to disable) * * @return 0 if success, otherwise errorcode */ int account_set_video_codecs(struct account *acc, const char *codecs) { char buf[256]; struct pl pl; if (!acc) return EINVAL; list_clear(&acc->vidcodecl); if (codecs) { re_snprintf(buf, sizeof(buf), ";video_codecs=%s", codecs); pl_set_str(&pl, buf); return video_codecs_decode(acc, &pl); } return 0; } /** * Sets the displayed name. Pass null in dname to disable display name * * @param acc User-Agent account * @param dname Display name (NULL to disable) * * @return 0 if success, otherwise errorcode */ int account_set_display_name(struct account *acc, const char *dname) { if (!acc) return EINVAL; acc->dispname = mem_deref(acc->dispname); if (dname) return str_dup(&acc->dispname, dname); return 0; } /** * Sets MWI on (value "yes") or off (value "no") * * @param acc User-Agent account * @param value "yes" or "no" * * @return 0 if success, otherwise errorcode */ int account_set_mwi(struct account *acc, const char *value) { if (!acc) return EINVAL; if (0 == str_casecmp(value, "yes")) acc->mwi = true; else if (0 == str_casecmp(value, "no")) acc->mwi = false; else { warning("account: unknown mwi value: %r\n", value); return EINVAL; } return 0; } /** * Sets call transfer on (value "yes") or off (value "no") * * @param acc User-Agent account * @param value "yes" or "no" * * @return 0 if success, otherwise errorcode */ int account_set_call_transfer(struct account *acc, const char *value) { if (!acc) return EINVAL; if (0 == str_casecmp(value, "yes")) acc->refer = true; else if (0 == str_casecmp(value, "no")) acc->refer = false; else { warning("account: unknown call transfer: %r\n", value); return EINVAL; } return 0; } /** * Authenticate a User-Agent (UA) * * @param acc User-Agent account * @param username Pointer to allocated username string * @param password Pointer to allocated password string * @param realm Realm string * * @return 0 if success, otherwise errorcode */ int account_auth(const struct account *acc, char **username, char **password, const char *realm) { int err = 0; if (!acc) return EINVAL; (void)realm; if (acc->auth_user) *username = mem_ref(acc->auth_user); else err = pl_strdup(username, &(acc->luri.user)); *password = mem_ref(acc->auth_pass); return err; } /** * Get the audio codecs of an account * * @param acc User-Agent account * * @return List of audio codecs (struct aucodec) */ struct list *account_aucodecl(const struct account *acc) { return (acc && !list_isempty(&acc->aucodecl)) ? (struct list *)&acc->aucodecl : baresip_aucodecl(); } /** * Get the video codecs of an account * * @param acc User-Agent account * * @return List of video codecs (struct vidcodec) */ struct list *account_vidcodecl(const struct account *acc) { return (acc && !list_isempty(&acc->vidcodecl)) ? (struct list *)&acc->vidcodecl : baresip_vidcodecl(); } /** * Get the SIP address of an account * * @param acc User-Agent account * * @return SIP address */ struct sip_addr *account_laddr(const struct account *acc) { return acc ? (struct sip_addr *)&acc->laddr : NULL; } /** * Get the decoded AOR URI of an account * * @param acc User-Agent account * * @return Decoded URI */ struct uri *account_luri(const struct account *acc) { return acc ? (struct uri *)&acc->luri : NULL; } /** * Get the Registration interval of an account * * @param acc User-Agent account * * @return Registration interval in [seconds] */ uint32_t account_regint(const struct account *acc) { return acc ? acc->regint : 0; } /** * Get the Publication interval of an account * * @param acc User-Agent account * * @return Publication interval in [seconds] */ uint32_t account_pubint(const struct account *acc) { return acc ? acc->pubint : 0; } /** * Get the answermode of an account * * @param acc User-Agent account * * @return Answermode */ enum answermode account_answermode(const struct account *acc) { return acc ? acc->answermode : ANSWERMODE_MANUAL; } /** * Set the answermode of an account * * @param acc User-Agent account * @param mode Answermode * * @return 0 if success, otherwise errorcode */ int account_set_answermode(struct account *acc, enum answermode mode) { if (!acc) return EINVAL; if ((mode != ANSWERMODE_MANUAL) && (mode != ANSWERMODE_EARLY) && (mode != ANSWERMODE_AUTO)) { warning("account: invalid answermode : `%d'\n", mode); return EINVAL; } acc->answermode = mode; return 0; } /** * Get the SIP Display Name of an account * * @param acc User-Agent account * * @return SIP Display Name */ const char *account_display_name(const struct account *acc) { return acc ? acc->dispname : NULL; } /** * Get the SIP Address-of-Record (AOR) of an account * * @param acc User-Agent account * * @return SIP Address-of-Record (AOR) */ const char *account_aor(const struct account *acc) { return acc ? acc->aor : NULL; } /** * Get the authentication username of an account * * @param acc User-Agent account * * @return Authentication username */ const char *account_auth_user(const struct account *acc) { return acc ? acc->auth_user : NULL; } /** * Get the SIP authentication password of an account * * @param acc User-Agent account * * @return Authentication password */ const char *account_auth_pass(const struct account *acc) { return acc ? acc->auth_pass : NULL; } /** * Get the outbound SIP server of an account * * @param acc User-Agent account * @param ix Index starting at zero * * @return Outbound SIP proxy, NULL if not configured */ const char *account_outbound(const struct account *acc, unsigned ix) { if (!acc || ix >= ARRAY_SIZE(acc->outboundv)) return NULL; return acc->outboundv[ix]; } /** * Get sipnat protocol of an account * * @param acc User-Agent account * * @return sipnat protocol or NULL if not set */ const char *account_sipnat(const struct account *acc) { return acc ? acc->sipnat : NULL; } /** * Get the audio packet-time (ptime) of an account * * @param acc User-Agent account * * @return Packet-time (ptime) */ uint32_t account_ptime(const struct account *acc) { return acc ? acc->ptime : 0; } /** * Get the STUN username of an account * * @param acc User-Agent account * * @return STUN username */ const char *account_stun_user(const struct account *acc) { return acc ? acc->stun_user : NULL; } /** * Get the STUN password of an account * * @param acc User-Agent account * * @return STUN password */ const char *account_stun_pass(const struct account *acc) { return acc ? acc->stun_pass : NULL; } /** * Get the STUN server URI of an account * * @param acc User-Agent account * * @return STUN server URI */ const struct stun_uri *account_stun_uri(const struct account *acc) { if (!acc) return NULL; return acc->stun_host ? acc->stun_host : NULL; } /** * Get the STUN hostname of an account * * @param acc User-Agent account * * @return STUN hostname */ const char *account_stun_host(const struct account *acc) { if (!acc) return NULL; return acc->stun_host ? acc->stun_host->host : NULL; } /** * Get the port of the STUN host of an account * * @param acc User-Agent account * * @return Port number or 0 if not set */ uint16_t account_stun_port(const struct account *acc) { if (!acc) return 0; return acc->stun_host ? acc->stun_host->port : 0; } static const char *answermode_str(enum answermode mode) { switch (mode) { case ANSWERMODE_MANUAL: return "manual"; case ANSWERMODE_EARLY: return "early"; case ANSWERMODE_AUTO: return "auto"; default: return "???"; } } /** * Get the media encryption of an account * * @param acc User-Agent account * * @return Media encryption id or NULL if not set */ const char *account_mediaenc(const struct account *acc) { return acc ? acc->mencid : NULL; } /** * Get the media NAT handling of an account * * @param acc User-Agent account * * @return Media NAT handling id or NULL if not set */ const char *account_medianat(const struct account *acc) { return acc ? acc->mnatid : NULL; } /** * Get MWI capability of an account * * @param acc User-Agent account * * @return "yes" or "no" */ const char *account_mwi(const struct account *acc) { if (!acc) return "no"; return acc->mwi ? "yes" : "no"; } /** * Get call transfer capability of an account * * @param acc User-Agent account * * @return "yes" or "no" */ const char *account_call_transfer(const struct account *acc) { if (!acc) return "no"; return acc->refer ? "yes" : "no"; } /** * Get extra parameter value of an account * * @param acc User-Agent account * * @return extra parameter value */ const char *account_extra(const struct account *acc) { return acc ? acc->extra : NULL; } /** * Print the account debug information * * @param pf Print function * @param acc User-Agent account * * @return 0 if success, otherwise errorcode */ int account_debug(struct re_printf *pf, const struct account *acc) { struct le *le; size_t i; int err = 0; if (!acc) return 0; err |= re_hprintf(pf, "\nAccount:\n"); err |= re_hprintf(pf, " address: %s\n", acc->buf); err |= re_hprintf(pf, " luri: %H\n", uri_encode, &acc->luri); err |= re_hprintf(pf, " aor: %s\n", acc->aor); err |= re_hprintf(pf, " dispname: %s\n", acc->dispname); err |= re_hprintf(pf, " answermode: %s\n", answermode_str(acc->answermode)); if (!list_isempty(&acc->aucodecl)) { err |= re_hprintf(pf, " audio_codecs:"); for (le = list_head(&acc->aucodecl); le; le = le->next) { const struct aucodec *ac = le->data; err |= re_hprintf(pf, " %s/%u/%u", ac->name, ac->srate, ac->ch); } err |= re_hprintf(pf, "\n"); } err |= re_hprintf(pf, " auth_user: %s\n", acc->auth_user); err |= re_hprintf(pf, " mediaenc: %s\n", acc->mencid ? acc->mencid : "none"); err |= re_hprintf(pf, " medianat: %s\n", acc->mnatid ? acc->mnatid : "none"); for (i=0; ioutboundv); i++) { if (acc->outboundv[i]) { err |= re_hprintf(pf, " outbound%d: %s\n", i+1, acc->outboundv[i]); } } err |= re_hprintf(pf, " mwi: %s\n", account_mwi(acc)); err |= re_hprintf(pf, " ptime: %u\n", acc->ptime); err |= re_hprintf(pf, " regint: %u\n", acc->regint); err |= re_hprintf(pf, " pubint: %u\n", acc->pubint); err |= re_hprintf(pf, " regq: %s\n", acc->regq); err |= re_hprintf(pf, " sipnat: %s\n", acc->sipnat); err |= re_hprintf(pf, " stunuser: %s\n", acc->stun_user); err |= re_hprintf(pf, " stunserver: %H\n", stunuri_print, acc->stun_host); if (!list_isempty(&acc->vidcodecl)) { err |= re_hprintf(pf, " video_codecs:"); for (le = list_head(&acc->vidcodecl); le; le = le->next) { const struct vidcodec *vc = le->data; err |= re_hprintf(pf, " %s", vc->name); } err |= re_hprintf(pf, "\n"); } err |= re_hprintf(pf, " call_transfer:%s\n", account_call_transfer(acc)); err |= re_hprintf(pf, " extra: %s\n", acc->extra ? acc->extra : "none"); return err; } /** * Print the account information in JSON * * @param od Account dict * @param odcfg Configuration dict * @param acc User-Agent account * * @return 0 if success, otherwise errorcode */ int account_json_api(struct odict *od, struct odict *odcfg, const struct account *acc) { int err = 0; struct odict *obn = NULL; const char *stunhost = ""; if (!acc) return 0; /* account */ err |= odict_entry_add(od, "aor", ODICT_STRING, acc->aor); if (acc->dispname) { err |= odict_entry_add(od, "display_name", ODICT_STRING, acc->dispname); } /* config */ if (acc->sipnat) { err |= odict_entry_add(odcfg, "sip_nat", ODICT_STRING, acc->sipnat); } err |= odict_alloc(&obn, 8); for (size_t i=0; ioutboundv); i++) { if (acc->outboundv[i]) { err |= odict_entry_add(obn, "outbound", ODICT_STRING, acc->outboundv[i]); } } err |= odict_entry_add(odcfg, "sip_nat_outbound", ODICT_ARRAY, obn); stunhost = account_stun_host(acc) ? account_stun_host(acc) : ""; err |= odict_entry_add(odcfg, "stun_host", ODICT_STRING, stunhost); err |= odict_entry_add(odcfg, "stun_port", ODICT_INT, account_stun_port(acc)); if (acc->stun_user) { err |= odict_entry_add(odcfg, "stun_user", ODICT_STRING, acc->stun_user); } err |= odict_entry_add(odcfg, "answer_mode", ODICT_STRING, answermode_str(acc->answermode)); err |= odict_entry_add(odcfg, "call_transfer", ODICT_BOOL, acc->refer); err |= odict_entry_add(odcfg, "packet_time", ODICT_INT, account_ptime(acc)); mem_deref(obn); return err; } baresip-1.0.0/src/aucodec.c000066400000000000000000000024211372575704200155060ustar00rootroot00000000000000/** * @file aucodec.c Audio Codec * * Copyright (C) 2010 Creytiv.com */ #include #include #include "core.h" /** * Register an Audio Codec * * @param aucodecl List of audio-codecs * @param ac Audio Codec object */ void aucodec_register(struct list *aucodecl, struct aucodec *ac) { if (!aucodecl || !ac) return; list_append(aucodecl, &ac->le, ac); info("aucodec: %s/%u/%u\n", ac->name, ac->srate, ac->ch); } /** * Unregister an Audio Codec * * @param ac Audio Codec object */ void aucodec_unregister(struct aucodec *ac) { if (!ac) return; list_unlink(&ac->le); } /** * Find an Audio Codec * * @param aucodecl List of audio-codecs * @param name Audio codec name * @param srate Audio codec sampling rate * @param ch Audio codec number of channels * * @return Matching audio codec if found, NULL if not found */ const struct aucodec *aucodec_find(const struct list *aucodecl, const char *name, uint32_t srate, uint8_t ch) { struct le *le; for (le=list_head(aucodecl); le; le=le->next) { struct aucodec *ac = le->data; if (name && 0 != str_casecmp(name, ac->name)) continue; if (srate && srate != ac->srate) continue; if (ch && ch != ac->ch) continue; return ac; } return NULL; } baresip-1.0.0/src/audio.c000066400000000000000000001441671372575704200152220ustar00rootroot00000000000000/** * @file src/audio.c Audio stream * * Copyright (C) 2010 Creytiv.com * \ref GenericAudioStream */ #define _DEFAULT_SOURCE 1 #define _BSD_SOURCE 1 #include #include #ifdef HAVE_UNISTD_H #include #endif #ifdef HAVE_PTHREAD #include #endif #include #include #include #include "core.h" /** Magic number */ #define MAGIC 0x000a0d10 #include "magic.h" /** * \page GenericAudioStream Generic Audio Stream * * Implements a generic audio stream. The application can allocate multiple * instances of a audio stream, mapping it to a particular SDP media line. * The audio object has a DSP sound card sink and source, and an audio encoder * and decoder. A particular audio object is mapped to a generic media * stream object. Each audio channel has an optional audio filtering chain. * *
 *            write  read
 *              |    /|\
 *             \|/    |
 * .------.   .---------.    .-------.
 * |filter|<--|  audio  |--->|encoder|
 * '------'   |         |    |-------|
 *            | object  |--->|decoder|
 *            '---------'    '-------'
 *              |    /|\
 *              |     |
 *             \|/    |
 *         .------. .-----.
 *         |auplay| |ausrc|
 *         '------' '-----'
 *
*/ enum { MAX_SRATE = 48000, /* Maximum sample rate in [Hz] */ MAX_CHANNELS = 2, /* Maximum number of channels */ MAX_PTIME = 60, /* Maximum packet time in [ms] */ AUDIO_SAMPSZ = MAX_SRATE * MAX_CHANNELS * MAX_PTIME / 1000, }; /** * Audio transmit/encoder * * \verbatim Processing encoder pipeline: . .-------. .-------. .--------. .--------. .--------. | | | | | | | | | | | |O-->| ausrc |-->| aubuf |-->| resamp |-->| aufilt |-->| encode |---> RTP | | | | | | | | | | | ' '-------' '-------' '--------' '--------' '--------' \endverbatim * */ struct autx { struct ausrc_st *ausrc; /**< Audio Source */ struct ausrc_prm ausrc_prm; /**< Audio Source parameters */ const struct aucodec *ac; /**< Current audio encoder */ struct auenc_state *enc; /**< Audio encoder state (optional) */ struct aubuf *aubuf; /**< Packetize outgoing stream */ size_t aubuf_maxsz; /**< Maximum aubuf size in [bytes] */ volatile bool aubuf_started; /**< Aubuf was started flag */ struct auresamp resamp; /**< Optional resampler for DSP */ struct list filtl; /**< Audio filters in encoding order */ struct mbuf *mb; /**< Buffer for outgoing RTP packets */ struct media_ctx **ctx; /**< Shared A/V source media context */ char *module; /**< Audio source module name */ char *device; /**< Audio source device name */ void *sampv; /**< Sample buffer */ int16_t *sampv_rs; /**< Sample buffer for resampler */ uint32_t ptime; /**< Packet time for sending */ uint64_t ts_ext; /**< Ext. Timestamp for outgoing RTP */ uint32_t ts_base; /**< First timestamp sent */ uint32_t ts_tel; /**< Timestamp for Telephony Events */ size_t psize; /**< Packet size for sending */ bool marker; /**< Marker bit for outgoing RTP */ bool muted; /**< Audio source is muted */ int cur_key; /**< Currently transmitted event */ enum aufmt src_fmt; /**< Sample format for audio source */ enum aufmt enc_fmt; /**< Sample format for encoder */ bool need_conv; /**< Sample format conversion needed */ struct { uint64_t aubuf_overrun; uint64_t aubuf_underrun; } stats; #ifdef HAVE_PTHREAD union { struct { pthread_t tid;/**< Audio transmit thread */ bool run; /**< Audio transmit thread running */ } thr; } u; #endif }; /** * Audio receive/decoder * \verbatim Processing decoder pipeline: .--------. .-------. .--------. .--------. .--------. |\ | | | | | | | | | | | |<--| auplay |<--| aubuf |<--| resamp |<--| aufilt |<--| decode |<--- RTP |/ | | | | | | | | | | '--------' '-------' '--------' '--------' '--------' \endverbatim */ struct aurx { struct auplay_st *auplay; /**< Audio Player */ struct auplay_prm auplay_prm; /**< Audio Player parameters */ const struct aucodec *ac; /**< Current audio decoder */ struct audec_state *dec; /**< Audio decoder state (optional) */ struct aubuf *aubuf; /**< Incoming audio buffer */ size_t aubuf_maxsz; /**< Maximum aubuf size in [bytes] */ volatile bool aubuf_started; /**< Aubuf was started flag */ struct auresamp resamp; /**< Optional resampler for DSP */ struct list filtl; /**< Audio filters in decoding order */ char *module; /**< Audio player module name */ char *device; /**< Audio player device name */ void *sampv; /**< Sample buffer */ int16_t *sampv_rs; /**< Sample buffer for resampler */ uint32_t ptime; /**< Packet time for receiving */ int pt; /**< Payload type for incoming RTP */ double level_last; /**< Last audio level value [dBov] */ bool level_set; /**< True if level_last is set */ enum aufmt play_fmt; /**< Sample format for audio playback*/ enum aufmt dec_fmt; /**< Sample format for decoder */ bool need_conv; /**< Sample format conversion needed */ struct timestamp_recv ts_recv;/**< Receive timestamp state */ size_t last_sampc; struct { uint64_t aubuf_overrun; uint64_t aubuf_underrun; uint64_t n_discard; } stats; }; /** Generic Audio stream */ struct audio { MAGIC_DECL /**< Magic number for debugging */ struct autx tx; /**< Transmit */ struct aurx rx; /**< Receive */ struct stream *strm; /**< Generic media stream */ struct telev *telev; /**< Telephony events */ struct config_audio cfg; /**< Audio configuration */ bool started; /**< Stream is started flag */ bool level_enabled; /**< Audio level RTP ext. enabled */ bool hold; /**< Local hold flag */ unsigned extmap_aulevel; /**< ID Range 1-14 inclusive */ audio_event_h *eventh; /**< Event handler */ audio_level_h *levelh; /**< Audio level handler */ audio_err_h *errh; /**< Audio error handler */ void *arg; /**< Handler argument */ }; /* RFC 6464 */ static const char *uri_aulevel = "urn:ietf:params:rtp-hdrext:ssrc-audio-level"; /** * Get the current audio receive buffer length in milliseconds * * @param au Audio object * * @return Audio buffer length in [ms] */ uint64_t audio_jb_current_value(const struct audio *au) { const struct aurx *rx; if (!au) return 0; rx = &au->rx; if (rx->aubuf) { uint64_t b_p_ms; /* bytes per ms */ b_p_ms = aufmt_sample_size(rx->play_fmt) * rx->auplay_prm.srate * rx->auplay_prm.ch / 1000; if (b_p_ms) { uint64_t val; val = aubuf_cur_size(rx->aubuf) / b_p_ms; return val; } } return 0; } static double autx_calc_seconds(const struct autx *autx) { uint64_t dur; if (!autx->ac) return .0; dur = autx->ts_ext - autx->ts_base; return timestamp_calc_seconds(dur, autx->ac->crate); } static double aurx_calc_seconds(const struct aurx *aurx) { uint64_t dur; if (!aurx->ac) return .0; dur = timestamp_duration(&aurx->ts_recv); return timestamp_calc_seconds(dur, aurx->ac->crate); } static void stop_tx(struct autx *tx, struct audio *a) { if (!tx || !a) return; switch (a->cfg.txmode) { #ifdef HAVE_PTHREAD case AUDIO_MODE_THREAD: if (tx->u.thr.run) { tx->u.thr.run = false; pthread_join(tx->u.thr.tid, NULL); } break; #endif default: break; } /* audio source must be stopped first */ tx->ausrc = mem_deref(tx->ausrc); tx->aubuf = mem_deref(tx->aubuf); list_flush(&tx->filtl); } static void stop_rx(struct aurx *rx) { if (!rx) return; /* audio player must be stopped first */ rx->auplay = mem_deref(rx->auplay); rx->aubuf = mem_deref(rx->aubuf); list_flush(&rx->filtl); } static void audio_destructor(void *arg) { struct audio *a = arg; debug("audio: destroyed (started=%d)\n", a->started); stop_tx(&a->tx, a); stop_rx(&a->rx); mem_deref(a->tx.enc); mem_deref(a->rx.dec); mem_deref(a->tx.aubuf); mem_deref(a->tx.mb); mem_deref(a->tx.sampv); mem_deref(a->rx.sampv); mem_deref(a->rx.aubuf); mem_deref(a->tx.sampv_rs); mem_deref(a->rx.sampv_rs); mem_deref(a->tx.module); mem_deref(a->tx.device); mem_deref(a->rx.module); mem_deref(a->rx.device); list_flush(&a->tx.filtl); list_flush(&a->rx.filtl); mem_deref(a->strm); mem_deref(a->telev); } /** * Calculate number of samples from sample rate, channels and packet time * * @param srate Sample rate in [Hz] * @param channels Number of channels * @param ptime Packet time in [ms] * * @return Number of samples */ static inline uint32_t calc_nsamp(uint32_t srate, uint8_t channels, uint16_t ptime) { return srate * channels * ptime / 1000; } static inline double calc_ptime(size_t nsamp, uint32_t srate, uint8_t channels) { double ptime; ptime = 1000.0 * (double)nsamp / (double)(srate * channels); return ptime; } static bool aucodec_equal(const struct aucodec *a, const struct aucodec *b) { if (!a || !b) return false; return a->srate == b->srate && a->ch == b->ch; } static int add_audio_codec(struct sdp_media *m, struct aucodec *ac) { if (ac->crate < 8000) { warning("audio: illegal clock rate %u\n", ac->crate); return EINVAL; } if (ac->ch == 0 || ac->pch == 0) { warning("audio: illegal channels for audio codec '%s'\n", ac->name); return EINVAL; } return sdp_format_add(NULL, m, false, ac->pt, ac->name, ac->crate, ac->pch, ac->fmtp_ench, ac->fmtp_cmph, ac, false, "%s", ac->fmtp); } static int append_rtpext(struct audio *au, struct mbuf *mb, enum aufmt fmt, const void *sampv, size_t sampc) { uint8_t data[1]; double level; int err; /* audio level must be calculated from the audio samples that * are actually sent on the network. */ level = aulevel_calc_dbov(fmt, sampv, sampc); data[0] = (int)-level & 0x7f; err = rtpext_encode(mb, au->extmap_aulevel, 1, data); if (err) { warning("audio: rtpext_encode failed (%m)\n", err); return err; } return err; } /* * Encode audio and send via stream * * @note This function has REAL-TIME properties */ static void encode_rtp_send(struct audio *a, struct autx *tx, int16_t *sampv, size_t sampc) { size_t frame_size; /* number of samples per channel */ size_t sampc_rtp; size_t len; size_t ext_len = 0; uint32_t ts_delta = 0; bool marker = tx->marker; int err; if (!tx->ac || !tx->ac->ench) return; tx->mb->pos = tx->mb->end = STREAM_PRESZ; if (a->level_enabled) { /* skip the extension header */ tx->mb->pos += RTPEXT_HDR_SIZE; err = append_rtpext(a, tx->mb, tx->enc_fmt, sampv, sampc); if (err) return; ext_len = tx->mb->pos - STREAM_PRESZ; /* write the Extension header at the beginning */ tx->mb->pos = STREAM_PRESZ; err = rtpext_hdr_encode(tx->mb, ext_len - RTPEXT_HDR_SIZE); if (err) return; tx->mb->pos = STREAM_PRESZ + ext_len; tx->mb->end = STREAM_PRESZ + ext_len; } len = mbuf_get_space(tx->mb); err = tx->ac->ench(tx->enc, &marker, mbuf_buf(tx->mb), &len, tx->enc_fmt, sampv, sampc); if ((err & 0xffff0000) == 0x00010000) { /* MPA needs some special treatment here */ ts_delta = err & 0xffff; sampc = 0; } else if (err) { warning("audio: %s encode error: %d samples (%m)\n", tx->ac->name, sampc, err); goto out; } tx->mb->pos = STREAM_PRESZ; tx->mb->end = STREAM_PRESZ + ext_len + len; if (mbuf_get_left(tx->mb)) { uint32_t rtp_ts = tx->ts_ext & 0xffffffff; if (len) { err = stream_send(a->strm, ext_len!=0, marker, -1, rtp_ts, tx->mb); if (err) goto out; } if (ts_delta) { tx->ts_ext += ts_delta; goto out; } } /* Convert from audio samplerate to RTP clockrate */ sampc_rtp = sampc * tx->ac->crate / tx->ac->srate; /* The RTP clock rate used for generating the RTP timestamp is * independent of the number of channels and the encoding * However, MPA support variable packet durations. Thus, MPA * should update the ts according to its current internal state. */ frame_size = sampc_rtp / tx->ac->ch; tx->ts_ext += (uint32_t)frame_size; out: tx->marker = false; } /* * @note This function has REAL-TIME properties */ static void poll_aubuf_tx(struct audio *a) { struct autx *tx = &a->tx; struct auframe af; int16_t *sampv = tx->sampv; size_t sampc; size_t sz; size_t num_bytes; struct le *le; int err = 0; sz = aufmt_sample_size(tx->src_fmt); if (!sz) return; num_bytes = tx->psize; sampc = tx->psize / sz; /* timed read from audio-buffer */ if (tx->src_fmt == tx->enc_fmt) { aubuf_read(tx->aubuf, (uint8_t *)tx->sampv, num_bytes); } else if (tx->enc_fmt == AUFMT_S16LE) { /* Convert from ausrc format to 16-bit format */ void *tmp_sampv; if (!tx->need_conv) { info("audio: NOTE: source sample conversion" " needed: %s --> %s\n", aufmt_name(tx->src_fmt), aufmt_name(AUFMT_S16LE)); tx->need_conv = true; } tmp_sampv = mem_zalloc(num_bytes, NULL); if (!tmp_sampv) return; aubuf_read(tx->aubuf, tmp_sampv, num_bytes); auconv_to_s16(sampv, tx->src_fmt, tmp_sampv, sampc); mem_deref(tmp_sampv); } else { warning("audio: tx: invalid sample formats (%s -> %s)\n", aufmt_name(tx->src_fmt), aufmt_name(tx->enc_fmt)); } /* optional resampler */ if (tx->resamp.resample) { size_t sampc_rs = AUDIO_SAMPSZ; if (tx->enc_fmt != AUFMT_S16LE) { warning("audio: skipping resampler due to" " incompatible format (%s)\n", aufmt_name(tx->enc_fmt)); return; } err = auresamp(&tx->resamp, tx->sampv_rs, &sampc_rs, tx->sampv, sampc); if (err) return; sampv = tx->sampv_rs; sampc = sampc_rs; } auframe_init(&af, tx->enc_fmt, sampv, sampc); /* Process exactly one audio-frame in list order */ for (le = tx->filtl.head; le; le = le->next) { struct aufilt_enc_st *st = le->data; if (st->af && st->af->ench) err |= st->af->ench(st, &af); } if (err) { warning("audio: aufilter encode: %m\n", err); } /* Encode and send */ encode_rtp_send(a, tx, af.sampv, af.sampc); } static void check_telev(struct audio *a, struct autx *tx) { const struct sdp_format *fmt; struct mbuf *mb; bool marker = false; int err; mb = mbuf_alloc(STREAM_PRESZ + 64); if (!mb) return; mb->pos = mb->end = STREAM_PRESZ; err = telev_poll(a->telev, &marker, mb); if (err) goto out; if (marker) tx->ts_tel = (uint32_t)tx->ts_ext; fmt = sdp_media_rformat(stream_sdpmedia(audio_strm(a)), telev_rtpfmt); if (!fmt) goto out; mb->pos = STREAM_PRESZ; err = stream_send(a->strm, false, marker, fmt->pt, tx->ts_tel, mb); if (err) { warning("audio: telev: stream_send %m\n", err); } out: mem_deref(mb); } /* * Write samples to Audio Player. * * @note This function has REAL-TIME properties * * @note The application is responsible for filling in silence in * the case of underrun * * @note This function may be called from any thread * * @note The sample format is set in rx->play_fmt */ static void auplay_write_handler(void *sampv, size_t sampc, void *arg) { struct aurx *rx = arg; size_t num_bytes = sampc * aufmt_sample_size(rx->play_fmt); if (rx->aubuf_started && aubuf_cur_size(rx->aubuf) < num_bytes) { ++rx->stats.aubuf_underrun; #if 0 debug("audio: rx aubuf underrun (total %llu)\n", rx->stats.aubuf_underrun); #endif } aubuf_read(rx->aubuf, sampv, num_bytes); } /* * Read samples from Audio Source * * @note This function has REAL-TIME properties * * @note This function may be called from any thread */ static void ausrc_read_handler(struct auframe *af, void *arg) { struct audio *a = arg; struct autx *tx = &a->tx; size_t num_bytes = auframe_size(af); if ((int)tx->src_fmt != af->fmt) { warning("audio: ausrc format mismatch:" " expected=%d(%s), actual=%d(%s)\n", tx->src_fmt, aufmt_name(tx->src_fmt), af->fmt, aufmt_name(af->fmt)); return; } if (tx->muted) auframe_mute(af); if (aubuf_cur_size(tx->aubuf) >= tx->aubuf_maxsz) { ++tx->stats.aubuf_overrun; debug("audio: tx aubuf overrun (total %llu)\n", tx->stats.aubuf_overrun); } (void)aubuf_write(tx->aubuf, af->sampv, num_bytes); tx->aubuf_started = true; if (a->cfg.txmode == AUDIO_MODE_POLL) { unsigned i; for (i=0; i<16; i++) { if (aubuf_cur_size(tx->aubuf) < tx->psize) break; poll_aubuf_tx(a); } } /* Exact timing: send Telephony-Events from here */ check_telev(a, tx); } static void ausrc_error_handler(int err, const char *str, void *arg) { struct audio *a = arg; MAGIC_CHECK(a); if (a->errh) a->errh(err, str, a->arg); } static int update_payload_type(struct audio *a, uint8_t pt_old, uint8_t pt_new) { const struct sdp_format *lc; lc = sdp_media_lformat(stream_sdpmedia(a->strm), pt_new); if (!lc) return ENOENT; if (pt_old != (uint8_t)-1) { info("Audio decoder changed payload %u -> %u\n", pt_old, pt_new); } a->rx.pt = pt_new; return audio_decoder_set(a, lc->data, lc->pt, lc->params); } static void handle_telev(struct audio *a, struct mbuf *mb) { int event, digit; bool end; if (telev_recv(a->telev, mb, &event, &end)) return; digit = telev_code2digit(event); if (digit >= 0 && a->eventh) a->eventh(digit, end, a->arg); } static int aurx_stream_decode(struct aurx *rx, bool marker, struct mbuf *mb, unsigned lostc) { struct auframe af; size_t sampc = AUDIO_SAMPSZ; void *sampv; struct le *le; int err = 0; /* No decoder set */ if (!rx->ac) return 0; if (lostc && rx->ac->plch) { err = rx->ac->plch(rx->dec, rx->dec_fmt, rx->sampv, &sampc, mbuf_buf(mb), mbuf_get_left(mb)); if (err) { warning("audio: %s codec decode %u bytes: %m\n", rx->ac->name, mbuf_get_left(mb), err); goto out; } } else if (mbuf_get_left(mb)) { err = rx->ac->dech(rx->dec, rx->dec_fmt, rx->sampv, &sampc, marker, mbuf_buf(mb), mbuf_get_left(mb)); if (err) { warning("audio: %s codec decode %u bytes: %m\n", rx->ac->name, mbuf_get_left(mb), err); goto out; } rx->last_sampc = sampc; } else { /* no PLC in the codec, might be done in filters below */ sampc = 0; } auframe_init(&af, rx->dec_fmt, rx->sampv, sampc); /* Process exactly one audio-frame in reverse list order */ for (le = rx->filtl.tail; le; le = le->prev) { struct aufilt_dec_st *st = le->data; if (st->af && st->af->dech) err |= st->af->dech(st, &af); } if (!rx->aubuf) goto out; sampv = af.sampv; sampc = af.sampc; /* optional resampler */ if (rx->resamp.resample) { size_t sampc_rs = AUDIO_SAMPSZ; if (rx->dec_fmt != AUFMT_S16LE) { warning("audio: skipping resampler due to" " incompatible format (%s)\n", aufmt_name(rx->dec_fmt)); return ENOTSUP; } err = auresamp(&rx->resamp, rx->sampv_rs, &sampc_rs, rx->sampv, sampc); if (err) return err; sampv = rx->sampv_rs; sampc = sampc_rs; } if (aubuf_cur_size(rx->aubuf) >= rx->aubuf_maxsz) { ++rx->stats.aubuf_overrun; #if 0 debug("audio: rx aubuf overrun (total %llu)\n", rx->stats.aubuf_overrun); #endif } if (rx->play_fmt == rx->dec_fmt) { size_t num_bytes = sampc * aufmt_sample_size(rx->play_fmt); err = aubuf_write(rx->aubuf, sampv, num_bytes); if (err) goto out; } else if (rx->dec_fmt == AUFMT_S16LE) { /* Convert from 16-bit to auplay format */ void *tmp_sampv; size_t num_bytes = sampc * aufmt_sample_size(rx->play_fmt); if (!rx->need_conv) { info("audio: NOTE: playback sample conversion" " needed: %s --> %s\n", aufmt_name(AUFMT_S16LE), aufmt_name(rx->play_fmt)); rx->need_conv = true; } tmp_sampv = mem_zalloc(num_bytes, NULL); if (!tmp_sampv) return ENOMEM; auconv_from_s16(rx->play_fmt, tmp_sampv, sampv, sampc); err = aubuf_write(rx->aubuf, tmp_sampv, num_bytes); mem_deref(tmp_sampv); if (err) goto out; } else { warning("audio: decode: invalid sample formats (%s -> %s)\n", aufmt_name(rx->dec_fmt), aufmt_name(rx->play_fmt)); } rx->aubuf_started = true; out: return err; } /* Handle incoming stream data from the network */ static void stream_recv_handler(const struct rtp_header *hdr, struct rtpext *extv, size_t extc, struct mbuf *mb, unsigned lostc, void *arg) { struct audio *a = arg; struct aurx *rx = &a->rx; bool discard = false; size_t i; int wrap; int err; MAGIC_CHECK(a); if (!mb) goto out; /* Telephone event? */ if (hdr->pt != rx->pt) { const struct sdp_format *fmt; fmt = sdp_media_lformat(stream_sdpmedia(a->strm), hdr->pt); if (fmt && !str_casecmp(fmt->name, "telephone-event")) { handle_telev(a, mb); return; } } /* Comfort Noise (CN) as of RFC 3389 */ if (PT_CN == hdr->pt) return; /* Audio payload-type changed? */ if (hdr->pt != rx->pt) { err = update_payload_type(a, rx->pt, hdr->pt); if (err) return; } /* RFC 5285 -- A General Mechanism for RTP Header Extensions */ for (i=0; iextmap_aulevel) { a->rx.level_last = -(double)(extv[i].data[0] & 0x7f); a->rx.level_set = true; } else { debug("audio: rtp header ext ignored (id=%u)\n", extv[i].id); } } /* Save timestamp for incoming RTP packets */ if (rx->ts_recv.is_set) { uint64_t ext_last, ext_now; ext_last = timestamp_calc_extended(rx->ts_recv.num_wraps, rx->ts_recv.last); ext_now = timestamp_calc_extended(rx->ts_recv.num_wraps, hdr->ts); if (ext_now <= ext_last) { uint64_t delta; delta = ext_last - ext_now; warning("audio: [time=%.3f]" " discard old frame (%.3f seconds old)\n", aurx_calc_seconds(rx), timestamp_calc_seconds(delta, rx->ac->crate)); discard = true; } } else { timestamp_set(&rx->ts_recv, hdr->ts); } wrap = timestamp_wrap(hdr->ts, rx->ts_recv.last); switch (wrap) { case -1: warning("audio: rtp timestamp wraps backwards" " (delta = %d) -- discard\n", (int32_t)(rx->ts_recv.last - hdr->ts)); discard = true; break; case 0: break; case 1: ++rx->ts_recv.num_wraps; break; default: break; } rx->ts_recv.last = hdr->ts; #if 0 re_printf("[time=%.3f] wrap=%d discard=%d\n", aurx_calc_seconds(rx), wrap, discard); #endif if (discard) { ++rx->stats.n_discard; return; } out: if (lostc) aurx_stream_decode(&a->rx, hdr->m, mb, lostc); (void)aurx_stream_decode(&a->rx, hdr->m, mb, 0); } static int add_telev_codec(struct audio *a) { struct sdp_media *m = stream_sdpmedia(audio_strm(a)); struct sdp_format *sf; int err; /* Use payload-type 101 if available, for CiscoGW interop */ err = sdp_format_add(&sf, m, false, (!sdp_media_lformat(m, 101)) ? "101" : NULL, telev_rtpfmt, TELEV_SRATE, 1, NULL, NULL, NULL, false, "0-15"); if (err) return err; return err; } /** * Allocate an audio stream * * @param ap Pointer to allocated audio stream object * @param streaml List of streams * @param stream_prm Stream parameters * @param cfg Global configuration * @param acc User-Agent account * @param sdp_sess SDP Session * @param label SDP label * @param mnat Media NAT (optional) * @param mnat_sess Media NAT session (optional) * @param menc Media Encryption (optional) * @param menc_sess Media Encryption session (optional) * @param ptime Packet time in [ms] * @param aucodecl List of audio codecs * @param offerer True if SDP offerer, false if SDP answerer * @param eventh Event handler * @param levelh Audio level handler * @param errh Error handler * @param arg Handler argument * * @return 0 if success, otherwise errorcode */ int audio_alloc(struct audio **ap, struct list *streaml, const struct stream_param *stream_prm, const struct config *cfg, struct account *acc, struct sdp_session *sdp_sess, int label, const struct mnat *mnat, struct mnat_sess *mnat_sess, const struct menc *menc, struct menc_sess *menc_sess, uint32_t ptime, const struct list *aucodecl, bool offerer, audio_event_h *eventh, audio_level_h *levelh, audio_err_h *errh, void *arg) { struct audio *a; struct autx *tx; struct aurx *rx; struct le *le; uint32_t minptime = ptime; int err; if (!ap || !cfg) return EINVAL; if (ptime < 1 || ptime > MAX_PTIME) { warning("audio: ptime %ums out of range (%ums - %ums)\n", ptime, 1, MAX_PTIME); return ENOTSUP; } a = mem_zalloc(sizeof(*a), audio_destructor); if (!a) return ENOMEM; MAGIC_INIT(a); a->cfg = cfg->audio; tx = &a->tx; rx = &a->rx; tx->src_fmt = cfg->audio.src_fmt; rx->play_fmt = cfg->audio.play_fmt; tx->enc_fmt = cfg->audio.enc_fmt; rx->dec_fmt = cfg->audio.dec_fmt; err = stream_alloc(&a->strm, streaml, stream_prm, &cfg->avt, sdp_sess, MEDIA_AUDIO, label, mnat, mnat_sess, menc, menc_sess, offerer, stream_recv_handler, NULL, a); if (err) goto out; if (cfg->avt.rtp_bw.max) { stream_set_bw(a->strm, AUDIO_BANDWIDTH); } /* Audio codecs */ for (le = list_head(aucodecl); le; le = le->next) { struct aucodec *ac = le->data; if (ac->ptime) minptime = min(minptime, ac->ptime); err = add_audio_codec(stream_sdpmedia(a->strm), ac); if (err) goto out; } err = sdp_media_set_lattr(stream_sdpmedia(a->strm), true, "minptime", "%u", minptime); err |= sdp_media_set_lattr(stream_sdpmedia(a->strm), true, "ptime", "%u", ptime); if (err) goto out; if (cfg->audio.level && offerer) { a->extmap_aulevel = 1; err = sdp_media_set_lattr(stream_sdpmedia(a->strm), true, "extmap", "%u %s", a->extmap_aulevel, uri_aulevel); if (err) goto out; } tx->mb = mbuf_alloc(STREAM_PRESZ + 4096); tx->sampv = mem_zalloc(AUDIO_SAMPSZ * aufmt_sample_size(tx->enc_fmt), NULL); rx->sampv = mem_zalloc(AUDIO_SAMPSZ * aufmt_sample_size(rx->dec_fmt), NULL); if (!tx->mb || !tx->sampv || !rx->sampv) { err = ENOMEM; goto out; } err = telev_alloc(&a->telev, ptime); if (err) goto out; err = add_telev_codec(a); if (err) goto out; auresamp_init(&tx->resamp); if (acc && acc->ausrc_mod) { tx->module = mem_ref(acc->ausrc_mod); tx->device = mem_ref(acc->ausrc_dev); info("audio: using account specific source: (%s,%s)\n", tx->module, tx->device); } else { err = str_dup(&tx->module, a->cfg.src_mod); err |= str_dup(&tx->device, a->cfg.src_dev); } tx->ptime = ptime; tx->ts_ext = tx->ts_base = rand_u16(); tx->marker = true; auresamp_init(&rx->resamp); if (acc && acc->auplay_mod) { rx->module = mem_ref(acc->auplay_mod); rx->device = mem_ref(acc->auplay_dev); info("audio: using account specific player: (%s,%s)\n", rx->module, rx->device); } else { err = str_dup(&rx->module, a->cfg.play_mod); err |= str_dup(&rx->device, a->cfg.play_dev); } rx->pt = -1; rx->ptime = ptime; a->eventh = eventh; a->levelh = levelh; a->errh = errh; a->arg = arg; out: if (err) mem_deref(a); else *ap = a; return err; } #ifdef HAVE_PTHREAD static void *tx_thread(void *arg) { struct audio *a = arg; struct autx *tx = &a->tx; uint64_t ts = 0; while (a->tx.u.thr.run) { uint64_t now; sys_msleep(4); if (!tx->aubuf_started) continue; if (!a->tx.u.thr.run) break; now = tmr_jiffies(); if (!ts) ts = now; if (ts > now) continue; /* Now is the time to send */ if (aubuf_cur_size(tx->aubuf) >= tx->psize) { poll_aubuf_tx(a); } else { ++tx->stats.aubuf_underrun; debug("audio: thread: tx aubuf underrun" " (total %llu)\n", tx->stats.aubuf_underrun); } ts += tx->ptime; } return NULL; } #endif static void aufilt_param_set(struct aufilt_prm *prm, const struct aucodec *ac, enum aufmt fmt) { prm->srate = ac->srate; prm->ch = ac->ch; prm->fmt = fmt; } static int autx_print_pipeline(struct re_printf *pf, const struct autx *autx) { struct le *le; int err; if (!autx) return 0; err = re_hprintf(pf, "audio tx pipeline: %10s", autx->ausrc ? autx->ausrc->as->name : "(src)"); for (le = list_head(&autx->filtl); le; le = le->next) { struct aufilt_enc_st *st = le->data; if (st->af->ench) err |= re_hprintf(pf, " ---> %s", st->af->name); } err |= re_hprintf(pf, " ---> %s\n", autx->ac ? autx->ac->name : "(encoder)"); return err; } static int aurx_print_pipeline(struct re_printf *pf, const struct aurx *aurx) { struct le *le; int err; if (!aurx) return 0; err = re_hprintf(pf, "audio rx pipeline: %10s", aurx->auplay ? aurx->auplay->ap->name : "(play)"); for (le = list_head(&aurx->filtl); le; le = le->next) { struct aufilt_dec_st *st = le->data; if (st->af->dech) err |= re_hprintf(pf, " <--- %s", st->af->name); } err |= re_hprintf(pf, " <--- %s\n", aurx->ac ? aurx->ac->name : "(decoder)"); return err; } /** * Setup the audio-filter chain * * must be called before auplay/ausrc-alloc * * @param a Audio object * * @return 0 if success, otherwise errorcode */ static int aufilt_setup(struct audio *a, struct list *aufiltl) { struct aufilt_prm encprm, decprm; struct autx *tx = &a->tx; struct aurx *rx = &a->rx; struct le *le; int err = 0; /* wait until we have both Encoder and Decoder */ if (!tx->ac || !rx->ac) return 0; if (!list_isempty(&tx->filtl) || !list_isempty(&rx->filtl)) return 0; aufilt_param_set(&encprm, tx->ac, tx->enc_fmt); aufilt_param_set(&decprm, rx->ac, rx->dec_fmt); /* Audio filters */ for (le = list_head(aufiltl); le; le = le->next) { struct aufilt *af = le->data; struct aufilt_enc_st *encst = NULL; struct aufilt_dec_st *decst = NULL; void *ctx = NULL; if (af->encupdh) { err = af->encupdh(&encst, &ctx, af, &encprm, a); if (err) { warning("audio: error in encode audio-filter" " '%s' (%m)\n", af->name, err); } else { encst->af = af; list_append(&tx->filtl, &encst->le, encst); } } if (af->decupdh) { err = af->decupdh(&decst, &ctx, af, &decprm, a); if (err) { warning("audio: error in decode audio-filter" " '%s' (%m)\n", af->name, err); } else { decst->af = af; list_append(&rx->filtl, &decst->le, decst); } } if (err) { warning("audio: audio-filter '%s'" " update failed (%m)\n", af->name, err); break; } } return 0; } static int start_player(struct aurx *rx, struct audio *a, struct list *auplayl) { const struct aucodec *ac = rx->ac; uint32_t srate_dsp; uint32_t channels_dsp; bool resamp = false; int err; if (!ac) return 0; srate_dsp = ac->srate; channels_dsp = ac->ch; if (a->cfg.srate_play && a->cfg.srate_play != srate_dsp) { resamp = true; srate_dsp = a->cfg.srate_play; } if (a->cfg.channels_play && a->cfg.channels_play != channels_dsp) { resamp = true; channels_dsp = a->cfg.channels_play; } /* Optional resampler, if configured */ if (resamp && !rx->sampv_rs) { info("audio: enable auplay resampler:" " %uHz/%uch --> %uHz/%uch\n", ac->srate, ac->ch, srate_dsp, channels_dsp); rx->sampv_rs = mem_zalloc(AUDIO_SAMPSZ * sizeof(int16_t), NULL); if (!rx->sampv_rs) return ENOMEM; err = auresamp_setup(&rx->resamp, ac->srate, ac->ch, srate_dsp, channels_dsp); if (err) { warning("audio: could not setup auplay resampler" " (%m)\n", err); return err; } } /* Start Audio Player */ if (!rx->auplay && auplay_find(auplayl, NULL)) { struct auplay_prm prm; prm.srate = srate_dsp; prm.ch = channels_dsp; prm.ptime = rx->ptime; prm.fmt = rx->play_fmt; if (!rx->aubuf) { const size_t sz = aufmt_sample_size(rx->play_fmt); const size_t ptime_min = a->cfg.buffer.min; const size_t ptime_max = a->cfg.buffer.max; size_t min_sz; size_t max_sz; if (!ptime_min || !ptime_max) return EINVAL; min_sz = sz*calc_nsamp(prm.srate, prm.ch, ptime_min); max_sz = sz*calc_nsamp(prm.srate, prm.ch, ptime_max); debug("audio: create recv buffer" " [%zu - %zu ms]" " [%zu - %zu bytes]\n", ptime_min, ptime_max, min_sz, max_sz); err = aubuf_alloc(&rx->aubuf, min_sz, max_sz); if (err) { warning("audio: aubuf alloc error (%m)\n", err); return err; } rx->aubuf_maxsz = max_sz; } err = auplay_alloc(&rx->auplay, auplayl, rx->module, &prm, rx->device, auplay_write_handler, rx); if (err) { warning("audio: start_player failed (%s.%s): %m\n", rx->module, rx->device, err); return err; } rx->auplay_prm = prm; info("audio: player started with sample format %s\n", aufmt_name(rx->play_fmt)); } return 0; } static int start_source(struct autx *tx, struct audio *a, struct list *ausrcl) { const struct aucodec *ac = tx->ac; uint32_t srate_dsp; uint32_t channels_dsp; bool resamp = false; int err; if (!ac) return 0; srate_dsp = ac->srate; channels_dsp = ac->ch; if (a->cfg.srate_src && a->cfg.srate_src != srate_dsp) { resamp = true; srate_dsp = a->cfg.srate_src; } if (a->cfg.channels_src && a->cfg.channels_src != channels_dsp) { resamp = true; channels_dsp = a->cfg.channels_src; } /* Optional resampler, if configured */ if (resamp && !tx->sampv_rs) { info("audio: enable ausrc resampler:" " %uHz/%uch <-- %uHz/%uch\n", ac->srate, ac->ch, srate_dsp, channels_dsp); tx->sampv_rs = mem_zalloc(AUDIO_SAMPSZ * sizeof(int16_t), NULL); if (!tx->sampv_rs) return ENOMEM; err = auresamp_setup(&tx->resamp, srate_dsp, channels_dsp, ac->srate, ac->ch); if (err) { warning("audio: could not setup ausrc resampler" " (%m)\n", err); return err; } } /* Start Audio Source */ if (!tx->ausrc && ausrc_find(ausrcl, NULL) && !a->hold) { struct ausrc_prm prm; size_t sz; prm.srate = srate_dsp; prm.ch = channels_dsp; prm.ptime = tx->ptime; prm.fmt = tx->src_fmt; sz = aufmt_sample_size(tx->src_fmt); tx->psize = sz * calc_nsamp(prm.srate, prm.ch, prm.ptime); tx->aubuf_maxsz = tx->psize * 30; if (!tx->aubuf) { err = aubuf_alloc(&tx->aubuf, tx->psize, tx->aubuf_maxsz); if (err) return err; } err = ausrc_alloc(&tx->ausrc, ausrcl, tx->ctx, tx->module, &prm, tx->device, ausrc_read_handler, ausrc_error_handler, a); if (err) { warning("audio: start_source failed (%s.%s): %m\n", tx->module, tx->device, err); return err; } switch (a->cfg.txmode) { case AUDIO_MODE_POLL: break; #ifdef HAVE_PTHREAD case AUDIO_MODE_THREAD: if (!tx->u.thr.run) { tx->u.thr.run = true; err = pthread_create(&tx->u.thr.tid, NULL, tx_thread, a); if (err) { tx->u.thr.run = false; return err; } } break; #endif default: warning("audio: tx mode not supported (%d)\n", a->cfg.txmode); return ENOTSUP; } tx->ausrc_prm = prm; info("audio: source started with sample format %s\n", aufmt_name(tx->src_fmt)); } return 0; } /** * Start the audio playback and recording * * @param a Audio object * * @return 0 if success, otherwise errorcode */ int audio_start(struct audio *a) { struct list *aufiltl = baresip_aufiltl(); int err; if (!a) return EINVAL; debug("audio: start\n"); /* Audio filter */ if (!list_isempty(aufiltl)) { err = aufilt_setup(a, aufiltl); if (err) return err; } err = start_player(&a->rx, a, baresip_auplayl()); err |= start_source(&a->tx, a, baresip_ausrcl()); if (err) return err; if (a->tx.ac && a->rx.ac) { if (!a->started) { info("%H%H", autx_print_pipeline, &a->tx, aurx_print_pipeline, &a->rx); } a->started = true; } return err; } /** * Start the audio source * * @param a Audio object * @param ausrcl List of audio sources * @param aufiltl List of audio filters * * @return 0 if success, otherwise errorcode */ int audio_start_source(struct audio *a, struct list *ausrcl, struct list *aufiltl) { int err; if (!a) return EINVAL; /* NOTE: audio encoder must be set first */ if (!a->tx.ac) { warning("audio: start_source: no encoder set\n"); return ENOENT; } /* Audio filter */ if (!list_isempty(aufiltl)) { err = aufilt_setup(a, aufiltl); if (err) return err; } err = start_source(&a->tx, a, ausrcl); if (err) return err; a->started = true; return 0; } /** * Stop the audio playback and recording * * @param a Audio object */ void audio_stop(struct audio *a) { if (!a) return; stop_tx(&a->tx, a); stop_rx(&a->rx); } /** * Check if audio has been started * * @param a Audio object * * @return True if audio has been started, otherwise false */ bool audio_started(const struct audio *a) { if (!a) return false; return a->started; } /** * Set the audio encoder used * * @param a Audio object * @param ac Audio codec to use * @param pt_tx Payload type for sending * @param params Optional encoder parameters * * @return 0 if success, otherwise errorcode */ int audio_encoder_set(struct audio *a, const struct aucodec *ac, int pt_tx, const char *params) { struct autx *tx; int err = 0; bool reset; if (!a || !ac) return EINVAL; tx = &a->tx; reset = !aucodec_equal(ac, tx->ac); if (ac != tx->ac) { info("audio: Set audio encoder: %s %uHz %dch\n", ac->name, ac->srate, ac->ch); /* Audio source must be stopped first */ if (reset) { tx->ausrc = mem_deref(tx->ausrc); aubuf_flush(tx->aubuf); } tx->enc = mem_deref(tx->enc); tx->ac = ac; } if (ac->encupdh) { struct auenc_param prm; prm.ptime = tx->ptime; prm.bitrate = 0; /* auto */ err = ac->encupdh(&tx->enc, ac, &prm, params); if (err) { warning("audio: alloc encoder: %m\n", err); return err; } } stream_set_srate(a->strm, ac->crate, 0); stream_update_encoder(a->strm, pt_tx); telev_set_srate(a->telev, ac->crate); /* use a codec-specific ptime */ if (ac->ptime) { const size_t sz = aufmt_sample_size(tx->src_fmt); tx->ptime = ac->ptime; tx->psize = sz * calc_nsamp(ac->srate, ac->ch, ac->ptime); } if (!tx->ausrc) { err |= audio_start(a); } return err; } /** * Set the audio decoder used * * @param a Audio object * @param ac Audio codec to use * @param pt_rx Payload type for receiving * @param params Optional decoder parameters * * @return 0 if success, otherwise errorcode */ int audio_decoder_set(struct audio *a, const struct aucodec *ac, int pt_rx, const char *params) { struct aurx *rx; struct sdp_media *m; bool reset = false; int err = 0; if (!a || !ac) return EINVAL; rx = &a->rx; reset = !aucodec_equal(ac, rx->ac); m = stream_sdpmedia(audio_strm(a)); reset |= sdp_media_dir(m)!=SDP_SENDRECV; if (ac != rx->ac) { info("audio: Set audio decoder: %s %uHz %dch\n", ac->name, ac->srate, ac->ch); rx->pt = pt_rx; rx->ac = ac; rx->dec = mem_deref(rx->dec); } if (ac->decupdh) { err = ac->decupdh(&rx->dec, ac, params); if (err) { warning("audio: alloc decoder: %m\n", err); return err; } } stream_set_srate(a->strm, 0, ac->crate); if (reset) { stream_reset(audio_strm(a)); rx->auplay = mem_deref(rx->auplay); aubuf_flush(rx->aubuf); /* Reset audio filter chain */ list_flush(&rx->filtl); err |= audio_start(a); } return err; } /** * Get the RTP Stream object from an Audio object * * @param au Audio object * * @return RTP Stream object */ struct stream *audio_strm(const struct audio *au) { return au ? au->strm : NULL; } int audio_send_digit(struct audio *a, char key) { int err = 0; if (!a) return EINVAL; if (key != KEYCODE_REL) { int event = telev_digit2code(key); info("audio: send DTMF digit: '%c'\n", key); if (event == -1) { warning("audio: invalid DTMF digit (0x%02x)\n", key); return EINVAL; } err = telev_send(a->telev, event, false); } else if (a->tx.cur_key && a->tx.cur_key != KEYCODE_REL) { /* Key release */ info("audio: send DTMF digit end: '%c'\n", a->tx.cur_key); err = telev_send(a->telev, telev_digit2code(a->tx.cur_key), true); } a->tx.cur_key = key; return err; } /** * Mute the audio stream source (i.e. Microphone) * * @param a Audio stream * @param muted True to mute, false to un-mute */ void audio_mute(struct audio *a, bool muted) { if (!a) return; a->tx.muted = muted; } /** * Get the mute state of an audio source * * @param a Audio stream * * @return True if muted, otherwise false */ bool audio_ismuted(const struct audio *a) { if (!a) return false; return a->tx.muted; } static bool extmap_handler(const char *name, const char *value, void *arg) { struct audio *au = arg; struct sdp_extmap extmap; int err; (void)name; MAGIC_CHECK(au); err = sdp_extmap_decode(&extmap, value); if (err) { warning("audio: sdp_extmap_decode error (%m)\n", err); return false; } if (0 == pl_strcasecmp(&extmap.name, uri_aulevel)) { if (extmap.id < RTPEXT_ID_MIN || extmap.id > RTPEXT_ID_MAX) { warning("audio: extmap id out of range (%u)\n", extmap.id); return false; } au->extmap_aulevel = extmap.id; err = sdp_media_set_lattr(stream_sdpmedia(au->strm), true, "extmap", "%u %s", au->extmap_aulevel, uri_aulevel); if (err) return false; au->level_enabled = true; info("audio: client-to-mixer audio levels enabled\n"); } return false; } void audio_sdp_attr_decode(struct audio *a) { const char *attr; if (!a) return; /* This is probably only meaningful for audio data, but may be used with other media types if it makes sense. */ attr = sdp_media_rattr(stream_sdpmedia(a->strm), "ptime"); if (attr) { struct autx *tx = &a->tx; uint32_t ptime_tx = atoi(attr); if (ptime_tx && ptime_tx != a->tx.ptime && ptime_tx <= MAX_PTIME) { info("audio: peer changed ptime_tx %ums -> %ums\n", a->tx.ptime, ptime_tx); tx->ptime = ptime_tx; if (tx->ac) { size_t sz; sz = aufmt_sample_size(tx->src_fmt); tx->psize = sz * calc_nsamp(tx->ac->srate, tx->ac->ch, ptime_tx); } sdp_media_set_lattr(stream_sdpmedia(a->strm), true, "ptime", "%u", ptime_tx); } } /* Client-to-Mixer Audio Level Indication */ if (a->cfg.level) { sdp_media_rattr_apply(stream_sdpmedia(a->strm), "extmap", extmap_handler, a); } } /** * Put an audio level value, call the level handler * * @param au Audio object * @param tx Direction; true for transmit, false for receive * @param lvl Audio level value */ void audio_level_put(const struct audio *au, bool tx, double lvl) { if (!au) return; if (au->levelh) au->levelh(tx, lvl, au->arg); } /** * Get the last value of the audio level from incoming RTP packets * * @param au Audio object * @param levelp Pointer to where to write audio level value * * @return 0 if success, otherwise errorcode */ int audio_level_get(const struct audio *au, double *levelp) { if (!au) return EINVAL; if (!au->level_enabled) return ENOTSUP; if (!au->rx.level_set) return ENOENT; if (levelp) *levelp = au->rx.level_last; return 0; } static int aucodec_print(struct re_printf *pf, const struct aucodec *ac) { if (!ac) return 0; return re_hprintf(pf, "%s %uHz/%dch", ac->name, ac->srate, ac->ch); } /** * Print the audio debug information * * @param pf Print function * @param a Audio object * * @return 0 if success, otherwise errorcode */ int audio_debug(struct re_printf *pf, const struct audio *a) { const struct autx *tx; const struct aurx *rx; size_t sztx, szrx; int err; if (!a) return 0; tx = &a->tx; rx = &a->rx; sztx = aufmt_sample_size(tx->src_fmt); szrx = aufmt_sample_size(rx->play_fmt); err = re_hprintf(pf, "\n--- Audio stream ---\n"); err |= re_hprintf(pf, " tx: encode: %H ptime=%ums %s\n", aucodec_print, tx->ac, tx->ptime, aufmt_name(tx->enc_fmt)); err |= re_hprintf(pf, " aubuf: %H" " (cur %.2fms, max %.2fms, or %llu, ur %llu)\n", aubuf_debug, tx->aubuf, calc_ptime(aubuf_cur_size(tx->aubuf)/sztx, tx->ausrc_prm.srate, tx->ausrc_prm.ch), calc_ptime(tx->aubuf_maxsz/sztx, tx->ausrc_prm.srate, tx->ausrc_prm.ch), tx->stats.aubuf_overrun, tx->stats.aubuf_underrun); err |= re_hprintf(pf, " source: %s,%s %s\n", tx->ausrc ? tx->ausrc->as->name : "none", tx->device, aufmt_name(tx->src_fmt)); err |= re_hprintf(pf, " time = %.3f sec\n", autx_calc_seconds(tx)); err |= re_hprintf(pf, " rx: decode: %H %s\n", aucodec_print, rx->ac, aufmt_name(rx->dec_fmt)); err |= re_hprintf(pf, " aubuf: %H" " (cur %.2fms, max %.2fms, or %llu, ur %llu)\n", aubuf_debug, rx->aubuf, calc_ptime(aubuf_cur_size(rx->aubuf)/szrx, rx->auplay_prm.srate, rx->auplay_prm.ch), calc_ptime(rx->aubuf_maxsz/szrx, rx->auplay_prm.srate, rx->auplay_prm.ch), rx->stats.aubuf_overrun, rx->stats.aubuf_underrun ); err |= re_hprintf(pf, " player: %s,%s %s\n", rx->auplay ? rx->auplay->ap->name : "none", rx->device, aufmt_name(rx->play_fmt)); err |= re_hprintf(pf, " n_discard:%llu\n", rx->stats.n_discard); if (rx->level_set) { err |= re_hprintf(pf, " level %.3f dBov\n", rx->level_last); } if (rx->ts_recv.is_set) { err |= re_hprintf(pf, " time = %.3f sec\n", aurx_calc_seconds(rx)); } else { err |= re_hprintf(pf, " time = (not started)\n"); } err |= re_hprintf(pf, " %H" " %H", autx_print_pipeline, tx, aurx_print_pipeline, rx); err |= stream_debug(pf, a->strm); return err; } /** * Set the audio source and player device name. This function does not * change the state of the audio source/player. * * @param a Audio object * @param src Audio source device name * @param play Audio player device name * * @return 0 if success, otherwise errorcode */ int audio_set_devicename(struct audio *a, const char *src, const char *play) { int err; if (!a) return EINVAL; a->tx.device = mem_deref(a->tx.device); a->rx.device = mem_deref(a->rx.device); err = str_dup(&a->tx.device, src); err |= str_dup(&a->rx.device, play); return err; } /** * Set the audio source state to a new audio source module and device. * The current audio source will be stopped. * * @param au Audio object * @param mod Audio source module (NULL to stop) * @param device Audio source device name * * @return 0 if success, otherwise errorcode */ int audio_set_source(struct audio *au, const char *mod, const char *device) { struct autx *tx; int err; if (!au) return EINVAL; tx = &au->tx; /* stop the audio device first */ tx->ausrc = mem_deref(tx->ausrc); if (str_isset(mod)) { err = ausrc_alloc(&tx->ausrc, baresip_ausrcl(), NULL, mod, &tx->ausrc_prm, device, ausrc_read_handler, ausrc_error_handler, au); if (err) { warning("audio: set_source failed (%s.%s): %m\n", mod, device, err); return err; } } return 0; } /** * Set the audio player state to a new audio player module and device. * The current audio player will be stopped. * * @param au Audio object * @param mod Audio player module (NULL to stop) * @param device Audio player device name * * @return 0 if success, otherwise errorcode */ int audio_set_player(struct audio *au, const char *mod, const char *device) { struct aurx *rx; int err; if (!au) return EINVAL; rx = &au->rx; /* stop the audio device first */ rx->auplay = mem_deref(rx->auplay); if (str_isset(mod)) { err = auplay_alloc(&rx->auplay, baresip_auplayl(), mod, &rx->auplay_prm, device, auplay_write_handler, rx); if (err) { warning("audio: set_player failed (%s.%s): %m\n", mod, device, err); return err; } } return 0; } /** * Set the bitrate for the audio encoder * * @param au Audio object * @param bitrate Encoder bitrate in [bits/s] * * @return 0 if success, otherwise errorcode */ int audio_set_bitrate(struct audio *au, uint32_t bitrate) { struct autx *tx; const struct aucodec *ac; int err; if (!au) return EINVAL; tx = &au->tx; ac = tx->ac; info("audio: set bitrate for encoder '%s' to %u bits/s\n", ac ? ac->name : "?", bitrate); if (ac) { if (ac->encupdh) { struct auenc_param prm; prm.ptime = tx->ptime; prm.bitrate = bitrate; err = ac->encupdh(&tx->enc, ac, &prm, NULL); if (err) { warning("audio: encupdh error: %m\n", err); return err; } } } else { info("audio: set_bitrate: no audio encoder\n"); } return 0; } /** * Check if audio receiving has started * * @param au Audio object * * @return True if started, otherwise false */ bool audio_rxaubuf_started(const struct audio *au) { const struct aurx *rx; if (!au) return false; rx = &au->rx; return rx->aubuf_started; } /** * Set the audio stream on hold * * @param au Audio object * @param hold True to hold, false to resume */ void audio_set_hold(struct audio *au, bool hold) { if (!au) return; au->hold = hold; } /** * Get audio codec of audio stream * * @param au Audio object * @param tx True to get transmit codec, false to get receive codec * * @return Audio codec if success, otherwise NULL */ const struct aucodec *audio_codec(const struct audio *au, bool tx) { if (!au) return NULL; return tx ? au->tx.ac : au->rx.ac; } /** * Accessor function to audio configuration * * @param au Audio object * * @return Audio configuration */ struct config_audio *audio_config(struct audio *au) { return au ? &au->cfg : NULL; } /** * Set the media context * * @param au Audio object * @param ctx Media context */ void audio_set_media_context(struct audio *au, struct media_ctx **ctx) { if (!au) return; au->tx.ctx = ctx; } baresip-1.0.0/src/aufilt.c000066400000000000000000000011251372575704200153670ustar00rootroot00000000000000/** * @file aufilt.c Audio Filter * * Copyright (C) 2010 Creytiv.com */ #include #include #include "core.h" /** * Register an Audio Filter * * @param aufiltl List of Audio Filters * @param af Audio Filter to register */ void aufilt_register(struct list *aufiltl, struct aufilt *af) { if (!aufiltl || !af) return; list_append(aufiltl, &af->le, af); info("aufilt: %s\n", af->name); } /** * Unregister an Audio Filter * * @param af Audio Filter to unregister */ void aufilt_unregister(struct aufilt *af) { if (!af) return; list_unlink(&af->le); } baresip-1.0.0/src/auframe.c000066400000000000000000000022571372575704200155320ustar00rootroot00000000000000/** * @file auframe.c Audio frame * * Copyright (C) 2010 - 2020 Creytiv.com */ #include #include #include #include /** * Initialize an audio frame * * @param af Audio frame * @param fmt Sample format (enum aufmt) * @param sampv Audio samples * @param sampc Total number of audio samples */ void auframe_init(struct auframe *af, int fmt, void *sampv, size_t sampc) { if (!af) return; if (0 == aufmt_sample_size(fmt)) { warning("auframe: init: unsupported sample format %d (%s)\n", fmt, aufmt_name(fmt)); } memset(af, 0, sizeof(*af)); af->fmt = fmt; af->sampv = sampv; af->sampc = sampc; } /** * Get the size of an audio frame * * @param af Audio frame * * @return Number of bytes */ size_t auframe_size(const struct auframe *af) { size_t sz; if (!af) return 0; sz = aufmt_sample_size(af->fmt); if (sz == 0) { warning("auframe: size: illegal format %d (%s)\n", af->fmt, aufmt_name(af->fmt)); } return af->sampc * sz; } /** * Silence all samples in an audio frame * * @param af Audio frame */ void auframe_mute(struct auframe *af) { if (!af) return; memset(af->sampv, 0, auframe_size(af)); } baresip-1.0.0/src/aulevel.c000066400000000000000000000037601372575704200155470ustar00rootroot00000000000000/** * @file src/aulevel.c Audio level * * Copyright (C) 2017 Creytiv.com */ #include #include #include #include #include "core.h" /** * Generic routine to calculate RMS (Root-Mean-Square) from * a set of signed 16-bit values * * \verbatim .--------------- | N-1 | ----. | \ | \ 2 | | s[n] | / | / _ | ----' \ | n=0 \ | ------------ \| N \endverbatim * * @param data Array of signed 16-bit values * @param len Number of values * * @return RMS value from 0 to 32768 */ static double calc_rms(const int16_t *data, size_t len) { double sum = 0; size_t i; if (!data || !len) return .0; for (i = 0; i < len; i++) { const double sample = data[i]; sum += sample * sample; } return sqrt(sum / (double)len); } static double calc_rms_float(const float *data, size_t len) { double sum = 0; size_t i; if (!data || !len) return .0; for (i = 0; i < len; i++) { const double sample = data[i]; sum += sample * sample; } return sqrt(sum / (double)len); } /** * Calculate the audio level in dBov from a set of audio samples. * dBov is the level, in decibels, relative to the overload point * of the system * * @param fmt Sample format (enum aufmt) * @param sampv Audio samples * @param sampc Number of audio samples * * @return Audio level expressed in dBov */ double aulevel_calc_dbov(int fmt, const void *sampv, size_t sampc) { static const double peak = 32767.0; double rms, dbov; if (!sampv || !sampc) return AULEVEL_MIN; switch (fmt) { case AUFMT_S16LE: rms = calc_rms(sampv, sampc) / peak; break; case AUFMT_FLOAT: rms = calc_rms_float(sampv, sampc) / 1.0; break; default: warning("aulevel: sample format not supported (%s)\n", aufmt_name(fmt)); return AULEVEL_MIN; } dbov = 20 * log10(rms); if (dbov < AULEVEL_MIN) dbov = AULEVEL_MIN; else if (dbov > AULEVEL_MAX) dbov = AULEVEL_MAX; return dbov; } baresip-1.0.0/src/auplay.c000066400000000000000000000044621372575704200154050ustar00rootroot00000000000000/** * @file auplay.c Audio Player * * Copyright (C) 2010 Creytiv.com */ #include #include #include "core.h" static void destructor(void *arg) { struct auplay *ap = arg; list_flush(&ap->dev_list); list_unlink(&ap->le); } /** * Register an Audio Player * * @param app Pointer to allocated Audio Player object * @param auplayl List of Audio Players * @param name Audio Player name * @param alloch Allocation handler * * @return 0 if success, otherwise errorcode */ int auplay_register(struct auplay **app, struct list *auplayl, const char *name, auplay_alloc_h *alloch) { struct auplay *ap; if (!app) return EINVAL; ap = mem_zalloc(sizeof(*ap), destructor); if (!ap) return ENOMEM; list_append(auplayl, &ap->le, ap); ap->name = name; ap->alloch = alloch; info("auplay: %s\n", name); *app = ap; return 0; } /** * Find an Audio Player by name * * @param auplayl List of Audio Players * @param name Name of the Audio Player to find * * @return Matching Audio Player if found, otherwise NULL */ const struct auplay *auplay_find(const struct list *auplayl, const char *name) { struct le *le; for (le=list_head(auplayl); le; le=le->next) { struct auplay *ap = le->data; if (str_isset(name) && 0 != str_casecmp(name, ap->name)) continue; return ap; } return NULL; } /** * Allocate an Audio Player state * * @param stp Pointer to allocated Audio Player state * @param auplayl List of Audio Players * @param name Name of Audio Player * @param prm Audio Player parameters * @param device Name of Audio Player device (driver specific) * @param wh Write handler * @param arg Handler argument * * @return 0 if success, otherwise errorcode */ int auplay_alloc(struct auplay_st **stp, struct list *auplayl, const char *name, struct auplay_prm *prm, const char *device, auplay_write_h *wh, void *arg) { struct auplay *ap; ap = (struct auplay *)auplay_find(auplayl, name); if (!ap) return ENOENT; if (!prm->srate || !prm->ch) return EINVAL; return ap->alloch(stp, ap, prm, device, wh, arg); } /** * Get the audio player module from a audio player state * * @param st Audio player state * * @return Audio player module */ struct auplay *auplay_get(struct auplay_st *st) { return st ? st->ap : NULL; } baresip-1.0.0/src/ausrc.c000066400000000000000000000045511372575704200152260ustar00rootroot00000000000000/** * @file ausrc.c Audio Source * * Copyright (C) 2010 Creytiv.com */ #include #include #include "core.h" static void destructor(void *arg) { struct ausrc *as = arg; list_flush(&as->dev_list); list_unlink(&as->le); } /** * Register an Audio Source * * @param asp Pointer to allocated Audio Source object * @param ausrcl List of Audio Sources * @param name Audio Source name * @param alloch Allocation handler * * @return 0 if success, otherwise errorcode */ int ausrc_register(struct ausrc **asp, struct list *ausrcl, const char *name, ausrc_alloc_h *alloch) { struct ausrc *as; if (!asp) return EINVAL; as = mem_zalloc(sizeof(*as), destructor); if (!as) return ENOMEM; list_append(ausrcl, &as->le, as); as->name = name; as->alloch = alloch; info("ausrc: %s\n", name); *asp = as; return 0; } /** * Find an Audio Source by name * * @param ausrcl List of Audio Sources * @param name Name of the Audio Source to find * * @return Matching Audio Source if found, otherwise NULL */ const struct ausrc *ausrc_find(const struct list *ausrcl, const char *name) { struct le *le; for (le=list_head(ausrcl); le; le=le->next) { struct ausrc *as = le->data; if (str_isset(name) && 0 != str_casecmp(name, as->name)) continue; return as; } return NULL; } /** * Allocate an Audio Source state * * @param stp Pointer to allocated Audio Source state * @param ausrcl List of Audio Sources * @param ctx Media context (optional) * @param name Name of Audio Source * @param prm Audio Source parameters * @param device Name of Audio Source device (driver specific) * @param rh Read handler * @param errh Error handler * @param arg Handler argument * * @return 0 if success, otherwise errorcode */ int ausrc_alloc(struct ausrc_st **stp, struct list *ausrcl, struct media_ctx **ctx, const char *name, struct ausrc_prm *prm, const char *device, ausrc_read_h *rh, ausrc_error_h *errh, void *arg) { struct ausrc *as; as = (struct ausrc *)ausrc_find(ausrcl, name); if (!as) return ENOENT; return as->alloch(stp, as, ctx, prm, device, rh, errh, arg); } /** * Get the audio source module from a audio source state * * @param st Audio source state * * @return Audio source module */ struct ausrc *ausrc_get(struct ausrc_st *st) { return st ? (struct ausrc *)st->as : NULL; } baresip-1.0.0/src/baresip.c000066400000000000000000000126361372575704200155410ustar00rootroot00000000000000/** * @file baresip.c Top-level baresip struct * * Copyright (C) 2010 - 2016 Creytiv.com */ #include #include #include "core.h" /* * Top-level struct that holds all other subsystems * (move this instance to main.c later) */ static struct baresip { struct network *net; struct contacts *contacts; struct commands *commands; struct player *player; struct message *message; struct list mnatl; struct list mencl; struct list aucodecl; struct list ausrcl; struct list auplayl; struct list aufiltl; struct list vidcodecl; struct list vidsrcl; struct list vidispl; struct list vidfiltl; struct ui_sub uis; } baresip; static int cmd_quit(struct re_printf *pf, void *unused) { int err; (void)unused; err = re_hprintf(pf, "Quit\n"); ua_stop_all(false); return err; } static int insmod_handler(struct re_printf *pf, void *arg) { const struct cmd_arg *carg = arg; char path[256]; int err; if (conf_get_str(conf_cur(), "module_path", path, sizeof(path))) str_ncpy(path, ".", sizeof(path)); err = module_load(path, carg->prm); if (err) { return re_hprintf(pf, "insmod: ERROR: could not load module" " '%s': %m\n", carg->prm, err); } return re_hprintf(pf, "loaded module %s\n", carg->prm); } static int rmmod_handler(struct re_printf *pf, void *arg) { const struct cmd_arg *carg = arg; (void)pf; module_unload(carg->prm); return 0; } static const struct cmd corecmdv[] = { {"quit", 'q', 0, "Quit", cmd_quit }, {"insmod", 0, CMD_PRM, "Load module", insmod_handler }, {"rmmod", 0, CMD_PRM, "Unload module", rmmod_handler }, }; /** * Initialise the top-level baresip object * * @param cfg Global configuration * * @return 0 if success, otherwise errorcode */ int baresip_init(struct config *cfg) { int err; if (!cfg) return EINVAL; baresip.net = mem_deref(baresip.net); list_init(&baresip.mnatl); list_init(&baresip.mencl); list_init(&baresip.aucodecl); list_init(&baresip.ausrcl); list_init(&baresip.auplayl); list_init(&baresip.vidcodecl); list_init(&baresip.vidsrcl); list_init(&baresip.vidispl); list_init(&baresip.vidfiltl); /* Initialise Network */ err = net_alloc(&baresip.net, &cfg->net); if (err) { warning("ua: network init failed: %m\n", err); return err; } err = contact_init(&baresip.contacts); if (err) return err; err = cmd_init(&baresip.commands); if (err) return err; err = play_init(&baresip.player); if (err) return err; err = message_init(&baresip.message); if (err) { warning("baresip: message init failed: %m\n", err); return err; } err = cmd_register(baresip.commands, corecmdv, ARRAY_SIZE(corecmdv)); if (err) return err; return 0; } /** * Close the top-level baresip object */ void baresip_close(void) { cmd_unregister(baresip.commands, corecmdv); baresip.message = mem_deref(baresip.message); baresip.player = mem_deref(baresip.player); baresip.commands = mem_deref(baresip.commands); baresip.contacts = mem_deref(baresip.contacts); baresip.net = mem_deref(baresip.net); ui_reset(&baresip.uis); } /** * Get the network subsystem * * @return Network subsystem */ struct network *baresip_network(void) { return baresip.net; } /** * Get the contacts subsystem * * @return Contacts subsystem */ struct contacts *baresip_contacts(void) { return baresip.contacts; } /** * Get the commands subsystem * * @return Commands subsystem */ struct commands *baresip_commands(void) { return baresip.commands; } /** * Get the audio player * * @return Audio player */ struct player *baresip_player(void) { return baresip.player; } /** * Get the list of Media NATs * * @return List of Media NATs */ struct list *baresip_mnatl(void) { return &baresip.mnatl; } /** * Get the list of Media encryptions * * @return List of Media encryptions */ struct list *baresip_mencl(void) { return &baresip.mencl; } /** * Get the Message subsystem * * @return Message subsystem */ struct message *baresip_message(void) { return baresip.message; } /** * Get the list of Audio Codecs * * @return List of audio-codecs */ struct list *baresip_aucodecl(void) { return &baresip.aucodecl; } /** * Get the list of Audio Sources * * @return List of audio-sources */ struct list *baresip_ausrcl(void) { return &baresip.ausrcl; } /** * Get the list of Audio Players * * @return List of audio-players */ struct list *baresip_auplayl(void) { return &baresip.auplayl; } /** * Get the list of Audio Filters * * @return List of audio-filters */ struct list *baresip_aufiltl(void) { return &baresip.aufiltl; } /** * Get the list of Video codecs * * @return List of video-codecs */ struct list *baresip_vidcodecl(void) { return &baresip.vidcodecl; } /** * Get the list of Video sources * * @return List of video-sources */ struct list *baresip_vidsrcl(void) { return &baresip.vidsrcl; } /** * Get the list of Video displays * * @return List of video-displays */ struct list *baresip_vidispl(void) { return &baresip.vidispl; } /** * Get the list of Video filters * * @return List of video-filters */ struct list *baresip_vidfiltl(void) { return &baresip.vidfiltl; } /** * Get the User Interface (UI) subsystem * * @return User Interface (UI) subsystem */ struct ui_sub *baresip_uis(void) { return &baresip.uis; } baresip-1.0.0/src/call.c000066400000000000000000001373121372575704200150260ustar00rootroot00000000000000/** * @file src/call.c Call Control * * Copyright (C) 2010 Creytiv.com */ #include #include #include #include #include #include #include #include "core.h" /** Magic number */ #define MAGIC 0xca11ca11 #include "magic.h" #define FOREACH_STREAM \ for (le = call->streaml.head; le; le = le->next) /** SIP Call Control object */ struct call { MAGIC_DECL /**< Magic number for debugging */ struct le le; /**< Linked list element */ struct ua *ua; /**< SIP User-agent */ struct account *acc; /**< Account (ref.) */ struct sipsess *sess; /**< SIP Session */ struct sdp_session *sdp; /**< SDP Session */ struct sipsub *sub; /**< Call transfer REFER subscription */ struct sipnot *not; /**< REFER/NOTIFY client */ struct list streaml; /**< List of mediastreams (struct stream) */ struct audio *audio; /**< Audio stream */ struct video *video; /**< Video stream */ struct media_ctx *ctx; /**< Shared A/V source media context */ enum call_state state; /**< Call state */ char *local_uri; /**< Local SIP uri */ char *local_name; /**< Local display name */ char *peer_uri; /**< Peer SIP Address */ char *peer_name; /**< Peer display name */ char *id; /**< Cached session call-id */ struct tmr tmr_inv; /**< Timer for incoming calls */ struct tmr tmr_dtmf; /**< Timer for incoming DTMF events */ time_t time_start; /**< Time when call started */ time_t time_conn; /**< Time when call initiated */ time_t time_stop; /**< Time when call stopped */ bool outgoing; /**< True if outgoing, false if incoming */ bool got_offer; /**< Got SDP Offer from Peer */ bool on_hold; /**< True if call is on hold (local) */ struct mnat_sess *mnats; /**< Media NAT session */ bool mnat_wait; /**< Waiting for MNAT to establish */ struct menc_sess *mencs; /**< Media encryption session state */ int af; /**< Preferred Address Family */ uint16_t scode; /**< Termination status code */ call_event_h *eh; /**< Event handler */ call_dtmf_h *dtmfh; /**< DTMF handler */ void *arg; /**< Handler argument */ struct config_avt config_avt; /**< AVT config */ struct config_call config_call; /**< Call config */ uint32_t rtp_timeout_ms; /**< RTP Timeout in [ms] */ uint32_t linenum; /**< Line number from 1 to N */ struct list custom_hdrs; /**< List of custom headers if any */ }; static int send_invite(struct call *call); static const char *state_name(enum call_state st) { switch (st) { case CALL_STATE_IDLE: return "IDLE"; case CALL_STATE_INCOMING: return "INCOMING"; case CALL_STATE_OUTGOING: return "OUTGOING"; case CALL_STATE_RINGING: return "RINGING"; case CALL_STATE_EARLY: return "EARLY"; case CALL_STATE_ESTABLISHED: return "ESTABLISHED"; case CALL_STATE_TERMINATED: return "TERMINATED"; case CALL_STATE_UNKNOWN: return "UNKNOWN"; default: return "???"; } } static void set_state(struct call *call, enum call_state st) { call->state = st; } static const struct sdp_format *sdp_media_rcodec(const struct sdp_media *m) { const struct list *lst; struct le *le; if (!m || !sdp_media_rport(m)) return NULL; lst = sdp_media_format_lst(m, false); for (le=list_head(lst); le; le=le->next) { const struct sdp_format *fmt = le->data; if (!fmt->sup) continue; if (!fmt->data) continue; return fmt; } return NULL; } static int start_audio(struct call *call) { const struct sdp_format *sc; int err = 0; /* Audio Stream */ sc = sdp_media_rcodec(stream_sdpmedia(audio_strm(call->audio))); if (sc) { struct aucodec *ac = sc->data; err = audio_encoder_set(call->audio, ac, sc->pt, sc->params); if (err) { warning("call: start:" " audio_encoder_set error: %m\n", err); } err |= audio_decoder_set(call->audio, ac, sc->pt, sc->params); if (err) { warning("call: start:" " audio_decoder_set error: %m\n", err); } if (!err) { err = audio_start(call->audio); if (err) { warning("call: start:" " audio_start error: %m\n", err); } } } else { info("call: audio stream is disabled..\n"); } return err; } static int start_video(struct call *call) { const struct sdp_format *sc; int err = 0; /* Video Stream */ sc = sdp_media_rformat(stream_sdpmedia(video_strm(call->video)), NULL); if (sc) { err = video_encoder_set(call->video, sc->data, sc->pt, sc->params); err |= video_decoder_set(call->video, sc->data, sc->pt, sc->rparams); if (err) return err; if (!video_is_started(call->video)) { err = video_start_display(call->video, call->peer_uri); err |= video_start_source(call->video, &call->ctx); } if (err) { warning("call: video stream error: %m\n", err); } } else if (call->video) { info("call: video stream is disabled..\n"); } return err; } static void call_stream_start(struct call *call, bool active) { int err; debug("call: stream start (active=%d)\n", active); if (stream_is_ready(audio_strm(call->audio))) { err = start_audio(call); if (err) { warning("call: could not start audio: %m\n", err); } } if (stream_is_ready(video_strm(call->video))) { err = start_video(call); if (err) { warning("call: could not start video: %m\n", err); } } if (active) { struct le *le; tmr_cancel(&call->tmr_inv); call->time_start = time(NULL); FOREACH_STREAM { stream_reset(le->data); } } } static void call_stream_stop(struct call *call) { if (!call) return; call->time_stop = time(NULL); /* Audio */ audio_stop(call->audio); /* Video */ video_stop(call->video); tmr_cancel(&call->tmr_inv); } static void call_event_handler(struct call *call, enum call_event ev, const char *fmt, ...) { call_event_h *eh = call->eh; void *eh_arg = call->arg; char buf[256]; va_list ap; if (!eh) return; va_start(ap, fmt); (void)re_vsnprintf(buf, sizeof(buf), fmt, ap); va_end(ap); eh(call, ev, buf, eh_arg); } static void invite_timeout(void *arg) { struct call *call = arg; info("%s: Local timeout after %u seconds\n", call->peer_uri, call->config_call.local_timeout); call_event_handler(call, CALL_EVENT_CLOSED, "Local timeout"); } /* Called when all media streams are established */ static void mnat_handler(int err, uint16_t scode, const char *reason, void *arg) { struct call *call = arg; MAGIC_CHECK(call); if (err) { warning("call: medianat '%s' failed: %m\n", call->acc->mnatid, err); call_event_handler(call, CALL_EVENT_CLOSED, "%m", err); return; } else if (scode) { warning("call: medianat failed: %u %s\n", scode, reason); call_event_handler(call, CALL_EVENT_CLOSED, "%u %s", scode, reason); return; } info("call: media-nat '%s' established/gathered\n", call->acc->mnatid); /* Re-INVITE */ if (!call->mnat_wait) { info("call: medianat established -- sending Re-INVITE\n"); (void)call_modify(call); return; } call->mnat_wait = false; switch (call->state) { case CALL_STATE_OUTGOING: (void)send_invite(call); break; case CALL_STATE_INCOMING: call_event_handler(call, CALL_EVENT_INCOMING, call->peer_uri); break; default: break; } } static int update_audio(struct call *call) { const struct sdp_format *sc; int err = 0; sc = sdp_media_rcodec(stream_sdpmedia(audio_strm(call->audio))); if (sc) { struct aucodec *ac = sc->data; err = audio_decoder_set(call->audio, ac, sc->pt, sc->params); if (err) { warning("call: update:" " audio_decoder_set error: %m\n", err); } err |= audio_encoder_set(call->audio, ac, sc->pt, sc->params); } else { info("audio stream is disabled..\n"); } return err; } static int update_video(struct call *call) { const struct sdp_format *sc = NULL; int err = 0; struct sdp_media *m = stream_sdpmedia(video_strm(call->video)); if (!sdp_media_disabled(m)) sc = sdp_media_rformat(m, NULL); if (sc) { err = video_encoder_set(call->video, sc->data, sc->pt, sc->params); if (err) { warning("call: video stream error: %m\n", err); return err; } if (!video_is_started(call->video)) { err = video_start_display(call->video, call->peer_uri); err |= video_start_source(call->video, &call->ctx); if (err) { warning("call: update: failed to" " start video (%m)\n", err); } } } else if (call->video) { info("video stream is disabled..\n"); video_stop(call->video); video_stop_display(call->video); } return err; } static int update_media(struct call *call) { struct le *le; int err = 0; debug("call: update media\n"); ua_event(call->ua, UA_EVENT_CALL_REMOTE_SDP, call, call->got_offer ? "offer" : "answer"); /* media attributes */ audio_sdp_attr_decode(call->audio); if (call->video) video_sdp_attr_decode(call->video); /* Update each stream */ FOREACH_STREAM { stream_update(le->data); } if (call->acc->mnat && call->acc->mnat->updateh && call->mnats) err = call->acc->mnat->updateh(call->mnats); if (stream_is_ready(audio_strm(call->audio))) { err |= update_audio(call); } if (stream_is_ready(video_strm(call->video))) { err |= update_video(call); } return err; } static void print_summary(const struct call *call) { uint32_t dur = call_duration(call); if (!dur) return; info("%s: Call with %s terminated (duration: %H)\n", call->local_uri, call->peer_uri, fmt_human_time, &dur); } static void call_destructor(void *arg) { struct call *call = arg; if (call->state != CALL_STATE_IDLE) print_summary(call); call_stream_stop(call); list_unlink(&call->le); tmr_cancel(&call->tmr_dtmf); mem_deref(call->sess); mem_deref(call->id); mem_deref(call->local_uri); mem_deref(call->local_name); mem_deref(call->peer_uri); mem_deref(call->peer_name); mem_deref(call->audio); mem_deref(call->video); mem_deref(call->sdp); mem_deref(call->mnats); mem_deref(call->mencs); mem_deref(call->sub); mem_deref(call->not); mem_deref(call->acc); list_flush(&call->custom_hdrs); } static void audio_event_handler(int key, bool end, void *arg) { struct call *call = arg; MAGIC_CHECK(call); info("received event: '%c' (end=%d)\n", key, end); if (call->dtmfh) call->dtmfh(call, end ? KEYCODE_REL : key, call->arg); } static void audio_level_handler(bool tx, double lvl, void *arg) { struct call *call = arg; MAGIC_CHECK(call); ua_event(call->ua, tx ? UA_EVENT_VU_TX : UA_EVENT_VU_RX, call, "%.2f", lvl); } static void audio_error_handler(int err, const char *str, void *arg) { struct call *call = arg; MAGIC_CHECK(call); if (err) { warning("call: audio device error: %m (%s)\n", err, str); } ua_event(call->ua, UA_EVENT_AUDIO_ERROR, call, "%d,%s", err, str); call_stream_stop(call); call_event_handler(call, CALL_EVENT_CLOSED, str); } static void video_error_handler(int err, const char *str, void *arg) { struct call *call = arg; MAGIC_CHECK(call); warning("call: video device error: %m (%s)\n", err, str); call_stream_stop(call); call_event_handler(call, CALL_EVENT_CLOSED, str); } static void menc_event_handler(enum menc_event event, const char *prm, struct stream *strm, void *arg) { struct call *call = arg; int err; (void)strm; MAGIC_CHECK(call); debug("call: mediaenc event '%s' (%s)\n", menc_event_name(event), prm); switch (event) { case MENC_EVENT_SECURE: if (strstr(prm, "audio")) { stream_set_secure(audio_strm(call->audio), true); stream_start(audio_strm(call->audio)); err = start_audio(call); if (err) { warning("call: secure: could not" " start audio: %m\n", err); } } else if (strstr(prm, "video")) { stream_set_secure(video_strm(call->video), true); stream_start(video_strm(call->video)); err = start_video(call); if (err) { warning("call: secure: could not" " start video: %m\n", err); } } else { info("call: mediaenc: no match for stream (%s)\n", prm); } break; default: break; } if (str_isset(prm)) call_event_handler(call, CALL_EVENT_MENC, "%u,%s", event, prm); else call_event_handler(call, CALL_EVENT_MENC, "%u", event); } static void menc_error_handler(int err, void *arg) { struct call *call = arg; MAGIC_CHECK(call); warning("call: mediaenc '%s' error: %m\n", call->acc->mencid, err); call_stream_stop(call); call_event_handler(call, CALL_EVENT_CLOSED, "mediaenc failed"); } static void stream_mnatconn_handler(struct stream *strm, void *arg) { struct call *call = arg; int err; MAGIC_CHECK(call); if (strm->mencs) { err = stream_start_mediaenc(strm); if (err) { call_event_handler(call, CALL_EVENT_CLOSED, "mediaenc failed %m", err); } } else if (stream_is_ready(strm)) { switch (strm->type) { case MEDIA_AUDIO: err = start_audio(call); if (err) { warning("call: mnatconn: could not" " start audio: %m\n", err); } break; case MEDIA_VIDEO: err = start_video(call); if (err) { warning("call: mnatconn: could not" " start video: %m\n", err); } break; } } } static void stream_rtpestab_handler(struct stream *strm, void *arg) { struct call *call = arg; MAGIC_CHECK(call); ua_event(call->ua, UA_EVENT_CALL_RTPESTAB, call, "%s", sdp_media_name(stream_sdpmedia(strm))); } static void stream_rtcp_handler(struct stream *strm, struct rtcp_msg *msg, void *arg) { struct call *call = arg; MAGIC_CHECK(call); switch (msg->hdr.pt) { case RTCP_SR: if (strm->cfg.rtp_stats) call_set_xrtpstat(call); ua_event(call->ua, UA_EVENT_CALL_RTCP, call, "%s", sdp_media_name(stream_sdpmedia(strm))); break; case RTCP_APP: ua_event(call->ua, UA_EVENT_CALL_RTCP, call, "%s", sdp_media_name(stream_sdpmedia(strm))); break; } } static void stream_error_handler(struct stream *strm, int err, void *arg) { struct call *call = arg; MAGIC_CHECK(call); info("call: error in \"%s\" rtp stream (%m)\n", sdp_media_name(stream_sdpmedia(strm)), err); call->scode = 701; set_state(call, CALL_STATE_TERMINATED); call_stream_stop(call); call_event_handler(call, CALL_EVENT_CLOSED, "rtp stream error"); } static int assign_linenum(uint32_t *linenum, const struct list *lst) { uint32_t num; for (num=CALL_LINENUM_MIN; numvidmode : VIDMODE_OFF; bool use_video = true, got_offer = false; int label = 0; int err = 0; if (!cfg || !local_uri || !acc || !ua || !prm) return EINVAL; debug("call: alloc with params laddr=%j, af=%s, use_rtp=%d\n", &prm->laddr, net_af2name(prm->af), prm->use_rtp); memset(&stream_prm, 0, sizeof(stream_prm)); stream_prm.use_rtp = prm->use_rtp; stream_prm.af = prm->af; stream_prm.cname = local_uri; call = mem_zalloc(sizeof(*call), call_destructor); if (!call) return ENOMEM; MAGIC_INIT(call); call->config_avt = cfg->avt; call->config_call = cfg->call; tmr_init(&call->tmr_inv); call->acc = mem_ref(acc); call->ua = ua; call->state = CALL_STATE_IDLE; call->eh = eh; call->arg = arg; call->af = prm->af; err = str_dup(&call->local_uri, local_uri); if (local_name) err |= str_dup(&call->local_name, local_name); if (err) goto out; /* Init SDP info */ err = sdp_session_alloc(&call->sdp, &prm->laddr); if (err) goto out; err = sdp_session_set_lattr(call->sdp, true, "tool", "baresip " BARESIP_VERSION); if (err) goto out; /* Check for incoming SDP Offer */ if (msg && mbuf_get_left(msg->mb)) got_offer = true; /* Initialise media NAT handling */ if (acc->mnat) { err = acc->mnat->sessh(&call->mnats, acc->mnat, dnsc, call->af, acc->stun_host, acc->stun_user, acc->stun_pass, call->sdp, !got_offer, mnat_handler, call); if (err) { warning("call: medianat session: %m\n", err); goto out; } } call->mnat_wait = true; /* Media encryption */ if (acc->menc) { if (acc->menc->sessh) { err = acc->menc->sessh(&call->mencs, call->sdp, !got_offer, menc_event_handler, menc_error_handler, call); if (err) { warning("call: mediaenc session: %m\n", err); goto out; } } } /* Audio stream */ err = audio_alloc(&call->audio, &call->streaml, &stream_prm, cfg, acc, call->sdp, ++label, acc->mnat, call->mnats, acc->menc, call->mencs, acc->ptime, account_aucodecl(call->acc), !got_offer, audio_event_handler, audio_level_handler, audio_error_handler, call); if (err) goto out; audio_set_media_context(call->audio, &call->ctx); /* We require at least one video codec, and at least one video source or video display */ use_video = (vidmode != VIDMODE_OFF) && (list_head(account_vidcodecl(call->acc)) != NULL) && (NULL != vidsrc_find(baresip_vidsrcl(), NULL) || NULL != vidisp_find(baresip_vidispl(), NULL)); debug("call: use_video=%d\n", use_video); /* Video stream */ if (use_video) { err = video_alloc(&call->video, &call->streaml, &stream_prm, cfg, call->sdp, ++label, acc->mnat, call->mnats, acc->menc, call->mencs, "main", account_vidcodecl(call->acc), baresip_vidfiltl(), !got_offer, video_error_handler, call); if (err) goto out; } /* inherit certain properties from original call */ if (xcall) { call->not = mem_ref(xcall->not); } FOREACH_STREAM { struct stream *strm = le->data; stream_set_session_handlers(strm, stream_mnatconn_handler, stream_rtpestab_handler, stream_rtcp_handler, stream_error_handler, call); } if (cfg->avt.rtp_timeout) { call_enable_rtp_timeout(call, cfg->avt.rtp_timeout*1000); } err = assign_linenum(&call->linenum, lst); if (err) { warning("call: could not assign linenumber\n"); goto out; } /* NOTE: The new call must always be added to the tail of list, * which indicates the current call. */ list_append(lst, &call->le, call); out: if (err) mem_deref(call); else if (callp) *callp = call; return err; } void call_set_custom_hdrs(struct call *call, const struct list *hdrs) { struct le *le; if (!call) return; list_flush(&call->custom_hdrs); LIST_FOREACH(hdrs, le) { struct sip_hdr *hdr = le->data; char *buf = NULL; if (re_sdprintf(&buf, "%r", &hdr->name)) return; if (custom_hdrs_add(&call->custom_hdrs, buf, "%r", &hdr->val)) { mem_deref(buf); return; } mem_deref(buf); } } /** * Get the list of custom SIP headers * * @param call Call object * * @return List of custom SIP headers (struct sip_hdr) */ const struct list *call_get_custom_hdrs(const struct call *call) { if (!call) return NULL; return &call->custom_hdrs; } /** * Connect an outgoing call to a given SIP uri * * @param call Call Object * @param paddr SIP address or uri to connect to * * @return 0 if success, otherwise errorcode */ int call_connect(struct call *call, const struct pl *paddr) { struct sip_addr addr; int err; if (!call || !paddr) return EINVAL; info("call: connecting to '%r'..\n", paddr); call->outgoing = true; /* if the peer-address is a full SIP address then we need * to parse it and extract the SIP uri part. */ if (0 == sip_addr_decode(&addr, paddr)) { if (pl_isset(&addr.params)) { err = re_sdprintf(&call->peer_uri, "%r%r", &addr.auri, &addr.params); } else { err = pl_strdup(&call->peer_uri, &addr.auri); } } else { err = pl_strdup(&call->peer_uri, paddr); } if (err) return err; set_state(call, CALL_STATE_OUTGOING); /* If we are using asyncronous medianat like STUN/TURN, then * wait until completed before sending the INVITE */ if (!call->acc->mnat) err = send_invite(call); return err; } /** * Update the current call by sending Re-INVITE or UPDATE * * @param call Call object * * @return 0 if success, otherwise errorcode */ int call_modify(struct call *call) { struct mbuf *desc; int err; if (!call) return EINVAL; debug("call: modify\n"); err = call_sdp_get(call, &desc, true); if (!err) err = sipsess_modify(call->sess, desc); mem_deref(desc); return err; } /** * Hangup the call * * @param call Call to hangup * @param scode Optional status code * @param reason Optional reason */ void call_hangup(struct call *call, uint16_t scode, const char *reason) { if (!call) return; if (call->config_avt.rtp_stats) call_set_xrtpstat(call); switch (call->state) { case CALL_STATE_INCOMING: if (scode < 400) { scode = 486; reason = "Rejected"; } info("call: rejecting incoming call from %s (%u %s)\n", call->peer_uri, scode, reason); (void)sipsess_reject(call->sess, scode, reason, NULL); break; default: info("call: terminate call '%s' with %s\n", sip_dialog_callid(sipsess_dialog(call->sess)), call->peer_uri); if (call->not) call_notify_sipfrag(call, 487, "Request Terminated"); call->sess = mem_deref(call->sess); break; } set_state(call, CALL_STATE_TERMINATED); call_stream_stop(call); } /** * Answer an incoming call with early media * * @param call Call to answer * * @return 0 if success, otherwise errorcode */ int call_progress(struct call *call) { struct mbuf *desc; int err; if (!call) return EINVAL; tmr_cancel(&call->tmr_inv); err = call_sdp_get(call, &desc, false); if (err) return err; err = sipsess_progress(call->sess, 183, "Session Progress", desc, "Allow: %H\r\n", ua_print_allowed, call->ua); if (!err) call_stream_start(call, false); mem_deref(desc); return 0; } /** * Answer an incoming call * * @param call Call to answer * @param scode Status code * @param vmode Wanted video mode * * @return 0 if success, otherwise errorcode */ int call_answer(struct call *call, uint16_t scode, enum vidmode vmode) { struct mbuf *desc; int err; if (!call || !call->sess) return EINVAL; if (CALL_STATE_INCOMING != call->state) { info("call: answer: call is not in incoming state (%s)\n", state_name(call->state)); return 0; } if (vmode == VIDMODE_OFF) call->video = mem_deref(call->video); info("call: answering call on line %u from %s with %u\n", call->linenum, call->peer_uri, scode); if (call->got_offer) { err = update_media(call); if (err) return err; } ua_event(call->ua, UA_EVENT_CALL_LOCAL_SDP, call, "%s", !call->got_offer ? "offer" : "answer"); err = sdp_encode(&desc, call->sdp, !call->got_offer); if (err) return err; err = sipsess_answer(call->sess, scode, "Answering", desc, "Allow: %H\r\n", ua_print_allowed, call->ua); mem_deref(desc); return err; } /** * Check if the current call has an active audio stream * * @param call Call object * * @return True if active stream, otherwise false */ bool call_has_audio(const struct call *call) { if (!call) return false; return sdp_media_has_media(stream_sdpmedia(audio_strm(call->audio))); } /** * Check if the current call has an active video stream * * @param call Call object * * @return True if active stream, otherwise false */ bool call_has_video(const struct call *call) { if (!call) return false; return sdp_media_has_media(stream_sdpmedia(video_strm(call->video))); } /** * Put the current call on hold/resume * * @param call Call object * @param hold True to hold, false to resume * * @return 0 if success, otherwise errorcode */ int call_hold(struct call *call, bool hold) { struct le *le; if (!call || !call->sess) return EINVAL; if (hold == call->on_hold) return 0; info("call: %s %s\n", hold ? "hold" : "resume", call->peer_uri); call->on_hold = hold; FOREACH_STREAM stream_hold(le->data, hold); return call_modify(call); } /** * Sets the video direction of the given call * * @param call Call object * @param dir SDP media direction * * @return 0 if success, otherwise errorcode */ int call_set_video_dir(struct call *call, enum sdp_dir dir) { if (!call) return EINVAL; stream_set_ldir(video_strm(call_video(call)), dir); return call_modify(call); } int call_sdp_get(const struct call *call, struct mbuf **descp, bool offer) { if (!call) return EINVAL; return sdp_encode(descp, call->sdp, offer); } /** * Get the session call-id for the call * * @param call Call object * * @return Session call-id */ const char *call_id(const struct call *call) { return call ? call->id : NULL; } /** * Get the URI of the peer * * @param call Call object * * @return Peer URI */ const char *call_peeruri(const struct call *call) { return call ? call->peer_uri : NULL; } /** * Get the local URI of the call * * @param call Call object * * @return Local URI */ const char *call_localuri(const struct call *call) { return call ? call->local_uri : NULL; } /** * Get the name of the peer * * @param call Call object * * @return Peer name */ const char *call_peername(const struct call *call) { return call ? call->peer_name : NULL; } /** * Print the call debug information * * @param pf Print function * @param call Call object * * @return 0 if success, otherwise errorcode */ int call_debug(struct re_printf *pf, const struct call *call) { int err; if (!call) return 0; err = re_hprintf(pf, "===== Call debug (%s) =====\n", state_name(call->state)); /* SIP Session debug */ err |= re_hprintf(pf, " local_uri: %s <%s>\n" " peer_uri: %s <%s>\n" " af=%s id=%s\n", call->local_name, call->local_uri, call->peer_name, call->peer_uri, net_af2name(call->af), call->id); err |= re_hprintf(pf, " direction: %s\n", call->outgoing ? "Outgoing" : "Incoming"); /* SDP debug */ err |= sdp_session_debug(pf, call->sdp); return err; } static int print_duration(struct re_printf *pf, const struct call *call) { const uint32_t dur = call_duration(call); const uint32_t sec = dur%60%60; const uint32_t min = dur/60%60; const uint32_t hrs = dur/60/60; return re_hprintf(pf, "%u:%02u:%02u", hrs, min, sec); } /** * Print the call status * * @param pf Print function * @param call Call object * * @return 0 if success, otherwise errorcode */ int call_status(struct re_printf *pf, const struct call *call) { struct le *le; int err; if (!call) return EINVAL; switch (call->state) { case CALL_STATE_EARLY: case CALL_STATE_ESTABLISHED: break; default: return 0; } err = re_hprintf(pf, "\r[%H]", print_duration, call); FOREACH_STREAM err |= stream_print(pf, le->data); err |= re_hprintf(pf, " (bit/s)"); if (call->video) err |= video_print(pf, call->video); /* remove old junk */ err |= re_hprintf(pf, " "); return err; } int call_jbuf_stat(struct re_printf *pf, const struct call *call) { struct le *le; int err = 0; if (!call) return EINVAL; FOREACH_STREAM err |= stream_jbuf_stat(pf, le->data); return err; } int call_info(struct re_printf *pf, const struct call *call) { if (!call) return 0; return re_hprintf(pf, "[line %u] %H %9s %s %s", call->linenum, print_duration, call, state_name(call->state), call->on_hold ? "(on hold)" : " ", call->peer_uri); } /** * Send a DTMF digit to the peer * * @param call Call object * @param key DTMF digit to send (KEYCODE_REL for key release) * * @return 0 if success, otherwise errorcode */ int call_send_digit(struct call *call, char key) { if (!call) return EINVAL; return audio_send_digit(call->audio, key); } /** * Get the User-Agent for the call * * @param call Call object * * @return User-Agent */ struct ua *call_get_ua(const struct call *call) { return call ? call->ua : NULL; } struct account *call_account(const struct call *call) { return call ? call->acc : NULL; } static int auth_handler(char **username, char **password, const char *realm, void *arg) { struct account *acc = arg; return account_auth(acc, username, password, realm); } static int sipsess_offer_handler(struct mbuf **descp, const struct sip_msg *msg, void *arg) { const bool got_offer = (0 != mbuf_get_left(msg->mb)); struct call *call = arg; int err; MAGIC_CHECK(call); info("call: got re-INVITE%s\n", got_offer ? " (SDP Offer)" : ""); if (got_offer) { call->got_offer = true; /* Decode SDP Offer */ err = sdp_decode(call->sdp, msg->mb, true); if (err) { warning("call: reinvite: could not decode SDP offer:" " %m\n", err); return err; } err = update_media(call); if (err) return err; } /* Encode SDP Answer */ return sdp_encode(descp, call->sdp, !got_offer); } static int sipsess_answer_handler(const struct sip_msg *msg, void *arg) { struct call *call = arg; int err; MAGIC_CHECK(call); debug("call: got SDP answer (%zu bytes)\n", mbuf_get_left(msg->mb)); call->got_offer = false; if (msg_ctype_cmp(&msg->ctyp, "multipart", "mixed")) (void)sdp_decode_multipart(&msg->ctyp.params, msg->mb); err = sdp_decode(call->sdp, msg->mb, false); if (err) { warning("call: could not decode SDP answer: %m\n", err); return err; } err = update_media(call); if (err) return err; return 0; } static void sipsess_estab_handler(const struct sip_msg *msg, void *arg) { struct call *call = arg; (void)msg; MAGIC_CHECK(call); if (call->state == CALL_STATE_ESTABLISHED) return; set_state(call, CALL_STATE_ESTABLISHED); call_stream_start(call, true); if (call->rtp_timeout_ms) { struct le *le; FOREACH_STREAM { struct stream *strm = le->data; stream_enable_rtp_timeout(strm, call->rtp_timeout_ms); } } /* the transferor will hangup this call */ if (call->not) { (void)call_notify_sipfrag(call, 200, "OK"); } /* must be done last, the handler might deref this call */ call_event_handler(call, CALL_EVENT_ESTABLISHED, call->peer_uri); } static void call_handle_info_req(struct call *call, const struct sip_msg *req) { struct pl body; bool pfu; int err; pl_set_mbuf(&body, req->mb); err = mctrl_handle_media_control(&body, &pfu); if (err) return; debug("call: receive media control: fast_update=%d\n", pfu); if (pfu) { video_update_picture(call->video); } } static void dtmfend_handler(void *arg) { struct call *call = arg; if (call->dtmfh) call->dtmfh(call, KEYCODE_REL, call->arg); } static void sipsess_info_handler(struct sip *sip, const struct sip_msg *msg, void *arg) { struct call *call = arg; if (msg_ctype_cmp(&msg->ctyp, "application", "dtmf-relay")) { struct pl body, sig, dur; int err; pl_set_mbuf(&body, msg->mb); err = re_regex(body.p, body.l, "Signal=[0-9*#a-d]+", &sig); err |= re_regex(body.p, body.l, "Duration=[0-9]+", &dur); if (err || !pl_isset(&sig) || sig.l == 0) { (void)sip_reply(sip, msg, 400, "Bad Request"); } else { char s = toupper(sig.p[0]); uint32_t duration = pl_u32(&dur); info("call: received DTMF: '%c' (duration=%r)\n", s, &dur); (void)sip_reply(sip, msg, 200, "OK"); if (call->dtmfh) { tmr_start(&call->tmr_dtmf, duration, dtmfend_handler, call); call->dtmfh(call, s, call->arg); } } } else if (msg_ctype_cmp(&msg->ctyp, "application", "media_control+xml")) { call_handle_info_req(call, msg); (void)sip_reply(sip, msg, 200, "OK"); } else { (void)sip_reply(sip, msg, 488, "Not Acceptable Here"); } } static void sipnot_close_handler(int err, const struct sip_msg *msg, void *arg) { struct call *call = arg; call->not = mem_deref(call->not); if (err) call_event_handler(call, CALL_EVENT_TRANSFER_FAILED, "%m", err); else if (msg && msg->scode >= 300) call_event_handler(call, CALL_EVENT_TRANSFER_FAILED, "%u %r", msg->scode, &msg->reason); } static void sipsess_refer_handler(struct sip *sip, const struct sip_msg *msg, void *arg) { struct call *call = arg; const struct sip_hdr *hdr; int err; /* get the transfer target */ hdr = sip_msg_hdr(msg, SIP_HDR_REFER_TO); if (!hdr) { warning("call: bad REFER request from %r\n", &msg->from.auri); (void)sip_reply(sip, msg, 400, "Missing Refer-To header"); return; } /* The REFER creates an implicit subscription. * Reply 202 to the REFER request */ call->not = mem_deref(call->not); err = sipevent_accept(&call->not, uag_sipevent_sock(), msg, sipsess_dialog(call->sess), NULL, 202, "Accepted", 60, 60, 60, ua_cuser(call->ua), "message/sipfrag", auth_handler, call->acc, true, sipnot_close_handler, call, "Allow: %H\r\n", ua_print_allowed, call->ua); if (err) { warning("call: refer: sipevent_accept failed: %m\n", err); return; } (void)call_notify_sipfrag(call, 100, "Trying"); call_event_handler(call, CALL_EVENT_TRANSFER, "%r", &hdr->val); } static void sipsess_close_handler(int err, const struct sip_msg *msg, void *arg) { struct call *call = arg; char reason[128] = ""; MAGIC_CHECK(call); if (err) { info("%s: session closed: %m\n", call->peer_uri, err); (void)re_snprintf(reason, sizeof(reason), "%m", err); if (call->not) { (void)call_notify_sipfrag(call, 500, "%m", err); } } else if (msg) { call->scode = msg->scode; (void)re_snprintf(reason, sizeof(reason), "%u %r", msg->scode, &msg->reason); info("%s: session closed: %u %r\n", call->peer_uri, msg->scode, &msg->reason); if (call->not) { (void)call_notify_sipfrag(call, msg->scode, "%r", &msg->reason); } } else { info("%s: session closed\n", call->peer_uri); } call_stream_stop(call); call_event_handler(call, CALL_EVENT_CLOSED, reason); } static bool have_common_audio_codecs(const struct call *call) { const struct sdp_format *sc; struct aucodec *ac; sc = sdp_media_rcodec(stream_sdpmedia(audio_strm(call->audio))); if (!sc) return false; ac = sc->data; /* note: this will exclude telephone-event */ return ac != NULL; } int call_accept(struct call *call, struct sipsess_sock *sess_sock, const struct sip_msg *msg) { bool got_offer; int err; if (!call || !msg) return EINVAL; call->outgoing = false; got_offer = (mbuf_get_left(msg->mb) > 0); err = pl_strdup(&call->peer_uri, &msg->from.auri); if (err) return err; if (pl_isset(&msg->from.dname)) { err = pl_strdup(&call->peer_name, &msg->from.dname); if (err) return err; } if (got_offer) { struct sdp_media *m; const struct sa *raddr; err = sdp_decode(call->sdp, msg->mb, true); if (err) return err; call->got_offer = true; /* * Each media description in the SDP answer MUST * use the same network type as the corresponding * media description in the offer. * * See RFC 6157 */ m = stream_sdpmedia(audio_strm(call->audio)); raddr = sdp_media_raddr(m); if (sa_af(raddr) != call->af) { info("call: incompatible address-family" " (local=%s, remote=%s)\n", net_af2name(call->af), net_af2name(sa_af(raddr))); sip_treply(NULL, uag_sip(), msg, 488, "Not Acceptable Here"); call_event_handler(call, CALL_EVENT_CLOSED, "Wrong address family"); return 0; } /* Check if we have any common audio codecs, after * the SDP offer has been parsed */ if (!have_common_audio_codecs(call)) { info("call: no common audio codecs - rejected\n"); sip_treply(NULL, uag_sip(), msg, 488, "Not Acceptable Here"); call_event_handler(call, CALL_EVENT_CLOSED, "No audio codecs"); return 0; } } err = sipsess_accept(&call->sess, sess_sock, msg, 180, "Ringing", ua_cuser(call->ua), "application/sdp", NULL, auth_handler, call->acc, true, sipsess_offer_handler, sipsess_answer_handler, sipsess_estab_handler, sipsess_info_handler, call->acc->refer ? sipsess_refer_handler : NULL, sipsess_close_handler, call, "Allow: %H\r\n", ua_print_allowed, call->ua); if (err) { warning("call: sipsess_accept: %m\n", err); return err; } err = str_dup(&call->id, sip_dialog_callid(sipsess_dialog(call->sess))); if (err) return err; set_state(call, CALL_STATE_INCOMING); /* New call */ if (call->config_call.local_timeout) { tmr_start(&call->tmr_inv, call->config_call.local_timeout*1000, invite_timeout, call); } if (!call->acc->mnat) call_event_handler(call, CALL_EVENT_INCOMING, call->peer_uri); return err; } static void sipsess_progr_handler(const struct sip_msg *msg, void *arg) { struct call *call = arg; bool media; MAGIC_CHECK(call); info("call: SIP Progress: %u %r (%r/%r)\n", msg->scode, &msg->reason, &msg->ctyp.type, &msg->ctyp.subtype); if (msg->scode <= 100) return; /* check for 18x and content-type * * 1. start media-stream if application/sdp * 2. play local ringback tone if not * * we must also handle changes to/from 180 and 183, * so we reset the media-stream/ringback each time. */ if (msg_ctype_cmp(&msg->ctyp, "application", "sdp") && mbuf_get_left(msg->mb) && !sdp_decode(call->sdp, msg->mb, false)) { media = true; } else if (msg_ctype_cmp(&msg->ctyp, "multipart", "mixed") && !sdp_decode_multipart(&msg->ctyp.params, msg->mb) && !sdp_decode(call->sdp, msg->mb, false)) { media = true; } else media = false; switch (msg->scode) { case 180: set_state(call, CALL_STATE_RINGING); break; case 183: set_state(call, CALL_STATE_EARLY); break; } call_stream_stop(call); if (media) call_stream_start(call, false); if (media) call_event_handler(call, CALL_EVENT_PROGRESS, call->peer_uri); else call_event_handler(call, CALL_EVENT_RINGING, call->peer_uri); if (media) update_media(call); } static int send_invite(struct call *call) { const char *routev[1]; struct mbuf *desc; int err; routev[0] = account_outbound(call->acc, 0); ua_event(call->ua, UA_EVENT_CALL_LOCAL_SDP, call, "offer"); err = call_sdp_get(call, &desc, true); if (err) return err; #if 0 info("- - - - - S D P - O f f e r - - - - -\n" "%b" "- - - - - - - - - - - - - - - - - - -\n", desc->buf, desc->end); #endif err = sipsess_connect(&call->sess, uag_sipsess_sock(), call->peer_uri, call->local_name, call->local_uri, ua_cuser(call->ua), routev[0] ? routev : NULL, routev[0] ? 1 : 0, "application/sdp", desc, auth_handler, call->acc, true, sipsess_offer_handler, sipsess_answer_handler, sipsess_progr_handler, sipsess_estab_handler, sipsess_info_handler, call->acc->refer ? sipsess_refer_handler : NULL, sipsess_close_handler, call, "Allow: %H\r\n%H%H", ua_print_allowed, call->ua, ua_print_supported, call->ua, custom_hdrs_print, &call->custom_hdrs); if (err) { warning("call: sipsess_connect: %m\n", err); goto out; } err = str_dup(&call->id, sip_dialog_callid(sipsess_dialog(call->sess))); /* save call setup timer */ call->time_conn = time(NULL); out: mem_deref(desc); return err; } /** * Get the current call duration in seconds * * @param call Call object * * @return Duration in seconds */ uint32_t call_duration(const struct call *call) { if (!call || !call->time_start) return 0; return (uint32_t)(time(NULL) - call->time_start); } /** * Get the current call setup time in seconds * * @param call Call object * * @return Call setup in seconds */ uint32_t call_setup_duration(const struct call *call) { if (!call || !call->time_conn || call->time_conn <= 0 ) return 0; return (uint32_t)(call->time_start - call->time_conn); } /** * Get the audio object for the current call * * @param call Call object * * @return Audio object */ struct audio *call_audio(const struct call *call) { return call ? call->audio : NULL; } /** * Get the video object for the current call * * @param call Call object * * @return Video object */ struct video *call_video(const struct call *call) { return call ? call->video : NULL; } /** * Get the list of media streams for the current call * * @param call Call object * * @return List of media streams */ struct list *call_streaml(const struct call *call) { return call ? (struct list *)&call->streaml : NULL; } int call_reset_transp(struct call *call, const struct sa *laddr) { if (!call) return EINVAL; sdp_session_set_laddr(call->sdp, laddr); return call_modify(call); } /** * Send a SIP NOTIFY with a SIP message fragment * * @param call Call object * @param scode SIP Status code * @param reason Formatted SIP Reason phrase * @param ... Variable arguments * * @return 0 if success, otherwise errorcode */ int call_notify_sipfrag(struct call *call, uint16_t scode, const char *reason, ...) { struct mbuf *mb; va_list ap; int err; if (!call) return EINVAL; mb = mbuf_alloc(512); if (!mb) return ENOMEM; va_start(ap, reason); (void)mbuf_printf(mb, "SIP/2.0 %u %v\n", scode, reason, &ap); va_end(ap); mb->pos = 0; if (scode >= 200) { err = sipevent_notify(call->not, mb, SIPEVENT_TERMINATED, SIPEVENT_NORESOURCE, 0); call->not = mem_deref(call->not); } else { err = sipevent_notify(call->not, mb, SIPEVENT_ACTIVE, SIPEVENT_NORESOURCE, 0); } mem_deref(mb); return err; } static void sipsub_notify_handler(struct sip *sip, const struct sip_msg *msg, void *arg) { struct call *call = arg; struct pl scode, reason; uint32_t sc; if (re_regex((char *)mbuf_buf(msg->mb), mbuf_get_left(msg->mb), "SIP/2.0 [0-9]+ [^\r\n]+", &scode, &reason)) { (void)sip_reply(sip, msg, 400, "Bad sipfrag"); return; } (void)sip_reply(sip, msg, 200, "OK"); sc = pl_u32(&scode); if (sc >= 300) { warning("call: transfer failed: %u %r\n", sc, &reason); call_event_handler(call, CALL_EVENT_TRANSFER_FAILED, "%u %r", sc, &reason); } else if (sc >= 200) { call_event_handler(call, CALL_EVENT_CLOSED, "Call transfered"); } } static void sipsub_close_handler(int err, const struct sip_msg *msg, const struct sipevent_substate *substate, void *arg) { struct call *call = arg; (void)substate; call->sub = mem_deref(call->sub); if (err) { info("call: subscription closed: %m\n", err); } else if (msg && msg->scode >= 300) { info("call: transfer failed: %u %r\n", msg->scode, &msg->reason); call_event_handler(call, CALL_EVENT_TRANSFER_FAILED, "%u %r", msg->scode, &msg->reason); } } static int normalize_uri(char **out, const char *uri, const struct uri *luri) { struct uri uri2; struct pl pl; int err; if (!out || !uri || !luri) return EINVAL; pl_set_str(&pl, uri); if (0 == uri_decode(&uri2, &pl)) { err = str_dup(out, uri); } else { uri2 = *luri; uri2.user = pl; uri2.password = pl_null; uri2.params = pl_null; err = re_sdprintf(out, "%H", uri_encode, &uri2); } return err; } /** * Transfer the call to a target SIP uri * * @param call Call object * @param uri Target SIP uri * * @return 0 if success, otherwise errorcode */ int call_transfer(struct call *call, const char *uri) { char *nuri; int err; if (!call || !uri) return EINVAL; err = normalize_uri(&nuri, uri, &call->acc->luri); if (err) return err; info("transferring call to %s\n", nuri); call->sub = mem_deref(call->sub); err = sipevent_drefer(&call->sub, uag_sipevent_sock(), sipsess_dialog(call->sess), ua_cuser(call->ua), auth_handler, call->acc, true, sipsub_notify_handler, sipsub_close_handler, call, "Refer-To: %s\r\n", nuri); if (err) { warning("call: sipevent_drefer: %m\n", err); } mem_deref(nuri); return err; } int call_af(const struct call *call) { return call ? call->af : AF_UNSPEC; } /** * Get the SIP status code for the outgoing call * * @param call Call object * * @return SIP Status code */ uint16_t call_scode(const struct call *call) { return call ? call->scode : 0; } /** * Get state of the call * * @param call Call object * * @return Call state or CALL_STATE_UNKNOWN if call object is NULL */ enum call_state call_state(const struct call *call) { if (!call) return CALL_STATE_UNKNOWN; return call->state; } /** * Set the callback handlers for a call object * * @param call Call object * @param eh Event handler * @param dtmfh DTMF handler * @param arg Handler argument */ void call_set_handlers(struct call *call, call_event_h *eh, call_dtmf_h *dtmfh, void *arg) { if (!call) return; if (eh) call->eh = eh; if (dtmfh) call->dtmfh = dtmfh; if (arg) call->arg = arg; } void call_set_xrtpstat(struct call *call) { if (!call) return; sipsess_set_close_headers(call->sess, "X-RTP-Stat: %H\r\n", rtpstat_print, call); } /** * Check if a call is locally on hold * * @param call Call object * * @return True if on hold (local), otherwise false */ bool call_is_onhold(const struct call *call) { return call ? call->on_hold : false; } /** * Check if a call has direction outgoing * * @param call Call object * * @return True if outgoing, otherwise false */ bool call_is_outgoing(const struct call *call) { return call ? call->outgoing : false; } /** * Enable RTP timeout for a call * * @param call Call object * @param timeout_ms RTP Timeout in [milliseconds] */ void call_enable_rtp_timeout(struct call *call, uint32_t timeout_ms) { if (!call) return; call->rtp_timeout_ms = timeout_ms; } /** * Get the line number for this call * * @param call Call object * * @return Line number from 1 to N */ uint32_t call_linenum(const struct call *call) { return call ? call->linenum : 0; } /** * Find the call with a given line number * * @param calls List of calls * @param linenum Line number from 1 to N * * @return Call object if found, NULL if not found */ struct call *call_find_linenum(const struct list *calls, uint32_t linenum) { struct le *le; for (le = list_head(calls); le; le = le->next) { struct call *call = le->data; if (linenum == call->linenum) return call; } return NULL; } /** * Find a call by call-id * * @param calls List of calls * @param id Call-id string * * @return Call object if found, NULL if not found */ struct call *call_find_id(const struct list *calls, const char *id) { struct le *le; for (le = list_head(calls); le; le = le->next) { struct call *call = le->data; if (0 == str_cmp(id, call->id)) return call; } return NULL; } /** * Set the current call * * @param calls List of calls * @param call Call to set as current */ void call_set_current(struct list *calls, struct call *call) { if (!calls || !call) return; list_unlink(&call->le); list_append(calls, &call->le, call); } baresip-1.0.0/src/cmd.c000066400000000000000000000323251372575704200146540ustar00rootroot00000000000000/** * @file src/cmd.c Command Interface * * Copyright (C) 2010 - 2016 Creytiv.com */ #include #include #include #include #include "core.h" enum { KEYCODE_DEL = 0x7f, LONG_PREFIX = '/' }; struct cmds { struct le le; const struct cmd *cmdv; size_t cmdc; }; struct cmd_ctx { struct mbuf *mb; const struct cmd *cmd; bool is_long; }; struct commands { struct list cmdl; /**< List of command blocks (struct cmds) */ }; static int cmd_print_all(struct re_printf *pf, const struct commands *commands, bool print_long, bool print_short, const char *match, size_t match_len); static void destructor(void *arg) { struct cmds *cmds = arg; list_unlink(&cmds->le); } static void ctx_destructor(void *arg) { struct cmd_ctx *ctx = arg; mem_deref(ctx->mb); } static void commands_destructor(void *data) { struct commands *commands = data; list_flush(&commands->cmdl); } static int ctx_alloc(struct cmd_ctx **ctxp, const struct cmd *cmd) { struct cmd_ctx *ctx; ctx = mem_zalloc(sizeof(*ctx), ctx_destructor); if (!ctx) return ENOMEM; ctx->mb = mbuf_alloc(32); if (!ctx->mb) { mem_deref(ctx); return ENOMEM; } ctx->cmd = cmd; *ctxp = ctx; return 0; } /** * Find a command block * * @param commands Commands container * @param cmdv Command vector * * @return Command block if found, otherwise NULL */ struct cmds *cmds_find(const struct commands *commands, const struct cmd *cmdv) { struct le *le; if (!commands || !cmdv) return NULL; for (le = commands->cmdl.head; le; le = le->next) { struct cmds *cmds = le->data; if (cmds->cmdv == cmdv) return cmds; } return NULL; } static const struct cmd *cmd_find_by_key(const struct commands *commands, char key) { struct le *le; if (!commands) return NULL; for (le = commands->cmdl.tail; le; le = le->prev) { struct cmds *cmds = le->data; size_t i; for (i=0; icmdc; i++) { const struct cmd *cmd = &cmds->cmdv[i]; if (cmd->key == key && cmd->h) return cmd; } } return NULL; } static const char *cmd_name(char *buf, size_t sz, const struct cmd *cmd) { switch (cmd->key) { case ' ': return "SPACE"; case '\n': return "ENTER"; case KEYCODE_ESC: return "ESC"; } buf[0] = cmd->key; buf[1] = '\0'; if (cmd->flags & CMD_PRM) strncat(buf, " ..", sz-1); return buf; } static size_t get_match_long(const struct commands *commands, const struct cmd **cmdp, const char *str, size_t len) { struct le *le; size_t nmatch = 0; if (!commands) return 0; for (le = commands->cmdl.head; le; le = le->next) { struct cmds *cmds = le->data; size_t i; for (i=0; icmdc; i++) { const struct cmd *cmd = &cmds->cmdv[i]; if (!str_isset(cmd->name)) continue; if (str_len(cmd->name) >= len && 0 == memcmp(cmd->name, str, len)) { ++nmatch; *cmdp = cmd; } } } return nmatch; } static int editor_input(struct commands *commands, struct mbuf *mb, char key, struct re_printf *pf, bool *del, bool is_long) { int err = 0; switch (key) { case KEYCODE_ESC: *del = true; return re_hprintf(pf, "\nCancel\n"); case KEYCODE_NONE: case KEYCODE_REL: break; case '\n': *del = true; return re_hprintf(pf, "\n"); case '\b': case KEYCODE_DEL: if (mb->pos > 0) { err |= re_hprintf(pf, "\b "); mb->pos = mb->end = (mb->pos - 1); } break; case '\t': if (is_long) { const struct cmd *cmd = NULL; size_t n; err = re_hprintf(pf, "TAB completion for \"%b\":\n", mb->buf, mb->end); if (err) return err; /* Find all long commands that matches the N * first characters of the input string. * * If the number of matches is exactly one, * we can regard it as TAB completion. */ err = cmd_print_all(pf, commands, true, false, (char *)mb->buf, mb->end); if (err) return err; n = get_match_long(commands, &cmd, (char *)mb->buf, mb->end); if (n == 1 && cmd) { mb->pos = 0; mbuf_write_str(mb, cmd->name); } else if (n == 0) { err = re_hprintf(pf, "(none)\n"); } } else { err = mbuf_write_u8(mb, key); } break; default: err = mbuf_write_u8(mb, key); break; } if (is_long) { err |= re_hprintf(pf, "\r%c%b", LONG_PREFIX, mb->buf, mb->end); } else err |= re_hprintf(pf, "\r> %32b", mb->buf, mb->end); return err; } static int cmd_report(const struct cmd *cmd, struct re_printf *pf, struct mbuf *mb, void *data) { struct cmd_arg arg; int err; memset(&arg, 0, sizeof(arg)); mb->pos = 0; err = mbuf_strdup(mb, &arg.prm, mb->end); if (err) return err; arg.key = cmd->key; arg.data = data; err = cmd->h(pf, &arg); mem_deref(arg.prm); return err; } /** * Process long commands * * @param commands Commands container * @param str Input string * @param len Length of input string * @param pf_resp Print function for response * @param data Application data * * @return 0 if success, otherwise errorcode */ int cmd_process_long(struct commands *commands, const char *str, size_t len, struct re_printf *pf_resp, void *data) { struct cmd_arg arg; const struct cmd *cmd_long; char *name = NULL, *prm = NULL; struct pl pl_name, pl_prm; int err; if (!str || !len) return EINVAL; memset(&arg, 0, sizeof(arg)); err = re_regex(str, len, "[^ ]+[ ]*[~]*", &pl_name, NULL, &pl_prm); if (err) { return err; } err = pl_strdup(&name, &pl_name); if (pl_isset(&pl_prm)) err |= pl_strdup(&prm, &pl_prm); if (err) goto out; cmd_long = cmd_find_long(commands, name); if (cmd_long) { arg.key = LONG_PREFIX; arg.prm = prm; arg.data = data; if (cmd_long->h) err = cmd_long->h(pf_resp, &arg); } else { (void)re_hprintf(pf_resp, "command not found (%s)\n", name); err = ENOTSUP; } out: mem_deref(name); mem_deref(prm); return err; } static int cmd_process_edit(struct commands *commands, struct cmd_ctx **ctxp, char key, struct re_printf *pf, void *data) { struct cmd_ctx *ctx; bool compl = (key == '\n'), del = false; int err; if (!ctxp) return EINVAL; ctx = *ctxp; err = editor_input(commands, ctx->mb, key, pf, &del, ctx->is_long); if (err) return err; if (ctx->is_long) { if (compl) { err = cmd_process_long(commands, (char *)ctx->mb->buf, ctx->mb->end, pf, data); } } else { if (compl) err = cmd_report(ctx->cmd, pf, ctx->mb, data); } if (del) *ctxp = mem_deref(*ctxp); return err; } /** * Register commands * * @param commands Commands container * @param cmdv Array of commands * @param cmdc Number of commands * * @return 0 if success, otherwise errorcode */ int cmd_register(struct commands *commands, const struct cmd *cmdv, size_t cmdc) { struct cmds *cmds; size_t i; if (!commands || !cmdv || !cmdc) return EINVAL; cmds = cmds_find(commands, cmdv); if (cmds) return EALREADY; /* verify that command is not registered */ for (i=0; ikey) { const struct cmd *x = cmd_find_by_key(commands, cmd->key); if (x) { warning("short command '%c' already" " registered as \"%s\"\n", x->key, x->desc); return EALREADY; } } if (cmd->key == LONG_PREFIX) { warning("cmd: cannot register command with" " short key '%c'\n", cmd->key); return EINVAL; } if (str_isset(cmd->name) && cmd_find_long(commands, cmd->name)) { warning("cmd: long command '%s' already registered\n", cmd->name); return EINVAL; } } cmds = mem_zalloc(sizeof(*cmds), destructor); if (!cmds) return ENOMEM; cmds->cmdv = cmdv; cmds->cmdc = cmdc; list_append(&commands->cmdl, &cmds->le, cmds); return 0; } /** * Unregister commands * * @param commands Commands container * @param cmdv Array of commands */ void cmd_unregister(struct commands *commands, const struct cmd *cmdv) { mem_deref(cmds_find(commands, cmdv)); } /** * Find a long command * * @param commands Commands container * @param name Name of command, excluding prefix * * @return Command if found, NULL if not found */ const struct cmd *cmd_find_long(const struct commands *commands, const char *name) { struct le *le; if (!commands || !name) return NULL; for (le = commands->cmdl.tail; le; le = le->prev) { struct cmds *cmds = le->data; size_t i; for (i=0; icmdc; i++) { const struct cmd *cmd = &cmds->cmdv[i]; if (0 == str_casecmp(name, cmd->name) && cmd->h) return cmd; } } return NULL; } /** * Process input characters to the command system * * @param commands Commands container * @param ctxp Pointer to context for editor (optional) * @param key Input character * @param pf Print function * @param data Application data * * @return 0 if success, otherwise errorcode */ int cmd_process(struct commands *commands, struct cmd_ctx **ctxp, char key, struct re_printf *pf, void *data) { const struct cmd *cmd; if (!commands) return EINVAL; if (key == KEYCODE_NONE) { warning("cmd: process: illegal keycode NONE\n"); return EINVAL; } /* are we in edit-mode? */ if (ctxp && *ctxp) { if (key == KEYCODE_REL) return 0; return cmd_process_edit(commands, ctxp, key, pf, data); } cmd = cmd_find_by_key(commands, key); if (cmd) { struct cmd_arg arg; /* check for parameters */ if (cmd->flags & CMD_PRM) { int err = 0; if (ctxp) { err = ctx_alloc(ctxp, cmd); if (err) return err; } key = isdigit(key) ? key : KEYCODE_REL; return cmd_process_edit(commands, ctxp, key, pf, data); } arg.key = key; arg.prm = NULL; arg.data = data; return cmd->h(pf, &arg); } else if (key == LONG_PREFIX) { int err; err = re_hprintf(pf, "%c", LONG_PREFIX); if (err) return err; if (!ctxp) { warning("cmd: ctxp is required\n"); return EINVAL; } err = ctx_alloc(ctxp, cmd); if (err) return err; (*ctxp)->is_long = true; return 0; } else if (key == '\t') { return cmd_print_all(pf, commands, false, true, NULL, 0); } if (key == KEYCODE_REL) return 0; return cmd_print(pf, commands); } struct cmd_sort { struct le le; const struct cmd *cmd; }; static bool sort_handler(struct le *le1, struct le *le2, void *arg) { struct cmd_sort *cs1 = le1->data; struct cmd_sort *cs2 = le2->data; const struct cmd *cmd1 = cs1->cmd; const struct cmd *cmd2 = cs2->cmd; bool print_long = *(bool *)arg; if (print_long) { return str_casecmp(cs2->cmd->name ? cs2->cmd->name : "", cs1->cmd->name ? cs1->cmd->name : "") >= 0; } else { return tolower(cmd2->key) >= tolower(cmd1->key); } } static int cmd_print_all(struct re_printf *pf, const struct commands *commands, bool print_long, bool print_short, const char *match, size_t match_len) { struct list sortedl = LIST_INIT; struct le *le; size_t width_long = 1; size_t width_short = 5; char fmt[64]; char buf[16]; int err = 0; if (!commands) return EINVAL; for (le = commands->cmdl.head; le; le = le->next) { struct cmds *cmds = le->data; size_t i; for (i=0; icmdc; i++) { const struct cmd *cmd = &cmds->cmdv[i]; struct cmd_sort *cs; if (match && match_len) { if (str_len(cmd->name) >= match_len && 0 == memcmp(cmd->name, match, match_len)) { /* Match */ } else { continue; } } if (!str_isset(cmd->desc)) continue; if (print_short && !print_long) { if (cmd->key == KEYCODE_NONE) continue; } cs = mem_zalloc(sizeof(*cs), NULL); if (!cs) { err = ENOMEM; goto out; } cs->cmd = cmd; list_append(&sortedl, &cs->le, cs); width_long = max(width_long, 1+str_len(cmd->name)+3); } } list_sort(&sortedl, sort_handler, &print_long); if (re_snprintf(fmt, sizeof(fmt), " %%-%zus %%-%zus %%s\n", width_long, width_short) < 0) { err = ENOMEM; goto out; } for (le = sortedl.head; le; le = le->next) { struct cmd_sort *cs = le->data; const struct cmd *cmd = cs->cmd; char namep[64] = ""; if (print_long && str_isset(cmd->name)) { re_snprintf(namep, sizeof(namep), "%c%s%s", LONG_PREFIX, cmd->name, (cmd->flags & CMD_PRM) ? " .." : ""); } err |= re_hprintf(pf, fmt, namep, (print_short && cmd->key) ? cmd_name(buf, sizeof(buf), cmd) : "", cmd->desc); } err |= re_hprintf(pf, "\n"); out: list_flush(&sortedl); return err; } /** * Print a list of available commands * * @param pf Print function * @param commands Commands container * * @return 0 if success, otherwise errorcode */ int cmd_print(struct re_printf *pf, const struct commands *commands) { int err = 0; if (!pf) return EINVAL; err |= re_hprintf(pf, "--- Help ---\n"); err |= cmd_print_all(pf, commands, true, true, NULL, 0); err |= re_hprintf(pf, "\n"); return err; } /** * Initialize the commands subsystem. * * @param commandsp Pointer to allocated commands * * @return 0 if success, otherwise errorcode */ int cmd_init(struct commands **commandsp) { struct commands *commands; if (!commandsp) return EINVAL; commands = mem_zalloc(sizeof(*commands), commands_destructor); if (!commands) return ENOMEM; list_init(&commands->cmdl); *commandsp = commands; return 0; } baresip-1.0.0/src/conf.c000066400000000000000000000167341372575704200150440ustar00rootroot00000000000000/** * @file conf.c Configuration utils * * Copyright (C) 2010 Creytiv.com */ #define _DEFAULT_SOURCE 1 #define _BSD_SOURCE 1 #include #ifdef HAVE_UNISTD_H #include #endif #include #include #ifdef HAVE_IO_H #include #endif #include #include #include #include "core.h" #define DEBUG_MODULE "" #define DEBUG_LEVEL 0 #include #ifdef WIN32 #define open _open #define read _read #define close _close #endif #if defined (WIN32) #define DIR_SEP "\\" #else #define DIR_SEP "/" #endif static const char *conf_path = NULL; static struct conf *conf_obj; /** * Check if a file exists * * @param path Filename * * @return True if exist, False if not */ bool conf_fileexist(const char *path) { struct stat st; if (!path) return false; if (stat(path, &st) < 0) return false; if ((st.st_mode & S_IFMT) != S_IFREG) return false; return true; } static void print_populated(const char *what, uint32_t n) { info("Populated %u %s%s\n", n, what, 1==n ? "" : "s"); } /** * Parse a config file, calling handler for each line * * @param filename Config file * @param ch Line handler * @param arg Handler argument * * @return 0 if success, otherwise errorcode */ int conf_parse(const char *filename, confline_h *ch, void *arg) { struct pl pl, val; struct mbuf *mb; int err = 0, fd = open(filename, O_RDONLY); if (fd < 0) return errno; mb = mbuf_alloc(1024); if (!mb) { err = ENOMEM; goto out; } for (;;) { uint8_t buf[1024]; const ssize_t n = read(fd, (void *)buf, sizeof(buf)); if (n < 0) { err = errno; break; } else if (n == 0) break; err |= mbuf_write_mem(mb, buf, n); } pl.p = (const char *)mb->buf; pl.l = mb->end; while (pl.p < ((const char *)mb->buf + mb->end) && !err) { const char *lb = pl_strchr(&pl, '\n'); val.p = pl.p; val.l = lb ? (uint32_t)(lb - pl.p) : pl.l; pl_advance(&pl, val.l + 1); if (!val.l || val.p[0] == '#') continue; err = ch(&val, arg); } out: mem_deref(mb); (void)close(fd); return err; } /** * Set the path to configuration files * * @param path Configuration path */ void conf_path_set(const char *path) { conf_path = path; } /** * Get the path to configuration files * * @param path Buffer to write path * @param sz Size of path buffer * * @return 0 if success, otherwise errorcode */ int conf_path_get(char *path, size_t sz) { char buf[FS_PATH_MAX]; int err; /* Use explicit conf path */ if (conf_path) { if (re_snprintf(path, sz, "%s", conf_path) < 0) return ENOMEM; return 0; } #ifdef CONFIG_PATH str_ncpy(buf, CONFIG_PATH, sizeof(buf)); (void)err; #else err = fs_gethome(buf, sizeof(buf)); if (err) return err; #endif if (re_snprintf(path, sz, "%s" DIR_SEP ".baresip", buf) < 0) return ENOMEM; return 0; } int conf_get_range(const struct conf *conf, const char *name, struct range *rng) { struct pl r, min, max; uint32_t v; int err; err = conf_get(conf, name, &r); if (err) return err; err = re_regex(r.p, r.l, "[0-9]+-[0-9]+", &min, &max); if (err) { /* fallback to non-range numeric value */ err = conf_get_u32(conf, name, &v); if (err) { warning("conf: %s: could not parse range: (%r)\n", name, &r); return err; } rng->min = rng->max = v; return err; } rng->min = pl_u32(&min); rng->max = pl_u32(&max); if (rng->min > rng->max) { warning("conf: %s: invalid range (%u - %u)\n", name, rng->min, rng->max); return EINVAL; } return 0; } int conf_get_csv(const struct conf *conf, const char *name, char *str1, size_t sz1, char *str2, size_t sz2) { struct pl r, pl1, pl2 = pl_null; int err; err = conf_get(conf, name, &r); if (err) return err; /* note: second value may be quoted */ err = re_regex(r.p, r.l, "[^,]+,[~]*", &pl1, &pl2); if (err) return err; (void)pl_strcpy(&pl1, str1, sz1); if (pl_isset(&pl2)) (void)pl_strcpy(&pl2, str2, sz2); return 0; } /** * Get the video size of a configuration item * * @param conf Configuration object * @param name Name of config item key * @param sz Returned video size of config item, if present * * @return 0 if success, otherwise errorcode */ int conf_get_vidsz(const struct conf *conf, const char *name, struct vidsz *sz) { struct pl r, w, h; int err; err = conf_get(conf, name, &r); if (err) return err; w.l = h.l = 0; err = re_regex(r.p, r.l, "[0-9]+x[0-9]+", &w, &h); if (err) return err; if (pl_isset(&w) && pl_isset(&h)) { sz->w = pl_u32(&w); sz->h = pl_u32(&h); } /* check resolution */ if (sz->w & 0x1 || sz->h & 0x1) { warning("conf: %s: should be multiple of 2 (%u x %u)\n", name, sz->w, sz->h); return EINVAL; } return 0; } /** * Get the socket address of a configuration item * * @param conf Configuration object * @param name Name of config item key * @param sa Returned socket address of config item, if present * * @return 0 if success, otherwise errorcode */ int conf_get_sa(const struct conf *conf, const char *name, struct sa *sa) { struct pl opt; int err; if (!conf || !name || !sa) return EINVAL; err = conf_get(conf, name, &opt); if (err) return err; return sa_decode(sa, opt.p, opt.l); } int conf_get_float(const struct conf *conf, const char *name, double *val) { struct pl opt; int err; if (!conf || !name || !val) return EINVAL; err = conf_get(conf, name, &opt); if (err) return err; *val = pl_float(&opt); return 0; } /** * Configure the system with default settings * * @return 0 if success, otherwise errorcode */ int conf_configure(void) { char path[FS_PATH_MAX], file[FS_PATH_MAX]; int err; #if defined (WIN32) dbg_init(DBG_INFO, DBG_NONE); #endif err = conf_path_get(path, sizeof(path)); if (err) { warning("conf: could not get config path: %m\n", err); return err; } if (re_snprintf(file, sizeof(file), "%s/config", path) < 0) return ENOMEM; if (!conf_fileexist(file)) { (void)fs_mkdir(path, 0700); err = config_write_template(file, conf_config()); if (err) goto out; } conf_obj = mem_deref(conf_obj); err = conf_alloc(&conf_obj, file); if (err) goto out; err = config_parse_conf(conf_config(), conf_obj); if (err) goto out; out: return err; } /** * Configure the system from a buffer * * @param buf Buffer with config * @param sz Size of buffer * * @return 0 if success, otherwise errorcode */ int conf_configure_buf(const uint8_t *buf, size_t sz) { int err; if (!buf || !sz) return EINVAL; conf_obj = mem_deref(conf_obj); err = conf_alloc_buf(&conf_obj, buf, sz); if (err) return err; return 0; } /** * Load all modules from config file * * @return 0 if success, otherwise errorcode * * @note conf_configure must be called first */ int conf_modules(void) { int err; err = module_init(conf_obj); if (err) { warning("conf: configure module parse error (%m)\n", err); goto out; } print_populated("audio codec", list_count(baresip_aucodecl())); print_populated("audio filter", list_count(baresip_aufiltl())); print_populated("video codec", list_count(baresip_vidcodecl())); print_populated("video filter", list_count(baresip_vidfiltl())); out: return err; } /** * Get the current configuration object * * @return Config object * * @note It is only available after init and before conf_close() */ struct conf *conf_cur(void) { if (!conf_obj) { warning("conf: no config object\n"); } return conf_obj; } /** * Close the current configuration object */ void conf_close(void) { conf_obj = mem_deref(conf_obj); } baresip-1.0.0/src/config.c000066400000000000000000000613101372575704200153520ustar00rootroot00000000000000/** * @file config.c Core Configuration * * Copyright (C) 2010 Creytiv.com */ #include #include #include #include #include #include "core.h" #ifndef PREFIX #define PREFIX "/usr" #endif /** Core Run-time Configuration - populated from config file */ static struct config core_config = { /** SIP User-Agent */ { "", "", "", "" }, /** Call config */ { 120, 4 }, /** Audio */ { SHARE_PATH, "","", "","", "","", 0, 0, 0, 0, AUDIO_MODE_POLL, false, AUFMT_S16LE, AUFMT_S16LE, AUFMT_S16LE, AUFMT_S16LE, {20, 160}, }, /** Video */ { "", "", "", "", 352, 288, 500000, 25, true, VID_FMT_YUV420P, }, /** Audio/Video Transport */ { 0xb8, {1024, 49152}, {0, 0}, false, {5, 10}, false, 0 }, /* Network */ { AF_UNSPEC, "", { {"",0} }, 0 }, }; static int range_print(struct re_printf *pf, const struct range *rng) { if (!rng) return 0; return re_hprintf(pf, "%u-%u", rng->min, rng->max); } static int dns_handler(const struct pl *pl, void *arg, bool fallback) { struct config_net *cfg = arg; const size_t max_count = ARRAY_SIZE(cfg->nsv); int err; if (cfg->nsc >= max_count) { warning("config: too many DNS nameservers (max %zu)\n", max_count); return EOVERFLOW; } /* Append dns_server to the network config */ err = pl_strcpy(pl, cfg->nsv[cfg->nsc].addr, sizeof(cfg->nsv[0].addr)); cfg->nsv[cfg->nsc].fallback = fallback; if (err) { warning("config: dns_server: could not copy string (%r)\n", pl); return err; } ++cfg->nsc; return 0; } static int dns_server_handler(const struct pl *pl, void *arg) { int err; err = dns_handler(pl, arg, false); return err; } static int dns_fallback_handler(const struct pl *pl, void *arg) { int err; err = dns_handler(pl, arg, true); return err; } static enum aufmt resolve_aufmt(const struct pl *fmt) { if (0 == pl_strcasecmp(fmt, "s16")) return AUFMT_S16LE; if (0 == pl_strcasecmp(fmt, "s16le")) return AUFMT_S16LE; if (0 == pl_strcasecmp(fmt, "float")) return AUFMT_FLOAT; if (0 == pl_strcasecmp(fmt, "s24_3le")) return AUFMT_S24_3LE; return (enum aufmt)-1; } static int conf_get_aufmt(const struct conf *conf, const char *name, int *fmtp) { struct pl pl; int fmt; int err; err = conf_get(conf, name, &pl); if (err) return err; fmt = resolve_aufmt(&pl); if (fmt == -1) { warning("config: %s: sample format not supported" " (%r)\n", name, &pl); return EINVAL; } *fmtp = fmt; return 0; } static int conf_get_vidfmt(const struct conf *conf, const char *name, int *fmtp) { struct pl pl; int fmt; int err; err = conf_get(conf, name, &pl); if (err) return err; for (fmt=0; fmtsip.local, sizeof(cfg->sip.local)); (void)conf_get_str(conf, "sip_certificate", cfg->sip.cert, sizeof(cfg->sip.cert)); (void)conf_get_str(conf, "sip_cafile", cfg->sip.cafile, sizeof(cfg->sip.cafile)); /* Call */ (void)conf_get_u32(conf, "call_local_timeout", &cfg->call.local_timeout); (void)conf_get_u32(conf, "call_max_calls", &cfg->call.max_calls); /* Audio */ (void)conf_get_str(conf, "audio_path", cfg->audio.audio_path, sizeof(cfg->audio.audio_path)); (void)conf_get_csv(conf, "audio_player", cfg->audio.play_mod, sizeof(cfg->audio.play_mod), cfg->audio.play_dev, sizeof(cfg->audio.play_dev)); (void)conf_get_csv(conf, "audio_source", cfg->audio.src_mod, sizeof(cfg->audio.src_mod), cfg->audio.src_dev, sizeof(cfg->audio.src_dev)); (void)conf_get_csv(conf, "audio_alert", cfg->audio.alert_mod, sizeof(cfg->audio.alert_mod), cfg->audio.alert_dev, sizeof(cfg->audio.alert_dev)); (void)conf_get_u32(conf, "ausrc_srate", &cfg->audio.srate_src); (void)conf_get_u32(conf, "auplay_srate", &cfg->audio.srate_play); (void)conf_get_u32(conf, "ausrc_channels", &cfg->audio.channels_src); (void)conf_get_u32(conf, "auplay_channels", &cfg->audio.channels_play); if (0 == conf_get(conf, "audio_txmode", &txmode)) { if (0 == pl_strcasecmp(&txmode, "poll")) cfg->audio.txmode = AUDIO_MODE_POLL; else if (0 == pl_strcasecmp(&txmode, "thread")) cfg->audio.txmode = AUDIO_MODE_THREAD; else { warning("unsupported audio txmode (%r)\n", &txmode); } } (void)conf_get_bool(conf, "audio_level", &cfg->audio.level); conf_get_aufmt(conf, "ausrc_format", &cfg->audio.src_fmt); conf_get_aufmt(conf, "auplay_format", &cfg->audio.play_fmt); conf_get_aufmt(conf, "auenc_format", &cfg->audio.enc_fmt); conf_get_aufmt(conf, "audec_format", &cfg->audio.dec_fmt); conf_get_range(conf, "audio_buffer", &cfg->audio.buffer); if (!cfg->audio.buffer.min || !cfg->audio.buffer.max) { warning("config: audio_buffer cannot be zero\n"); return EINVAL; } /* Video */ (void)conf_get_csv(conf, "video_source", cfg->video.src_mod, sizeof(cfg->video.src_mod), cfg->video.src_dev, sizeof(cfg->video.src_dev)); (void)conf_get_csv(conf, "video_display", cfg->video.disp_mod, sizeof(cfg->video.disp_mod), cfg->video.disp_dev, sizeof(cfg->video.disp_dev)); if (0 == conf_get_vidsz(conf, "video_size", &size)) { cfg->video.width = size.w; cfg->video.height = size.h; } (void)conf_get_u32(conf, "video_bitrate", &cfg->video.bitrate); (void)conf_get_float(conf, "video_fps", &cfg->video.fps); (void)conf_get_bool(conf, "video_fullscreen", &cfg->video.fullscreen); conf_get_vidfmt(conf, "videnc_format", &cfg->video.enc_fmt); /* AVT - Audio/Video Transport */ if (0 == conf_get_u32(conf, "rtp_tos", &v)) cfg->avt.rtp_tos = v; (void)conf_get_range(conf, "rtp_ports", &cfg->avt.rtp_ports); if (0 == conf_get_range(conf, "rtp_bandwidth", &cfg->avt.rtp_bw)) { cfg->avt.rtp_bw.min *= 1000; cfg->avt.rtp_bw.max *= 1000; } (void)conf_get_bool(conf, "rtcp_mux", &cfg->avt.rtcp_mux); (void)conf_get_range(conf, "jitter_buffer_delay", &cfg->avt.jbuf_del); (void)conf_get_bool(conf, "rtp_stats", &cfg->avt.rtp_stats); (void)conf_get_u32(conf, "rtp_timeout", &cfg->avt.rtp_timeout); if (err) { warning("config: configure parse error (%m)\n", err); } /* Network */ (void)conf_apply(conf, "dns_server", dns_server_handler, &cfg->net); (void)conf_apply(conf, "dns_fallback", dns_fallback_handler, &cfg->net); (void)conf_get_str(conf, "net_interface", cfg->net.ifname, sizeof(cfg->net.ifname)); return err; } /** * Print the baresip core config * * @param pf Print function * @param cfg Baresip core config * * @return 0 if success, otherwise errorcode */ int config_print(struct re_printf *pf, const struct config *cfg) { int err; if (!cfg) return 0; err = re_hprintf(pf, "\n" "# SIP\n" "sip_listen\t\t%s\n" "sip_certificate\t%s\n" "sip_cafile\t\t%s\n" "\n" "# Call\n" "call_local_timeout\t%u\n" "call_max_calls\t\t%u\n" "\n" "# Audio\n" "audio_path\t\t%s\n" "audio_player\t\t%s,%s\n" "audio_source\t\t%s,%s\n" "audio_alert\t\t%s,%s\n" "auplay_srate\t\t%u\n" "ausrc_srate\t\t%u\n" "auplay_channels\t\t%u\n" "ausrc_channels\t\t%u\n" "audio_level\t\t%s\n" "\n" "# Video\n" "video_source\t\t%s,%s\n" "video_display\t\t%s,%s\n" "video_size\t\t\"%ux%u\"\n" "video_bitrate\t\t%u\n" "video_fps\t\t%.2f\n" "video_fullscreen\t%s\n" "videnc_format\t\t%s\n" "\n" "# AVT\n" "rtp_tos\t\t\t%u\n" "rtp_ports\t\t%H\n" "rtp_bandwidth\t\t%H\n" "rtcp_mux\t\t%s\n" "jitter_buffer_delay\t%H\n" "rtp_stats\t\t%s\n" "rtp_timeout\t\t%u # in seconds\n" "\n" "# Network\n" "net_interface\t\t%s\n" "\n" , cfg->sip.local, cfg->sip.cert, cfg->sip.cafile, cfg->call.local_timeout, cfg->call.max_calls, cfg->audio.audio_path, cfg->audio.play_mod, cfg->audio.play_dev, cfg->audio.src_mod, cfg->audio.src_dev, cfg->audio.alert_mod, cfg->audio.alert_dev, cfg->audio.srate_play, cfg->audio.srate_src, cfg->audio.channels_play, cfg->audio.channels_src, cfg->audio.level ? "yes" : "no", cfg->video.src_mod, cfg->video.src_dev, cfg->video.disp_mod, cfg->video.disp_dev, cfg->video.width, cfg->video.height, cfg->video.bitrate, cfg->video.fps, cfg->video.fullscreen ? "yes" : "no", vidfmt_name(cfg->video.enc_fmt), cfg->avt.rtp_tos, range_print, &cfg->avt.rtp_ports, range_print, &cfg->avt.rtp_bw, cfg->avt.rtcp_mux ? "yes" : "no", range_print, &cfg->avt.jbuf_del, cfg->avt.rtp_stats ? "yes" : "no", cfg->avt.rtp_timeout, cfg->net.ifname ); return err; } static const char *default_cafile(void) { #if defined (DEFAULT_CAFILE) return DEFAULT_CAFILE; #elif defined (DARWIN) return "/etc/ssl/cert.pem"; #else return "/etc/ssl/certs/ca-certificates.crt"; #endif } static const char *default_audio_device(void) { #if defined (DEFAULT_AUDIO_DEVICE) return DEFAULT_AUDIO_DEVICE; #elif defined (ANDROID) return "opensles,nil"; #elif defined (DARWIN) return "coreaudio,default"; #elif defined (FREEBSD) return "oss,/dev/dsp"; #elif defined (OPENBSD) return "sndio,default"; #elif defined (WIN32) return "winwave,nil"; #else return "alsa,default"; #endif } static const char *default_video_device(void) { #ifdef DARWIN #ifdef QTCAPTURE_RUNLOOP return "qtcapture,nil"; #else return "avcapture,nil"; #endif #elif defined (WIN32) return "dshow,nil"; #else return "v4l2,/dev/video0"; #endif } static const char *default_video_display(void) { #ifdef DARWIN return "sdl,nil"; #elif defined (WIN32) return "sdl,nil"; #else return "x11,nil"; #endif } static const char *default_avcodec_hwaccel(void) { #if defined (LINUX) return "vaapi"; #elif defined (DARWIN) return "videotoolbox"; #else return "none"; #endif } static int default_interface_print(struct re_printf *pf, void *unused) { char ifname[64]; (void)unused; if (0 == net_rt_default_get(AF_INET, ifname, sizeof(ifname))) return re_hprintf(pf, "%s", ifname); else return re_hprintf(pf, "eth0"); } static int core_config_template(struct re_printf *pf, const struct config *cfg) { int err = 0; if (!cfg) return 0; err |= re_hprintf(pf, "\n# Core\n" "poll_method\t\t%s\t\t# poll, select" #ifdef HAVE_EPOLL ", epoll .." #endif #ifdef HAVE_KQUEUE ", kqueue .." #endif "\n" "\n# SIP\n" "#sip_listen\t\t0.0.0.0:5060\n" "#sip_certificate\tcert.pem\n" "#sip_cafile\t\t%s\n" "\n" "# Call\n" "call_local_timeout\t%u\n" "call_max_calls\t\t%u\n" "\n" "# Audio\n" #if defined (SHARE_PATH) "#audio_path\t\t" SHARE_PATH "\n" #elif defined (PREFIX) "#audio_path\t\t" PREFIX "/share/baresip\n" #else "#audio_path\t\t/usr/share/baresip\n" #endif "audio_player\t\t%s\n" "audio_source\t\t%s\n" "audio_alert\t\t%s\n" "#ausrc_srate\t\t48000\n" "#auplay_srate\t\t48000\n" "#ausrc_channels\t\t0\n" "#auplay_channels\t0\n" "#audio_txmode\t\tpoll\t\t# poll, thread\n" "audio_level\t\tno\n" "ausrc_format\t\ts16\t\t# s16, float, ..\n" "auplay_format\t\ts16\t\t# s16, float, ..\n" "auenc_format\t\ts16\t\t# s16, float, ..\n" "audec_format\t\ts16\t\t# s16, float, ..\n" "audio_buffer\t\t%H\t\t# ms\n" , poll_method_name(poll_method_best()), default_cafile(), cfg->call.local_timeout, cfg->call.max_calls, default_audio_device(), default_audio_device(), default_audio_device(), range_print, &cfg->audio.buffer); err |= re_hprintf(pf, "\n# Video\n" "#video_source\t\t%s\n" "#video_display\t\t%s\n" "video_size\t\t%dx%d\n" "video_bitrate\t\t%u\n" "video_fps\t\t%.2f\n" "video_fullscreen\tno\n" "videnc_format\t\t%s\n" , default_video_device(), default_video_display(), cfg->video.width, cfg->video.height, cfg->video.bitrate, cfg->video.fps, vidfmt_name(cfg->video.enc_fmt)); err |= re_hprintf(pf, "\n# AVT - Audio/Video Transport\n" "rtp_tos\t\t\t184\n" "#rtp_ports\t\t10000-20000\n" "#rtp_bandwidth\t\t512-1024 # [kbit/s]\n" "rtcp_mux\t\tno\n" "jitter_buffer_delay\t%u-%u\t\t# frames\n" "rtp_stats\t\tno\n" "#rtp_timeout\t\t60\n" "\n# Network\n" "#dns_server\t\t1.1.1.1:53\n" "#dns_server\t\t1.0.0.1:53\n" "#dns_fallback\t\t8.8.8.8:53\n" "#net_interface\t\t%H\n", cfg->avt.jbuf_del.min, cfg->avt.jbuf_del.max, default_interface_print, NULL); return err; } static uint32_t count_modules(const char *path) { DIR *dirp; struct dirent *dp; uint32_t n = 0; dirp = opendir(path); if (!dirp) return 0; while ((dp = readdir(dirp)) != NULL) { size_t len = strlen(dp->d_name); const size_t x = sizeof(MOD_EXT)-1; if (len <= x) continue; if (0==memcmp(&dp->d_name[len-x], MOD_EXT, x)) ++n; } (void)closedir(dirp); return n; } static const char *detect_module_path(bool *valid) { static const char * const pathv[] = { #if defined (MOD_PATH) MOD_PATH, #elif defined (PREFIX) "" PREFIX "/lib/baresip/modules", #else "/usr/local/lib/baresip/modules", "/usr/lib/baresip/modules", #endif }; const char *current = pathv[0]; uint32_t nmax = 0; size_t i; for (i=0; i nmax) { nmax = n; current = pathv[i]; } } if (nmax > 0) *valid = true; return current; } /** * Write the baresip core config template to a file * * @param file Filename of output file * @param cfg Baresip core config * * @return 0 if success, otherwise errorcode */ int config_write_template(const char *file, const struct config *cfg) { FILE *f = NULL; int err = 0; const char *modpath; bool modpath_valid = false; if (!file || !cfg) return EINVAL; info("config: creating config template %s\n", file); f = fopen(file, "w"); if (!f) { warning("config: writing %s: %m\n", file, errno); return errno; } (void)re_fprintf(f, "#\n" "# baresip configuration\n" "#\n" "\n" "#------------------------------------" "------------------------------------------\n"); (void)re_fprintf(f, "%H", core_config_template, cfg); (void)re_fprintf(f, "\n#------------------------------------" "------------------------------------------\n" "# Modules\n" "\n"); modpath = detect_module_path(&modpath_valid); (void)re_fprintf(f, "%smodule_path\t\t%s\n", modpath_valid ? "" : "#", modpath); (void)re_fprintf(f, "\n# UI Modules\n"); #if defined (WIN32) (void)re_fprintf(f, "module\t\t\t" "wincons" MOD_EXT "\n"); #else (void)re_fprintf(f, "module\t\t\t" "stdio" MOD_EXT "\n"); #endif (void)re_fprintf(f, "#module\t\t\t" "cons" MOD_EXT "\n"); (void)re_fprintf(f, "#module\t\t\t" "evdev" MOD_EXT "\n"); (void)re_fprintf(f, "#module\t\t\t" "httpd" MOD_EXT "\n"); (void)re_fprintf(f, "\n# Audio codec Modules (in order)\n"); (void)re_fprintf(f, "#module\t\t\t" "opus" MOD_EXT "\n"); (void)re_fprintf(f, "#module\t\t\t" "amr" MOD_EXT "\n"); (void)re_fprintf(f, "#module\t\t\t" "g7221" MOD_EXT "\n"); (void)re_fprintf(f, "#module\t\t\t" "g722" MOD_EXT "\n"); (void)re_fprintf(f, "#module\t\t\t" "g726" MOD_EXT "\n"); (void)re_fprintf(f, "module\t\t\t" "g711" MOD_EXT "\n"); (void)re_fprintf(f, "#module\t\t\t" "gsm" MOD_EXT "\n"); (void)re_fprintf(f, "#module\t\t\t" "l16" MOD_EXT "\n"); (void)re_fprintf(f, "#module\t\t\t" "mpa" MOD_EXT "\n"); (void)re_fprintf(f, "#module\t\t\t" "codec2" MOD_EXT "\n"); (void)re_fprintf(f, "#module\t\t\t" "ilbc" MOD_EXT "\n"); (void)re_fprintf(f, "#module\t\t\t" "isac" MOD_EXT "\n"); (void)re_fprintf(f, "\n# Audio filter Modules (in encoding order)\n"); (void)re_fprintf(f, "#module\t\t\t" "vumeter" MOD_EXT "\n"); (void)re_fprintf(f, "#module\t\t\t" "sndfile" MOD_EXT "\n"); (void)re_fprintf(f, "#module\t\t\t" "speex_pp" MOD_EXT "\n"); (void)re_fprintf(f, "#module\t\t\t" "plc" MOD_EXT "\n"); (void)re_fprintf(f, "#module\t\t\t" "webrtc_aec" MOD_EXT "\n"); (void)re_fprintf(f, "\n# Audio driver Modules\n"); #if defined (ANDROID) (void)re_fprintf(f, "module\t\t\t" "opensles" MOD_EXT "\n"); #elif defined (DARWIN) (void)re_fprintf(f, "module\t\t\t" "coreaudio" MOD_EXT "\n"); (void)re_fprintf(f, "#module\t\t\t" "audiounit" MOD_EXT "\n"); #elif defined (FREEBSD) (void)re_fprintf(f, "module\t\t\t" "oss" MOD_EXT "\n"); #elif defined (OPENBSD) (void)re_fprintf(f, "module\t\t\t" "sndio" MOD_EXT "\n"); #elif defined (WIN32) (void)re_fprintf(f, "module\t\t\t" "winwave" MOD_EXT "\n"); #else if (!strncmp(default_audio_device(), "pulse", 5)) { (void)re_fprintf(f, "#module\t\t\t" "alsa" MOD_EXT "\n"); (void)re_fprintf(f, "module\t\t\t" "pulse" MOD_EXT "\n"); } else { (void)re_fprintf(f, "module\t\t\t" "alsa" MOD_EXT "\n"); (void)re_fprintf(f, "#module\t\t\t" "pulse" MOD_EXT "\n"); } #endif (void)re_fprintf(f, "#module\t\t\t" "jack" MOD_EXT "\n"); (void)re_fprintf(f, "#module\t\t\t" "portaudio" MOD_EXT "\n"); (void)re_fprintf(f, "#module\t\t\t" "aubridge" MOD_EXT "\n"); (void)re_fprintf(f, "#module\t\t\t" "aufile" MOD_EXT "\n"); (void)re_fprintf(f, "#module\t\t\t" "ausine" MOD_EXT "\n"); (void)re_fprintf(f, "\n# Video codec Modules (in order)\n"); (void)re_fprintf(f, "#module\t\t\t" "avcodec" MOD_EXT "\n"); (void)re_fprintf(f, "#module\t\t\t" "vp8" MOD_EXT "\n"); (void)re_fprintf(f, "#module\t\t\t" "vp9" MOD_EXT "\n"); (void)re_fprintf(f, "\n# Video filter Modules (in encoding order)\n"); (void)re_fprintf(f, "#module\t\t\t" "selfview" MOD_EXT "\n"); (void)re_fprintf(f, "#module\t\t\t" "snapshot" MOD_EXT "\n"); (void)re_fprintf(f, "#module\t\t\t" "swscale" MOD_EXT "\n"); (void)re_fprintf(f, "#module\t\t\t" "vidinfo" MOD_EXT "\n"); (void)re_fprintf(f, "#module\t\t\t" "avfilter" MOD_EXT "\n"); (void)re_fprintf(f, "\n# Video source modules\n"); #if defined (DARWIN) #ifdef QTCAPTURE_RUNLOOP (void)re_fprintf(f, "module\t\t\t" "qtcapture" MOD_EXT "\n"); #else (void)re_fprintf(f, "module\t\t\t" "avcapture" MOD_EXT "\n"); #endif #elif defined (WIN32) (void)re_fprintf(f, "module\t\t\t" "dshow" MOD_EXT "\n"); #else (void)re_fprintf(f, "#module\t\t\t" "v4l2" MOD_EXT "\n"); (void)re_fprintf(f, "#module\t\t\t" "v4l2_codec" MOD_EXT "\n"); #endif (void)re_fprintf(f, "#module\t\t\t" "x11grab" MOD_EXT "\n"); (void)re_fprintf(f, "#module\t\t\t" "cairo" MOD_EXT "\n"); (void)re_fprintf(f, "#module\t\t\t" "vidbridge" MOD_EXT "\n"); (void)re_fprintf(f, "\n# Video display modules\n"); #ifdef LINUX (void)re_fprintf(f, "#module\t\t\t" "directfb" MOD_EXT "\n"); #endif (void)re_fprintf(f, "#module\t\t\t" "x11" MOD_EXT "\n"); (void)re_fprintf(f, "#module\t\t\t" "sdl" MOD_EXT "\n"); (void)re_fprintf(f, "#module\t\t\t" "fakevideo" MOD_EXT "\n"); (void)re_fprintf(f, "\n# Audio/Video source modules\n"); (void)re_fprintf(f, "#module\t\t\t" "avformat" MOD_EXT "\n"); (void)re_fprintf(f, "#module\t\t\t" "rst" MOD_EXT "\n"); (void)re_fprintf(f, "#module\t\t\t" "gst" MOD_EXT "\n"); (void)re_fprintf(f, "#module\t\t\t" "gst_video" MOD_EXT "\n"); (void)re_fprintf(f, "\n# Compatibility modules\n"); (void)re_fprintf(f, "#module\t\t\t" "ebuacip" MOD_EXT "\n"); (void)re_fprintf(f, "\n# Media NAT modules\n"); (void)re_fprintf(f, "module\t\t\t" "stun" MOD_EXT "\n"); (void)re_fprintf(f, "module\t\t\t" "turn" MOD_EXT "\n"); (void)re_fprintf(f, "module\t\t\t" "ice" MOD_EXT "\n"); (void)re_fprintf(f, "#module\t\t\t" "natpmp" MOD_EXT "\n"); (void)re_fprintf(f, "#module\t\t\t" "pcp" MOD_EXT "\n"); (void)re_fprintf(f, "\n# Media encryption modules\n"); (void)re_fprintf(f, "#module\t\t\t" "srtp" MOD_EXT "\n"); (void)re_fprintf(f, "#module\t\t\t" "dtls_srtp" MOD_EXT "\n"); (void)re_fprintf(f, "#module\t\t\t" "zrtp" MOD_EXT "\n"); (void)re_fprintf(f, "\n"); (void)re_fprintf(f, "\n#------------------------------------" "------------------------------------------\n"); (void)re_fprintf(f, "# Temporary Modules (loaded then unloaded)\n"); (void)re_fprintf(f, "\n"); (void)re_fprintf(f, "module_tmp\t\t" "uuid" MOD_EXT "\n"); (void)re_fprintf(f, "module_tmp\t\t" "account" MOD_EXT "\n"); (void)re_fprintf(f, "\n"); (void)re_fprintf(f, "\n#------------------------------------" "------------------------------------------\n"); (void)re_fprintf(f, "# Application Modules\n"); (void)re_fprintf(f, "\n"); (void)re_fprintf(f, "module_app\t\t" "auloop"MOD_EXT"\n"); (void)re_fprintf(f, "#module_app\t\t" "b2bua"MOD_EXT"\n"); (void)re_fprintf(f, "module_app\t\t" "contact"MOD_EXT"\n"); (void)re_fprintf(f, "module_app\t\t" "debug_cmd"MOD_EXT"\n"); (void)re_fprintf(f, "#module_app\t\t" "echo"MOD_EXT"\n"); (void)re_fprintf(f, "#module_app\t\t" "gtk" MOD_EXT "\n"); (void)re_fprintf(f, "module_app\t\t" "menu"MOD_EXT"\n"); (void)re_fprintf(f, "#module_app\t\t" "mwi"MOD_EXT"\n"); (void)re_fprintf(f, "#module_app\t\t" "presence"MOD_EXT"\n"); (void)re_fprintf(f, "#module_app\t\t" "syslog"MOD_EXT"\n"); (void)re_fprintf(f, "#module_app\t\t" "mqtt" MOD_EXT "\n"); (void)re_fprintf(f, "#module_app\t\t" "ctrl_tcp" MOD_EXT "\n"); (void)re_fprintf(f, "module_app\t\t" "vidloop"MOD_EXT"\n"); (void)re_fprintf(f, "\n"); (void)re_fprintf(f, "\n#------------------------------------" "------------------------------------------\n"); (void)re_fprintf(f, "# Module parameters\n"); (void)re_fprintf(f, "\n"); (void)re_fprintf(f, "\n# UI Modules parameters\n"); (void)re_fprintf(f, "cons_listen\t\t0.0.0.0:5555 # cons\n"); (void)re_fprintf(f, "\n"); (void)re_fprintf(f, "http_listen\t\t0.0.0.0:8000 # httpd - server\n"); (void)re_fprintf(f, "\n"); (void)re_fprintf(f, "ctrl_tcp_listen\t\t0.0.0.0:4444 # ctrl_tcp\n"); (void)re_fprintf(f, "\n"); (void)re_fprintf(f, "evdev_device\t\t/dev/input/event0\n"); (void)re_fprintf(f, "\n# Opus codec parameters\n"); (void)re_fprintf(f, "opus_bitrate\t\t28000 # 6000-510000\n"); (void)re_fprintf(f, "#opus_stereo\t\tyes\n"); (void)re_fprintf(f, "#opus_sprop_stereo\tyes\n"); (void)re_fprintf(f, "#opus_cbr\t\tno\n"); (void)re_fprintf(f, "#opus_inbandfec\t\tno\n"); (void)re_fprintf(f, "#opus_dtx\t\tno\n"); (void)re_fprintf(f, "#opus_mirror\t\tno\n"); (void)re_fprintf(f, "#opus_complexity\t10\n"); (void)re_fprintf(f, "#opus_application\taudio\t# {voip,audio}\n"); (void)re_fprintf(f, "#opus_samplerate\t48000\n"); (void)re_fprintf(f, "#opus_packet_loss\t10\t# 0-100 percent\n"); (void)re_fprintf(f, "\n# Opus Multistream codec parameters\n"); (void)re_fprintf(f, "#opus_ms_channels\t2\t#total channels (2 or 4)\n"); (void)re_fprintf(f, "#opus_ms_streams\t\t2\t#number of streams\n"); (void)re_fprintf(f, "#opus_ms_c_streams\t2\t#number of coupled streams\n"); (void)re_fprintf(f, "\n"); (void)re_fprintf(f, "vumeter_stderr\t\tyes\n"); (void)re_fprintf(f, "\n"); (void)re_fprintf(f, "#jack_connect_ports\tyes\n"); (void)re_fprintf(f, "\n# Selfview\n" "video_selfview\t\twindow # {window,pip}\n" "#selfview_size\t\t64x64\n"); (void)re_fprintf(f, "\n# ZRTP\n" "#zrtp_hash\t\tno # Disable SDP zrtp-hash " "(not recommended)\n"); (void)re_fprintf(f, "\n# Menu\n" "#menu_bell\t\tyes\n" "#redial_attempts\t0 # Num or \n" "#redial_delay\t\t5 # Delay in seconds\n" "#ringback_disabled\tno\n" "#statmode_default\toff\n"); (void)re_fprintf(f, "\n# avcodec\n" "#avcodec_h264enc\tlibx264\n" "#avcodec_h264dec\th264\n" "#avcodec_h265enc\tlibx265\n" "#avcodec_h265dec\thevc\n" "#avcodec_hwaccel\t%s\n", default_avcodec_hwaccel()); (void)re_fprintf(f, "\n# mqtt\n" "#mqtt_broker_host\t127.0.0.1\n" "#mqtt_broker_port\t1883\n" "#mqtt_broker_clientid\tbaresip01\n" "#mqtt_broker_user\tuser\n" "#mqtt_broker_password\tpass\n" "#mqtt_basetopic\t\tbaresip/01\n"); (void)re_fprintf(f, "\n# sndfile\n" "#snd_path\t\t/tmp\n"); (void)re_fprintf(f, "\n# EBU ACIP\n" "#ebuacip_jb_type\tfixed\t# auto,fixed\n"); if (f) (void)fclose(f); return err; } /** * Get the baresip core config * * @return Core config */ struct config *conf_config(void) { return &core_config; } baresip-1.0.0/src/contact.c000066400000000000000000000212531372575704200155420ustar00rootroot00000000000000/** * @file src/contact.c Contacts handling * * Copyright (C) 2010 Creytiv.com */ #include #include #include enum access { ACCESS_UNKNOWN = 0, ACCESS_BLOCK, ACCESS_ALLOW }; struct contact { struct le le; struct le he; /* hash-element with key 'auri' */ struct sip_addr addr; char *buf; char *uri; enum presence_status status; enum access access; }; struct contacts { struct list cl; struct hash *cht; struct contact *cur; bool enable_presence; contact_update_h *handler; void *handler_arg; }; static void destructor(void *arg) { struct contact *c = arg; hash_unlink(&c->he); list_unlink(&c->le); mem_deref(c->buf); mem_deref(c->uri); } static void contacts_destructor(void *data) { struct contacts *contacts = data; mem_deref(contacts->cur); hash_clear(contacts->cht); mem_deref(contacts->cht); list_flush(&contacts->cl); } /** * Add a contact * * @param contacts Contacts container * @param contactp Pointer to allocated contact (optional) * @param addr Contact in SIP address format * * @return 0 if success, otherwise errorcode */ int contact_add(struct contacts *contacts, struct contact **contactp, const struct pl *addr) { struct contact *c; struct pl pl; int err; if (!contacts) return EINVAL; c = mem_zalloc(sizeof(*c), destructor); if (!c) return ENOMEM; err = pl_strdup(&c->buf, addr); if (err) goto out; pl_set_str(&pl, c->buf); err = sip_addr_decode(&c->addr, &pl); if (err) { warning("contact: decode error '%r'\n", addr); goto out; } err = pl_strdup(&c->uri, &c->addr.auri); if (err) goto out; if (0 == msg_param_decode(&c->addr.params, "access", &pl)) { if (0 == pl_strcasecmp(&pl, "block")) { c->access = ACCESS_BLOCK; } else if (0 == pl_strcasecmp(&pl, "allow")) { c->access = ACCESS_ALLOW; } else { warning("contact: unknown 'access=%r' for '%r'\n", &pl, addr); err = EINVAL; goto out; } } else c->access = ACCESS_UNKNOWN; c->status = PRESENCE_UNKNOWN; list_append(&contacts->cl, &c->le, c); hash_append(contacts->cht, hash_joaat_pl(&c->addr.auri), &c->he, c); if (contacts->handler) contacts->handler(c, false, contacts->handler_arg); out: if (err) mem_deref(c); else if (contactp) *contactp = c; return err; } /** * Remove a contact * * @param contacts Contacts container * @param contact Contact to be removed */ void contact_remove(struct contacts *contacts, struct contact *contact) { if (!contacts || !contact) return; if (contacts->handler) contacts->handler(contact, true, contacts->handler_arg); hash_unlink(&contact->he); list_unlink(&contact->le); if (contacts->cur == contact) contacts->cur = mem_deref(contacts->cur); mem_deref(contact); } /** * Set the contacts update handler * * @param contacts Contacts container * @param updateh Update handler * @param arg Handler argument */ void contact_set_update_handler(struct contacts *contacts, contact_update_h *updateh, void *arg) { if (!contacts) return; contacts->handler = updateh; contacts->handler_arg = arg; } /** * Get the SIP address of a contact * * @param c Contact * * @return SIP Address */ struct sip_addr *contact_addr(const struct contact *c) { return c ? (struct sip_addr *)&c->addr : NULL; } /** * Get the contact string * * @param c Contact * * @return Contact string */ const char *contact_str(const struct contact *c) { return c ? c->buf : NULL; } /** * Get the SIP uri of a contact * * @param c Contact * * @return SIP uri */ const char *contact_uri(const struct contact *c) { return c ? c->uri : NULL; } /** * Get the list of contacts * * @param contacts Contacts container * * @return List of contacts */ struct list *contact_list(const struct contacts *contacts) { if (!contacts) return NULL; return (struct list *)&contacts->cl; } /** * Set the presence status for a contact * * @param c Contact * @param status Presence status */ void contact_set_presence(struct contact *c, enum presence_status status) { if (!c) return; if (c->status != PRESENCE_UNKNOWN && c->status != status) { info("<%r> changed status from %s to %s\n", &c->addr.auri, contact_presence_str(c->status), contact_presence_str(status)); } c->status = status; } /** * Get the presence status for a contact * * @param c Contact * * @return Presence status */ enum presence_status contact_presence(const struct contact *c) { if (!c) return PRESENCE_UNKNOWN; return c->status; } /** * Get the presence status string * * @param status Presence status * * @return Presence status string */ const char *contact_presence_str(enum presence_status status) { switch (status) { default: case PRESENCE_UNKNOWN: return "\x1b[32mUnknown\x1b[;m"; case PRESENCE_OPEN: return "\x1b[32mOnline\x1b[;m"; case PRESENCE_CLOSED: return "\x1b[31mOffline\x1b[;m"; case PRESENCE_BUSY: return "\x1b[31mBusy\x1b[;m"; } } /** * Print a contact * * @param pf Print function * @param cnt Contact to print * * @return 0 if success, otherwise errorcode */ int contact_print(struct re_printf *pf, const struct contact *cnt) { if (!cnt) return 0; return re_hprintf(pf, "%r <%r>", &cnt->addr.dname, &cnt->addr.auri); } /** * Print all contacts * * @param pf Print function * @param contacts Contacts container * * @return 0 if success, otherwise errorcode */ int contacts_print(struct re_printf *pf, const struct contacts *contacts) { const struct list *lst; struct le *le; int err; if (!contacts) return 0; lst = contact_list(contacts); err = re_hprintf(pf, "\n--- Contacts (%u) ---\n", list_count(lst)); for (le = list_head(lst); le && !err; le = le->next) { const struct contact *c = le->data; err = re_hprintf(pf, "%s ", c == contacts->cur ? ">" : " "); if (contacts->enable_presence) { err |= re_hprintf(pf, "%20s ", contact_presence_str(c->status)); } err |= re_hprintf(pf, "%H\n", contact_print, c); } err |= re_hprintf(pf, "\n"); return err; } /** * Initialise the contacts sub-system * * @param contactsp Pointer to allocated contacts container * * @return 0 if success, otherwise errorcode */ int contact_init(struct contacts **contactsp) { struct contacts *contacts; int err = 0; if (!contactsp) return EINVAL; contacts = mem_zalloc(sizeof(*contacts), contacts_destructor); if (!contacts) return ENOMEM; list_init(&contacts->cl); err = hash_alloc(&contacts->cht, 32); if (err) goto out; out: if (err) mem_deref(contacts); else *contactsp = contacts; return err; } static bool find_handler(struct le *le, void *arg) { struct contact *c = le->data; return 0 == pl_strcmp(&c->addr.auri, arg); } /** * Lookup a SIP uri in all registered contacts * * @param contacts Contacts container * @param uri SIP uri to lookup * * @return Matching contact if found, otherwise NULL */ struct contact *contact_find(const struct contacts *contacts, const char *uri) { if (!contacts) return NULL; return list_ledata(hash_lookup(contacts->cht, hash_joaat_str(uri), find_handler, (void *)uri)); } /** * Check the access parameter of a SIP uri * * - Matching uri has first presedence * - Global uri has second presedence * * @param contacts Contacts container * @param uri SIP uri to check for access * * @return True if blocked, false if allowed */ bool contact_block_access(const struct contacts *contacts, const char *uri) { struct contact *c; c = contact_find(contacts, uri); if (c && c->access != ACCESS_UNKNOWN) return c->access == ACCESS_BLOCK; c = contact_find(contacts, "sip:*@*"); if (c && c->access != ACCESS_UNKNOWN) return c->access == ACCESS_BLOCK; return false; } /** * Set the current contact * * @param contacts Contacts container * @param cnt Contact to be set as current */ void contacts_set_current(struct contacts *contacts, struct contact *cnt) { if (!contacts || !cnt) return; mem_deref(contacts->cur); contacts->cur = mem_ref(cnt); } /** * Get the current contact * * @param contacts Contacts container * * @return Current contact, or NULL if no current contact */ struct contact *contacts_current(const struct contacts *contacts) { if (!contacts) return NULL; return contacts->cur; } /** * Get the linked list element from a contact * * @param cnt Contact * * @return Linked-list element */ struct le *contact_le(struct contact *cnt) { return cnt ? &cnt->le : NULL; } /** * Enable or disable presence * * @param contacts Contacts container * @param enabled True to enable presence, false to disable */ void contacts_enable_presence(struct contacts *contacts, bool enabled) { if (!contacts) return; contacts->enable_presence = enabled; } baresip-1.0.0/src/core.h000066400000000000000000000273741372575704200150560ustar00rootroot00000000000000/** * @file core.h Internal API * * Copyright (C) 2010 Creytiv.com */ #include /* max bytes in pathname */ #if defined (PATH_MAX) #define FS_PATH_MAX PATH_MAX #elif defined (_POSIX_PATH_MAX) #define FS_PATH_MAX _POSIX_PATH_MAX #else #define FS_PATH_MAX 512 #endif /** * RFC 3551: * * 0 - 95 Static payload types * 96 - 127 Dynamic payload types */ enum { PT_CN = 13, }; /** Media constants */ enum { AUDIO_BANDWIDTH = 128000, /**< Bandwidth for audio in bits/s */ VIDEO_SRATE = 90000, /**< Sampling rate for video */ }; /* forward declarations */ struct stream_param; /* * Account */ struct account { char *buf; /**< Buffer for the SIP address */ struct sip_addr laddr; /**< Decoded SIP address */ struct uri luri; /**< Decoded AOR uri */ char *dispname; /**< Display name */ char *aor; /**< Local SIP uri */ /* parameters: */ enum answermode answermode; /**< Answermode for incoming calls */ struct le acv[16]; /**< List elements for aucodecl */ struct list aucodecl; /**< List of preferred audio-codecs */ char *auth_user; /**< Authentication username */ char *auth_pass; /**< Authentication password */ char *mnatid; /**< Media NAT handling */ char *mencid; /**< Media encryption type */ const struct mnat *mnat; /**< MNAT module */ const struct menc *menc; /**< MENC module */ char *outboundv[2]; /**< Optional SIP outbound proxies */ uint32_t ptime; /**< Configured packet time in [ms] */ uint32_t regint; /**< Registration interval in [seconds] */ uint32_t rwait; /**< R. Int. in [%] from proxy expiry */ uint32_t pubint; /**< Publication interval in [seconds] */ char *regq; /**< Registration Q-value */ char *sipnat; /**< SIP Nat mechanism */ char *stun_user; /**< STUN Username */ char *stun_pass; /**< STUN Password */ struct stun_uri *stun_host; /**< STUN Server */ struct le vcv[4]; /**< List elements for vidcodecl */ struct list vidcodecl; /**< List of preferred video-codecs */ bool mwi; /**< MWI on/off */ bool refer; /**< REFER method on/off */ char *ausrc_mod; char *ausrc_dev; char *auplay_mod; char *auplay_dev; char *extra; /**< Extra parameters */ }; /* * Audio Player */ struct auplay_st { struct auplay *ap; }; /* * Audio Source */ struct ausrc_st { const struct ausrc *as; }; /* * Audio Stream */ struct audio; int audio_send_digit(struct audio *a, char key); void audio_sdp_attr_decode(struct audio *a); /* * Call Control */ enum { CALL_LINENUM_MIN = 1, CALL_LINENUM_MAX = 256 }; struct call; /** Call parameters */ struct call_prm { struct sa laddr; enum vidmode vidmode; int af; bool use_rtp; }; int call_alloc(struct call **callp, const struct config *cfg, struct list *lst, const char *local_name, const char *local_uri, struct account *acc, struct ua *ua, const struct call_prm *prm, const struct sip_msg *msg, struct call *xcall, struct dnsc *dnsc, call_event_h *eh, void *arg); int call_accept(struct call *call, struct sipsess_sock *sess_sock, const struct sip_msg *msg); int call_sdp_get(const struct call *call, struct mbuf **descp, bool offer); int call_jbuf_stat(struct re_printf *pf, const struct call *call); int call_info(struct re_printf *pf, const struct call *call); int call_reset_transp(struct call *call, const struct sa *laddr); int call_af(const struct call *call); void call_set_xrtpstat(struct call *call); struct account *call_account(const struct call *call); void call_set_custom_hdrs(struct call *call, const struct list *hdrs); /* * Custom headers */ int custom_hdrs_print(struct re_printf *pf, const struct list *custom_hdrs); /* * Conf */ int conf_get_range(const struct conf *conf, const char *name, struct range *rng); int conf_get_csv(const struct conf *conf, const char *name, char *str1, size_t sz1, char *str2, size_t sz2); int conf_get_float(const struct conf *conf, const char *name, double *val); /* * Media control */ int mctrl_handle_media_control(struct pl *body, bool *pfu); /* * Metric */ struct metric { /* internal stuff: */ struct tmr tmr; struct lock *lock; uint64_t ts_start; bool started; /* counters: */ uint32_t n_packets; uint32_t n_bytes; uint32_t n_err; /* bitrate calculation */ uint32_t cur_bitrate; uint64_t ts_last; uint32_t n_bytes_last; }; int metric_init(struct metric *metric); void metric_reset(struct metric *metric); void metric_add_packet(struct metric *metric, size_t packetsize); double metric_avg_bitrate(const struct metric *metric); /* * Module */ int module_init(const struct conf *conf); /* * Register client */ struct reg; int reg_add(struct list *lst, struct ua *ua, int regid); int reg_register(struct reg *reg, const char *reg_uri, const char *params, uint32_t regint, const char *outbound); void reg_unregister(struct reg *reg); bool reg_isok(const struct reg *reg); int reg_debug(struct re_printf *pf, const struct reg *reg); int reg_json_api(struct odict *od, const struct reg *reg); int reg_status(struct re_printf *pf, const struct reg *reg); int reg_af(const struct reg *reg); /* * RTP Header Extensions */ #define RTPEXT_HDR_SIZE 4 #define RTPEXT_TYPE_MAGIC 0xbede enum { RTPEXT_ID_MIN = 1, RTPEXT_ID_MAX = 14, }; enum { RTPEXT_LEN_MIN = 1, RTPEXT_LEN_MAX = 16, }; struct rtpext { unsigned id:4; unsigned len:4; uint8_t data[RTPEXT_LEN_MAX]; }; int rtpext_hdr_encode(struct mbuf *mb, size_t num_bytes); int rtpext_encode(struct mbuf *mb, unsigned id, unsigned len, const uint8_t *data); int rtpext_decode(struct rtpext *ext, struct mbuf *mb); /* * RTP Stats */ int rtpstat_print(struct re_printf *pf, const struct call *call); /* * SDP */ int sdp_decode_multipart(const struct pl *ctype_prm, struct mbuf *mb); /* * Stream */ enum media_type { MEDIA_AUDIO = 0, MEDIA_VIDEO, }; struct rtp_header; enum {STREAM_PRESZ = 4+12}; /* same as RTP_HEADER_SIZE */ typedef void (stream_rtp_h)(const struct rtp_header *hdr, struct rtpext *extv, size_t extc, struct mbuf *mb, unsigned lostc, void *arg); /** Defines a generic media stream */ struct stream { #ifndef RELEASE uint32_t magic; /**< Magic number for debugging */ #endif struct le le; /**< Linked list element */ struct config_avt cfg; /**< Stream configuration */ struct sdp_media *sdp; /**< SDP Media line */ struct rtp_sock *rtp; /**< RTP Socket */ struct rtcp_stats rtcp_stats;/**< RTCP statistics */ struct jbuf *jbuf; /**< Jitter Buffer for incoming RTP */ const struct mnat *mnat; /**< Media NAT traversal module */ struct mnat_media *mns; /**< Media NAT traversal state */ const struct menc *menc; /**< Media encryption module */ struct menc_sess *mencs; /**< Media encryption session state */ struct menc_media *mes; /**< Media Encryption media state */ struct metric metric_tx; /**< Metrics for transmit */ struct metric metric_rx; /**< Metrics for receiving */ struct sa raddr_rtp; /**< Remote RTP address */ struct sa raddr_rtcp; /**< Remote RTCP address */ enum media_type type; /**< Media type, e.g. audio/video */ char *cname; /**< RTCP Canonical end-point identifier */ uint32_t ssrc_rx; /**< Incoming syncronizing source */ uint32_t pseq; /**< Sequence number for incoming RTP */ bool pseq_set; /**< True if sequence number is set */ int pt_enc; /**< Payload type for encoding */ bool rtcp_mux; /**< RTP/RTCP multiplex supported by peer */ bool jbuf_started; /**< True if jitter-buffer was started */ struct tmr tmr_rtp; /**< Timer for detecting RTP timeout */ uint64_t ts_last; /**< Timestamp of last received RTP pkt */ bool terminated; /**< Stream is terminated flag */ uint32_t rtp_timeout_ms; /**< RTP Timeout value in [ms] */ bool rtp_estab; /**< True if RTP stream is established */ bool hold; /**< Stream is on-hold (local) */ bool mnat_connected; /**< Media NAT is connected */ bool menc_secure; /**< Media stream is secure */ stream_rtp_h *rtph; /**< Stream RTP handler */ stream_rtcp_h *rtcph; /**< Stream RTCP handler */ void *arg; /**< Handler argument */ stream_mnatconn_h *mnatconnh;/**< Medianat connected handler */ stream_rtpestab_h *rtpestabh;/**< RTP established handler */ stream_rtcp_h *sessrtcph; /**< Stream RTCP handler */ stream_error_h *errorh; /**< Stream error handler */ void *sess_arg; /**< Session handlers argument */ }; int stream_alloc(struct stream **sp, struct list *streaml, const struct stream_param *prm, const struct config_avt *cfg, struct sdp_session *sdp_sess, enum media_type type, int label, const struct mnat *mnat, struct mnat_sess *mnat_sess, const struct menc *menc, struct menc_sess *menc_sess, bool offerer, stream_rtp_h *rtph, stream_rtcp_h *rtcph, void *arg); int stream_send(struct stream *s, bool ext, bool marker, int pt, uint32_t ts, struct mbuf *mb); void stream_update_encoder(struct stream *s, int pt_enc); int stream_jbuf_stat(struct re_printf *pf, const struct stream *s); void stream_hold(struct stream *s, bool hold); void stream_set_ldir(struct stream *s, enum sdp_dir dir); void stream_set_srate(struct stream *s, uint32_t srate_tx, uint32_t srate_rx); void stream_send_fir(struct stream *s, bool pli); void stream_reset(struct stream *s); void stream_set_bw(struct stream *s, uint32_t bps); int stream_print(struct re_printf *pf, const struct stream *s); void stream_enable_rtp_timeout(struct stream *strm, uint32_t timeout_ms); int stream_jbuf_reset(struct stream *strm, uint32_t frames_min, uint32_t frames_max); bool stream_is_ready(const struct stream *strm); /* * User-Agent */ struct ua; void ua_printf(const struct ua *ua, const char *fmt, ...); int ua_print_allowed(struct re_printf *pf, const struct ua *ua); /* * Video Stream */ struct video; bool video_is_started(const struct video *v); int video_decoder_set(struct video *v, struct vidcodec *vc, int pt_rx, const char *fmtp); void video_update_picture(struct video *v); int video_print(struct re_printf *pf, const struct video *v); /* * Timestamp helpers */ /** * This struct is used to keep track of timestamps for * incoming RTP packets. */ struct timestamp_recv { uint32_t first; uint32_t last; bool is_set; unsigned num_wraps; }; int timestamp_wrap(uint32_t ts_new, uint32_t ts_old); void timestamp_set(struct timestamp_recv *ts, uint32_t rtp_ts); uint64_t timestamp_duration(const struct timestamp_recv *ts); uint64_t timestamp_calc_extended(uint32_t num_wraps, uint32_t ts); double timestamp_calc_seconds(uint64_t ts, uint32_t clock_rate); baresip-1.0.0/src/custom_hdrs.c000066400000000000000000000035711372575704200164440ustar00rootroot00000000000000/** * @file src/custom_hdrs.c Custom headers control * * Copyright (C) 2010 Creytiv.com */ #include #include #include "core.h" static void hdr_destructor(void *arg) { struct sip_hdr *hdr = arg; mem_deref((char *)hdr->name.p); mem_deref((char *)hdr->val.p); } /** * Add a custom SIP header to the list * * @param hdrs List of custom headers * @param name Header name * @param fmt Formatted header value * @param ... Variable arguments * * @return 0 if success, otherwise errorcode */ int custom_hdrs_add(struct list *hdrs, const char *name, const char *fmt, ...) { struct pl temp_pl = { NULL, 0 }; struct sip_hdr *hdr; char *value = NULL; va_list ap; int err = 0; va_start(ap, fmt); err = re_vsdprintf(&value, fmt, ap); va_end(ap); hdr = mem_zalloc(sizeof(*hdr), hdr_destructor); if (!hdr || !value) goto error; pl_set_str(&temp_pl, name); err = pl_dup(&hdr->name, &temp_pl); if (err) goto error; pl_set_str(&hdr->val, value); hdr->id = SIP_HDR_NONE; list_append(hdrs, &hdr->le, hdr); return 0; error: mem_deref(hdr); return err; } /** * Apply a function callback handler to all custom headers * * @param hdrs List of custom SIP headers * @param h Function handler * @param arg Handler argument * * @return Return value from function handler, if errors */ int custom_hdrs_apply(const struct list *hdrs, custom_hdrs_h *h, void *arg) { struct le *le; int err; LIST_FOREACH(hdrs, le) { struct sip_hdr *hdr = le->data; err = h(&hdr->name, &hdr->val, arg); if (err) return err; } return 0; } static int hdr_print_helper(const struct pl *name, const struct pl *val, void *arg) { struct re_printf *pf = arg; return re_hprintf(pf, "%r: %r\r\n", name, val); } int custom_hdrs_print(struct re_printf *pf, const struct list *custom_hdrs) { return custom_hdrs_apply(custom_hdrs, hdr_print_helper, pf); } baresip-1.0.0/src/event.c000066400000000000000000000134111372575704200152250ustar00rootroot00000000000000/** * @file src/event.c Baresip event handling * * Copyright (C) 2017 Creytiv.com */ #include #include #include "core.h" static const char *event_class_name(enum ua_event ev) { switch (ev) { case UA_EVENT_REGISTERING: case UA_EVENT_REGISTER_OK: case UA_EVENT_REGISTER_FAIL: case UA_EVENT_UNREGISTERING: return "register"; case UA_EVENT_MWI_NOTIFY: return "mwi"; case UA_EVENT_SHUTDOWN: case UA_EVENT_EXIT: return "application"; case UA_EVENT_CALL_INCOMING: case UA_EVENT_CALL_RINGING: case UA_EVENT_CALL_PROGRESS: case UA_EVENT_CALL_ESTABLISHED: case UA_EVENT_CALL_CLOSED: case UA_EVENT_CALL_TRANSFER: case UA_EVENT_CALL_TRANSFER_FAILED: case UA_EVENT_CALL_DTMF_START: case UA_EVENT_CALL_DTMF_END: case UA_EVENT_CALL_RTCP: case UA_EVENT_CALL_MENC: return "call"; case UA_EVENT_VU_RX: case UA_EVENT_VU_TX: return "VU_REPORT"; default: return "other"; } } static int add_rtcp_stats(struct odict *od_parent, const struct rtcp_stats *rs) { struct odict *od = NULL, *tx = NULL, *rx = NULL; int err = 0; if (!od_parent || !rs) return EINVAL; err = odict_alloc(&od, 8); err |= odict_alloc(&tx, 8); err |= odict_alloc(&rx, 8); if (err) goto out; err = odict_entry_add(tx, "sent", ODICT_INT, (int64_t)rs->tx.sent); err |= odict_entry_add(tx, "lost", ODICT_INT, (int64_t)rs->tx.lost); err |= odict_entry_add(tx, "jit", ODICT_INT, (int64_t)rs->tx.jit); if (err) goto out; err = odict_entry_add(rx, "sent", ODICT_INT, (int64_t)rs->rx.sent); err |= odict_entry_add(rx, "lost", ODICT_INT, (int64_t)rs->rx.lost); err |= odict_entry_add(rx, "jit", ODICT_INT, (int64_t)rs->rx.jit); if (err) goto out; err = odict_entry_add(od, "tx", ODICT_OBJECT, tx); err |= odict_entry_add(od, "rx", ODICT_OBJECT, rx); err |= odict_entry_add(od, "rtt", ODICT_INT, (int64_t)rs->rtt); if (err) goto out; /* add object to the parent */ err = odict_entry_add(od_parent, "rtcp_stats", ODICT_OBJECT, od); if (err) goto out; out: mem_deref(od); mem_deref(tx); mem_deref(rx); return err; } /** * Encode an event to a dictionary * * @param od Dictionary to encode into * @param ua User-Agent * @param ev Event type * @param call Call object (optional) * @param prm Event parameters * * @return 0 if success, otherwise errorcode */ int event_encode_dict(struct odict *od, struct ua *ua, enum ua_event ev, struct call *call, const char *prm) { const char *event_str = uag_event_str(ev); int err = 0; if (!od) return EINVAL; err |= odict_entry_add(od, "type", ODICT_STRING, event_str); err |= odict_entry_add(od, "class", ODICT_STRING, event_class_name(ev)); if (ua) { err |= odict_entry_add(od, "accountaor", ODICT_STRING, ua_aor(ua)); } if (err) goto out; if (call) { const char *dir; const char *call_identifier; const char *peerdisplayname; dir = call_is_outgoing(call) ? "outgoing" : "incoming"; err |= odict_entry_add(od, "direction", ODICT_STRING, dir); err |= odict_entry_add(od, "peeruri", ODICT_STRING, call_peeruri(call)); peerdisplayname = call_peername(call); if (peerdisplayname){ err |= odict_entry_add(od, "peerdisplayname", ODICT_STRING, peerdisplayname); } call_identifier = call_id(call); if (call_identifier) { err |= odict_entry_add(od, "id", ODICT_STRING, call_identifier); } if (err) goto out; } if (str_isset(prm)) { err = odict_entry_add(od, "param", ODICT_STRING, prm); if (err) goto out; } if (ev == UA_EVENT_CALL_RTCP) { struct stream *strm = NULL; if (0 == str_casecmp(prm, "audio")) strm = audio_strm(call_audio(call)); else if (0 == str_casecmp(prm, "video")) strm = video_strm(call_video(call)); err = add_rtcp_stats(od, stream_rtcp_stats(strm)); if (err) goto out; } out: return err; } /** * Add audio buffer status * * @param od_parent Dictionary to encode into * @param call Call object * * @return 0 if success, otherwise errorcode */ int event_add_au_jb_stat(struct odict *od_parent, const struct call *call) { int err = 0; err = odict_entry_add(od_parent, "audio_jb_ms",ODICT_INT, (int64_t)audio_jb_current_value(call_audio(call))); return err; } /** * Get the name of the User-Agent event * * @param ev User-Agent event * * @return Name of the event */ const char *uag_event_str(enum ua_event ev) { switch (ev) { case UA_EVENT_REGISTERING: return "REGISTERING"; case UA_EVENT_REGISTER_OK: return "REGISTER_OK"; case UA_EVENT_REGISTER_FAIL: return "REGISTER_FAIL"; case UA_EVENT_UNREGISTERING: return "UNREGISTERING"; case UA_EVENT_MWI_NOTIFY: return "MWI_NOTIFY"; case UA_EVENT_SHUTDOWN: return "SHUTDOWN"; case UA_EVENT_EXIT: return "EXIT"; case UA_EVENT_CALL_INCOMING: return "CALL_INCOMING"; case UA_EVENT_CALL_RINGING: return "CALL_RINGING"; case UA_EVENT_CALL_PROGRESS: return "CALL_PROGRESS"; case UA_EVENT_CALL_ESTABLISHED: return "CALL_ESTABLISHED"; case UA_EVENT_CALL_CLOSED: return "CALL_CLOSED"; case UA_EVENT_CALL_TRANSFER: return "TRANSFER"; case UA_EVENT_CALL_TRANSFER_FAILED: return "TRANSFER_FAILED"; case UA_EVENT_CALL_DTMF_START: return "CALL_DTMF_START"; case UA_EVENT_CALL_DTMF_END: return "CALL_DTMF_END"; case UA_EVENT_CALL_RTPESTAB: return "CALL_RTPESTAB"; case UA_EVENT_CALL_RTCP: return "CALL_RTCP"; case UA_EVENT_CALL_MENC: return "CALL_MENC"; case UA_EVENT_VU_TX: return "VU_TX_REPORT"; case UA_EVENT_VU_RX: return "VU_RX_REPORT"; case UA_EVENT_AUDIO_ERROR: return "AUDIO_ERROR"; case UA_EVENT_CALL_LOCAL_SDP: return "CALL_LOCAL_SDP"; case UA_EVENT_CALL_REMOTE_SDP: return "CALL_REMOTE_SDP"; default: return "?"; } } baresip-1.0.0/src/h264.c000066400000000000000000000103131372575704200145650ustar00rootroot00000000000000/** * @file src/h264.c H.264 video codec packetization (RFC 3984) * * Copyright (C) 2010 - 2015 Creytiv.com */ #include #include #include #include int h264_hdr_encode(const struct h264_hdr *hdr, struct mbuf *mb) { uint8_t v; v = hdr->f<<7 | hdr->nri<<5 | hdr->type<<0; return mbuf_write_u8(mb, v); } int h264_hdr_decode(struct h264_hdr *hdr, struct mbuf *mb) { uint8_t v; if (mbuf_get_left(mb) < 1) return ENOENT; v = mbuf_read_u8(mb); hdr->f = v>>7 & 0x1; hdr->nri = v>>5 & 0x3; hdr->type = v>>0 & 0x1f; return 0; } int h264_fu_hdr_encode(const struct h264_fu *fu, struct mbuf *mb) { uint8_t v = fu->s<<7 | fu->s<<6 | fu->r<<5 | fu->type; return mbuf_write_u8(mb, v); } int h264_fu_hdr_decode(struct h264_fu *fu, struct mbuf *mb) { uint8_t v; if (mbuf_get_left(mb) < 1) return ENOENT; v = mbuf_read_u8(mb); fu->s = v>>7 & 0x1; fu->e = v>>6 & 0x1; fu->r = v>>5 & 0x1; fu->type = v>>0 & 0x1f; return 0; } /* * Find the NAL start sequence in a H.264 byte stream * * @note: copied from ffmpeg source */ const uint8_t *h264_find_startcode(const uint8_t *p, const uint8_t *end) { const uint8_t *a = p + 4 - ((long)p & 3); for (end -= 3; p < a && p < end; p++ ) { if (p[0] == 0 && p[1] == 0 && p[2] == 1) return p; } for (end -= 3; p < end; p += 4) { uint32_t x = *(const uint32_t*)(void *)p; if ( (x - 0x01010101) & (~x) & 0x80808080 ) { if (p[1] == 0 ) { if ( p[0] == 0 && p[2] == 1 ) return p; if ( p[2] == 0 && p[3] == 1 ) return p+1; } if ( p[3] == 0 ) { if ( p[2] == 0 && p[4] == 1 ) return p+2; if ( p[4] == 0 && p[5] == 1 ) return p+3; } } } for (end += 3; p < end; p++) { if (p[0] == 0 && p[1] == 0 && p[2] == 1) return p; } return end + 3; } static int rtp_send_data(const uint8_t *hdr, size_t hdr_sz, const uint8_t *buf, size_t sz, bool eof, uint64_t rtp_ts, videnc_packet_h *pkth, void *arg) { return pkth(eof, rtp_ts, hdr, hdr_sz, buf, sz, arg); } int h264_nal_send(bool first, bool last, bool marker, uint32_t ihdr, uint64_t rtp_ts, const uint8_t *buf, size_t size, size_t maxsz, videnc_packet_h *pkth, void *arg) { uint8_t hdr = (uint8_t)ihdr; int err = 0; if (first && last && size <= maxsz) { err = rtp_send_data(&hdr, 1, buf, size, marker, rtp_ts, pkth, arg); } else { uint8_t fu_hdr[2]; const uint8_t type = hdr & 0x1f; const uint8_t nri = hdr & 0x60; const size_t sz = maxsz - 2; fu_hdr[0] = nri | H264_NAL_FU_A; fu_hdr[1] = first ? (1<<7 | type) : type; while (size > sz) { err |= rtp_send_data(fu_hdr, 2, buf, sz, false, rtp_ts, pkth, arg); buf += sz; size -= sz; fu_hdr[1] &= ~(1 << 7); } if (last) fu_hdr[1] |= 1<<6; /* end bit */ err |= rtp_send_data(fu_hdr, 2, buf, size, marker && last, rtp_ts, pkth, arg); } return err; } int h264_packetize(uint64_t rtp_ts, const uint8_t *buf, size_t len, size_t pktsize, videnc_packet_h *pkth, void *arg) { const uint8_t *start = buf; const uint8_t *end = buf + len; const uint8_t *r; int err = 0; r = h264_find_startcode(start, end); while (r < end) { const uint8_t *r1; /* skip zeros */ while (!*(r++)) ; r1 = h264_find_startcode(r, end); err |= h264_nal_send(true, true, (r1 >= end), r[0], rtp_ts, r+1, r1-r-1, pktsize, pkth, arg); r = r1; } return err; } /** * Get the name of an H.264 nal unit * * @param type NAL unit type * * @return A string containing the NAL unit name */ const char *h264_nalunit_name(int type) { switch (type) { case H264_NAL_SLICE: return "SLICE"; case H264_NAL_DPA: return "DPA"; case H264_NAL_DPB: return "DPB"; case H264_NAL_DPC: return "DPC"; case H264_NAL_IDR_SLICE: return "IDR_SLICE"; case H264_NAL_SEI: return "SEI"; case H264_NAL_SPS: return "SPS"; case H264_NAL_PPS: return "PPS"; case H264_NAL_AUD: return "AUD"; case H264_NAL_FILLER_DATA: return "FILLER"; case H264_NAL_STAP_A: return "STAP-A"; case H264_NAL_STAP_B: return "STAP-B"; case H264_NAL_FU_A: return "FU-A"; case H264_NAL_FU_B: return "FU-B"; } return "???"; } baresip-1.0.0/src/log.c000066400000000000000000000065261372575704200146760ustar00rootroot00000000000000/** * @file log.c Logging * * Copyright (C) 2010 Creytiv.com */ #include #include static struct { struct list logl; enum log_level level; bool enable_stdout; } lg = { LIST_INIT, LEVEL_INFO, true }; /** * Register a log handler * * @param log Log handler */ void log_register_handler(struct log *log) { if (!log) return; list_append(&lg.logl, &log->le, log); } /** * Unregister a log handler * * @param log Log handler */ void log_unregister_handler(struct log *log) { if (!log) return; list_unlink(&log->le); } /** * Set the current log level * * @param level Log level */ void log_level_set(enum log_level level) { lg.level = level; } /** * Get the current log level * * @return Log level */ enum log_level log_level_get(void) { return lg.level; } /** * Get the log level as a string * * @param level Log level * * @return String with log level name */ const char *log_level_name(enum log_level level) { switch (level) { case LEVEL_DEBUG: return "DEBUG"; case LEVEL_INFO: return "INFO"; case LEVEL_WARN: return "WARNING"; case LEVEL_ERROR: return "ERROR"; default: return "???"; } } /** * Enable debug-level logging * * @param enable True to enable, false to disable */ void log_enable_debug(bool enable) { lg.level = enable ? LEVEL_DEBUG : LEVEL_INFO; } /** * Enable info-level logging * * @param enable True to enable, false to disable */ void log_enable_info(bool enable) { lg.level = enable ? LEVEL_INFO : LEVEL_WARN; } /** * Enable logging to standard-out * * @param enable True to enable, false to disable */ void log_enable_stdout(bool enable) { lg.enable_stdout = enable; } /** * Print a message to the logging system * * @param level Log level * @param fmt Formatted message * @param ap Variable argument list */ void vlog(enum log_level level, const char *fmt, va_list ap) { char buf[4096]; struct le *le; if (level < lg.level) return; if (re_vsnprintf(buf, sizeof(buf), fmt, ap) < 0) return; if (lg.enable_stdout) { bool color = level == LEVEL_WARN || level == LEVEL_ERROR; if (color) (void)re_fprintf(stdout, "\x1b[31m"); /* Red */ (void)re_fprintf(stdout, "%s", buf); if (color) (void)re_fprintf(stdout, "\x1b[;m"); } le = lg.logl.head; while (le) { struct log *log = le->data; le = le->next; if (log->h) log->h(level, buf); } } /** * Print a message to the logging system * * @param level Log level * @param fmt Formatted message * @param ... Variable arguments */ void loglv(enum log_level level, const char *fmt, ...) { va_list ap; va_start(ap, fmt); vlog(level, fmt, ap); va_end(ap); } /** * Print a DEBUG message to the logging system * * @param fmt Formatted message * @param ... Variable arguments */ void debug(const char *fmt, ...) { va_list ap; va_start(ap, fmt); vlog(LEVEL_DEBUG, fmt, ap); va_end(ap); } /** * Print an INFO message to the logging system * * @param fmt Formatted message * @param ... Variable arguments */ void info(const char *fmt, ...) { va_list ap; va_start(ap, fmt); vlog(LEVEL_INFO, fmt, ap); va_end(ap); } /** * Print a WARNING message to the logging system * * @param fmt Formatted message * @param ... Variable arguments */ void warning(const char *fmt, ...) { va_list ap; va_start(ap, fmt); vlog(LEVEL_WARN, fmt, ap); va_end(ap); } baresip-1.0.0/src/magic.h000066400000000000000000000010421372575704200151660ustar00rootroot00000000000000/** * @file magic.h Interface to magic macros * * Copyright (C) 2010 Creytiv.com */ #ifndef RELEASE #ifndef MAGIC #error "macro MAGIC must be defined" #endif /** Check magic number */ #define MAGIC_DECL uint32_t magic; #define MAGIC_INIT(s) (s)->magic = MAGIC #define MAGIC_CHECK(s) \ if (MAGIC != s->magic) { \ warning("%s: wrong magic struct=%p (magic=0x%08x)\n", \ __REFUNC__, s, s->magic); \ BREAKPOINT; \ } #else #define MAGIC_DECL #define MAGIC_INIT(s) #define MAGIC_CHECK(s) do {(void)(s);} while (0); #endif baresip-1.0.0/src/main.c000066400000000000000000000132061372575704200150320ustar00rootroot00000000000000/** * @file src/main.c Main application code * * Copyright (C) 2010 - 2015 Creytiv.com */ #ifdef SOLARIS #define __EXTENSIONS__ 1 #endif #include #ifdef HAVE_UNISTD_H #include #endif #include #include #include static void signal_handler(int sig) { static bool term = false; if (term) { mod_close(); exit(0); } term = true; info("terminated by signal %d\n", sig); ua_stop_all(false); } static void net_change_handler(void *arg) { (void)arg; info("IP-address changed: %j\n", net_laddr_af(baresip_network(), AF_INET)); (void)uag_reset_transp(true, true); } static void ua_exit_handler(void *arg) { (void)arg; debug("ua exited -- stopping main runloop\n"); /* The main run-loop can be stopped now */ re_cancel(); } static void tmr_quit_handler(void *arg) { (void)arg; ua_stop_all(false); } static void usage(void) { (void)re_fprintf(stderr, "Usage: baresip [options]\n" "options:\n" "\t-4 Force IPv4 only\n" #if HAVE_INET6 "\t-6 Force IPv6 only\n" #endif "\t-d Daemon\n" "\t-e Execute commands (repeat)\n" "\t-f Config path\n" "\t-m Pre-load modules (repeat)\n" "\t-p Audio files\n" "\t-h -? Help\n" "\t-s Enable SIP trace\n" "\t-t Quit after seconds\n" "\t-n Specify network interface\n" "\t-u Extra UA parameters\n" "\t-v Verbose debug\n" ); } int main(int argc, char *argv[]) { int af = AF_UNSPEC, run_daemon = false; const char *ua_eprm = NULL; const char *execmdv[16]; const char *net_interface = NULL; const char *audio_path = NULL; const char *modv[16]; struct tmr tmr_quit; bool sip_trace = false; size_t execmdc = 0; size_t modc = 0; size_t i; uint32_t tmo = 0; int err; /* * turn off buffering on stdout */ setbuf(stdout, NULL); (void)re_fprintf(stdout, "baresip v%s" " Copyright (C) 2010 - 2020" " Alfred E. Heggestad et al.\n", BARESIP_VERSION); (void)sys_coredump_set(true); err = libre_init(); if (err) goto out; tmr_init(&tmr_quit); for (;;) { const int c = getopt(argc, argv, "46de:f:p:hu:n:vst:m:"); if (0 > c) break; switch (c) { case '?': case 'h': usage(); return -2; case '4': af = AF_INET; break; #if HAVE_INET6 case '6': af = AF_INET6; break; #endif case 'd': run_daemon = true; break; case 'e': if (execmdc >= ARRAY_SIZE(execmdv)) { warning("max %zu commands\n", ARRAY_SIZE(execmdv)); err = EINVAL; goto out; } execmdv[execmdc++] = optarg; break; case 'f': conf_path_set(optarg); break; case 'm': if (modc >= ARRAY_SIZE(modv)) { warning("max %zu modules\n", ARRAY_SIZE(modv)); err = EINVAL; goto out; } modv[modc++] = optarg; break; case 'p': audio_path = optarg; break; case 's': sip_trace = true; break; case 't': tmo = atoi(optarg); break; case 'n': net_interface = optarg; break; case 'u': ua_eprm = optarg; break; case 'v': log_enable_debug(true); break; default: break; } } err = conf_configure(); if (err) { warning("main: configure failed: %m\n", err); goto out; } /* * Set the network interface before initializing the config */ if (net_interface) { struct config *theconf = conf_config(); str_ncpy(theconf->net.ifname, net_interface, sizeof(theconf->net.ifname)); } /* * Set prefer_ipv6 preferring the one given in -6 argument (if any) */ if (af != AF_UNSPEC) conf_config()->net.af = af; /* * Initialise the top-level baresip struct, must be * done AFTER configuration is complete. */ err = baresip_init(conf_config()); if (err) { warning("main: baresip init failed (%m)\n", err); goto out; } /* Set audio path preferring the one given in -p argument (if any) */ if (audio_path) play_set_path(baresip_player(), audio_path); else if (str_isset(conf_config()->audio.audio_path)) { play_set_path(baresip_player(), conf_config()->audio.audio_path); } /* NOTE: must be done after all arguments are processed */ if (modc) { info("pre-loading modules: %zu\n", modc); for (i=0; i #include #include "core.h" /* * RFC 5168 XML Schema for Media Control * note: deprecated, use RTCP FIR instead * * * Example XML Document: * *

   
     
       
         
           
	   
	 
       
     

  
*/ int mctrl_handle_media_control(struct pl *body, bool *pfu) { if (!body) return EINVAL; /* Poor-mans XML parsing */ if (0 == re_regex(body->p, body->l, "picture_fast_update")) { if (pfu) *pfu = true; } return 0; } baresip-1.0.0/src/mediadev.c000066400000000000000000000037761372575704200156770ustar00rootroot00000000000000/** * @file mediadev.c Media device * * Copyright (C) 2010 - 2018 Creytiv.com */ #include #include static void destructor(void *data) { struct mediadev *dev = data; mem_deref(dev->name); } /** * Add a media device to the devices list * * @param dev_list Device list * @param name Device name * * @return 0 if success, otherwise errorcode */ int mediadev_add(struct list *dev_list, const char *name) { struct mediadev *dev; int err; if (!dev_list || !str_isset(name)) return EINVAL; if (mediadev_find(dev_list, name)) return 0; dev = mem_zalloc(sizeof(*dev), destructor); if (!dev) return ENOMEM; err = str_dup(&dev->name, name); if (err) goto out; list_append(dev_list, &dev->le, dev); out: if (err) mem_deref(dev); return err; } /** * Find a media device in the device list * * @param dev_list Device list * @param name Device name * * @return Media device if found, NULL if not found */ struct mediadev *mediadev_find(const struct list *dev_list, const char *name) { struct le *le; for (le = list_head(dev_list); le; le = le->next) { struct mediadev *dev = le->data; if (!str_casecmp(dev->name, name)) return dev; } return NULL; } /** * Get the default media device * * @param dev_list Device list * * @return Default media device, NULL if none */ struct mediadev *mediadev_get_default(const struct list *dev_list) { struct le *le; if (!dev_list) return NULL; le = list_head(dev_list); if (le) return le->data; return NULL; } /** * Print all media devices * * @param pf Print function * @param dev_list Device list * * @return 0 if success, otherwise errorcode */ int mediadev_print(struct re_printf *pf, const struct list *dev_list) { struct le *le; int err; if (!dev_list) return 0; err = re_hprintf(pf, "Devices: (%u)\n", list_count(dev_list)); for (le = list_head(dev_list); le; le = le->next) { struct mediadev *dev = le->data; err |= re_hprintf(pf, "%s\n", dev->name); } return err; } baresip-1.0.0/src/menc.c000066400000000000000000000030121372575704200150220ustar00rootroot00000000000000/** * @file menc.c Media encryption * * Copyright (C) 2010 Creytiv.com */ #include #include #include "core.h" /** * Register a new Media encryption module * * @param mencl List of Media-encryption modules * @param menc Media encryption module */ void menc_register(struct list *mencl, struct menc *menc) { if (!mencl || !menc) return; list_append(mencl, &menc->le, menc); info("mediaenc: %s\n", menc->id); } /** * Unregister a Media encryption module * * @param menc Media encryption module */ void menc_unregister(struct menc *menc) { if (!menc) return; list_unlink(&menc->le); } /** * Find a Media Encryption module by name * * @param mencl List of Media-encryption modules * @param id Name of the Media Encryption module to find * * @return Matching Media Encryption module if found, otherwise NULL */ const struct menc *menc_find(const struct list *mencl, const char *id) { struct le *le; if (!mencl) return NULL; for (le = mencl->head; le; le = le->next) { struct menc *me = le->data; if (0 == str_casecmp(id, me->id)) return me; } return NULL; } /** * Get the name of a media encryption event * * @param event Media encryption event * * @return String with media encryption event name */ const char *menc_event_name(enum menc_event event) { switch (event) { case MENC_EVENT_SECURE: return "Secure"; case MENC_EVENT_VERIFY_REQUEST: return "Verify Request"; case MENC_EVENT_PEER_VERIFIED: return "Peer Verified"; default: return "?"; } } baresip-1.0.0/src/message.c000066400000000000000000000100721372575704200155300ustar00rootroot00000000000000/** * @file src/message.c SIP MESSAGE -- RFC 3428 * * Copyright (C) 2010 Creytiv.com */ #include #include #include "core.h" struct message { struct list lsnrl; /* struct message_lsnr */ struct sip_lsnr *sip_lsnr; }; struct message_lsnr { struct le le; message_recv_h *recvh; void *arg; }; static void destructor(void *data) { struct message *message = data; list_flush(&message->lsnrl); mem_deref(message->sip_lsnr); } static void listener_destructor(void *data) { struct message_lsnr *lsnr = data; list_unlink(&lsnr->le); } static void handle_message(struct message_lsnr *lsnr, struct ua *ua, const struct sip_msg *msg) { static const char ctype_text[] = "text/plain"; struct pl ctype_pl = {ctype_text, sizeof(ctype_text)-1}; (void)ua; if (msg_ctype_cmp(&msg->ctyp, "text", "plain") && lsnr->recvh) { lsnr->recvh(ua, &msg->from.auri, &ctype_pl, msg->mb, lsnr->arg); (void)sip_reply(uag_sip(), msg, 200, "OK"); } else { (void)sip_replyf(uag_sip(), msg, 415, "Unsupported Media Type", "Accept: %s\r\n" "Content-Length: 0\r\n" "\r\n", ctype_text); } } static bool request_handler(const struct sip_msg *msg, void *arg) { struct message *message = arg; struct ua *ua; struct le *le = message->lsnrl.head; bool hdld = false; if (pl_strcmp(&msg->met, "MESSAGE")) return false; ua = uag_find(&msg->uri.user); if (!ua) { (void)sip_treply(NULL, uag_sip(), msg, 404, "Not Found"); return true; } while (le) { struct message_lsnr *lsnr = le->data; le = le->next; handle_message(lsnr, ua, msg); hdld = true; } return hdld; } /** * Create the messaging subsystem * * @param messagep Pointer to allocated messaging subsystem * * @return 0 if success, otherwise errorcode */ int message_init(struct message **messagep) { struct message *message; if (!messagep) return EINVAL; message = mem_zalloc(sizeof(*message), destructor); if (!message) return ENOMEM; /* note: cannot create sip listener here, there is not UAs yet */ *messagep = message; return 0; } /** * Listen to incoming SIP MESSAGE messages * * @param message Messaging subsystem * @param recvh Message receive handler * @param arg Handler argument * * @return 0 if success, otherwise errorcode */ int message_listen(struct message *message, message_recv_h *recvh, void *arg) { struct message_lsnr *lsnr; int err = 0; if (!message || !recvh) return EINVAL; /* create the SIP listener if it does not exist */ if (!message->sip_lsnr) { err = sip_listen(&message->sip_lsnr, uag_sip(), true, request_handler, message); if (err) goto out; } lsnr = mem_zalloc(sizeof(*lsnr), listener_destructor); if (!lsnr) return ENOMEM; lsnr->recvh = recvh; lsnr->arg = arg; list_append(&message->lsnrl, &lsnr->le, lsnr); out: return err; } /** * Stop listening to incoming SIP MESSAGE messages * * @param message Messaging subsystem * @param recvh Message receive handler */ void message_unlisten(struct message *message, message_recv_h *recvh) { struct le *le; if (!message) return; le = message->lsnrl.head; while (le) { struct message_lsnr *lsnr = le->data; le = le->next; if (lsnr->recvh == recvh) mem_deref(lsnr); } } /** * Send SIP instant MESSAGE to a peer * * @param ua User-Agent object * @param peer Peer SIP Address * @param msg Message to send * @param resph Response handler * @param arg Handler argument * * @return 0 if success, otherwise errorcode */ int message_send(struct ua *ua, const char *peer, const char *msg, sip_resp_h *resph, void *arg) { struct sip_addr addr; struct pl pl; char *uri = NULL; int err = 0; if (!ua || !peer || !msg) return EINVAL; pl_set_str(&pl, peer); err = sip_addr_decode(&addr, &pl); if (err) return err; err = pl_strdup(&uri, &addr.auri); if (err) return err; err = sip_req_send(ua, "MESSAGE", uri, resph, arg, "Accept: text/plain\r\n" "Content-Type: text/plain\r\n" "Content-Length: %zu\r\n" "\r\n%s", str_len(msg), msg); mem_deref(uri); return err; } baresip-1.0.0/src/metric.c000066400000000000000000000034421372575704200153720ustar00rootroot00000000000000/** * @file metric.c Metrics for media transmit/receive * * Copyright (C) 2010 Creytiv.com */ #include #include #include "core.h" enum {TMR_INTERVAL = 3}; static void tmr_handler(void *arg) { struct metric *metric = arg; const uint64_t now = tmr_jiffies(); uint32_t diff; tmr_start(&metric->tmr, TMR_INTERVAL * 1000, tmr_handler, metric); lock_write_get(metric->lock); if (!metric->started) goto out; if (now <= metric->ts_last) goto out; if (metric->ts_last) { uint32_t bytes = metric->n_bytes - metric->n_bytes_last; diff = (uint32_t)(now - metric->ts_last); metric->cur_bitrate = 1000 * 8 * bytes / diff; } /* Update counters */ metric->ts_last = now; metric->n_bytes_last = metric->n_bytes; out: lock_rel(metric->lock); } static void metric_start(struct metric *metric) { if (metric->started) return; metric->ts_start = tmr_jiffies(); metric->started = true; } int metric_init(struct metric *metric) { int err; if (!metric) return EINVAL; err = lock_alloc(&metric->lock); if (err) return err; tmr_start(&metric->tmr, 100, tmr_handler, metric); return 0; } void metric_reset(struct metric *metric) { if (!metric) return; tmr_cancel(&metric->tmr); metric->lock = mem_deref(metric->lock); } /* * NOTE: may be called from any thread */ void metric_add_packet(struct metric *metric, size_t packetsize) { if (!metric) return; lock_write_get(metric->lock); if (!metric->started) metric_start(metric); metric->n_bytes += (uint32_t)packetsize; metric->n_packets++; lock_rel(metric->lock); } double metric_avg_bitrate(const struct metric *metric) { int diff; if (!metric || !metric->ts_start) return 0; diff = (int)(tmr_jiffies() - metric->ts_start); return 1000.0 * 8 * (double)metric->n_bytes / (double)diff; } baresip-1.0.0/src/mnat.c000066400000000000000000000021461372575704200150460ustar00rootroot00000000000000/** * @file mnat.c Media NAT * * Copyright (C) 2010 Creytiv.com */ #include #include #include "core.h" /** * Register a Media NAT traversal module * * @param mnatl List of Media-NAT modules * @param mnat Media NAT traversal module */ void mnat_register(struct list *mnatl, struct mnat *mnat) { if (!mnatl || !mnat) return; list_append(mnatl, &mnat->le, mnat); info("medianat: %s\n", mnat->id); } /** * Unregister a Media NAT traversal module * * @param mnat Media NAT traversal module */ void mnat_unregister(struct mnat *mnat) { if (!mnat) return; list_unlink(&mnat->le); } /** * Find a Media NAT module by name * * @param mnatl List of Media-NAT modules * @param id Name of the Media NAT module to find * * @return Matching Media NAT module if found, otherwise NULL */ const struct mnat *mnat_find(const struct list *mnatl, const char *id) { struct mnat *mnat; struct le *le; if (!mnatl) return NULL; for (le=mnatl->head; le; le=le->next) { mnat = le->data; if (str_casecmp(mnat->id, id)) continue; return mnat; } return NULL; } baresip-1.0.0/src/module.c000066400000000000000000000110601372575704200153670ustar00rootroot00000000000000/** * @file src/module.c Module loading * * Copyright (C) 2010 Creytiv.com */ #include #include #include "core.h" /* * Append module extension, if not exist * * input: foobar * output: foobar.so * */ static void append_extension(char *buf, size_t sz, const char *name) { if (0 == re_regex(name, str_len(name), "[^.]+"MOD_EXT, NULL)) { str_ncpy(buf, name, sz); } else { re_snprintf(buf, sz, "%s"MOD_EXT, name); } } #ifdef STATIC /* Declared in static.c */ extern const struct mod_export *mod_table[]; static const struct mod_export *lookup_static_module(const struct pl *pl) { struct pl name; uint32_t i; if (re_regex(pl->p, pl->l, "[^.]+.[^]*", &name, NULL)) name = *pl; for (i=0; ; i++) { const struct mod_export *me = mod_table[i]; if (!me) return NULL; if (0 == pl_strcasecmp(&name, me->name)) return me; } return NULL; } #endif static int load_module(struct mod **modp, const struct pl *modpath, const struct pl *name) { char file[FS_PATH_MAX]; char namestr[256]; struct mod *m = NULL; int err = 0; if (!name) return EINVAL; #ifdef STATIC /* Try static first */ pl_strcpy(name, namestr, sizeof(namestr)); if (mod_find(namestr)) { info("static module already loaded: %r\n", name); return EALREADY; } err = mod_add(&m, lookup_static_module(name)); if (!err) goto out; #else (void)namestr; #endif /* Then dynamic */ if (re_snprintf(file, sizeof(file), "%r/%r", modpath, name) < 0) { err = ENOMEM; goto out; } err = mod_load(&m, file); if (err) goto out; out: if (err) { warning("module %r: %m\n", name, err); } else if (modp) *modp = m; return err; } static int module_handler(const struct pl *val, void *arg) { (void)load_module(NULL, arg, val); return 0; } static int module_tmp_handler(const struct pl *val, void *arg) { struct mod *mod = NULL; (void)load_module(&mod, arg, val); mem_deref(mod); return 0; } static int module_app_handler(const struct pl *val, void *arg) { struct mod *mod = NULL; const struct mod_export *me; debug("module: loading app %r\n", val); if (load_module(&mod, arg, val)) { return 0; } me = mod_export(mod); if (0 != str_casecmp(me->type, "application")) { warning("module_app %r should be type application (%s)\n", val, me->type); } return 0; } int module_init(const struct conf *conf) { struct pl path; int err; if (!conf) return EINVAL; if (conf_get(conf, "module_path", &path)) pl_set_str(&path, "."); err = conf_apply(conf, "module", module_handler, &path); if (err) return err; err = conf_apply(conf, "module_tmp", module_tmp_handler, &path); if (err) return err; err = conf_apply(conf, "module_app", module_app_handler, &path); if (err) return err; return 0; } /** * Unload all application modules in reverse order */ void module_app_unload(void) { struct le *le = list_tail(mod_list()); /* unload in reverse order */ while (le) { struct mod *mod = le->data; const struct mod_export *me = mod_export(mod); le = le->prev; if (me && 0 == str_casecmp(me->type, "application")) { debug("module: unloading app %s\n", me->name); mem_deref(mod); } } } /** * Pre-load a module from the current working directory * * @param module Module name including extension * * @return 0 if success, otherwise errorcode */ int module_preload(const char *module) { struct pl path, name; if (!module) return EINVAL; pl_set_str(&path, "."); pl_set_str(&name, module); return load_module(NULL, &path, &name); } /** * Load a module by name or by filename * * @param path Module path * @param name Module name incl/excl extension, excluding module path * * @return 0 if success, otherwise errorcode * * example: "foo" * example: "foo.so" */ int module_load(const char *path, const char *name) { char filename[256]; struct pl pl_path, pl_name; int err; if (!str_isset(name)) return EINVAL; append_extension(filename, sizeof(filename), name); pl_set_str(&pl_path, path); pl_set_str(&pl_name, filename); err = load_module(NULL, &pl_path, &pl_name); return err; } /** * Unload a module by name or by filename * * @param name module name incl/excl extension, excluding module path * * example: "foo" * example: "foo.so" */ void module_unload(const char *name) { char filename[256]; struct mod *mod; if (!str_isset(name)) return; append_extension(filename, sizeof(filename), name); mod = mod_find(filename); if (mod) { info("unloading module: %s\n", filename); mem_deref(mod); return; } info("ERROR: Module %s is not currently loaded\n", name); } baresip-1.0.0/src/net.c000066400000000000000000000331461372575704200147010ustar00rootroot00000000000000/** * @file src/net.c Networking code * * Copyright (C) 2010 - 2016 Creytiv.com */ #include #include #include "core.h" struct network { struct config_net cfg; struct sa laddr; #ifdef HAVE_INET6 struct sa laddr6; #endif struct tmr tmr; struct dnsc *dnsc; struct sa nsv[NET_MAX_NS];/**< Configured name servers */ uint32_t nsn; /**< Number of configured name servers */ struct sa nsvf[NET_MAX_NS];/**< Configured fallback name servers */ uint32_t nsnf; /**< Number of configured fallback name servers */ uint32_t interval; char domain[64]; /**< DNS domain from network */ net_change_h *ch; void *arg; }; struct ifentry { int af; char *ifname; struct sa *ip; size_t sz; bool found; }; static void net_destructor(void *data) { struct network *net = data; tmr_cancel(&net->tmr); mem_deref(net->dnsc); } static bool if_getname_handler(const char *ifname, const struct sa *sa, void *arg) { struct ifentry *ife = arg; if (ife->af != sa_af(sa)) return false; if (sa_cmp(sa, ife->ip, SA_ADDR)) { str_ncpy(ife->ifname, ifname, ife->sz); ife->found = true; return true; } return false; } static int network_if_getname(char *ifname, size_t sz, int af, const struct sa *ip) { struct ifentry ife; int err; if (!ifname || !sz || !ip) return EINVAL; ife.af = af; ife.ifname = ifname; ife.ip = (struct sa *)ip; ife.sz = sz; ife.found = false; err = net_if_apply(if_getname_handler, &ife); return ife.found ? err : ENODEV; } static int print_addr(struct re_printf *pf, const struct sa *ip) { if (!ip) return 0; if (sa_isset(ip, SA_ADDR)) { char ifname[256] = "???"; network_if_getname(ifname, sizeof(ifname), sa_af(ip), ip); return re_hprintf(pf, "%s|%j", ifname, ip); } else { return re_hprintf(pf, "(not set)"); } } static int net_dns_srv_add(struct network *net, const struct sa *sa, bool fallback) { if (!net) return EINVAL; if (!fallback && net->nsn >= ARRAY_SIZE(net->nsv)) return E2BIG; if (fallback && net->nsnf >= ARRAY_SIZE(net->nsvf)) return E2BIG; if (fallback) sa_cpy(&net->nsvf[net->nsnf++], sa); else sa_cpy(&net->nsv[net->nsn++], sa); return 0; } static int net_dns_srv_get(const struct network *net, struct sa *srvv, uint32_t *n, bool *from_sys) { struct sa nsv[NET_MAX_NS]; uint32_t i, nsn = ARRAY_SIZE(nsv); uint32_t offset; uint32_t limit = *n; int err; err = dns_srv_get(NULL, 0, nsv, &nsn); if (err) { nsn = 0; } if (net->nsn) { if (net->nsn > limit) return E2BIG; /* Use any configured nameservers */ for (i=0; insn; i++) { srvv[i] = net->nsv[i]; } *n = net->nsn; if (from_sys) *from_sys = false; } else { if (nsn > limit) return E2BIG; for (i=0; insnf) { offset = *n; if ((offset + net->nsnf) > limit) { warning("net: too many DNS nameservers, " "fallback DNS ignored\n"); return 0; } for (i=0; insnf; i++) { srvv[offset+i] = net->nsvf[i]; } *n = offset + net->nsnf; } return 0; } /* * Check for DNS Server updates */ static void dns_refresh(struct network *net) { struct sa nsv[NET_MAX_NS]; uint32_t nsn; int err; nsn = ARRAY_SIZE(nsv); err = net_dns_srv_get(net, nsv, &nsn, NULL); if (err) return; (void)dnsc_srv_set(net->dnsc, nsv, nsn); } /* * Detect changes in IP address(es) */ static void ipchange_handler(void *arg) { struct network *net = arg; bool change; tmr_start(&net->tmr, net->interval * 1000, ipchange_handler, net); dns_refresh(net); change = net_check(net); if (change && net->ch) { net->ch(net->arg); } } /** * Check if local IP address(es) changed * * @param net Network instance * * @return True if changed, otherwise false */ bool net_check(struct network *net) { struct sa laddr; #ifdef HAVE_INET6 struct sa laddr6; #endif bool change = false; if (!net) return false; laddr = net->laddr; #ifdef HAVE_INET6 laddr6 = net->laddr6; #endif if (str_isset(net->cfg.ifname)) { if (net_af_enabled(net, AF_INET)) net_if_getaddr(net->cfg.ifname, AF_INET, &net->laddr); #ifdef HAVE_INET6 if (net_af_enabled(net, AF_INET6)) net_if_getaddr(net->cfg.ifname, AF_INET6, &net->laddr6); #endif } else { if (net_af_enabled(net, AF_INET)) net_default_source_addr_get(AF_INET, &net->laddr); #ifdef HAVE_INET6 if (net_af_enabled(net, AF_INET6)) net_default_source_addr_get(AF_INET6, &net->laddr6); #endif } if (sa_isset(&net->laddr, SA_ADDR) && !sa_cmp(&laddr, &net->laddr, SA_ADDR)) { change = true; info("net: local IPv4 address changed: %j -> %j\n", &laddr, &net->laddr); } #ifdef HAVE_INET6 if (sa_isset(&net->laddr6, SA_ADDR) && !sa_cmp(&laddr6, &net->laddr6, SA_ADDR)) { change = true; info("net: local IPv6 address changed: %j -> %j\n", &laddr6, &net->laddr6); } #endif return change; } /** * Check if address family is enabled * * @param net Network instance * @param af AF_INET or AF_INET6 * * @return True if enabled, false if disabled */ bool net_af_enabled(const struct network *net, int af) { if (!net || af == AF_UNSPEC) return false; switch (net->cfg.af) { case AF_UNSPEC: return true; default: return af == net->cfg.af; } } static int dns_init(struct network *net) { struct sa nsv[NET_MAX_NS]; uint32_t nsn = ARRAY_SIZE(nsv); int err; err = net_dns_srv_get(net, nsv, &nsn, NULL); if (err) return err; return dnsc_alloc(&net->dnsc, NULL, nsv, nsn); } /** * Return TRUE if libre supports IPv6 */ static bool check_ipv6(void) { struct sa sa; return 0 == sa_set_str(&sa, "::1", 2000); } /** * Initialise networking * * @param netp Pointer to allocated network instance * @param cfg Network configuration * * @return 0 if success, otherwise errorcode */ int net_alloc(struct network **netp, const struct config_net *cfg) { struct network *net; struct sa nsv[NET_MAX_NS]; uint32_t nsn = ARRAY_SIZE(nsv); char buf4[128] = "", buf6[128] = ""; int err; if (!netp || !cfg) return EINVAL; /* * baresip/libre must be built with matching HAVE_INET6 value. * if different the size of `struct sa' will not match and the * application is very likely to crash. */ #ifdef HAVE_INET6 if (!check_ipv6()) { warning("libre was compiled without IPv6-support" ", but baresip was compiled with\n"); return EAFNOSUPPORT; } #else if (check_ipv6()) { warning("libre was compiled with IPv6-support" ", but baresip was compiled without\n"); return EAFNOSUPPORT; } #endif net = mem_zalloc(sizeof(*net), net_destructor); if (!net) return ENOMEM; net->cfg = *cfg; tmr_init(&net->tmr); if (cfg->nsc) { size_t i; for (i=0; insc; i++) { const char *ns = cfg->nsv[i].addr; struct sa sa; err = sa_decode(&sa, ns, str_len(ns)); if (err) { warning("net: dns_server:" " could not decode `%s' (%m)\n", ns, err); goto out; } err = net_dns_srv_add(net, &sa, cfg->nsv[i].fallback); if (err) { warning("net: failed to add nameserver: %m\n", err); goto out; } } } /* Initialise DNS resolver */ err = dns_init(net); if (err) { warning("net: dns_init: %m\n", err); goto out; } sa_init(&net->laddr, AF_INET); if (str_isset(cfg->ifname)) { struct sa temp_sa; bool got_it = false; info("Binding to interface or IP address '%s'\n", cfg->ifname); /* check for valid IP-address */ if (0 == sa_set_str(&temp_sa, cfg->ifname, 0)) { switch (sa_af(&temp_sa)) { case AF_INET: net->laddr = temp_sa; break; #ifdef HAVE_INET6 case AF_INET6: net->laddr6 = temp_sa; break; #endif default: err = EAFNOSUPPORT; goto out; } goto print_network_data; } if (net_af_enabled(net, AF_INET)) { err = net_if_getaddr(cfg->ifname, AF_INET, &net->laddr); if (err) { info("net: %s: could not get IPv4 address" " (%m)\n", cfg->ifname, err); } else got_it = true; } #ifdef HAVE_INET6 if (net_af_enabled(net, AF_INET6)) { err = net_if_getaddr(cfg->ifname, AF_INET6, &net->laddr6); if (err) { info("net: %s: could not get IPv6 address" " (%m)\n", cfg->ifname, err); } else got_it = true; } #endif if (got_it) err = 0; else { warning("net: %s: could not get network address\n", cfg->ifname); err = EADDRNOTAVAIL; goto out; } } else { if (net_af_enabled(net, AF_INET)) net_default_source_addr_get(AF_INET, &net->laddr); #ifdef HAVE_INET6 sa_init(&net->laddr6, AF_INET6); if (net_af_enabled(net, AF_INET6)) net_default_source_addr_get(AF_INET6, &net->laddr6); #endif } print_network_data: if (sa_isset(&net->laddr, SA_ADDR)) { re_snprintf(buf4, sizeof(buf4), " IPv4=%H", print_addr, &net->laddr); } #ifdef HAVE_INET6 if (sa_isset(&net->laddr6, SA_ADDR)) { re_snprintf(buf6, sizeof(buf6), " IPv6=%H", print_addr, &net->laddr6); } #endif (void)dns_srv_get(net->domain, sizeof(net->domain), nsv, &nsn); info("Local network address: %s %s\n", buf4, buf6); out: if (err) mem_deref(net); else *netp = net; return err; } /** * Use a specific DNS server * * @param net Network instance * @param srvv DNS Nameservers * @param srvc Number of nameservers * * @return 0 if success, otherwise errorcode */ int net_use_nameserver(struct network *net, const struct sa *srvv, size_t srvc) { size_t i; if (!net) return EINVAL; net->nsn = (uint32_t)min(ARRAY_SIZE(net->nsv), srvc); if (srvv) { for (i=0; insv[i] = srvv[i]; } } dns_refresh(net); return 0; } /** * Set network IP address * * @param net Network instance * @param ip IP address * * @return 0 if success, otherwise errorcode */ int net_set_address(struct network *net, const struct sa *ip) { if (!net) return EINVAL; switch (sa_af(ip)) { case AF_INET: sa_cpy(&net->laddr, ip); break; #ifdef HAVE_INET6 case AF_INET6: sa_cpy(&net->laddr6, ip); break; #endif default: return EAFNOSUPPORT; } return 0; } /** * Check for networking changes with a regular interval * * @param net Network instance * @param interval Interval in seconds * @param ch Handler called when a change was detected * @param arg Handler argument */ void net_change(struct network *net, uint32_t interval, net_change_h *ch, void *arg) { if (!net) return; net->interval = interval; net->ch = ch; net->arg = arg; if (interval) tmr_start(&net->tmr, interval * 1000, ipchange_handler, net); else tmr_cancel(&net->tmr); } /** * Force a change in the network interfaces * * @param net Network instance */ void net_force_change(struct network *net) { if (net && net->ch) { net->ch(net->arg); } } /** * Print DNS server debug information * * @param pf Print handler for debug output * @param net Network instance * * @return 0 if success, otherwise errorcode */ int net_dns_debug(struct re_printf *pf, const struct network *net) { struct sa nsv[NET_MAX_NS]; uint32_t i, nsn = ARRAY_SIZE(nsv); bool from_sys = false; int err; if (!net) return 0; err = net_dns_srv_get(net, nsv, &nsn, &from_sys); if (err) nsn = 0; err = re_hprintf(pf, " DNS Servers from %s: (%u)\n", from_sys ? "System" : "Config", nsn); for (i=0; icfg.af = af; return 0; } static bool if_debug_handler(const char *ifname, const struct sa *sa, void *arg) { void **argv = arg; struct re_printf *pf = argv[0]; struct network *net = argv[1]; int err = 0; if (net_af_enabled(net, sa_af(sa))) err = re_hprintf(pf, " %10s: %j\n", ifname, sa); return err != 0; } /** * Get the local IP Address for a specific Address Family (AF) * * @param net Network instance * @param af Address Family * * @return Local IP Address */ const struct sa *net_laddr_af(const struct network *net, int af) { if (!net) return NULL; switch (af) { case AF_INET: return &net->laddr; #ifdef HAVE_INET6 case AF_INET6: return &net->laddr6; #endif default: return NULL; } } /** * Get the DNS Client * * @param net Network instance * * @return DNS Client */ struct dnsc *net_dnsc(const struct network *net) { if (!net) return NULL; return net->dnsc; } /** * Get the network domain name * * @param net Network instance * * @return Network domain */ const char *net_domain(const struct network *net) { if (!net) return NULL; return net->domain[0] ? net->domain : NULL; } /** * Print networking debug information * * @param pf Print handler for debug output * @param net Network instance * * @return 0 if success, otherwise errorcode */ int net_debug(struct re_printf *pf, const struct network *net) { void *argv[2] = {pf, (void *)net}; int err; if (!net) return 0; err = re_hprintf(pf, "--- Network debug ---\n"); err |= re_hprintf(pf, " Local IPv4: [%s] %H\n", net_af_enabled(net, AF_INET) ? "E" : ".", print_addr, &net->laddr); #ifdef HAVE_INET6 err |= re_hprintf(pf, " Local IPv6: [%s] %H\n", net_af_enabled(net, AF_INET6) ? "E" : ".", print_addr, &net->laddr6); #endif err |= re_hprintf(pf, " Domain: %s\n", net->domain); err |= re_hprintf(pf, "net interfaces:\n"); err |= net_if_apply(if_debug_handler, argv); err |= net_dns_debug(pf, net); return err; } baresip-1.0.0/src/play.c000066400000000000000000000144031372575704200150530ustar00rootroot00000000000000/** * @file src/play.c Audio-file player * * Copyright (C) 2010 Creytiv.com */ #include #include #include #include #include #include "core.h" enum {PTIME = 40}; /** Audio file player */ struct play { struct le le; struct play **playp; struct lock *lock; struct mbuf *mb; struct auplay_st *auplay; struct tmr tmr; int repeat; bool eof; }; #ifndef PREFIX #define PREFIX "/usr" #endif static const char default_play_path[FS_PATH_MAX] = PREFIX "/share/baresip"; struct player { struct list playl; char play_path[FS_PATH_MAX]; }; static void tmr_polling(void *arg); static void tmr_stop(void *arg) { struct play *play = arg; debug("play: player complete.\n"); mem_deref(play); } static void tmr_polling(void *arg) { struct play *play = arg; lock_write_get(play->lock); tmr_start(&play->tmr, 1000, tmr_polling, arg); if (play->eof) { if (play->repeat == 0) tmr_start(&play->tmr, 1, tmr_stop, arg); } lock_rel(play->lock); } /* * NOTE: DSP cannot be destroyed inside handler */ static void write_handler(void *sampv, size_t sampc, void *arg) { struct play *play = arg; size_t sz = sampc * 2; size_t pos = 0; size_t left; size_t count; lock_write_get(play->lock); if (play->eof) goto silence; while (pos < sz) { left = mbuf_get_left(play->mb); count = (left > sz - pos) ? sz - pos : left; (void)mbuf_read_mem(play->mb, (uint8_t *)sampv + pos, count); pos += count; if (pos < sz) { if (play->repeat > 0) play->repeat--; if (play->repeat == 0) { play->eof = true; goto silence; } play->mb->pos = 0; } } silence: if (play->eof) memset((uint8_t *)sampv + pos, 0, sz - pos); lock_rel(play->lock); } static void destructor(void *arg) { struct play *play = arg; list_unlink(&play->le); tmr_cancel(&play->tmr); lock_write_get(play->lock); play->eof = true; lock_rel(play->lock); mem_deref(play->auplay); mem_deref(play->mb); mem_deref(play->lock); if (play->playp) *play->playp = NULL; } static int aufile_load(struct mbuf *mb, const char *filename, uint32_t *srate, uint8_t *channels) { struct aufile_prm prm; struct aufile *af; int err; err = aufile_open(&af, &prm, filename, AUFILE_READ); if (err) return err; while (!err) { uint8_t buf[4096]; size_t i, n; int16_t *p = (void *)buf; n = sizeof(buf); err = aufile_read(af, buf, &n); if (err || !n) break; switch (prm.fmt) { case AUFMT_S16LE: /* convert from Little-Endian to Native-Endian */ for (i=0; ipos = 0; *srate = prm.srate; *channels = prm.channels; } return err; } /** * Play a tone from a PCM buffer * * @param playp Pointer to allocated player object * @param player Audio-file player * @param tone PCM buffer to play * @param srate Sampling rate * @param ch Number of channels * @param repeat Number of times to repeat * @param play_mod Audio player module * @param play_dev Audio player device * * @return 0 if success, otherwise errorcode */ int play_tone(struct play **playp, struct player *player, struct mbuf *tone, uint32_t srate, uint8_t ch, int repeat, const char *play_mod, const char *play_dev) { struct auplay_prm wprm; struct play *play; int err; if (!player) return EINVAL; if (playp && *playp) return EALREADY; play = mem_zalloc(sizeof(*play), destructor); if (!play) return ENOMEM; tmr_init(&play->tmr); play->repeat = repeat; play->mb = mem_ref(tone); err = lock_alloc(&play->lock); if (err) goto out; wprm.ch = ch; wprm.srate = srate; wprm.ptime = PTIME; wprm.fmt = AUFMT_S16LE; err = auplay_alloc(&play->auplay, baresip_auplayl(), play_mod, &wprm, play_dev, write_handler, play); if (err) goto out; list_append(&player->playl, &play->le, play); tmr_start(&play->tmr, 1000, tmr_polling, play); out: if (err) { mem_deref(play); } else if (playp) { play->playp = playp; *playp = play; } return err; } /** * Play an audio file in WAV format * * @param playp Pointer to allocated player object * @param player Audio-file player * @param filename Name of WAV file to play * @param repeat Number of times to repeat * @param play_mod Audio player module * @param play_dev Audio player device * * @return 0 if success, otherwise errorcode */ int play_file(struct play **playp, struct player *player, const char *filename, int repeat, const char *play_mod, const char *play_dev) { struct mbuf *mb; char path[FS_PATH_MAX]; uint32_t srate = 0; uint8_t ch = 0; int err; if (!player) return EINVAL; if (playp && *playp) return EALREADY; if (re_snprintf(path, sizeof(path), "%s/%s", player->play_path, filename) < 0) return ENOMEM; mb = mbuf_alloc(1024); if (!mb) return ENOMEM; err = aufile_load(mb, path, &srate, &ch); if (err) { warning("play: %s: %m\n", path, err); goto out; } err = play_tone(playp, player, mb, srate, ch, repeat, play_mod, play_dev); out: mem_deref(mb); return err; } static void player_destructor(void *data) { struct player *player = data; list_flush(&player->playl); } /** * Initialize the audio player * * @param playerp Pointer to allocated player state * * @return 0 if success, otherwise errorcode */ int play_init(struct player **playerp) { struct player *player; if (!playerp) return EINVAL; player = mem_zalloc(sizeof(*player), player_destructor); if (!player) return ENOMEM; list_init(&player->playl); str_ncpy(player->play_path, default_play_path, sizeof(player->play_path)); *playerp = player; return 0; } /** * Set the path to the audio files * * @param player Player state * @param path Path to audio files */ void play_set_path(struct player *player, const char *path) { if (!player) return; str_ncpy(player->play_path, path, sizeof(player->play_path)); } baresip-1.0.0/src/reg.c000066400000000000000000000146511372575704200146700ustar00rootroot00000000000000/** * @file reg.c Register Client * * Copyright (C) 2010 Creytiv.com */ #include #include #include "core.h" /** Register client */ struct reg { struct le le; /**< Linked list element */ struct ua *ua; /**< Pointer to parent UA object */ struct sipreg *sipreg; /**< SIP Register client */ int id; /**< Registration ID (for SIP outbound) */ /* status: */ uint16_t scode; /**< Registration status code */ char *srv; /**< SIP Server id */ int af; /**< Cached address family for SIP conn */ }; static void destructor(void *arg) { struct reg *reg = arg; list_unlink(®->le); mem_deref(reg->sipreg); mem_deref(reg->srv); } static int sipmsg_af(const struct sip_msg *msg) { struct sa laddr; int err = 0; if (!msg) return AF_UNSPEC; switch (msg->tp) { case SIP_TRANSP_UDP: err = udp_local_get(msg->sock, &laddr); break; case SIP_TRANSP_TCP: case SIP_TRANSP_TLS: err = tcp_conn_local_get(sip_msg_tcpconn(msg), &laddr); break; default: return AF_UNSPEC; } return err ? AF_UNSPEC : sa_af(&laddr); } static const char *af_name(int af) { switch (af) { case AF_INET: return "v4"; case AF_INET6: return "v6"; default: return "v?"; } } static int sip_auth_handler(char **username, char **password, const char *realm, void *arg) { struct account *acc = arg; return account_auth(acc, username, password, realm); } static bool contact_handler(const struct sip_hdr *hdr, const struct sip_msg *msg, void *arg) { struct reg *reg = arg; struct sip_addr addr; (void)msg; if (sip_addr_decode(&addr, &hdr->val)) return false; /* match our contact */ return 0 == pl_strcasecmp(&addr.uri.user, ua_local_cuser(reg->ua)); } static void register_handler(int err, const struct sip_msg *msg, void *arg) { struct reg *reg = arg; const struct sip_hdr *hdr; if (err) { warning("reg: %s: Register: %m\n", ua_aor(reg->ua), err); reg->scode = 999; ua_event(reg->ua, UA_EVENT_REGISTER_FAIL, NULL, "%m", err); return; } hdr = sip_msg_hdr(msg, SIP_HDR_SERVER); if (hdr) { reg->srv = mem_deref(reg->srv); (void)pl_strdup(®->srv, &hdr->val); } if (200 <= msg->scode && msg->scode <= 299) { uint32_t n_bindings; n_bindings = sip_msg_hdr_count(msg, SIP_HDR_CONTACT); reg->af = sipmsg_af(msg); if (msg->scode != reg->scode) { ua_printf(reg->ua, "{%d/%s/%s} %u %r (%s)" " [%u binding%s]\n", reg->id, sip_transp_name(msg->tp), af_name(reg->af), msg->scode, &msg->reason, reg->srv, n_bindings, 1==n_bindings?"":"s"); } reg->scode = msg->scode; hdr = sip_msg_hdr_apply(msg, true, SIP_HDR_CONTACT, contact_handler, reg); if (hdr) { struct sip_addr addr; struct pl pval; if (0 == sip_addr_decode(&addr, &hdr->val) && 0 == msg_param_decode(&addr.params, "pub-gruu", &pval)) { ua_pub_gruu_set(reg->ua, &pval); } } ua_event(reg->ua, UA_EVENT_REGISTER_OK, NULL, "%u %r", msg->scode, &msg->reason); } else if (msg->scode >= 300) { warning("reg: %s: %u %r (%s)\n", ua_aor(reg->ua), msg->scode, &msg->reason, reg->srv); reg->scode = msg->scode; ua_event(reg->ua, UA_EVENT_REGISTER_FAIL, NULL, "%u %r", msg->scode, &msg->reason); } } int reg_add(struct list *lst, struct ua *ua, int regid) { struct reg *reg; if (!lst || !ua) return EINVAL; reg = mem_zalloc(sizeof(*reg), destructor); if (!reg) return ENOMEM; reg->ua = ua; reg->id = regid; list_append(lst, ®->le, reg); return 0; } int reg_register(struct reg *reg, const char *reg_uri, const char *params, uint32_t regint, const char *outbound) { struct account *acc; const char *routev[1]; int err; if (!reg || !reg_uri) return EINVAL; reg->scode = 0; routev[0] = outbound; acc = ua_account(reg->ua); reg->sipreg = mem_deref(reg->sipreg); err = sipreg_register(®->sipreg, uag_sip(), reg_uri, account_aor(acc), acc ? acc->dispname : NULL, account_aor(acc), regint, ua_local_cuser(reg->ua), routev[0] ? routev : NULL, routev[0] ? 1 : 0, reg->id, sip_auth_handler, ua_account(reg->ua), true, register_handler, reg, params[0] ? ¶ms[1] : NULL, "Allow: %H\r\n", ua_print_allowed, reg->ua); if (err) return err; if (acc->rwait) err = sipreg_set_rwait(reg->sipreg, acc->rwait); return err; } void reg_unregister(struct reg *reg) { if (!reg) return; reg->scode = 0; reg->af = 0; reg->sipreg = mem_deref(reg->sipreg); } bool reg_isok(const struct reg *reg) { if (!reg) return false; return 200 <= reg->scode && reg->scode <= 299; } static const char *print_scode(uint16_t scode) { if (0 == scode) return "\x1b[33m" "zzz" "\x1b[;m"; else if (200 == scode) return "\x1b[32m" "OK " "\x1b[;m"; else return "\x1b[31m" "ERR" "\x1b[;m"; } /** * Print the registration debug information * * @param pf Print function * @param reg Registration object * * @return 0 if success, otherwise errorcode */ int reg_debug(struct re_printf *pf, const struct reg *reg) { int err = 0; if (!reg) return 0; err |= re_hprintf(pf, "\nRegister client:\n"); err |= re_hprintf(pf, " id: %d\n", reg->id); err |= re_hprintf(pf, " scode: %u (%s)\n", reg->scode, print_scode(reg->scode)); err |= re_hprintf(pf, " srv: %s\n", reg->srv); err |= re_hprintf(pf, " af: %s\n", af_name(reg->af)); return err; } /** * Print the registration information in JSON * * @param od Registration dict * @param reg Registration object * * @return 0 if success, otherwise errorcode */ int reg_json_api(struct odict *od, const struct reg *reg) { int err = 0; if (!reg) return 0; err |= odict_entry_add(od, "id", ODICT_INT, (int64_t) reg->id); err |= odict_entry_add(od, "state", ODICT_BOOL, reg_isok(reg)); err |= odict_entry_add(od, "code", ODICT_INT, (int64_t) reg->scode); if (reg->srv) err |= odict_entry_add(od, "srv", ODICT_STRING, reg->srv); err |= odict_entry_add(od, "ipv", ODICT_STRING, af_name(reg->af)); return err; } int reg_status(struct re_printf *pf, const struct reg *reg) { if (!reg) return 0; return re_hprintf(pf, " %s %s Expires %us", print_scode(reg->scode), reg->srv, sipreg_proxy_expires(reg->sipreg)); } int reg_af(const struct reg *reg) { if (!reg) return 0; return reg->af; } baresip-1.0.0/src/rtpext.c000066400000000000000000000035771372575704200154460ustar00rootroot00000000000000/** * @file rtpext.c RTP Header Extensions * * Copyright (C) 2017 Creytiv.com */ #include #include #include #include "core.h" /* * RFC 5285 A General Mechanism for RTP Header Extensions * * - One-Byte Header: Supported * - Two-Byte Header: Not supported */ int rtpext_hdr_encode(struct mbuf *mb, size_t num_bytes) { int err = 0; if (!mb || !num_bytes) return EINVAL; if (num_bytes & 0x3) { warning("rtpext: hdr_encode: num_bytes (%zu) must be multiple" " of 4\n", num_bytes); return EINVAL; } err |= mbuf_write_u16(mb, htons(RTPEXT_TYPE_MAGIC)); err |= mbuf_write_u16(mb, htons((uint16_t)(num_bytes / 4))); return err; } int rtpext_encode(struct mbuf *mb, unsigned id, unsigned len, const uint8_t *data) { size_t start; int err; if (!mb || !data) return EINVAL; if (id < RTPEXT_ID_MIN || id > RTPEXT_ID_MAX) return EINVAL; if (len < RTPEXT_LEN_MIN || len > RTPEXT_LEN_MAX) return EINVAL; start = mb->pos; err = mbuf_write_u8(mb, id << 4 | (len-1)); err |= mbuf_write_mem(mb, data, len); if (err) return err; /* padding */ while ((mb->pos - start) & 0x03) err |= mbuf_write_u8(mb, 0x00); return err; } int rtpext_decode(struct rtpext *ext, struct mbuf *mb) { uint8_t v; int err; if (!ext || !mb) return EINVAL; if (mbuf_get_left(mb) < 1) return EBADMSG; memset(ext, 0, sizeof(*ext)); v = mbuf_read_u8(mb); ext->id = v >> 4; ext->len = (v & 0x0f) + 1; if (ext->id < RTPEXT_ID_MIN || ext->id > RTPEXT_ID_MAX) { warning("rtpext: invalid ID %u\n", ext->id); return EBADMSG; } if (ext->len > mbuf_get_left(mb)) { warning("rtpext: short read\n"); return ENODATA; } err = mbuf_read_mem(mb, ext->data, ext->len); if (err) return err; /* skip padding */ while (mbuf_get_left(mb)) { uint8_t pad = mbuf_buf(mb)[0]; if (pad != 0x00) break; mbuf_advance(mb, 1); } return 0; } baresip-1.0.0/src/rtpstat.c000066400000000000000000000034121372575704200156050ustar00rootroot00000000000000/** * @file rtpstat.c RTP Statistics * * Copyright (C) 2010 Creytiv.com */ #include #include #include "core.h" /* * Reference: * * https://www.avm.de/de/Extern/files/x-rtp/xrtpv32.pdf */ int rtpstat_print(struct re_printf *pf, const struct call *call) { struct audio *a = call_audio(call); const struct aucodec *ac_tx, *ac_rx; const struct rtcp_stats *rtcp; const struct stream *s; int srate_tx = 8000; int srate_rx = 8000; int err; if (!call || !a) return 0; s = audio_strm(a); rtcp = &s->rtcp_stats; if (!rtcp->tx.sent) return 1; ac_tx = audio_codec(a, true); ac_rx = audio_codec(a, false); if (ac_tx) srate_tx = ac_tx->srate; if (ac_rx) srate_rx = ac_rx->srate; err = re_hprintf(pf, "EX=BareSip;" /* Reporter Identifier */ "CS=%d;" /* Call Setup in milliseconds */ "CD=%d;" /* Call Duration in seconds */ "PR=%u;PS=%u;" /* Packets RX, TX */ "PL=%d,%d;" /* Packets Lost RX, TX */ "PD=%d,%d;" /* Packets Discarded, RX, TX */ "JI=%.1f,%.1f;" /* Jitter RX, TX in timestamp units */ "IP=%J,%J" /* Local, Remote IPs */ , call_setup_duration(call) * 1000, call_duration(call), s->metric_rx.n_packets, s->metric_tx.n_packets, rtcp->rx.lost, rtcp->tx.lost, s->metric_rx.n_err, s->metric_tx.n_err, /* timestamp units (ie: 8 ts units = 1 ms @ 8KHZ) */ 1.0 * rtcp->rx.jit/1000 * (srate_rx/1000), 1.0 * rtcp->tx.jit/1000 * (srate_tx/1000), sdp_media_laddr(s->sdp), sdp_media_raddr(s->sdp) ); if (ac_tx) err |= re_hprintf(pf, ";EN=%s/%d", ac_tx->name, srate_tx); if (ac_rx) err |= re_hprintf(pf, ";DE=%s/%d", ac_rx->name, srate_rx); return err; } baresip-1.0.0/src/sdp.c000066400000000000000000000050531372575704200146750ustar00rootroot00000000000000/** * @file src/sdp.c SDP functions * * Copyright (C) 2011 Creytiv.com */ #include #include #include #include "core.h" /** * Decode an SDP fingerprint value * * @param attr SDP attribute value * @param hash Returned hash method * @param md Returned message digest * @param sz Message digest size, set on return * * @return 0 if success, otherwise errorcode * * Reference: RFC 4572 */ int sdp_fingerprint_decode(const char *attr, struct pl *hash, uint8_t *md, size_t *sz) { struct pl f; const char *p; int err; if (!attr || !hash) return EINVAL; err = re_regex(attr, str_len(attr), "[^ ]+ [0-9A-F:]+", hash, &f); if (err) return err; if (md && sz) { if (*sz < (f.l+1)/3) return EOVERFLOW; for (p = f.p; p < (f.p+f.l); p += 3) { *md++ = ch_hex(p[0]) << 4 | ch_hex(p[1]); } *sz = (f.l+1)/3; } return 0; } /** * Check if an SDP media object has valid media. It is considered * valid if it has one or more codecs, and the port number is set. * * @param m SDP Media object * * @return True if it has media, false if not */ bool sdp_media_has_media(const struct sdp_media *m) { bool has; has = sdp_media_rformat(m, NULL) != NULL; if (has) return sdp_media_rport(m) != 0; return false; } static void decode_part(const struct pl *part, struct mbuf *mb) { struct pl hdrs, body; if (re_regex(part->p, part->l, "\r\n\r\n[^]+", &body)) return; hdrs.p = part->p; hdrs.l = body.p - part->p - 2; if (0 == re_regex(hdrs.p, hdrs.l, "application/sdp")) { mb->pos += (body.p - (char *)mbuf_buf(mb)); mb->end = mb->pos + body.l; } } /** * Decode a multipart/mixed message and find the part with application/sdp * * @param ctype_prm Content type parameter * @param mb Mbuffer containing the SDP * * @return 0 if success, otherwise errorcode */ int sdp_decode_multipart(const struct pl *ctype_prm, struct mbuf *mb) { struct pl bnd, s, e, p; char expr[64]; int err; if (!ctype_prm || !mb) return EINVAL; /* fetch the boundary tag, excluding quotes */ err = re_regex(ctype_prm->p, ctype_prm->l, "boundary=[~]+", &bnd); if (err) return err; if (re_snprintf(expr, sizeof(expr), "--%r[^]+", &bnd) < 0) return ENOMEM; /* find 1st boundary */ err = re_regex((char *)mbuf_buf(mb), mbuf_get_left(mb), expr, &s); if (err) return err; /* iterate over each part */ while (s.l > 2) { if (re_regex(s.p, s.l, expr, &e)) return 0; p.p = s.p + 2; p.l = e.p - p.p - bnd.l - 2; /* valid part in "p" */ decode_part(&p, mb); s = e; } return 0; } baresip-1.0.0/src/sipreq.c000066400000000000000000000053211372575704200154100ustar00rootroot00000000000000/** * @file sipreq.c SIP Authenticated Request * * Copyright (C) 2011 Creytiv.com */ #include #include #include "core.h" /** SIP Authenticated Request */ struct sip_req { struct sip_loopstate ls; struct sip_dialog *dlg; struct sip_auth *auth; struct sip_request *req; char *method; char *fmt; sip_resp_h *resph; void *arg; }; static int request(struct sip_req *sr); static void destructor(void *arg) { struct sip_req *sr = arg; mem_deref(sr->req); mem_deref(sr->auth); mem_deref(sr->dlg); mem_deref(sr->method); mem_deref(sr->fmt); } static void resp_handler(int err, const struct sip_msg *msg, void *arg) { struct sip_req *sr = arg; if (err || sip_request_loops(&sr->ls, msg->scode)) goto out; if (msg->scode < 200) { return; } else if (msg->scode < 300) { ; } else { switch (msg->scode) { case 401: case 407: err = sip_auth_authenticate(sr->auth, msg); if (err) { err = (err == EAUTH) ? 0 : err; break; } err = request(sr); if (err) break; return; case 403: sip_auth_reset(sr->auth); break; } } out: if (sr->resph) sr->resph(err, msg, sr->arg); /* destroy now */ mem_deref(sr); } static int auth_handler(char **username, char **password, const char *realm, void *arg) { struct account *acc = arg; return account_auth(acc, username, password, realm); } static int request(struct sip_req *sr) { return sip_drequestf(&sr->req, uag_sip(), true, sr->method, sr->dlg, 0, sr->auth, NULL, resp_handler, sr, sr->fmt ? "%s" : NULL, sr->fmt); } /** * Send a SIP request * * @param ua User-Agent * @param method SIP method * @param uri Target SIP uri * @param resph Response handler * @param arg Handler argument * @param fmt Formatted SIP headers and body * @param ... Variable arguments * * @return 0 if success, otherwise errorcode */ int sip_req_send(struct ua *ua, const char *method, const char *uri, sip_resp_h *resph, void *arg, const char *fmt, ...) { const char *routev[1]; struct sip_req *sr; int err; if (!ua || !method || !uri || !fmt) return EINVAL; routev[0] = ua_outbound(ua); sr = mem_zalloc(sizeof(*sr), destructor); if (!sr) return ENOMEM; sr->resph = resph; sr->arg = arg; err = str_dup(&sr->method, method); if (fmt) { va_list ap; va_start(ap, fmt); err |= re_vsdprintf(&sr->fmt, fmt, ap); va_end(ap); } if (err) goto out; err = sip_dialog_alloc(&sr->dlg, uri, uri, NULL, ua_aor(ua), routev[0] ? routev : NULL, routev[0] ? 1 : 0); if (err) goto out; err = sip_auth_alloc(&sr->auth, auth_handler, ua_account(ua), true); if (err) goto out; err = request(sr); out: if (err) mem_deref(sr); return err; } baresip-1.0.0/src/srcs.mk000066400000000000000000000015511372575704200152450ustar00rootroot00000000000000# # srcs.mk All application source files. # # Copyright (C) 2010 Creytiv.com # SRCS += account.c SRCS += aucodec.c SRCS += audio.c SRCS += aufilt.c SRCS += auframe.c SRCS += aulevel.c SRCS += auplay.c SRCS += ausrc.c SRCS += baresip.c SRCS += call.c SRCS += cmd.c SRCS += conf.c SRCS += config.c SRCS += contact.c SRCS += custom_hdrs.c SRCS += event.c SRCS += h264.c SRCS += log.c SRCS += mctrl.c SRCS += mediadev.c SRCS += menc.c SRCS += message.c SRCS += metric.c SRCS += mnat.c SRCS += module.c SRCS += net.c SRCS += play.c SRCS += reg.c SRCS += rtpext.c SRCS += rtpstat.c SRCS += sdp.c SRCS += sipreq.c SRCS += stream.c SRCS += stunuri.c SRCS += timer.c SRCS += timestamp.c SRCS += ua.c SRCS += ui.c SRCS += vidcodec.c SRCS += video.c SRCS += vidfilt.c SRCS += vidisp.c SRCS += vidsrc.c SRCS += vidutil.c ifneq ($(STATIC),) SRCS += static.c endif APP_SRCS += main.c baresip-1.0.0/src/stream.c000066400000000000000000000507441372575704200154110ustar00rootroot00000000000000/** * @file stream.c Generic Media Stream * * Copyright (C) 2010 Creytiv.com */ #include #include #include #include #include "core.h" /** Magic number */ #define MAGIC 0x00511ea3 #include "magic.h" enum { RTP_RECV_SIZE = 8192, RTP_CHECK_INTERVAL = 1000, /* how often to check for RTP [ms] */ PORT_DISCARD = 9, }; static void print_rtp_stats(const struct stream *s) { bool started = s->metric_tx.n_packets>0 || s->metric_rx.n_packets>0; if (!started) return; info("\n%-9s Transmit: Receive:\n" "packets: %7u %7u\n" "avg. bitrate: %7.1f %7.1f (kbit/s)\n" "errors: %7d %7d\n" , sdp_media_name(s->sdp), s->metric_tx.n_packets, s->metric_rx.n_packets, 1.0*metric_avg_bitrate(&s->metric_tx)/1000.0, 1.0*metric_avg_bitrate(&s->metric_rx)/1000.0, s->metric_tx.n_err, s->metric_rx.n_err ); if (s->rtcp_stats.tx.sent || s->rtcp_stats.rx.sent) { info("pkt.report: %7u %7u\n" "lost: %7d %7d\n" "jitter: %7.1f %7.1f (ms)\n", s->rtcp_stats.tx.sent, s->rtcp_stats.rx.sent, s->rtcp_stats.tx.lost, s->rtcp_stats.rx.lost, 1.0*s->rtcp_stats.tx.jit/1000, 1.0*s->rtcp_stats.rx.jit/1000); } } static void stream_destructor(void *arg) { struct stream *s = arg; if (s->cfg.rtp_stats) print_rtp_stats(s); metric_reset(&s->metric_tx); metric_reset(&s->metric_rx); tmr_cancel(&s->tmr_rtp); list_unlink(&s->le); mem_deref(s->sdp); mem_deref(s->mes); mem_deref(s->mencs); mem_deref(s->mns); mem_deref(s->jbuf); mem_deref(s->rtp); mem_deref(s->cname); } static bool mnat_ready(const struct stream *strm) { if (strm->mnat && strm->mnat->wait_connected) return strm->mnat_connected; else return true; } static void stream_close(struct stream *strm, int err) { stream_error_h *errorh = strm->errorh; strm->terminated = true; strm->errorh = NULL; if (errorh) errorh(strm, err, strm->sess_arg); } static void check_rtp_handler(void *arg) { struct stream *strm = arg; const uint64_t now = tmr_jiffies(); int diff_ms; MAGIC_CHECK(strm); tmr_start(&strm->tmr_rtp, RTP_CHECK_INTERVAL, check_rtp_handler, strm); /* If no RTP was received at all, check later */ if (!strm->ts_last) return; /* We are in sendrecv mode, check when the last RTP packet * was received. */ if (sdp_media_dir(strm->sdp) == SDP_SENDRECV) { diff_ms = (int)(now - strm->ts_last); debug("stream: last \"%s\" RTP packet: %d milliseconds\n", sdp_media_name(strm->sdp), diff_ms); /* check for large jumps in time */ if (diff_ms > (3600 * 1000)) { strm->ts_last = 0; return; } if (diff_ms > (int)strm->rtp_timeout_ms) { info("stream: no %s RTP packets received for" " %d milliseconds\n", sdp_media_name(strm->sdp), diff_ms); stream_close(strm, ETIMEDOUT); } } else { re_printf("check_rtp: not checking (dir=%s)\n", sdp_dir_name(sdp_media_dir(strm->sdp))); } } static inline int lostcalc(struct stream *s, uint16_t seq) { const uint16_t delta = seq - s->pseq; int lostc; if (s->pseq == (uint32_t)-1) lostc = 0; else if (delta == 0) return -1; else if (delta < 3000) lostc = delta - 1; else if (delta < 0xff9c) lostc = 0; else return -2; s->pseq = seq; return lostc; } static const char *media_name(enum media_type type) { switch (type) { case MEDIA_AUDIO: return "audio"; case MEDIA_VIDEO: return "video"; default: return "???"; } } static void handle_rtp(struct stream *s, const struct rtp_header *hdr, struct mbuf *mb, unsigned lostc) { struct rtpext extv[8]; size_t extc = 0; /* RFC 5285 -- A General Mechanism for RTP Header Extensions */ if (hdr->ext && hdr->x.len && mb) { const size_t pos = mb->pos; const size_t end = mb->end; const size_t ext_stop = mb->pos; size_t ext_len; size_t i; int err; if (hdr->x.type != RTPEXT_TYPE_MAGIC) { debug("stream: unknown ext type ignored (0x%04x)\n", hdr->x.type); goto handler; } ext_len = hdr->x.len*sizeof(uint32_t); if (mb->pos < ext_len) { warning("stream: corrupt rtp packet," " not enough space for rtpext of %zu bytes\n", ext_len); return; } mb->pos = mb->pos - ext_len; mb->end = ext_stop; for (i=0; ipos = pos; mb->end = end; } handler: s->rtph(hdr, extv, extc, mb, lostc, s->arg); } static inline bool is_rtcp_packet(unsigned pt) { return 64 <= pt && pt <= 95; } static void rtp_handler(const struct sa *src, const struct rtp_header *hdr, struct mbuf *mb, void *arg) { struct stream *s = arg; bool flush = false; int err; MAGIC_CHECK(s); if (is_rtcp_packet(hdr->pt)) { info("stream: drop incoming RTCP packet on RTP port" " (pt=%u)\n", hdr->pt); return; } s->ts_last = tmr_jiffies(); if (!mbuf_get_left(mb)) return; if (!(sdp_media_ldir(s->sdp) & SDP_RECVONLY)) return; #if 0 /* The marker bit indicates the beginning of a talkspurt. */ if (hdr->m && s->type == MEDIA_AUDIO) flush = true; #endif metric_add_packet(&s->metric_rx, mbuf_get_left(mb)); if (!s->rtp_estab) { info("stream: incoming rtp for '%s' established" ", receiving from %J\n", sdp_media_name(s->sdp), src); s->rtp_estab = true; if (s->rtpestabh) s->rtpestabh(s, s->sess_arg); } if (!s->pseq_set) { s->ssrc_rx = hdr->ssrc; s->pseq = hdr->seq - 1; s->pseq_set = true; } else if (hdr->ssrc != s->ssrc_rx) { info("stream: %s: SSRC changed 0x%x -> 0x%x" " (%u bytes from %J)\n", sdp_media_name(s->sdp), s->ssrc_rx, hdr->ssrc, mbuf_get_left(mb), src); s->ssrc_rx = hdr->ssrc; s->pseq = hdr->seq - 1; flush = true; } if (s->jbuf) { struct rtp_header hdr2; void *mb2 = NULL; int lostc; /* Put frame in Jitter Buffer */ if (flush && s->jbuf_started) jbuf_flush(s->jbuf); err = jbuf_put(s->jbuf, hdr, mb); if (err) { info("stream: %s: dropping %u bytes from %J" " [seq=%u, ts=%u] (%m)\n", sdp_media_name(s->sdp), mb->end, src, hdr->seq, hdr->ts, err); s->metric_rx.n_err++; } if (jbuf_get(s->jbuf, &hdr2, &mb2)) { if (!s->jbuf_started) return; memset(&hdr2, 0, sizeof(hdr2)); } s->jbuf_started = true; lostc = lostcalc(s, hdr2.seq); handle_rtp(s, &hdr2, mb2, lostc > 0 ? lostc : 0); mem_deref(mb2); } else { handle_rtp(s, hdr, mb, 0); } } static void rtcp_handler(const struct sa *src, struct rtcp_msg *msg, void *arg) { struct stream *s = arg; (void)src; MAGIC_CHECK(s); s->ts_last = tmr_jiffies(); switch (msg->hdr.pt) { case RTCP_SR: (void)rtcp_stats(s->rtp, msg->r.sr.ssrc, &s->rtcp_stats); break; } if (s->rtcph) s->rtcph(s, msg, s->arg); if (s->sessrtcph) s->sessrtcph(s, msg, s->sess_arg); } static int stream_sock_alloc(struct stream *s, int af) { struct sa laddr; int tos, err; if (!s) return EINVAL; /* we listen on all interfaces */ sa_init(&laddr, af); err = rtp_listen(&s->rtp, IPPROTO_UDP, &laddr, s->cfg.rtp_ports.min, s->cfg.rtp_ports.max, true, rtp_handler, rtcp_handler, s); if (err) { warning("stream: rtp_listen failed: af=%s ports=%u-%u" " (%m)\n", net_af2name(af), s->cfg.rtp_ports.min, s->cfg.rtp_ports.max, err); return err; } tos = s->cfg.rtp_tos; (void)udp_setsockopt(rtp_sock(s->rtp), IPPROTO_IP, IP_TOS, &tos, sizeof(tos)); (void)udp_setsockopt(rtcp_sock(s->rtp), IPPROTO_IP, IP_TOS, &tos, sizeof(tos)); udp_rxsz_set(rtp_sock(s->rtp), RTP_RECV_SIZE); udp_sockbuf_set(rtp_sock(s->rtp), 65536); return 0; } /** * Start media encryption * * @param strm Stream object * * @return 0 if success, otherwise errorcode */ int stream_start_mediaenc(struct stream *strm) { int err; if (!strm) return EINVAL; if (strm->menc && strm->menc->mediah) { info("stream: %s: starting mediaenc '%s' (wait_secure=%d)\n", media_name(strm->type), strm->menc->id, strm->menc->wait_secure); err = strm->menc->mediah(&strm->mes, strm->mencs, strm->rtp, rtp_sock(strm->rtp), strm->rtcp_mux ? NULL : rtcp_sock(strm->rtp), &strm->raddr_rtp, strm->rtcp_mux ? NULL : &strm->raddr_rtcp, strm->sdp, strm); if (err) { warning("stream: start mediaenc error: %m\n", err); return err; } } return 0; } static void mnat_connected_handler(const struct sa *raddr1, const struct sa *raddr2, void *arg) { struct stream *strm = arg; info("stream: mnat '%s' connected: raddr %J %J\n", strm->mnat->id, raddr1, raddr2); strm->raddr_rtp = *raddr1; if (strm->rtcp_mux) strm->raddr_rtcp = *raddr1; else if (raddr2) strm->raddr_rtcp = *raddr2; strm->mnat_connected = true; if (stream_is_ready(strm)) { stream_start(strm); } if (strm->mnatconnh) strm->mnatconnh(strm, strm->sess_arg); } int stream_alloc(struct stream **sp, struct list *streaml, const struct stream_param *prm, const struct config_avt *cfg, struct sdp_session *sdp_sess, enum media_type type, int label, const struct mnat *mnat, struct mnat_sess *mnat_sess, const struct menc *menc, struct menc_sess *menc_sess, bool offerer, stream_rtp_h *rtph, stream_rtcp_h *rtcph, void *arg) { struct stream *s; int err; if (!sp || !prm || !cfg || !rtph) return EINVAL; s = mem_zalloc(sizeof(*s), stream_destructor); if (!s) return ENOMEM; MAGIC_INIT(s); s->cfg = *cfg; s->type = type; s->rtph = rtph; s->rtcph = rtcph; s->arg = arg; s->pseq = -1; if (prm->use_rtp) { err = stream_sock_alloc(s, prm->af); if (err) { warning("stream: failed to create socket" " for media '%s' (%m)\n", media_name(type), err); goto out; } } err = str_dup(&s->cname, prm->cname); if (err) goto out; /* Jitter buffer */ if (cfg->jbuf_del.min && cfg->jbuf_del.max) { err = jbuf_alloc(&s->jbuf, cfg->jbuf_del.min, cfg->jbuf_del.max); if (err) goto out; } err = sdp_media_add(&s->sdp, sdp_sess, media_name(type), s->rtp ? sa_port(rtp_local(s->rtp)) : PORT_DISCARD, (menc && menc->sdp_proto) ? menc->sdp_proto : sdp_proto_rtpavp); if (err) goto out; if (label) { err |= sdp_media_set_lattr(s->sdp, true, "label", "%d", label); } /* RFC 5506 */ if (offerer || sdp_media_rattr(s->sdp, "rtcp-rsize")) err |= sdp_media_set_lattr(s->sdp, true, "rtcp-rsize", NULL); /* RFC 5576 */ err |= sdp_media_set_lattr(s->sdp, true, "ssrc", "%u cname:%s", rtp_sess_ssrc(s->rtp), prm->cname); /* RFC 5761 */ if (cfg->rtcp_mux && (offerer || sdp_media_rattr(s->sdp, "rtcp-mux"))) { err |= sdp_media_set_lattr(s->sdp, true, "rtcp-mux", NULL); } if (err) goto out; if (mnat && s->rtp) { s->mnat = mnat; err = mnat->mediah(&s->mns, mnat_sess, rtp_sock(s->rtp), cfg->rtcp_mux ? NULL : rtcp_sock(s->rtp), s->sdp, mnat_connected_handler, s); if (err) goto out; } if (menc && s->rtp) { s->menc = menc; s->mencs = mem_ref(menc_sess); err = stream_start_mediaenc(s); if (err) goto out; } s->pt_enc = -1; err = metric_init(&s->metric_tx); err |= metric_init(&s->metric_rx); if (err) goto out; list_append(streaml, &s->le, s); out: if (err) mem_deref(s); else *sp = s; return err; } /** * Get the sdp object from the stream * * @param strm Stream object * * @return SDP media object */ struct sdp_media *stream_sdpmedia(const struct stream *strm) { return strm ? strm->sdp : NULL; } int stream_send(struct stream *s, bool ext, bool marker, int pt, uint32_t ts, struct mbuf *mb) { int err = 0; if (!s) return EINVAL; if (!sa_isset(&s->raddr_rtp, SA_ALL)) return 0; if (!(sdp_media_rdir(s->sdp) & SDP_SENDONLY)) return 0; if (s->hold) return 0; if (!stream_is_ready(s)) { warning("stream: send: not ready\n"); return EINTR; } metric_add_packet(&s->metric_tx, mbuf_get_left(mb)); if (pt < 0) pt = s->pt_enc; if (pt >= 0) { err = rtp_send(s->rtp, &s->raddr_rtp, ext, marker, pt, ts, mb); if (err) s->metric_tx.n_err++; } return err; } static void stream_remote_set(struct stream *s) { if (!s) return; /* RFC 5761 */ if (s->cfg.rtcp_mux && sdp_media_rattr(s->sdp, "rtcp-mux")) { if (!s->rtcp_mux) info("%s: RTP/RTCP multiplexing enabled\n", sdp_media_name(s->sdp)); s->rtcp_mux = true; sdp_media_set_lattr(s->sdp, true, "rtcp-mux", NULL); } rtcp_enable_mux(s->rtp, s->rtcp_mux); sa_cpy(&s->raddr_rtp, sdp_media_raddr(s->sdp)); if (s->rtcp_mux) s->raddr_rtcp = s->raddr_rtp; else sdp_media_raddr_rtcp(s->sdp, &s->raddr_rtcp); if (stream_is_ready(s)) { stream_start(s); } } /** * Update the media stream * * @param s Stream object */ void stream_update(struct stream *s) { const struct sdp_format *fmt; int err = 0; if (!s) return; info("stream: update '%s'\n", media_name(s->type)); fmt = sdp_media_rformat(s->sdp, NULL); s->pt_enc = fmt ? fmt->pt : -1; if (sdp_media_has_media(s->sdp)) stream_remote_set(s); if (s->mencs && mnat_ready(s)) { err = stream_start_mediaenc(s); if (err) { warning("stream: mediaenc update: %m\n", err); } } } void stream_update_encoder(struct stream *s, int pt_enc) { if (!s) return; if (pt_enc >= 0) s->pt_enc = pt_enc; } int stream_jbuf_stat(struct re_printf *pf, const struct stream *s) { struct jbuf_stat stat; int err; if (!s) return EINVAL; err = re_hprintf(pf, " %s:", sdp_media_name(s->sdp)); err |= jbuf_stats(s->jbuf, &stat); if (err) { err = re_hprintf(pf, "Jbuf stat: (not available)"); } else { err = re_hprintf(pf, "Jbuf stat: put=%u get=%u or=%u ur=%u", stat.n_put, stat.n_get, stat.n_overflow, stat.n_underflow); } return err; } void stream_hold(struct stream *s, bool hold) { if (!s) return; s->hold = hold; sdp_media_set_ldir(s->sdp, hold ? SDP_SENDONLY : SDP_SENDRECV); stream_reset(s); } void stream_set_ldir(struct stream *s, enum sdp_dir dir) { if (!s) return; if (dir == SDP_INACTIVE) { sdp_media_set_disabled(s->sdp, true); } else { sdp_media_set_disabled(s->sdp, false); sdp_media_set_ldir(s->sdp, dir); } stream_reset(s); } void stream_set_srate(struct stream *s, uint32_t srate_tx, uint32_t srate_rx) { if (!s) return; if (srate_tx) rtcp_set_srate_tx(s->rtp, srate_tx); if (srate_rx) rtcp_set_srate_rx(s->rtp, srate_rx); } void stream_send_fir(struct stream *s, bool pli) { int err; if (!s) return; if (pli) err = rtcp_send_pli(s->rtp, s->ssrc_rx); else err = rtcp_send_fir(s->rtp, rtp_sess_ssrc(s->rtp)); if (err) { s->metric_tx.n_err++; warning("stream: failed to send RTCP %s: %m\n", pli ? "PLI" : "FIR", err); } } void stream_reset(struct stream *s) { if (!s) return; if (s->jbuf && s->jbuf_started) jbuf_flush(s->jbuf); } void stream_set_bw(struct stream *s, uint32_t bps) { if (!s) return; sdp_media_set_lbandwidth(s->sdp, SDP_BANDWIDTH_AS, bps / 1000); } void stream_enable_rtp_timeout(struct stream *strm, uint32_t timeout_ms) { if (!strm) return; strm->rtp_timeout_ms = timeout_ms; tmr_cancel(&strm->tmr_rtp); if (timeout_ms) { info("stream: Enable RTP timeout (%u milliseconds)\n", timeout_ms); strm->ts_last = tmr_jiffies(); tmr_start(&strm->tmr_rtp, 10, check_rtp_handler, strm); } } /** * Set optional session handlers * * @param strm Stream object * @param mnatconnh Media NAT connected handler * @param rtpestabh Incoming RTP established handler * @param rtcph Incoming RTCP message handler * @param errorh Error handler * @param arg Handler argument */ void stream_set_session_handlers(struct stream *strm, stream_mnatconn_h *mnatconnh, stream_rtpestab_h *rtpestabh, stream_rtcp_h *rtcph, stream_error_h *errorh, void *arg) { if (!strm) return; strm->mnatconnh = mnatconnh; strm->rtpestabh = rtpestabh; strm->sessrtcph = rtcph; strm->errorh = errorh; strm->sess_arg = arg; } /** * Print stream debug info * * @param pf Print function * @param s Stream object * * @return 0 if success, otherwise errorcode */ int stream_debug(struct re_printf *pf, const struct stream *s) { int err; if (!s) return 0; err = re_hprintf(pf, " %s dir=%s pt_enc=%d\n", sdp_media_name(s->sdp), sdp_dir_name(sdp_media_dir(s->sdp)), s->pt_enc); err |= re_hprintf(pf, " local: %J, remote: %J/%J\n", sdp_media_laddr(s->sdp), &s->raddr_rtp, &s->raddr_rtcp); err |= re_hprintf(pf, " mnat: %s (connected=%s)\n", s->mnat ? s->mnat->id : "(none)", s->mnat_connected ? "yes" : "no"); err |= re_hprintf(pf, " menc: %s (secure=%s)\n", s->menc ? s->menc->id : "(none)", s->menc_secure ? "yes" : "no"); err |= rtp_debug(pf, s->rtp); err |= jbuf_debug(pf, s->jbuf); return err; } int stream_print(struct re_printf *pf, const struct stream *s) { if (!s) return 0; return re_hprintf(pf, " %s=%u/%u", sdp_media_name(s->sdp), s->metric_tx.cur_bitrate, s->metric_rx.cur_bitrate); } /** * Get the RTCP Statistics from a media stream * * @param strm Stream object * * @return RTCP Statistics */ const struct rtcp_stats *stream_rtcp_stats(const struct stream *strm) { return strm ? &strm->rtcp_stats : NULL; } /** * Get the number of transmitted RTP packets * * @param strm Stream object * * @return Number of transmitted RTP packets */ uint32_t stream_metric_get_tx_n_packets(const struct stream *strm) { return strm ? strm->metric_tx.n_packets : 0; } /** * Get the number of transmitted RTP bytes * * @param strm Stream object * * @return Number of transmitted RTP bytes */ uint32_t stream_metric_get_tx_n_bytes(const struct stream *strm) { return strm ? strm->metric_tx.n_bytes : 0; } /** * Get the number of transmission errors * * @param strm Stream object * * @return Number of transmission errors */ uint32_t stream_metric_get_tx_n_err(const struct stream *strm) { return strm ? strm->metric_tx.n_err : 0; } /** * Get the number of received RTP packets * * @param strm Stream object * * @return Number of received RTP packets */ uint32_t stream_metric_get_rx_n_packets(const struct stream *strm) { return strm ? strm->metric_rx.n_packets : 0; } /** * Get the number of received RTP bytes * * @param strm Stream object * * @return Number of received RTP bytes */ uint32_t stream_metric_get_rx_n_bytes(const struct stream *strm) { return strm ? strm->metric_rx.n_bytes : 0; } /** * Get the number of receive errors * * @param strm Stream object * * @return Number of receive errors */ uint32_t stream_metric_get_rx_n_err(const struct stream *strm) { return strm ? strm->metric_rx.n_err : 0; } int stream_jbuf_reset(struct stream *strm, uint32_t frames_min, uint32_t frames_max) { if (!strm) return EINVAL; strm->jbuf = mem_deref(strm->jbuf); if (frames_min && frames_max) return jbuf_alloc(&strm->jbuf, frames_min, frames_max); return 0; } bool stream_is_ready(const struct stream *strm) { if (!strm) return false; /* Media NAT */ if (strm->mnat) { if (!mnat_ready(strm)) return false; } /* Media Enc */ if (strm->menc && strm->menc->wait_secure) { if (!strm->menc_secure) return false; } if (!sa_isset(&strm->raddr_rtp, SA_ALL)) return false; return !strm->terminated; } /** * Set the secure flag on the stream object * * @param strm Stream object * @param secure True for secure, false for insecure */ void stream_set_secure(struct stream *strm, bool secure) { if (!strm) return; strm->menc_secure = secure; } /** * Get the secure flag on the stream object * * @param strm Stream object * * @return True for secure, false for insecure */ bool stream_is_secure(const struct stream *strm) { return strm ? strm->menc_secure : false; } /** * Start the media stream * * @param strm Stream object * * @return 0 if success, otherwise errorcode */ int stream_start(const struct stream *strm) { int err; if (!strm) return EINVAL; debug("stream: %s: starting RTCP with remote %J\n", media_name(strm->type), &strm->raddr_rtcp); rtcp_start(strm->rtp, strm->cname, &strm->raddr_rtcp); if (!strm->mnat) { /* Send a dummy RTCP packet to open NAT pinhole */ err = rtcp_send_app(strm->rtp, "PING", (void *)"PONG", 4); if (err) { warning("stream: rtcp_send_app failed (%m)\n", err); return err; } } return 0; } /** * Get the name of the stream type (e.g. audio or video) * * @param strm Stream object * * @return Name of stream type */ const char *stream_name(const struct stream *strm) { if (!strm) return NULL; return media_name(strm->type); } baresip-1.0.0/src/stunuri.c000066400000000000000000000075251372575704200156260ustar00rootroot00000000000000/** * @file stunuri.c URI Scheme for STUN/TURN Protocol * * Copyright (C) 2010 Creytiv.com */ #include #include #include "core.h" /* https://tools.ietf.org/html/rfc7064 https://tools.ietf.org/html/rfc7065 +-----------------------+ | URI | +-----------------------+ | stun:example.org | | stuns:example.org | | stun:example.org:8000 | +-----------------------+ +---------------------------------+----------+--------+-------------+ | URI | | | | +---------------------------------+----------+--------+-------------+ | turn:example.org | false | | | | turns:example.org | true | | | | turn:example.org:8000 | false | 8000 | | | turn:example.org?transport=udp | false | | UDP | | turn:example.org?transport=tcp | false | | TCP | | turns:example.org?transport=tcp | true | | TLS | +---------------------------------+----------+--------+-------------+ */ static void destructor(void *arg) { struct stun_uri *su = arg; mem_deref(su->host); } /** * Decode a STUN uri from a string * * @param sup Pointer to allocated STUN uri * @param pl Pointer-length string * * @return 0 if success, otherwise errorcode */ int stunuri_decode(struct stun_uri **sup, const struct pl *pl) { struct stun_uri *su; struct uri uri; enum stun_scheme scheme; int err; if (!sup || !pl) return EINVAL; err = uri_decode(&uri, pl); if (err) { warning("stunuri: decode '%r' failed (%m)\n", pl, err); return err; } if (0 == pl_strcasecmp(&uri.scheme, "stun")) scheme = STUN_SCHEME_STUN; else if (0 == pl_strcasecmp(&uri.scheme, "stuns")) scheme = STUN_SCHEME_STUNS; else if (0 == pl_strcasecmp(&uri.scheme, "turn")) scheme = STUN_SCHEME_TURN; else if (0 == pl_strcasecmp(&uri.scheme, "turns")) scheme = STUN_SCHEME_TURNS; else { warning("stunuri: scheme not supported (%r)\n", &uri.scheme); return ENOTSUP; } su = mem_zalloc(sizeof(*su), destructor); if (!su) return ENOMEM; su->scheme = scheme; err = pl_strdup(&su->host, &uri.host); su->port = uri.port; if (err) mem_deref(su); else *sup = su; return err; } /** * Set the hostname on a STUN uri * * @param su STUN uri * @param host Hostname to set * * @return 0 if success, otherwise errorcode */ int stunuri_set_host(struct stun_uri *su, const char *host) { if (!su || !host) return EINVAL; su->host = mem_deref(su->host); return str_dup(&su->host, host); } /** * Set the port number on a STUN uri * * @param su STUN uri * @param port Port number to set * * @return 0 if success, otherwise errorcode */ int stunuri_set_port(struct stun_uri *su, uint16_t port) { if (!su) return EINVAL; su->port = port; return 0; } /** * Print a STUN uri * * @param pf Print function * @param su STUN uri * * @return 0 if success, otherwise errorcode */ int stunuri_print(struct re_printf *pf, const struct stun_uri *su) { int err = 0; if (!su) return 0; err |= re_hprintf(pf, "scheme=%s", stunuri_scheme_name(su->scheme)); err |= re_hprintf(pf, " host='%s'", su->host); err |= re_hprintf(pf, " port=%u", su->port); return err; } /** * Get the name of the STUN scheme * * @param scheme STUN scheme * * @return String with STUN scheme */ const char *stunuri_scheme_name(enum stun_scheme scheme) { switch (scheme) { case STUN_SCHEME_STUN: return "stun"; case STUN_SCHEME_STUNS: return "stuns"; case STUN_SCHEME_TURN: return "turn"; case STUN_SCHEME_TURNS: return "turns"; default: return "?"; } } baresip-1.0.0/src/timer.c000066400000000000000000000023311372575704200152230ustar00rootroot00000000000000/** * @file timer.c Timer functions * * Copyright (C) 2010 Creytiv.com */ #define _BSD_SOURCE 1 #define _DEFAULT_SOURCE 1 #ifdef HAVE_SYS_TIME_H #include #endif #ifdef WIN32 #include #include #else #include #endif #include #include #include "core.h" /** * Get the timer jiffies in microseconds [us] * * @return Jiffies in [us] */ uint64_t tmr_jiffies_usec(void) { uint64_t jfs; #if defined(WIN32) FILETIME ft; ULARGE_INTEGER li; GetSystemTimeAsFileTime(&ft); li.LowPart = ft.dwLowDateTime; li.HighPart = ft.dwHighDateTime; jfs = li.QuadPart/10; #elif defined(HAVE_CLOCK_GETTIME) struct timespec now; clockid_t clock_id; #if defined (CLOCK_BOOTTIME) clock_id = CLOCK_BOOTTIME; #else clock_id = CLOCK_MONOTONIC; #endif if (0 != clock_gettime(clock_id, &now)) { warning("timer: clock_gettime() failed (%m)\n", errno); return 0; } jfs = (long)now.tv_sec * (uint64_t)1000000; jfs += now.tv_nsec / (uint64_t)1000; #else struct timeval now; if (0 != gettimeofday(&now, NULL)) { warning("timer: gettimeofday() failed (%m)\n", errno); return 0; } jfs = (long)now.tv_sec * (uint64_t)1000000; jfs += now.tv_usec; #endif return jfs; } baresip-1.0.0/src/timestamp.c000066400000000000000000000031361372575704200161120ustar00rootroot00000000000000/** * @file timestamp.c Timestamp helpers * * Copyright (C) 2010 Creytiv.com */ #include #include #include "core.h" /** * Check if a 32-bit timestamp wraps around * * @param ts_new Timestamp of the current packet * @param ts_old Timestamp of the previous packet * * @return Integer describing the wrap-around * @retval -1 backwards wrap-around * @retval 0 no wrap-around * @retval 1 forward wrap-around */ int timestamp_wrap(uint32_t ts_new, uint32_t ts_old) { int32_t delta; if (ts_new < ts_old) { delta = (int32_t)ts_new - (int32_t)ts_old; if (delta > 0) return 1; } else if ((int32_t)(ts_old - ts_new) > 0) { return -1; } return 0; } void timestamp_set(struct timestamp_recv *ts, uint32_t rtp_ts) { if (!ts) return; ts->first = rtp_ts; ts->last = rtp_ts; ts->is_set = true; } /** * Calculate the total timestamp duration, in timestamp units. * The duration is calculated as the delta between the * last extended timestamp and the first extended timestamp. * * @param ts Receiver timestamp struct * * @return Timestamp duration */ uint64_t timestamp_duration(const struct timestamp_recv *ts) { uint64_t last_ext; if (!ts || !ts->is_set) return 0; last_ext = timestamp_calc_extended(ts->num_wraps, ts->last); return last_ext - ts->first; } uint64_t timestamp_calc_extended(uint32_t num_wraps, uint32_t ts) { uint64_t ext_ts; ext_ts = (uint64_t)num_wraps * 0x100000000ULL; ext_ts += (uint64_t)ts; return ext_ts; } double timestamp_calc_seconds(uint64_t ts, uint32_t clock_rate) { return (double)ts / (double)clock_rate; } baresip-1.0.0/src/ua.c000066400000000000000000001260771372575704200145260ustar00rootroot00000000000000/** * @file src/ua.c User-Agent * * Copyright (C) 2010 Creytiv.com */ #include #include #include #include "core.h" #include /** Magic number */ #define MAGIC 0x0a0a0a0a #include "magic.h" /** Defines a SIP User Agent object */ struct ua { MAGIC_DECL /**< Magic number for struct ua */ struct le le; /**< Linked list element */ struct account *acc; /**< Account Parameters */ struct list regl; /**< List of Register clients */ struct list calls; /**< List of active calls (struct call) */ struct pl extensionv[8]; /**< Vector of SIP extensions */ size_t extensionc; /**< Number of SIP extensions */ char *cuser; /**< SIP Contact username */ char *pub_gruu; /**< SIP Public GRUU */ int af_media; /**< Preferred Address Family for media */ enum presence_status my_status; /**< Presence Status */ bool catchall; /**< Catch all inbound requests */ struct list hdr_filter; /**< Filter for incoming headers */ struct list custom_hdrs; /**< List of outgoing headers */ }; struct ua_eh { struct le le; ua_event_h *h; void *arg; }; struct ua_xhdr_filter { struct le le; char *hdr_name; }; static struct { struct config_sip *cfg; /**< SIP configuration */ struct list ual; /**< List of User-Agents (struct ua) */ struct list ehl; /**< Event handlers (struct ua_eh) */ struct sip *sip; /**< SIP Stack */ struct sip_lsnr *lsnr; /**< SIP Listener */ struct sipsess_sock *sock; /**< SIP Session socket */ struct sipevent_sock *evsock; /**< SIP Event socket */ struct ua *ua_cur; /**< Current User-Agent */ bool use_udp; /**< Use UDP transport */ bool use_tcp; /**< Use TCP transport */ bool use_tls; /**< Use TLS transport */ bool delayed_close; /**< Module will close SIP stack */ sip_msg_h *subh; /**< Subscribe handler */ ua_exit_h *exith; /**< UA Exit handler */ void *arg; /**< UA Exit handler argument */ char *eprm; /**< Extra UA parameters */ #ifdef USE_TLS struct tls *tls; /**< TLS Context */ #endif } uag = { NULL, LIST_INIT, LIST_INIT, NULL, NULL, NULL, NULL, NULL, true, true, true, false, NULL, NULL, NULL, NULL, #ifdef USE_TLS NULL, #endif }; static void ua_destructor(void *arg) { struct ua *ua = arg; list_unlink(&ua->le); if (!list_isempty(&ua->regl)) ua_event(ua, UA_EVENT_UNREGISTERING, NULL, NULL); list_flush(&ua->calls); list_flush(&ua->regl); mem_deref(ua->cuser); mem_deref(ua->pub_gruu); mem_deref(ua->acc); if (uag.delayed_close && list_isempty(&uag.ual)) { sip_close(uag.sip, false); } list_flush(&ua->custom_hdrs); list_flush(&ua->hdr_filter); } /* This function is called when all SIP transactions are done */ static void exit_handler(void *arg) { (void)arg; ua_event(NULL, UA_EVENT_EXIT, NULL, NULL); debug("ua: sip-stack exit\n"); if (uag.exith) uag.exith(uag.arg); } void ua_printf(const struct ua *ua, const char *fmt, ...) { va_list ap; if (!ua) return; va_start(ap, fmt); info("%r@%r: %v", &ua->acc->luri.user, &ua->acc->luri.host, fmt, &ap); va_end(ap); } /** * Send a User-Agent event to all UA event handlers * * @param ua User-Agent object (optional) * @param ev User-agent event * @param call Call object (optional) * @param fmt Formatted arguments * @param ... Variable arguments */ void ua_event(struct ua *ua, enum ua_event ev, struct call *call, const char *fmt, ...) { struct le *le; char buf[256]; va_list ap; va_start(ap, fmt); (void)re_vsnprintf(buf, sizeof(buf), fmt, ap); va_end(ap); /* send event to all clients */ le = uag.ehl.head; while (le) { struct ua_eh *eh = le->data; le = le->next; eh->h(ua, ev, call, buf, eh->arg); } } /** * Start registration of a User-Agent * * @param ua User-Agent * * @return 0 if success, otherwise errorcode */ int ua_register(struct ua *ua) { struct account *acc; struct le *le; struct uri uri; char *reg_uri = NULL; char params[256] = ""; unsigned i; int err; if (!ua) return EINVAL; acc = ua->acc; if (acc->regint == 0) return 0; uri = ua->acc->luri; uri.user = uri.password = pl_null; err = re_sdprintf(®_uri, "%H", uri_encode, &uri); if (err) goto out; if (uag.cfg && str_isset(uag.cfg->uuid)) { if (re_snprintf(params, sizeof(params), ";+sip.instance=\"\"", uag.cfg->uuid) < 0) { err = ENOMEM; goto out; } } if (acc->regq) { if (re_snprintf(¶ms[strlen(params)], sizeof(params) - strlen(params), ";q=%s", acc->regq) < 0) { err = ENOMEM; goto out; } } if (acc->mnat && acc->mnat->ftag) { if (re_snprintf(¶ms[strlen(params)], sizeof(params) - strlen(params), ";%s", acc->mnat->ftag) < 0) { err = ENOMEM; goto out; } } ua_event(ua, UA_EVENT_REGISTERING, NULL, NULL); for (le = ua->regl.head, i=0; le; le = le->next, i++) { struct reg *reg = le->data; err = reg_register(reg, reg_uri, params, acc->regint, acc->outboundv[i]); if (err) { warning("ua: SIP register failed: %m\n", err); ua_event(ua, UA_EVENT_REGISTER_FAIL, NULL, "%m", err); goto out; } } out: mem_deref(reg_uri); return err; } /** * Unregister all Register clients of a User-Agent * * @param ua User-Agent */ void ua_unregister(struct ua *ua) { struct le *le; if (!ua) return; if (!list_isempty(&ua->regl)) ua_event(ua, UA_EVENT_UNREGISTERING, NULL, NULL); for (le = ua->regl.head; le; le = le->next) { struct reg *reg = le->data; reg_unregister(reg); } } /** * Check if a User-Agent is registered * * @param ua User-Agent object * * @return True if registered, false if not registered */ bool ua_isregistered(const struct ua *ua) { struct le *le; if (!ua) return false; for (le = ua->regl.head; le; le = le->next) { const struct reg *reg = le->data; /* it is enough if one of the registrations work */ if (reg_isok(reg)) return true; } return false; } /** * Destroy the user-agent, terminate all active calls and * send the SHUTDOWN event. * * @param ua User-Agent object * * @return Number of remaining references */ unsigned ua_destroy(struct ua *ua) { unsigned nrefs; if (!ua) return 0; list_unlink(&ua->le); /* send the shutdown event */ ua_event(ua, UA_EVENT_SHUTDOWN, NULL, NULL); /* terminate all calls now */ list_flush(&ua->calls); /* number of remaining references (excluding this one) */ nrefs = mem_nrefs(ua) - 1; mem_deref(ua); return nrefs; } static struct call *ua_find_call_onhold(const struct ua *ua) { struct le *le; if (!ua) return NULL; for (le = ua->calls.tail; le; le = le->prev) { struct call *call = le->data; if (call_is_onhold(call)) return call; } return NULL; } static void resume_call(struct ua *ua) { struct call *call; call = ua_find_call_onhold(ua); if (call) { ua_printf(ua, "resuming previous call with '%s'\n", call_peeruri(call)); call_hold(call, false); } } static void call_event_handler(struct call *call, enum call_event ev, const char *str, void *arg) { struct ua *ua = arg; const char *peeruri; MAGIC_CHECK(ua); peeruri = call_peeruri(call); switch (ev) { case CALL_EVENT_INCOMING: if (contact_block_access(baresip_contacts(), peeruri)) { info("ua: blocked access: \"%s\"\n", peeruri); ua_event(ua, UA_EVENT_CALL_CLOSED, call, str); mem_deref(call); break; } switch (ua->acc->answermode) { case ANSWERMODE_EARLY: (void)call_progress(call); break; case ANSWERMODE_AUTO: (void)call_answer(call, 200, VIDMODE_ON); break; case ANSWERMODE_MANUAL: ua_event(ua, UA_EVENT_CALL_INCOMING, call, peeruri); break; } break; case CALL_EVENT_RINGING: ua_event(ua, UA_EVENT_CALL_RINGING, call, peeruri); break; case CALL_EVENT_PROGRESS: ua_printf(ua, "Call in-progress: %s\n", peeruri); ua_event(ua, UA_EVENT_CALL_PROGRESS, call, peeruri); break; case CALL_EVENT_ESTABLISHED: ua_printf(ua, "Call established: %s\n", peeruri); ua_event(ua, UA_EVENT_CALL_ESTABLISHED, call, peeruri); break; case CALL_EVENT_CLOSED: ua_event(ua, UA_EVENT_CALL_CLOSED, call, str); mem_deref(call); resume_call(ua); break; case CALL_EVENT_TRANSFER: ua_event(ua, UA_EVENT_CALL_TRANSFER, call, str); break; case CALL_EVENT_TRANSFER_FAILED: ua_event(ua, UA_EVENT_CALL_TRANSFER_FAILED, call, str); mem_deref(call); break; case CALL_EVENT_MENC: ua_event(ua, UA_EVENT_CALL_MENC, call, str); break; } } static void call_dtmf_handler(struct call *call, char key, void *arg) { struct ua *ua = arg; char key_str[2]; MAGIC_CHECK(ua); if (key != KEYCODE_REL) { key_str[0] = key; key_str[1] = '\0'; ua_event(ua, UA_EVENT_CALL_DTMF_START, call, key_str); } else { ua_event(ua, UA_EVENT_CALL_DTMF_END, call, NULL); } } static int best_effort_af(struct ua *ua, const struct network *net) { struct le *le; const int afv[2] = { AF_INET, AF_INET6 }; size_t i; for (le = ua->regl.head, i=0; le; le = le->next, i++) { const struct reg *reg = le->data; if (reg_isok(reg)) return reg_af(reg); } for (i=0; imb))) { info("ua: using AF from sdp offer: af=%s\n", net_af2name(af_sdp)); af = af_sdp; } else if (ua->af_media && sa_isset(net_laddr_af(net, ua->af_media), SA_ADDR)) { info("ua: using ua's preferred AF: af=%s\n", net_af2name(ua->af_media)); af = ua->af_media; } else { af = best_effort_af(ua, net); info("ua: using best effort AF: af=%s\n", net_af2name(af)); } memset(&cprm, 0, sizeof(cprm)); sa_cpy(&cprm.laddr, net_laddr_af(net, af)); cprm.vidmode = vmode; cprm.af = af; cprm.use_rtp = use_rtp; err = call_alloc(callp, conf_config(), &ua->calls, ua->acc->dispname, local_uri ? local_uri : ua->acc->aor, ua->acc, ua, &cprm, msg, xcall, net_dnsc(net), call_event_handler, ua); if (err) return err; call_set_handlers(*callp, NULL, call_dtmf_handler, ua); return 0; } static void handle_options(struct ua *ua, const struct sip_msg *msg) { struct sip_contact contact; struct call *call = NULL; struct mbuf *desc = NULL; const struct sip_hdr *hdr; bool accept_sdp = true; int err; debug("ua: incoming OPTIONS message from %r (%J)\n", &msg->from.auri, &msg->src); /* application/sdp is the default if the Accept header field is not present */ hdr = sip_msg_hdr(msg, SIP_HDR_ACCEPT); if (hdr) { accept_sdp = 0==pl_strcasecmp(&hdr->val, "application/sdp"); } if (accept_sdp) { err = ua_call_alloc(&call, ua, VIDMODE_ON, NULL, NULL, NULL, false); if (err) { (void)sip_treply(NULL, uag.sip, msg, 500, "Call Error"); return; } err = call_sdp_get(call, &desc, true); if (err) goto out; } sip_contact_set(&contact, ua_cuser(ua), &msg->dst, msg->tp); err = sip_treplyf(NULL, NULL, uag.sip, msg, true, 200, "OK", "Allow: %H\r\n" "%H" "%H" "%s" "Content-Length: %zu\r\n" "\r\n" "%b", ua_print_allowed, ua, ua_print_supported, ua, sip_contact_print, &contact, desc ? "Content-Type: application/sdp\r\n" : "", desc ? mbuf_get_left(desc) : (size_t)0, desc ? mbuf_buf(desc) : NULL, desc ? mbuf_get_left(desc) : (size_t)0); if (err) { warning("ua: options: sip_treplyf: %m\n", err); } out: mem_deref(desc); mem_deref(call); } static bool request_handler(const struct sip_msg *msg, void *arg) { struct ua *ua; (void)arg; if (pl_strcmp(&msg->met, "OPTIONS")) return false; ua = uag_find(&msg->uri.user); if (!ua) { (void)sip_treply(NULL, uag_sip(), msg, 404, "Not Found"); return true; } handle_options(ua, msg); return true; } static void add_extension(struct ua *ua, const char *extension) { struct pl e; if (ua->extensionc >= ARRAY_SIZE(ua->extensionv)) { warning("ua: maximum %zu number of SIP extensions\n", ARRAY_SIZE(ua->extensionv)); return; } pl_set_str(&e, extension); ua->extensionv[ua->extensionc++] = e; } static int create_register_clients(struct ua *ua) { int err = 0; /* Register clients */ if (uag.cfg && str_isset(uag.cfg->uuid)) add_extension(ua, "gruu"); if (0 == str_casecmp(ua->acc->sipnat, "outbound")) { size_t i; add_extension(ua, "path"); add_extension(ua, "outbound"); if (!str_isset(uag.cfg->uuid)) { warning("ua: outbound requires valid UUID!\n"); err = ENOSYS; goto out; } for (i=0; iacc->outboundv); i++) { if (ua->acc->outboundv[i] && ua->acc->regint) { err = reg_add(&ua->regl, ua, (int)i+1); if (err) break; } } } else if (ua->acc->regint) { err = reg_add(&ua->regl, ua, 0); } out: return err; } /** * Allocate a SIP User-Agent * * @param uap Pointer to allocated User-Agent object * @param aor SIP Address-of-Record (AOR) * * @return 0 if success, otherwise errorcode */ int ua_alloc(struct ua **uap, const char *aor) { struct ua *ua; char *buf = NULL; int err; if (!aor) return EINVAL; ua = mem_zalloc(sizeof(*ua), ua_destructor); if (!ua) return ENOMEM; MAGIC_INIT(ua); list_init(&ua->calls); ua->af_media = AF_UNSPEC; /* Decode SIP address */ if (uag.eprm) { err = re_sdprintf(&buf, "%s;%s", aor, uag.eprm); if (err) goto out; aor = buf; } err = account_alloc(&ua->acc, aor); if (err) goto out; /* generate a unique contact-user, this is needed to route incoming requests when using multiple useragents */ err = re_sdprintf(&ua->cuser, "%r-%p", &ua->acc->luri.user, ua); if (err) goto out; if (ua->acc->sipnat) { ua_printf(ua, "Using sipnat: '%s'\n", ua->acc->sipnat); } if (ua->acc->mnat) { ua_printf(ua, "Using medianat '%s'\n", ua->acc->mnat->id); if (0 == str_casecmp(ua->acc->mnat->id, "ice")) add_extension(ua, "ice"); } if (ua->acc->menc) { ua_printf(ua, "Using media encryption '%s'\n", ua->acc->menc->id); } err = create_register_clients(ua); if (err) goto out; list_append(&uag.ual, &ua->le, ua); if (!uag_current()) uag_current_set(ua); out: mem_deref(buf); if (err) mem_deref(ua); else if (uap) *uap = ua; return err; } /** * Update a User-agent object, reset register clients * * @param ua User-Agent object * * @return 0 if success, otherwise errorcode */ int ua_update_account(struct ua *ua) { if (!ua) return EINVAL; /* clear extensions and reg clients */ ua->extensionc = 0; list_flush(&ua->regl); return create_register_clients(ua); } /** * Auto complete a SIP uri, add scheme and domain if missing * * @param ua User-Agent * @param buf Target buffer to print SIP uri * @param uri Input SIP uri * * @return 0 if success, otherwise errorcode */ int ua_uri_complete(struct ua *ua, struct mbuf *buf, const char *uri) { struct account *acc; struct sa sa_addr; size_t len; bool uri_is_ip; int err = 0; if (!ua || !buf || !uri) return EINVAL; acc = ua->acc; /* Skip initial whitespace */ while (isspace(*uri)) ++uri; len = str_len(uri); /* Append sip: scheme if missing */ if (0 != re_regex(uri, len, "sip:")) err |= mbuf_printf(buf, "sip:"); err |= mbuf_write_str(buf, uri); /* Append domain if missing and uri is not IP address */ /* check if uri is valid IP address */ uri_is_ip = (0 == sa_set_str(&sa_addr, uri, 0)); if (0 != re_regex(uri, len, "[^@]+@[^]+", NULL, NULL) && 1 != uri_is_ip) { #if HAVE_INET6 if (AF_INET6 == acc->luri.af) err |= mbuf_printf(buf, "@[%r]", &acc->luri.host); else #endif err |= mbuf_printf(buf, "@%r", &acc->luri.host); /* Also append port if specified and not 5060 */ switch (acc->luri.port) { case 0: case SIP_PORT: break; default: err |= mbuf_printf(buf, ":%u", acc->luri.port); break; } } return err; } /** * Connect an outgoing call to a given SIP uri * * @param ua User-Agent * @param callp Optional pointer to allocated call object * @param from_uri Optional From uri, or NULL for default AOR * @param req_uri SIP uri to connect to * @param vmode Video mode * * @return 0 if success, otherwise errorcode */ int ua_connect(struct ua *ua, struct call **callp, const char *from_uri, const char *req_uri, enum vidmode vmode) { struct call *call = NULL; struct mbuf *dialbuf; struct pl pl; int err = 0; if (!ua || !str_isset(req_uri)) return EINVAL; dialbuf = mbuf_alloc(64); if (!dialbuf) return ENOMEM; err |= ua_uri_complete(ua, dialbuf, req_uri); /* Append any optional URI parameters */ err |= mbuf_write_pl(dialbuf, &ua->acc->luri.params); if (err) goto out; err = ua_call_alloc(&call, ua, vmode, NULL, NULL, from_uri, true); if (err) goto out; pl.p = (char *)dialbuf->buf; pl.l = dialbuf->end; if (!list_isempty(&ua->custom_hdrs)) call_set_custom_hdrs(call, &ua->custom_hdrs); err = call_connect(call, &pl); if (err) mem_deref(call); else if (callp) *callp = call; out: mem_deref(dialbuf); return err; } /** * Hangup the current call * * @param ua User-Agent * @param call Call to hangup, or NULL for current call * @param scode Optional status code * @param reason Optional reason */ void ua_hangup(struct ua *ua, struct call *call, uint16_t scode, const char *reason) { if (!ua) return; if (!call) { call = ua_call(ua); if (!call) return; } call_hangup(call, scode, reason); ua_event(ua, UA_EVENT_CALL_CLOSED, call, reason ? reason : "Connection reset by user"); mem_deref(call); resume_call(ua); } /** * Answer an incoming call * * @param ua User-Agent * @param call Call to answer, or NULL for current call * @param vmode Wanted video mode * * @return 0 if success, otherwise errorcode */ int ua_answer(struct ua *ua, struct call *call, enum vidmode vmode) { if (!ua) return EINVAL; if (!call) { call = ua_call(ua); if (!call) return ENOENT; } return call_answer(call, 200, vmode); } /** * Put the current call on hold and answer the incoming call * * @param ua User-Agent * @param call Call to answer, or NULL for current call * @param vmode Wanted video mode for the incoming call * * @return 0 if success, otherwise errorcode */ int ua_hold_answer(struct ua *ua, struct call *call, enum vidmode vmode) { struct call *pcall; int err; if (!ua) return EINVAL; if (!call) { call = ua_call(ua); if (!call) return ENOENT; } /* put previous call on-hold */ pcall = ua_prev_call(ua); if (pcall) { ua_printf(ua, "putting call with '%s' on hold\n", call_peeruri(pcall)); err = call_hold(pcall, true); if (err) return err; } return ua_answer(ua, call, vmode); } /** * Print the user-agent registration status * * @param pf Print function * @param ua User-Agent object * * @return 0 if success, otherwise errorcode */ int ua_print_status(struct re_printf *pf, const struct ua *ua) { struct le *le; int err; if (!ua) return 0; err = re_hprintf(pf, "%-42s", ua->acc->aor); for (le = ua->regl.head; le; le = le->next) err |= reg_status(pf, le->data); err |= re_hprintf(pf, "\n"); return err; } /** * Send SIP OPTIONS message to a peer * * @param ua User-Agent object * @param uri Peer SIP Address * @param resph Response handler * @param arg Handler argument * * @return 0 if success, otherwise errorcode */ int ua_options_send(struct ua *ua, const char *uri, options_resp_h *resph, void *arg) { struct mbuf *dialbuf; int err = 0; if (!ua || !str_isset(uri)) return EINVAL; dialbuf = mbuf_alloc(64); if (!dialbuf) return ENOMEM; err = ua_uri_complete(ua, dialbuf, uri); if (err) goto out; dialbuf->buf[dialbuf->end] = '\0'; err = sip_req_send(ua, "OPTIONS", (char *)dialbuf->buf, resph, arg, "Accept: application/sdp\r\n" "Content-Length: 0\r\n" "\r\n"); if (err) { warning("ua: send options: (%m)\n", err); } out: mem_deref(dialbuf); return err; } /** * Get the AOR of a User-Agent * * @param ua User-Agent object * * @return AOR */ const char *ua_aor(const struct ua *ua) { return ua ? account_aor(ua->acc) : NULL; } /** * Get presence status of a User-Agent * * @param ua User-Agent object * * @return presence status */ enum presence_status ua_presence_status(const struct ua *ua) { return ua ? ua->my_status : PRESENCE_UNKNOWN; } /** * Set presence status of a User-Agent * * @param ua User-Agent object * @param status Presence status */ void ua_presence_status_set(struct ua *ua, const enum presence_status status) { if (!ua) return; ua->my_status = status; } /** * Get the outbound SIP proxy of a User-Agent * * @param ua User-Agent object * * @return Outbound SIP proxy uri */ const char *ua_outbound(const struct ua *ua) { /* NOTE: we pick the first outbound server, should be rotated? */ return ua ? ua->acc->outboundv[0] : NULL; } /** * Get the current call object of a User-Agent * * @param ua User-Agent object * * @return Current call, NULL if no active calls * * * Current call strategy: * * We can only have 1 current call. The current call is the one that was * added last (end of the list). */ struct call *ua_call(const struct ua *ua) { if (!ua) return NULL; return list_ledata(list_tail(&ua->calls)); } /** * Get the previous call * * @param ua User-Agent * * @return Previous call or NULL if none */ struct call *ua_prev_call(const struct ua *ua) { struct le *le; int prev = 0; if (!ua) return NULL; for (le = ua->calls.tail; le; le = le->prev) { if ( prev == 1) { struct call *call = le->data; return call; } if ( prev == 0) prev = 1; } return NULL; } /** * Print the user-agent debug information * * @param pf Print function * @param ua User-Agent object * * @return 0 if success, otherwise errorcode */ int ua_debug(struct re_printf *pf, const struct ua *ua) { struct le *le; int err; if (!ua) return 0; err = re_hprintf(pf, "--- %s ---\n", ua->acc->aor); err |= re_hprintf(pf, " nrefs: %u\n", mem_nrefs(ua)); err |= re_hprintf(pf, " cuser: %s\n", ua->cuser); err |= re_hprintf(pf, " pub-gruu: %s\n", ua->pub_gruu); err |= re_hprintf(pf, " af_media: %s\n", net_af2name(ua->af_media)); err |= re_hprintf(pf, " %H", ua_print_supported, ua); err |= account_debug(pf, ua->acc); for (le = ua->regl.head; le; le = le->next) err |= reg_debug(pf, le->data); return err; } /** * Print the user-agent information in JSON * * @param od User-Agent dict * @param ua User-Agent object * * @return 0 if success, otherwise errorcode */ int ua_state_json_api(struct odict *od, const struct ua *ua) { struct odict *reg = NULL; struct odict *cfg = NULL; struct le *le; size_t i = 0; int err = 0; if (!ua) return 0; err |= odict_alloc(®, 8); err |= odict_alloc(&cfg, 8); /* user-agent info */ err |= odict_entry_add(od, "cuser", ODICT_STRING, ua->cuser); err |= odict_entry_add(od, "selected_ua", ODICT_BOOL, ua == uag_current()); /* account info */ err |= account_json_api(od, cfg, ua->acc); if (err) warning("ua: failed to encode json account (%m)\n", err); /* registration info */ for (le = list_head(&ua->regl); le; le = le->next) { struct reg *regm = le->data; err |= reg_json_api(reg, regm); ++i; } if (i > 1) warning("ua: multiple registrations for one account"); err |= odict_entry_add(reg, "interval", ODICT_INT, (int64_t) ua->acc->regint); err |= odict_entry_add(reg, "q_value", ODICT_DOUBLE, ua->acc->regq); if (err) warning("ua: failed to encode json registration (%m)\n", err); /* package */ err |= odict_entry_add(od, "settings", ODICT_OBJECT, cfg); err |= odict_entry_add(od, "registration", ODICT_OBJECT, reg); if (err) warning("ua: failed to encode json package (%m)\n", err); mem_deref(cfg); mem_deref(reg); return err; } /* One instance */ static int add_transp_af(const struct sa *laddr) { struct sa local; int err = 0; if (str_isset(uag.cfg->local)) { err = sa_decode(&local, uag.cfg->local, str_len(uag.cfg->local)); if (err) { err = sa_set_str(&local, uag.cfg->local, 0); if (err) { warning("ua: decode failed: '%s'\n", uag.cfg->local); return err; } } if (!sa_isset(&local, SA_ADDR)) { uint16_t port = sa_port(&local); (void)sa_set_sa(&local, &laddr->u.sa); sa_set_port(&local, port); } if (sa_af(laddr) != sa_af(&local)) return 0; } else { sa_cpy(&local, laddr); sa_set_port(&local, 0); } if (uag.use_udp) err |= sip_transp_add(uag.sip, SIP_TRANSP_UDP, &local); if (uag.use_tcp) err |= sip_transp_add(uag.sip, SIP_TRANSP_TCP, &local); if (err) { warning("ua: SIP Transport failed: %m\n", err); return err; } #ifdef USE_TLS if (uag.use_tls) { /* Build our SSL context*/ if (!uag.tls) { const char *cert = NULL; if (str_isset(uag.cfg->cert)) { cert = uag.cfg->cert; info("SIP Certificate: %s\n", cert); } err = tls_alloc(&uag.tls, TLS_METHOD_SSLV23, cert, NULL); if (err) { warning("ua: tls_alloc() failed: %m\n", err); return err; } if (str_isset(uag.cfg->cafile)) { const char *ca = uag.cfg->cafile; info("ua: adding SIP CA: %s\n", ca); err = tls_add_ca(uag.tls, ca); if (err) { warning("ua: tls_add_ca() failed:" " %m\n", err); return err; } } } if (sa_isset(&local, SA_PORT)) sa_set_port(&local, sa_port(&local) + 1); err = sip_transp_add(uag.sip, SIP_TRANSP_TLS, &local, uag.tls); if (err) { warning("ua: SIP/TLS transport failed: %m\n", err); return err; } } #endif return err; } static int ua_add_transp(struct network *net) { int err = 0; if (sa_isset(net_laddr_af(net, AF_INET), SA_ADDR)) err |= add_transp_af(net_laddr_af(net, AF_INET)); #if HAVE_INET6 if (sa_isset(net_laddr_af(net, AF_INET6), SA_ADDR)) err |= add_transp_af(net_laddr_af(net, AF_INET6)); #endif return err; } static bool require_handler(const struct sip_hdr *hdr, const struct sip_msg *msg, void *arg) { struct ua *ua = arg; bool supported = false; size_t i; (void)msg; for (i=0; iextensionc; i++) { if (!pl_casecmp(&hdr->val, &ua->extensionv[i])) { supported = true; break; } } return !supported; } /* Handle incoming calls */ static void sipsess_conn_handler(const struct sip_msg *msg, void *arg) { struct config *config = conf_config(); const struct network *net = baresip_network(); const struct sip_hdr *hdr; int af_sdp; struct ua *ua; struct call *call = NULL; char to_uri[256]; int err; (void)arg; debug("ua: sipsess connect via %s %J --> %J\n", sip_transp_name(msg->tp), &msg->src, &msg->dst); ua = uag_find(&msg->uri.user); if (!ua) { warning("ua: %r: UA not found: %r\n", &msg->from.auri, &msg->uri.user); (void)sip_treply(NULL, uag_sip(), msg, 404, "Not Found"); return; } /* handle multiple calls */ if (config->call.max_calls && list_count(&ua->calls) + 1 > config->call.max_calls) { info("ua: rejected call from %r (maximum %d calls)\n", &msg->from.auri, config->call.max_calls); (void)sip_treply(NULL, uag.sip, msg, 486, "Max Calls"); return; } /* Handle Require: header, check for any required extensions */ hdr = sip_msg_hdr_apply(msg, true, SIP_HDR_REQUIRE, require_handler, ua); if (hdr) { info("ua: call from %r rejected with 420" " -- option-tag '%r' not supported\n", &msg->from.auri, &hdr->val); (void)sip_treplyf(NULL, NULL, uag.sip, msg, false, 420, "Bad Extension", "Unsupported: %r\r\n" "Content-Length: 0\r\n\r\n", &hdr->val); return; } /* Check if offered media AF is supported and available */ af_sdp = sdp_af_hint(msg->mb); if (af_sdp) { if (!net_af_enabled(net, af_sdp)) { warning("ua: SDP offer AF not supported (%s)\n", net_af2name(af_sdp)); af_sdp = 0; } else if (!sa_isset(net_laddr_af(net, af_sdp), SA_ADDR)) { warning("ua: SDP offer AF not available (%s)\n", net_af2name(af_sdp)); af_sdp = 0; } if (!af_sdp) { (void)sip_treply(NULL, uag_sip(), msg, 488, "Not Acceptable Here"); return; } } (void)pl_strcpy(&msg->to.auri, to_uri, sizeof(to_uri)); err = ua_call_alloc(&call, ua, VIDMODE_ON, msg, NULL, to_uri, true); if (err) { warning("ua: call_alloc: %m\n", err); goto error; } if (!list_isempty(&ua->hdr_filter)) { struct list hdrs; struct le *le; list_init(&hdrs); le = list_head(&ua->hdr_filter); while (le) { const struct sip_hdr *tmp_hdr; const struct ua_xhdr_filter *filter = le->data; le = le->next; tmp_hdr = sip_msg_xhdr(msg, filter->hdr_name); if (tmp_hdr) { char name[256]; pl_strcpy(&tmp_hdr->name, name, sizeof(name)); if (custom_hdrs_add(&hdrs, name, "%r", &tmp_hdr->val)) goto error; } } call_set_custom_hdrs(call, &hdrs); list_flush(&hdrs); } err = call_accept(call, uag.sock, msg); if (err) goto error; return; error: mem_deref(call); (void)sip_treply(NULL, uag.sip, msg, 500, "Call Error"); } static void ua_xhdr_filter_destructor(void *arg) { struct ua_xhdr_filter *filter = arg; mem_deref(filter->hdr_name); } /** * Add custom SIP header to filter for incoming calls * * @param ua User-Agent * @param hdr_name SIP Header name * * @return 0 if success, otherwise errorcode */ int ua_add_xhdr_filter(struct ua *ua, const char *hdr_name) { struct ua_xhdr_filter *filter; if (!ua) return EINVAL; filter = mem_zalloc(sizeof(*filter), ua_xhdr_filter_destructor); if (!filter) return ENOMEM; if (str_dup(&filter->hdr_name, hdr_name)) { mem_deref(filter); return ENOMEM; } list_append(&ua->hdr_filter, &filter->le, filter); return 0; } static bool sub_handler(const struct sip_msg *msg, void *arg) { struct ua *ua; (void)arg; ua = uag_find(&msg->uri.user); if (!ua) { warning("subscribe: no UA found for %r\n", &msg->uri.user); (void)sip_treply(NULL, uag_sip(), msg, 404, "Not Found"); return true; } if (uag.subh) uag.subh(msg, ua); return true; } #ifdef LIBRE_HAVE_SIPTRACE static void sip_trace_handler(bool tx, enum sip_transp tp, const struct sa *src, const struct sa *dst, const uint8_t *pkt, size_t len, void *arg) { (void)tx; (void)arg; re_printf("\x1b[36;1m" "#\n" "%s %J -> %J\n" "%b" "\x1b[;m\n" , sip_transp_name(tp), src, dst, pkt, len); } #endif /** * Initialise the User-Agents * * @param software SIP User-Agent string * @param udp Enable UDP transport * @param tcp Enable TCP transport * @param tls Enable TLS transport * * @return 0 if success, otherwise errorcode */ int ua_init(const char *software, bool udp, bool tcp, bool tls) { struct config *cfg = conf_config(); struct network *net = baresip_network(); uint32_t bsize; int err; if (!net) { warning("ua: no network\n"); return EINVAL; } uag.cfg = &cfg->sip; bsize = 16; uag.use_udp = udp; uag.use_tcp = tcp; uag.use_tls = tls; list_init(&uag.ual); err = sip_alloc(&uag.sip, net_dnsc(net), bsize, bsize, bsize, software, exit_handler, NULL); if (err) { warning("ua: sip stack failed: %m\n", err); goto out; } err = ua_add_transp(net); if (err) goto out; err = sip_listen(&uag.lsnr, uag.sip, true, request_handler, NULL); if (err) goto out; err = sipsess_listen(&uag.sock, uag.sip, bsize, sipsess_conn_handler, NULL); if (err) goto out; err = sipevent_listen(&uag.evsock, uag.sip, bsize, bsize, sub_handler, NULL); if (err) goto out; out: if (err) { warning("ua: init failed (%m)\n", err); ua_close(); } return err; } /** * Close all active User-Agents */ void ua_close(void) { uag.evsock = mem_deref(uag.evsock); uag.sock = mem_deref(uag.sock); uag.lsnr = mem_deref(uag.lsnr); uag.sip = mem_deref(uag.sip); uag.eprm = mem_deref(uag.eprm); #ifdef USE_TLS uag.tls = mem_deref(uag.tls); #endif list_flush(&uag.ual); list_flush(&uag.ehl); } /** * Stop all User-Agents * * @param forced True to force, otherwise false */ void ua_stop_all(bool forced) { struct le *le; unsigned ext_ref = 0; info("ua: stop all (forced=%d)\n", forced); /* check if someone else has grabbed a ref to ua */ le = uag.ual.head; while (le) { struct ua *ua = le->data; le = le->next; if (ua_destroy(ua) != 0) { ++ext_ref; } } if (ext_ref) { info("ua: in use (%u) by app module\n", ext_ref); uag.delayed_close = true; return; } if (forced) sipsess_close_all(uag.sock); sip_close(uag.sip, forced); } /** * Set the global UA exit handler. The exit handler will be called * asyncronously when the SIP stack has exited. * * @param exith Exit handler * @param arg Handler argument */ void uag_set_exit_handler(ua_exit_h *exith, void *arg) { uag.exith = exith; uag.arg = arg; } /** * Enable SIP message tracing * * @param enable True to enable, false to disable */ void uag_enable_sip_trace(bool enable) { #ifdef LIBRE_HAVE_SIPTRACE sip_set_trace_handler(uag.sip, enable ? sip_trace_handler : NULL); #else (void)enable; warning("no sip trace in libre\n"); #endif } /** * Reset the SIP transports for all User-Agents * * @param reg True to reset registration * @param reinvite True to update active calls * * @return 0 if success, otherwise errorcode */ int uag_reset_transp(bool reg, bool reinvite) { struct network *net = baresip_network(); struct le *le; int err; /* Update SIP transports */ sip_transp_flush(uag.sip); (void)net_check(net); err = ua_add_transp(net); if (err) return err; /* Re-REGISTER all User-Agents */ for (le = uag.ual.head; le; le = le->next) { struct ua *ua = le->data; if (reg && ua->acc->regint) { err |= ua_register(ua); } /* update all active calls */ if (reinvite) { struct le *lec; for (lec = ua->calls.head; lec; lec = lec->next) { struct call *call = lec->data; const struct sa *laddr; laddr = net_laddr_af(net, call_af(call)); err |= call_reset_transp(call, laddr); } } } return err; } /** * Print all calls for a given User-Agent * * @param pf Print handler for debug output * @param ua User-Agent * * @return 0 if success, otherwise errorcode */ int ua_print_calls(struct re_printf *pf, const struct ua *ua) { uint32_t n, count=0; uint32_t linenum; int err = 0; if (!ua) { err |= re_hprintf(pf, "\n--- No active calls ---\n"); return err; } n = list_count(&ua->calls); err |= re_hprintf(pf, "\n--- Active calls (%u) ---\n", n); for (linenum=CALL_LINENUM_MIN; linenumcalls, linenum); if (call) { ++count; err |= re_hprintf(pf, "%s %H\n", call == ua_call(ua) ? ">" : " ", call_info, call); } if (count >= n) break; } err |= re_hprintf(pf, "\n"); return err; } /** * Get the global SIP Stack * * @return SIP Stack */ struct sip *uag_sip(void) { return uag.sip; } /** * Get the global SIP Session socket * * @return SIP Session socket */ struct sipsess_sock *uag_sipsess_sock(void) { return uag.sock; } /** * Get the global SIP Event socket * * @return SIP Event socket */ struct sipevent_sock *uag_sipevent_sock(void) { return uag.evsock; } /** * Find the correct UA from the contact user * * @param cuser Contact username * * @return Matching UA if found, NULL if not found */ struct ua *uag_find(const struct pl *cuser) { struct le *le; for (le = uag.ual.head; le; le = le->next) { struct ua *ua = le->data; if (0 == pl_strcasecmp(cuser, ua->cuser)) return ua; } /* Try also matching by AOR, for better interop */ for (le = uag.ual.head; le; le = le->next) { struct ua *ua = le->data; if (0 == pl_casecmp(cuser, &ua->acc->luri.user)) return ua; } /* Last resort, try any catchall UAs */ for (le = uag.ual.head; le; le = le->next) { struct ua *ua = le->data; if (ua->catchall) return ua; } return NULL; } /** * Find a User-Agent (UA) from an Address-of-Record (AOR) * * @param aor Address-of-Record string * * @return User-Agent (UA) if found, otherwise NULL */ struct ua *uag_find_aor(const char *aor) { struct le *le; for (le = uag.ual.head; le; le = le->next) { struct ua *ua = le->data; if (str_isset(aor) && str_cmp(ua->acc->aor, aor)) continue; return ua; } return NULL; } /** * Find a User-Agent (UA) which has certain address parameter and/or value * * @param name SIP Address parameter name * @param value SIP Address parameter value (optional) * * @return User-Agent (UA) if found, otherwise NULL */ struct ua *uag_find_param(const char *name, const char *value) { struct le *le; for (le = uag.ual.head; le; le = le->next) { struct ua *ua = le->data; struct sip_addr *laddr = account_laddr(ua->acc); struct pl val; if (value) { if (0 == msg_param_decode(&laddr->params, name, &val) && 0 == pl_strcasecmp(&val, value)) { return ua; } } else { if (0 == msg_param_exists(&laddr->params, name, &val)) return ua; } } return NULL; } /** * Get the contact user/uri of a User-Agent (UA) * * If the Public GRUU is set, it will be returned. * Otherwise the local contact-user (cuser) will be returned. * * @param ua User-Agent * * @return Contact user */ const char *ua_cuser(const struct ua *ua) { if (!ua) return NULL; if (str_isset(ua->pub_gruu)) return ua->pub_gruu; return ua->cuser; } /** * Get the local contact username * * @param ua User-Agent * * @return Local contact username */ const char *ua_local_cuser(const struct ua *ua) { return ua ? ua->cuser : NULL; } /** * Get Account of a User-Agent * * @param ua User-Agent * * @return Pointer to UA's account */ struct account *ua_account(const struct ua *ua) { return ua ? ua->acc : NULL; } /** * Set Public GRUU of a User-Agent (UA) * * @param ua User-Agent * @param pval Public GRUU */ void ua_pub_gruu_set(struct ua *ua, const struct pl *pval) { if (!ua) return; ua->pub_gruu = mem_deref(ua->pub_gruu); (void)pl_strdup(&ua->pub_gruu, pval); } /** * Get the list of User-Agents * * @return List of User-Agents (struct ua) */ struct list *uag_list(void) { return &uag.ual; } /** * Print list of methods allowed by the UA * * @param pf Print function * @param ua User-Agent * * @return 0 if success, otherwise errorcode */ int ua_print_allowed(struct re_printf *pf, const struct ua *ua) { int err; if (!ua || !ua->acc) return 0; err = re_hprintf(pf, "INVITE,ACK,BYE,CANCEL,OPTIONS," "NOTIFY,SUBSCRIBE,INFO,MESSAGE"); if (ua->acc->refer) err |= re_hprintf(pf, ",REFER"); return err; } /** * Print the supported extensions * * @param pf Print function * @param ua User-Agent object * * @return 0 if success, otherwise errorcode */ int ua_print_supported(struct re_printf *pf, const struct ua *ua) { size_t i; int err; if (!ua) return 0; err = re_hprintf(pf, "Supported:"); for (i=0; iextensionc; i++) { err |= re_hprintf(pf, "%s%r", i==0 ? " " : ",", &ua->extensionv[i]); } err |= re_hprintf(pf, "\r\n"); return err; } /** * Get the list of call objects * * @param ua User-Agent * * @return List of call objects (struct call) */ struct list *ua_calls(const struct ua *ua) { return ua ? (struct list *)&ua->calls : NULL; } static void eh_destructor(void *arg) { struct ua_eh *eh = arg; list_unlink(&eh->le); } /** * Register a User-Agent event handler * * @param h Event handler * @param arg Handler argument * * @return 0 if success, otherwise errorcode */ int uag_event_register(ua_event_h *h, void *arg) { struct ua_eh *eh; if (!h) return EINVAL; uag_event_unregister(h); eh = mem_zalloc(sizeof(*eh), eh_destructor); if (!eh) return ENOMEM; eh->h = h; eh->arg = arg; list_append(&uag.ehl, &eh->le, eh); return 0; } /** * Unregister a User-Agent event handler * * @param h Event handler */ void uag_event_unregister(ua_event_h *h) { struct le *le; for (le = uag.ehl.head; le; le = le->next) { struct ua_eh *eh = le->data; if (eh->h == h) { mem_deref(eh); break; } } } /** * Set the handler to receive incoming SIP SUBSCRIBE messages * * @param subh Subscribe handler */ void uag_set_sub_handler(sip_msg_h *subh) { uag.subh = subh; } /** * Set the current User-Agent * * @param ua User-Agent to set as current */ void uag_current_set(struct ua *ua) { uag.ua_cur = ua; } /** * Get the current User-Agent * * @return Current User-Agent, NULL if none */ struct ua *uag_current(void) { if (list_isempty(uag_list())) return NULL; return uag.ua_cur; } /** * Set the preferred address family for media * * @param ua User-Agent * @param af_media Address family (e.g. AF_INET, AF_INET6) */ void ua_set_media_af(struct ua *ua, int af_media) { if (!ua) return; ua->af_media = af_media; } /** * Enable handling of all inbound requests, even if * the request uri is not matching. * * @param ua User-Agent * @param enabled True to enable, false to disable */ void ua_set_catchall(struct ua *ua, bool enabled) { if (!ua) return; ua->catchall = enabled; } /** * Set extra parameters to use for all SIP Accounts * * @param eprm Extra parameters * * @return 0 if success, otherwise errorcode */ int uag_set_extra_params(const char *eprm) { uag.eprm = mem_deref(uag.eprm); if (eprm) return str_dup(&uag.eprm, eprm); return 0; } /** * Set a list of custom SIP headers * * @param ua User-Agent * @param custom_headers List of custom SIP headers (struct sip_hdr) * * @return 0 if success, otherwise errorcode */ int ua_set_custom_hdrs(struct ua *ua, struct list *custom_headers) { struct le *le; int err; if (!ua) return EINVAL; list_flush(&ua->custom_hdrs); LIST_FOREACH(custom_headers, le) { struct sip_hdr *hdr = le->data; char *buf; err = pl_strdup(&buf, &hdr->name); if (err) return err; err = custom_hdrs_add(&ua->custom_hdrs, buf, "%r", &hdr->val); mem_deref(buf); if (err) return err; } return 0; } baresip-1.0.0/src/ui.c000066400000000000000000000102411372575704200145170ustar00rootroot00000000000000/** * @file ui.c User Interface * * Copyright (C) 2010 Creytiv.com */ #include #include #include #include "core.h" static int stdout_handler(const char *p, size_t size, void *arg) { (void)arg; if (1 != fwrite(p, size, 1, stdout)) return ENOMEM; return 0; } /** * Register a new User-Interface (UI) module * * @param uis UI Subsystem * @param ui The User-Interface (UI) module to register */ void ui_register(struct ui_sub *uis, struct ui *ui) { if (!uis || !ui) return; list_append(&uis->uil, &ui->le, ui); debug("ui: %s\n", ui->name); } /** * Un-register a User-Interface (UI) module * * @param ui The User-Interface (UI) module to un-register */ void ui_unregister(struct ui *ui) { if (!ui) return; list_unlink(&ui->le); } /** * Send an input key to the UI subsystem, with a print function for response * * @param uis UI Subsystem * @param key Input character * @param pf Print function for the response */ void ui_input_key(struct ui_sub *uis, char key, struct re_printf *pf) { if (!uis) return; (void)cmd_process(baresip_commands(), &uis->uictx, key, pf, NULL); } /** * Send an input string to the UI subsystem * * @param str Input string */ void ui_input_str(const char *str) { struct re_printf pf; struct pl pl; if (!str) return; pf.vph = stdout_handler; pf.arg = NULL; pl_set_str(&pl, str); (void)ui_input_pl(&pf, &pl); } /** * Send an input pointer-length string to the UI subsystem * * @param pf Print function * @param pl Input pointer-length string * * @return 0 if success, otherwise errorcode */ int ui_input_pl(struct re_printf *pf, const struct pl *pl) { struct cmd_ctx *ctx = NULL; struct commands *commands = baresip_commands(); size_t i; int err = 0; if (!pf || !pl) return EINVAL; for (i=0; il; i++) { err |= cmd_process(commands, &ctx, pl->p[i], pf, NULL); } if (pl->l > 1 && ctx) err |= cmd_process(commands, &ctx, '\n', pf, NULL); return err; } /** * Send a long command with arguments to the UI subsystem. * The slash prefix is optional. * * @param pf Print function for the response * @param pl Long command with or without '/' prefix * * @return 0 if success, otherwise errorcode */ int ui_input_long_command(struct re_printf *pf, const struct pl *pl) { size_t offset; int err; if (!pl) return EINVAL; /* strip the prefix, if present */ if (pl->l > 1 && pl->p[0] == '/') offset = 1; else offset = 0; err = cmd_process_long(baresip_commands(), pl->p + offset, pl->l - offset, pf, NULL); return err; } /** * Send output to all modules registered in the UI subsystem * * @param uis UI Subsystem * @param fmt Formatted output string */ void ui_output(struct ui_sub *uis, const char *fmt, ...) { char buf[512]; struct le *le; va_list ap; int n; if (!uis) return; va_start(ap, fmt); n = re_vsnprintf(buf, sizeof(buf), fmt, ap); va_end(ap); if (n < 0) return; for (le = uis->uil.head; le; le = le->next) { const struct ui *ui = le->data; if (ui->outputh) ui->outputh(buf); } } /** * Reset the state of the UI subsystem, free resources * * @param uis UI Subsystem */ void ui_reset(struct ui_sub *uis) { if (!uis) return; uis->uictx = mem_deref(uis->uictx); } /** * Check if the UI is in editor mode * * @param uis UI Subsystem * * @return True if editing, otherwise false */ bool ui_isediting(const struct ui_sub *uis) { if (!uis) return false; return uis->uictx != NULL; } /** * Prompt the user interactively for a password * * NOTE: This function is blocking and should not be called from * any re_main event handlers. * * @param passwordp Pointer to allocated password string * * @return 0 if success, otherwise errorcode */ int ui_password_prompt(char **passwordp) { char pwd[64]; char *nl; int err; if (!passwordp) return EINVAL; /* note: blocking UI call */ fgets(pwd, sizeof(pwd), stdin); pwd[sizeof(pwd) - 1] = '\0'; nl = strchr(pwd, '\n'); if (nl == NULL) { (void)re_printf("Invalid password (0 - 63 characters" " followed by newline)\n"); return EINVAL; } *nl = '\0'; err = str_dup(passwordp, pwd); if (err) return err; return 0; } baresip-1.0.0/src/vidcodec.c000066400000000000000000000042641372575704200156720ustar00rootroot00000000000000/** * @file vidcodec.c Video Codec * * Copyright (C) 2010 Creytiv.com */ #include #include /** * Register a Video Codec * * @param vidcodecl List of video-codecs * @param vc Video Codec */ void vidcodec_register(struct list *vidcodecl, struct vidcodec *vc) { if (!vidcodecl || !vc) return; list_append(vidcodecl, &vc->le, vc); info("vidcodec: %s\n", vc->name); } /** * Unregister a Video Codec * * @param vc Video Codec */ void vidcodec_unregister(struct vidcodec *vc) { if (!vc) return; list_unlink(&vc->le); } /** * Find a Video Codec by name * * @param vidcodecl List of video-codecs * @param name Name of the Video Codec to find * @param variant Codec Variant * * @return Matching Video Codec if found, otherwise NULL */ const struct vidcodec *vidcodec_find(const struct list *vidcodecl, const char *name, const char *variant) { struct le *le; for (le=list_head(vidcodecl); le; le=le->next) { struct vidcodec *vc = le->data; if (name && 0 != str_casecmp(name, vc->name)) continue; if (variant && 0 != str_casecmp(variant, vc->variant)) continue; return vc; } return NULL; } /** * Find a Video Encoder by name * * @param vidcodecl List of video-codecs * @param name Name of the Video Encoder to find * * @return Matching Video Encoder if found, otherwise NULL */ const struct vidcodec *vidcodec_find_encoder(const struct list *vidcodecl, const char *name) { struct le *le; for (le=list_head(vidcodecl); le; le=le->next) { struct vidcodec *vc = le->data; if (name && 0 != str_casecmp(name, vc->name)) continue; if (vc->ench) return vc; } return NULL; } /** * Find a Video Decoder by name * * @param vidcodecl List of video-codecs * @param name Name of the Video Decoder to find * * @return Matching Video Decoder if found, otherwise NULL */ const struct vidcodec *vidcodec_find_decoder(const struct list *vidcodecl, const char *name) { struct le *le; for (le=list_head(vidcodecl); le; le=le->next) { struct vidcodec *vc = le->data; if (name && 0 != str_casecmp(name, vc->name)) continue; if (vc->dech) return vc; } return NULL; } baresip-1.0.0/src/video.c000066400000000000000000000775571372575704200152370ustar00rootroot00000000000000/** * @file src/video.c Video stream * * Copyright (C) 2010 Creytiv.com * * \ref GenericVideoStream */ #include #include #include #include #include #include "core.h" /** Magic number */ #define MAGIC 0x00070d10 #include "magic.h" /** Video transmit parameters */ enum { MEDIA_POLL_RATE = 250, /**< in [Hz] */ BURST_MAX = 8192, /**< in bytes */ RTP_PRESZ = 4 + RTP_HEADER_SIZE, /**< TURN and RTP header */ RTP_TRAILSZ = 12 + 4, /**< SRTP/SRTCP trailer */ PICUP_INTERVAL = 500, }; /** * \page GenericVideoStream Generic Video Stream * * Implements a generic video stream. The application can allocate multiple * instances of a video stream, mapping it to a particular SDP media line. * The video object has a Video Display and Source, and a video encoder * and decoder. A particular video object is mapped to a generic media * stream object. * *
 *            recv  send
 *              |    /|\
 *             \|/    |
 *            .---------.    .-------.
 *            |  video  |--->|encoder|
 *            |         |    |-------|
 *            | object  |--->|decoder|
 *            '---------'    '-------'
 *              |    /|\
 *              |     |
 *             \|/    |
 *        .-------.  .-------.
 *        |Video  |  |Video  |
 *        |Display|  |Source |
 *        '-------'  '-------'
 *
*/ /** * Video stream - transmitter/encoder direction \verbatim Processing encoder pipeline: . .--------. .- - - - -. .---------. .---------. | ._O_. | | ! ! | | | | | |___|-->| vidsrc |-->! vidconv !-->| vidfilt |-->| encoder |---> RTP | | | ! ! | | | | ' '--------' '- - - - -' '---------' '---------' (optional) \endverbatim */ struct vtx { struct video *video; /**< Parent */ const struct vidcodec *vc; /**< Current Video encoder */ struct videnc_state *enc; /**< Video encoder state */ struct vidsrc_prm vsrc_prm; /**< Video source parameters */ struct vidsz vsrc_size; /**< Video source size */ struct vidsrc_st *vsrc; /**< Video source */ struct lock *lock_enc; /**< Lock for encoder */ struct vidframe *frame; /**< Source frame */ struct lock *lock_tx; /**< Protect the sendq */ struct list sendq; /**< Tx-Queue (struct vidqent) */ struct tmr tmr_rtp; /**< Timer for sending RTP */ unsigned skipc; /**< Number of frames skipped */ struct list filtl; /**< Filters in encoding order */ enum vidfmt fmt; /**< Outgoing pixel format */ char device[128]; /**< Source device name */ uint32_t ts_offset; /**< Random timestamp offset */ bool picup; /**< Send picture update */ int frames; /**< Number of frames sent */ double efps; /**< Estimated frame-rate */ uint64_t ts_base; /**< First RTP timestamp sent */ uint64_t ts_last; /**< Last RTP timestamp sent */ /** Statistics */ struct { uint64_t src_frames; /**< Total frames from vidsrc */ } stats; }; /** * Video stream - receiver/decoder direction \verbatim Processing decoder pipeline: .~~~~~~~~. .--------. .---------. .---------. | _o_ | | | | | | | | | |<--| vidisp |<--| vidfilt |<--| decoder |<--- RTP | /'\ | | | | | | | '~~~~~~~~' '--------' '---------' '---------' \endverbatim */ struct vrx { struct video *video; /**< Parent */ const struct vidcodec *vc; /**< Current video decoder */ struct viddec_state *dec; /**< Video decoder state */ struct vidisp_prm vidisp_prm; /**< Video display parameters */ struct vidisp_st *vidisp; /**< Video display */ struct lock *lock; /**< Lock for decoder */ struct list filtl; /**< Filters in decoding order */ struct tmr tmr_picup; /**< Picture update timer */ struct vidsz size; /**< Incoming video resolution */ enum vidfmt fmt; /**< Incoming pixel format */ enum vidorient orient; /**< Display orientation */ char device[128]; /**< Display device name */ int pt_rx; /**< Incoming RTP payload type */ int frames; /**< Number of frames received */ double efps; /**< Estimated frame-rate */ unsigned n_intra; /**< Intra-frames decoded */ unsigned n_picup; /**< Picture updates sent */ struct timestamp_recv ts_recv; /**< Receive timestamp state */ /** Statistics */ struct { uint64_t disp_frames; /** Total frames displayed */ } stats; }; /** Generic Video stream */ struct video { MAGIC_DECL /**< Magic number for debugging */ struct config_video cfg;/**< Video configuration */ struct stream *strm; /**< Generic media stream */ struct vtx vtx; /**< Transmit/encoder direction */ struct vrx vrx; /**< Receive/decoder direction */ struct tmr tmr; /**< Timer for frame-rate estimation */ bool started; /**< True if video is started */ char *peer; /**< Peer URI */ bool nack_pli; /**< Send NACK/PLI to peer */ video_err_h *errh; /**< Error handler */ void *arg; /**< Error handler argument */ }; struct vidqent { struct le le; struct sa dst; bool marker; uint8_t pt; uint32_t ts; struct mbuf *mb; }; static void request_picture_update(struct vrx *vrx); static void vidqent_destructor(void *arg) { struct vidqent *qent = arg; list_unlink(&qent->le); mem_deref(qent->mb); } static int vidqent_alloc(struct vidqent **qentp, bool marker, uint8_t pt, uint32_t ts, const uint8_t *hdr, size_t hdr_len, const uint8_t *pld, size_t pld_len) { struct vidqent *qent; int err = 0; if (!qentp || !pld) return EINVAL; qent = mem_zalloc(sizeof(*qent), vidqent_destructor); if (!qent) return ENOMEM; qent->marker = marker; qent->pt = pt; qent->ts = ts; qent->mb = mbuf_alloc(RTP_PRESZ + hdr_len + pld_len + RTP_TRAILSZ); if (!qent->mb) { err = ENOMEM; goto out; } qent->mb->pos = qent->mb->end = RTP_PRESZ; if (hdr) (void)mbuf_write_mem(qent->mb, hdr, hdr_len); (void)mbuf_write_mem(qent->mb, pld, pld_len); qent->mb->pos = RTP_PRESZ; out: if (err) mem_deref(qent); else *qentp = qent; return err; } static void vidqueue_poll(struct vtx *vtx, uint64_t jfs, uint64_t prev_jfs) { size_t burst, sent; uint64_t bandwidth_kbps; struct le *le; if (!vtx) return; lock_write_get(vtx->lock_tx); le = vtx->sendq.head; if (!le) goto out; /* * time [ms] * bitrate [kbps] / 8 = bytes */ bandwidth_kbps = vtx->video->cfg.bitrate / 1000; burst = (size_t)((1 + jfs - prev_jfs) * bandwidth_kbps / 4); burst = min(burst, BURST_MAX); sent = 0; while (le) { struct vidqent *qent = le->data; sent += mbuf_get_left(qent->mb); stream_send(vtx->video->strm, false, qent->marker, qent->pt, qent->ts, qent->mb); le = le->next; mem_deref(qent); if (sent > burst) { break; } } out: lock_rel(vtx->lock_tx); } static void rtp_tmr_handler(void *arg) { struct vtx *vtx = arg; uint64_t pjfs; pjfs = vtx->tmr_rtp.jfs; tmr_start(&vtx->tmr_rtp, 1000/MEDIA_POLL_RATE, rtp_tmr_handler, vtx); vidqueue_poll(vtx, vtx->tmr_rtp.jfs, pjfs); } static void video_destructor(void *arg) { struct video *v = arg; struct vtx *vtx = &v->vtx; struct vrx *vrx = &v->vrx; /* transmit */ lock_write_get(vtx->lock_tx); list_flush(&vtx->sendq); lock_rel(vtx->lock_tx); mem_deref(vtx->lock_tx); tmr_cancel(&vtx->tmr_rtp); mem_deref(vtx->vsrc); lock_write_get(vtx->lock_enc); mem_deref(vtx->frame); mem_deref(vtx->enc); list_flush(&vtx->filtl); lock_rel(vtx->lock_enc); mem_deref(vtx->lock_enc); /* receive */ tmr_cancel(&vrx->tmr_picup); lock_write_get(vrx->lock); mem_deref(vrx->dec); mem_deref(vrx->vidisp); list_flush(&vrx->filtl); lock_rel(vrx->lock); mem_deref(vrx->lock); tmr_cancel(&v->tmr); mem_deref(v->strm); mem_deref(v->peer); } static double get_fps(const struct video *v) { const char *attr; /* RFC4566 */ attr = sdp_media_rattr(stream_sdpmedia(v->strm), "framerate"); if (attr) { return atof(attr); } else return v->cfg.fps; } static int packet_handler(bool marker, uint64_t ts, const uint8_t *hdr, size_t hdr_len, const uint8_t *pld, size_t pld_len, void *arg) { struct vtx *vtx = arg; struct stream *strm = vtx->video->strm; struct vidqent *qent; uint32_t rtp_ts; int err; MAGIC_CHECK(vtx->video); if (!vtx->ts_base) vtx->ts_base = ts; vtx->ts_last = ts; /* add random timestamp offset */ rtp_ts = vtx->ts_offset + (ts & 0xffffffff); err = vidqent_alloc(&qent, marker, strm->pt_enc, rtp_ts, hdr, hdr_len, pld, pld_len); if (err) return err; lock_write_get(vtx->lock_tx); qent->dst = *sdp_media_raddr(strm->sdp); list_append(&vtx->sendq, &qent->le, qent); lock_rel(vtx->lock_tx); return err; } /** * Encode video and send via RTP stream * * @note This function has REAL-TIME properties * * @param vtx Video transmit object * @param frame Video frame to send * @param timestamp Frame timestamp in VIDEO_TIMEBASE units */ static void encode_rtp_send(struct vtx *vtx, struct vidframe *frame, uint64_t timestamp) { struct le *le; int err = 0; bool sendq_empty; if (!vtx->enc) return; lock_write_get(vtx->lock_tx); sendq_empty = (vtx->sendq.head == NULL); lock_rel(vtx->lock_tx); if (!sendq_empty) { ++vtx->skipc; return; } lock_write_get(vtx->lock_enc); /* Convert image */ if (frame->fmt != (enum vidfmt)vtx->video->cfg.enc_fmt) { vtx->vsrc_size = frame->size; if (!vtx->frame) { err = vidframe_alloc(&vtx->frame, vtx->video->cfg.enc_fmt, &vtx->vsrc_size); if (err) goto out; } vidconv(vtx->frame, frame, 0); frame = vtx->frame; } /* Process video frame through all Video Filters */ for (le = vtx->filtl.head; le; le = le->next) { struct vidfilt_enc_st *st = le->data; if (st->vf && st->vf->ench) err |= st->vf->ench(st, frame, ×tamp); } if (err) goto out; if (frame) vtx->fmt = frame->fmt; /* Encode the whole picture frame */ err = vtx->vc->ench(vtx->enc, vtx->picup, frame, timestamp); if (err) goto out; vtx->picup = false; out: lock_rel(vtx->lock_enc); } /** * Read frames from video source * * @param frame Video frame * @param timestamp Frame timestamp in VIDEO_TIMEBASE units * @param arg Handler argument * * @note This function has REAL-TIME properties */ static void vidsrc_frame_handler(struct vidframe *frame, uint64_t timestamp, void *arg) { struct vtx *vtx = arg; MAGIC_CHECK(vtx->video); lock_write_get(vtx->lock_enc); ++vtx->frames; lock_rel(vtx->lock_enc); ++vtx->stats.src_frames; /* Encode and send */ encode_rtp_send(vtx, frame, timestamp); } static void vidsrc_error_handler(int err, void *arg) { struct vtx *vtx = arg; MAGIC_CHECK(vtx->video); warning("video: video-source error: %m\n", err); vtx->vsrc = mem_deref(vtx->vsrc); } static int vtx_alloc(struct vtx *vtx, struct video *video) { int err; err = lock_alloc(&vtx->lock_enc); err |= lock_alloc(&vtx->lock_tx); if (err) return err; tmr_init(&vtx->tmr_rtp); vtx->video = video; /* The initial value of the timestamp SHOULD be random */ vtx->ts_offset = rand_u16(); str_ncpy(vtx->device, video->cfg.src_dev, sizeof(vtx->device)); tmr_start(&vtx->tmr_rtp, 1, rtp_tmr_handler, vtx); vtx->fmt = (enum vidfmt)-1; return err; } static int vrx_alloc(struct vrx *vrx, struct video *video) { int err; err = lock_alloc(&vrx->lock); if (err) return err; vrx->video = video; vrx->pt_rx = -1; vrx->orient = VIDORIENT_PORTRAIT; str_ncpy(vrx->device, video->cfg.disp_dev, sizeof(vrx->device)); vrx->fmt = (enum vidfmt)-1; return err; } static void picup_tmr_handler(void *arg) { struct vrx *vrx = arg; MAGIC_CHECK(vrx->video); request_picture_update(vrx); } static void request_picture_update(struct vrx *vrx) { struct video *v = vrx->video; if (tmr_isrunning(&vrx->tmr_picup)) return; tmr_start(&vrx->tmr_picup, PICUP_INTERVAL, picup_tmr_handler, vrx); /* send RTCP FIR to peer */ stream_send_fir(v->strm, v->nack_pli); ++vrx->n_picup; } static void update_rtp_timestamp(struct timestamp_recv *tsr, uint32_t rtp_ts) { int wrap; if (tsr->is_set) { wrap = timestamp_wrap(rtp_ts, tsr->last); switch (wrap) { case -1: info("video: rtp timestamp wraps backwards" " (delta = %d) -- discard\n", (int32_t)(tsr->last - rtp_ts)); return; case 0: break; case 1: ++tsr->num_wraps; break; default: break; } } else { timestamp_set(tsr, rtp_ts); } tsr->last = rtp_ts; } /** * Decode incoming RTP packets using the Video decoder * * NOTE: mb=NULL if no packet received * * @param vrx Video receive object * @param hdr RTP Header * @param mb Buffer with RTP payload * * @return 0 if success, otherwise errorcode */ static int video_stream_decode(struct vrx *vrx, const struct rtp_header *hdr, struct mbuf *mb) { struct video *v = vrx->video; struct vidframe *frame_filt = NULL; struct vidframe frame_store, *frame = &frame_store; struct le *le; uint64_t timestamp; bool intra; int err = 0; if (!hdr || !mbuf_get_left(mb)) return 0; lock_write_get(vrx->lock); /* No decoder set */ if (!vrx->dec) { warning("video: No video decoder!\n"); goto out; } update_rtp_timestamp(&vrx->ts_recv, hdr->ts); /* convert the RTP timestamp to VIDEO_TIMEBASE timestamp */ timestamp = video_calc_timebase_timestamp( timestamp_calc_extended(vrx->ts_recv.num_wraps, vrx->ts_recv.last)); frame->data[0] = NULL; err = vrx->vc->dech(vrx->dec, frame, &intra, hdr->m, hdr->seq, mb); if (err) { if (err != EPROTO) { warning("video: %s decode error" " (seq=%u, %u bytes): %m\n", vrx->vc->name, hdr->seq, mbuf_get_left(mb), err); } request_picture_update(vrx); goto out; } if (intra) { tmr_cancel(&vrx->tmr_picup); ++vrx->n_intra; } /* Got a full picture-frame? */ if (!vidframe_isvalid(frame)) goto out; if (!vrx->size.w) { info("video: receiving with resolution %u x %u" " and format '%s'\n", frame->size.w, frame->size.h, vidfmt_name(frame->fmt)); } vrx->size = frame->size; vrx->fmt = frame->fmt; if (!list_isempty(&vrx->filtl)) { err = vidframe_alloc(&frame_filt, frame->fmt, &frame->size); if (err) goto out; vidframe_copy(frame_filt, frame); frame = frame_filt; } /* Process video frame through all Video Filters */ for (le = vrx->filtl.head; le; le = le->next) { struct vidfilt_dec_st *st = le->data; if (st->vf && st->vf->dech) err |= st->vf->dech(st, frame, ×tamp); } ++vrx->stats.disp_frames; err = vidisp_display(vrx->vidisp, v->peer, frame, timestamp); frame_filt = mem_deref(frame_filt); if (err == ENODEV) { warning("video: video-display was closed\n"); vrx->vidisp = mem_deref(vrx->vidisp); lock_rel(vrx->lock); if (v->errh) { v->errh(err, "display closed", v->arg); } return err; } ++vrx->frames; out: lock_rel(vrx->lock); return err; } static int update_payload_type(struct video *v, uint8_t pt_old, uint8_t pt_new) { const struct sdp_format *lc; lc = sdp_media_lformat(stream_sdpmedia(v->strm), pt_new); if (!lc) return ENOENT; if (pt_old != (uint8_t)-1) { info("Video decoder changed payload %u -> %u\n", pt_old, pt_new); } v->vrx.pt_rx = pt_new; return video_decoder_set(v, lc->data, lc->pt, lc->rparams); } /* Handle incoming stream data from the network */ static void stream_recv_handler(const struct rtp_header *hdr, struct rtpext *extv, size_t extc, struct mbuf *mb, unsigned lostc, void *arg) { struct video *v = arg; int err; (void)extv; (void)extc; MAGIC_CHECK(v); /* in case of packet loss, we need to receive a new keyframe */ if (lostc) request_picture_update(&v->vrx); if (!mb) goto out; /* Video payload-type changed? */ if (hdr->pt == v->vrx.pt_rx) goto out; err = update_payload_type(v, v->vrx.pt_rx, hdr->pt); if (err) return; out: (void)video_stream_decode(&v->vrx, hdr, mb); } static void rtcp_handler(struct stream *strm, struct rtcp_msg *msg, void *arg) { struct video *v = arg; (void)strm; MAGIC_CHECK(v); switch (msg->hdr.pt) { case RTCP_FIR: v->vtx.picup = true; break; case RTCP_PSFB: if (msg->hdr.count == RTCP_PSFB_PLI) v->vtx.picup = true; break; case RTCP_RTPFB: if (msg->hdr.count == RTCP_RTPFB_GNACK) v->vtx.picup = true; break; default: break; } } static int vtx_print_pipeline(struct re_printf *pf, const struct vtx *vtx) { struct le *le; struct vidsrc *vs; int err; if (!vtx) return 0; vs = vidsrc_get(vtx->vsrc); err = re_hprintf(pf, "video tx pipeline: %10s", vs ? vs->name : "src"); for (le = list_head(&vtx->filtl); le; le = le->next) { struct vidfilt_enc_st *st = le->data; if (st->vf->ench) err |= re_hprintf(pf, " ---> %s", st->vf->name); } err |= re_hprintf(pf, " ---> %s\n", vtx->vc ? vtx->vc->name : "encoder"); return err; } static int vrx_print_pipeline(struct re_printf *pf, const struct vrx *vrx) { struct le *le; struct vidisp *vd; int err; if (!vrx) return 0; vd = vidisp_get(vrx->vidisp); err = re_hprintf(pf, "video rx pipeline: %10s", vd ? vd->name : "disp"); for (le = list_head(&vrx->filtl); le; le = le->next) { struct vidfilt_dec_st *st = le->data; if (st->vf->dech) err |= re_hprintf(pf, " <--- %s", st->vf->name); } err |= re_hprintf(pf, " <--- %s\n", vrx->vc ? vrx->vc->name : "decoder"); return err; } /** * Allocate a video stream * * @param vp Pointer to allocated video stream object * @param streaml List of streams * @param stream_prm Stream parameters * @param cfg Global configuration * @param sdp_sess SDP Session * @param label SDP label * @param mnat Media NAT (optional) * @param mnat_sess Media NAT session (optional) * @param menc Media Encryption (optional) * @param menc_sess Media Encryption session (optional) * @param content SDP content attribute * @param vidcodecl List of video codecs * @param vidfiltl List of video filters * @param offerer True if SDP offerer, false if SDP answerer * @param errh Error handler * @param arg Handler argument * * @return 0 if success, otherwise errorcode */ int video_alloc(struct video **vp, struct list *streaml, const struct stream_param *stream_prm, const struct config *cfg, struct sdp_session *sdp_sess, int label, const struct mnat *mnat, struct mnat_sess *mnat_sess, const struct menc *menc, struct menc_sess *menc_sess, const char *content, const struct list *vidcodecl, const struct list *vidfiltl, bool offerer, video_err_h *errh, void *arg) { struct video *v; struct le *le; int err = 0; if (!vp || !cfg) return EINVAL; v = mem_zalloc(sizeof(*v), video_destructor); if (!v) return ENOMEM; MAGIC_INIT(v); v->cfg = cfg->video; tmr_init(&v->tmr); err = stream_alloc(&v->strm, streaml, stream_prm, &cfg->avt, sdp_sess, MEDIA_VIDEO, label, mnat, mnat_sess, menc, menc_sess, offerer, stream_recv_handler, rtcp_handler, v); if (err) goto out; if (vidisp_find(baresip_vidispl(), NULL) == NULL) sdp_media_set_ldir(v->strm->sdp, SDP_SENDONLY); stream_set_srate(v->strm, VIDEO_SRATE, VIDEO_SRATE); if (cfg->avt.rtp_bw.max >= AUDIO_BANDWIDTH) { stream_set_bw(v->strm, cfg->avt.rtp_bw.max - AUDIO_BANDWIDTH); } err |= sdp_media_set_lattr(stream_sdpmedia(v->strm), true, "framerate", "%.2f", v->cfg.fps); /* RFC 4585 */ err |= sdp_media_set_lattr(stream_sdpmedia(v->strm), true, "rtcp-fb", "* nack pli"); /* RFC 4796 */ if (content) { err |= sdp_media_set_lattr(stream_sdpmedia(v->strm), true, "content", "%s", content); } if (err) goto out; v->errh = errh; v->arg = arg; err = vtx_alloc(&v->vtx, v); err |= vrx_alloc(&v->vrx, v); if (err) goto out; /* Video codecs */ for (le = list_head(vidcodecl); le; le = le->next) { struct vidcodec *vc = le->data; err |= sdp_format_add(NULL, stream_sdpmedia(v->strm), false, vc->pt, vc->name, 90000, 1, vc->fmtp_ench, vc->fmtp_cmph, vc, false, "%s", vc->fmtp); } /* Video filters */ for (le = list_head(vidfiltl); le; le = le->next) { struct vidfilt *vf = le->data; struct vidfilt_prm prm; void *ctx = NULL; prm.width = v->cfg.width; prm.height = v->cfg.height; prm.fmt = v->cfg.enc_fmt; prm.fps = get_fps(v); err |= vidfilt_enc_append(&v->vtx.filtl, &ctx, vf, &prm, v); err |= vidfilt_dec_append(&v->vrx.filtl, &ctx, vf, &prm, v); if (err) { warning("video: video-filter '%s' failed (%m)\n", vf->name, err); break; } } out: if (err) mem_deref(v); else *vp = v; return err; } static void vidisp_resize_handler(const struct vidsz *sz, void *arg) { struct vrx *vrx = arg; (void)vrx; MAGIC_CHECK(vrx->video); info("video: display resized: %u x %u\n", sz->w, sz->h); } /* Set the video display - can be called multiple times */ static int set_vidisp(struct vrx *vrx) { struct vidisp *vd; vrx->vidisp = mem_deref(vrx->vidisp); vrx->vidisp_prm.fullscreen = vrx->video->cfg.fullscreen; vd = (struct vidisp *)vidisp_find(baresip_vidispl(), vrx->video->cfg.disp_mod); if (!vd) return ENOENT; return vd->alloch(&vrx->vidisp, vd, &vrx->vidisp_prm, vrx->device, vidisp_resize_handler, vrx); } enum {TMR_INTERVAL = 5}; static void tmr_handler(void *arg) { struct video *v = arg; MAGIC_CHECK(v); tmr_start(&v->tmr, TMR_INTERVAL * 1000, tmr_handler, v); /* protect vtx.frames */ lock_write_get(v->vtx.lock_enc); /* Estimate framerates */ v->vtx.efps = (double)v->vtx.frames / (double)TMR_INTERVAL; v->vrx.efps = (double)v->vrx.frames / (double)TMR_INTERVAL; v->vtx.frames = 0; v->vrx.frames = 0; lock_rel(v->vtx.lock_enc); } /** * Start the video source * * @param v Video object * @param ctx Media context * * @return 0 if success, otherwise errorcode */ int video_start_source(struct video *v, struct media_ctx **ctx) { struct vtx *vtx = &v->vtx; struct vidsz size; int err; if (!v) return EINVAL; if (vidsrc_find(baresip_vidsrcl(), NULL)) { struct vidsrc *vs; vs = (struct vidsrc *)vidsrc_find(baresip_vidsrcl(), v->cfg.src_mod); if (!vs) { warning("video: source not found: %s\n", v->cfg.src_mod); return ENOENT; } size.w = v->cfg.width; size.h = v->cfg.height; vtx->vsrc_size = size; vtx->vsrc_prm.fps = get_fps(v); vtx->vsrc_prm.fmt = v->cfg.enc_fmt; vtx->vsrc = mem_deref(vtx->vsrc); err = vs->alloch(&vtx->vsrc, vs, ctx, &vtx->vsrc_prm, &vtx->vsrc_size, NULL, v->vtx.device, vidsrc_frame_handler, vidsrc_error_handler, vtx); if (err) { warning("video: could not set source to" " [%u x %u] %m\n", size.w, size.h, err); } } else { info("video: no video source\n"); } tmr_start(&v->tmr, TMR_INTERVAL * 1000, tmr_handler, v); if (v->vtx.vc && v->vrx.vc) { info("%H%H", vtx_print_pipeline, &v->vtx, vrx_print_pipeline, &v->vrx); } v->started = true; return 0; } /** * Start the video display * * @param v Video object * @param peer Peer name * * @return 0 if success, otherwise errorcode */ int video_start_display(struct video *v, const char *peer) { int err; if (!v) return EINVAL; if (peer) { v->peer = mem_deref(v->peer); err = str_dup(&v->peer, peer); if (err) return err; } if (vidisp_find(baresip_vidispl(), NULL)) { err = set_vidisp(&v->vrx); if (err) { warning("video: could not set vidisp '%s': %m\n", v->vrx.device, err); return err; } } else { info("video: no video display\n"); } return 0; } /** * Stop the video source * * @param v Video object */ void video_stop(struct video *v) { if (!v) return; debug("video: stopping video source ..\n"); v->started = false; v->vtx.vsrc = mem_deref(v->vtx.vsrc); } /** * Stop the video display * * @param v Video object */ void video_stop_display(struct video *v) { if (!v) return; debug("video: stopping video display ..\n"); v->vrx.vidisp = mem_deref(v->vrx.vidisp); } bool video_is_started(const struct video *v) { return v ? v->started : false; } static int vidisp_update(struct vrx *vrx) { struct vidisp *vd = vidisp_get(vrx->vidisp); int err = 0; if (vd->updateh) { err = vd->updateh(vrx->vidisp, vrx->vidisp_prm.fullscreen, vrx->orient, NULL); } return err; } /** * Enable video display fullscreen * * @param v Video stream * @param fs True for fullscreen, otherwise false * * @return 0 if success, otherwise errorcode */ int video_set_fullscreen(struct video *v, bool fs) { if (!v) return EINVAL; v->vrx.vidisp_prm.fullscreen = fs; return vidisp_update(&v->vrx); } static void vidsrc_update(struct vtx *vtx, const char *dev) { struct vidsrc *vs = vidsrc_get(vtx->vsrc); if (vs && vs->updateh) vs->updateh(vtx->vsrc, &vtx->vsrc_prm, dev); } /** * Set the video encoder used * * @param v Video object * @param vc Video codec to use * @param pt_tx Payload type for sending * @param params Optional encoder parameters * * @return 0 if success, otherwise errorcode */ int video_encoder_set(struct video *v, struct vidcodec *vc, int pt_tx, const char *params) { struct vtx *vtx; int err = 0; if (!v) return EINVAL; vtx = &v->vtx; if (!vc->encupdh) { info("video: vidcodec '%s' has no encoder\n", vc->name); return ENOENT; } lock_write_get(vtx->lock_enc); if (vc != vtx->vc) { struct videnc_param prm; prm.bitrate = v->cfg.bitrate; prm.pktsize = 1024; prm.fps = get_fps(v); prm.max_fs = -1; info("Set video encoder: %s %s (%u bit/s, %.2f fps)\n", vc->name, vc->variant, prm.bitrate, prm.fps); vtx->enc = mem_deref(vtx->enc); err = vc->encupdh(&vtx->enc, vc, &prm, params, packet_handler, vtx); if (err) { warning("video: encoder alloc: %m\n", err); goto out; } vtx->vc = vc; } stream_update_encoder(v->strm, pt_tx); out: lock_rel(vtx->lock_enc); return err; } int video_decoder_set(struct video *v, struct vidcodec *vc, int pt_rx, const char *fmtp) { struct vrx *vrx; int err = 0; if (!v) return EINVAL; /* handle vidcodecs without a decoder */ if (!vc->decupdh) { struct list *vidcodecl = vc->le.list; struct vidcodec *vcd; info("video: vidcodec '%s' has no decoder\n", vc->name); vcd = (struct vidcodec *)vidcodec_find_decoder(vidcodecl, vc->name); if (!vcd) { warning("video: could not find decoder (%s)\n", vc->name); return ENOENT; } vc = vcd; } vrx = &v->vrx; vrx->pt_rx = pt_rx; if (vc != vrx->vc) { info("Set video decoder: %s %s\n", vc->name, vc->variant); vrx->dec = mem_deref(vrx->dec); err = vc->decupdh(&vrx->dec, vc, fmtp); if (err) { warning("video: decoder alloc: %m\n", err); return err; } vrx->vc = vc; } return err; } /** * Get the RTP Stream object from a Video object * * @param v Video object * * @return RTP Stream object */ struct stream *video_strm(const struct video *v) { return v ? v->strm : NULL; } void video_update_picture(struct video *v) { if (!v) return; v->vtx.picup = true; } /** * Set the current Video Source device name * * @param v Video stream * @param dev Device name */ void video_vidsrc_set_device(struct video *v, const char *dev) { if (!v) return; vidsrc_update(&v->vtx, dev); } static bool nack_handler(const char *name, const char *value, void *arg) { (void)name; (void)arg; return 0 == re_regex(value, str_len(value), "nack"); } void video_sdp_attr_decode(struct video *v) { if (!v) return; /* RFC 4585 */ if (sdp_media_rattr_apply(v->strm->sdp, "rtcp-fb", nack_handler, 0)) v->nack_pli = true; } static int vtx_debug(struct re_printf *pf, const struct vtx *vtx) { int err = 0; err |= re_hprintf(pf, " tx: encode: %s %s\n", vtx->vc ? vtx->vc->name : "none", vidfmt_name(vtx->fmt)); err |= re_hprintf(pf, " source: %s %u x %u, fps=%.2f" " frames=%llu\n", vtx->vsrc ? vidsrc_get(vtx->vsrc)->name : "none", vtx->vsrc_size.w, vtx->vsrc_size.h, vtx->vsrc_prm.fps, vtx->stats.src_frames); err |= re_hprintf(pf, " skipc=%u sendq=%u\n", vtx->skipc, list_count(&vtx->sendq)); if (vtx->ts_base) { err |= re_hprintf(pf, " time = %.3f sec\n", video_calc_seconds(vtx->ts_last - vtx->ts_base)); } else { err |= re_hprintf(pf, " time = (not started)\n"); } return err; } static int vrx_debug(struct re_printf *pf, const struct vrx *vrx) { int err = 0; err |= re_hprintf(pf, " rx: decode: %s %s\n", vrx->vc ? vrx->vc->name : "none", vidfmt_name(vrx->fmt)); err |= re_hprintf(pf, " vidisp: %s %u x %u frames=%llu\n", vrx->vidisp ? vidisp_get(vrx->vidisp)->name : "none", vrx->size.w, vrx->size.h, vrx->stats.disp_frames); err |= re_hprintf(pf, " n_keyframes=%u, n_picup=%u\n", vrx->n_intra, vrx->n_picup); if (vrx->ts_recv.is_set) { err |= re_hprintf(pf, " time = %.3f sec\n", video_calc_seconds(timestamp_duration(&vrx->ts_recv))); } else { err |= re_hprintf(pf, " time = (not started)\n"); } return err; } /** * Print the video debug information * * @param pf Print function * @param v Video object * * @return 0 if success, otherwise errorcode */ int video_debug(struct re_printf *pf, const struct video *v) { const struct vtx *vtx; const struct vrx *vrx; int err; if (!v) return 0; vtx = &v->vtx; vrx = &v->vrx; err = re_hprintf(pf, "\n--- Video stream ---\n"); err |= re_hprintf(pf, " started: %s\n", v->started ? "yes" : "no"); err |= vtx_debug(pf, vtx); err |= vrx_debug(pf, vrx); if (err) return err; if (!list_isempty(&vtx->filtl)) err |= vtx_print_pipeline(pf, vtx); if (!list_isempty(&vrx->filtl)) err |= vrx_print_pipeline(pf, vrx); err |= stream_debug(pf, v->strm); return err; } int video_print(struct re_printf *pf, const struct video *v) { if (!v) return 0; return re_hprintf(pf, " efps=%.1f/%.1f", v->vtx.efps, v->vrx.efps); } /** * Set the active video source * * @param v Video object * @param name Video source name * @param dev Video source device * * @return 0 if success, otherwise errorcode */ int video_set_source(struct video *v, const char *name, const char *dev) { struct vidsrc *vs = (struct vidsrc *)vidsrc_find(baresip_vidsrcl(), name); struct vtx *vtx; if (!v) return EINVAL; if (!vs) return ENOENT; vtx = &v->vtx; vtx->vsrc = mem_deref(vtx->vsrc); return vs->alloch(&vtx->vsrc, vs, NULL, &vtx->vsrc_prm, &vtx->vsrc_size, NULL, dev, vidsrc_frame_handler, vidsrc_error_handler, vtx); } /** * Set the device name of video source and display * * @param v Video object * @param src Video source device * @param disp Video display device */ void video_set_devicename(struct video *v, const char *src, const char *disp) { if (!v) return; str_ncpy(v->vtx.device, src, sizeof(v->vtx.device)); str_ncpy(v->vrx.device, disp, sizeof(v->vrx.device)); } /** * Get video codec of video stream * * @param vid Video object * @param tx True to get transmit codec, false to get receive codec * * @return Video codec if success, otherwise NULL */ const struct vidcodec *video_codec(const struct video *vid, bool tx) { if (!vid) return NULL; return tx ? vid->vtx.vc : vid->vrx.vc; } baresip-1.0.0/src/vidfilt.c000066400000000000000000000044511372575704200155510ustar00rootroot00000000000000/** * @file vidfilt.c Video Filter * * Copyright (C) 2010 Creytiv.com */ #include #include #include "core.h" /** * Register a new Video Filter * * @param vidfiltl List of Video-Filters * @param vf Video Filter to register */ void vidfilt_register(struct list *vidfiltl, struct vidfilt *vf) { if (!vf) return; list_append(vidfiltl, &vf->le, vf); info("vidfilt: %s\n", vf->name); } /** * Unregister a Video Filter * * @param vf Video Filter to unregister */ void vidfilt_unregister(struct vidfilt *vf) { if (!vf) return; list_unlink(&vf->le); } static void vidfilt_enc_destructor(void *arg) { struct vidfilt_enc_st *st = arg; list_unlink(&st->le); } /** * Allocate a video-filter encode state and append to list * * @param filtl List of video-filter states * @param ctx Media context * @param vf Video filter * @param prm Video filter parameters * @param vid Pointer to video object (optional) * * @return 0 if success, otherwise errorcode */ int vidfilt_enc_append(struct list *filtl, void **ctx, const struct vidfilt *vf, struct vidfilt_prm *prm, const struct video *vid) { struct vidfilt_enc_st *st = NULL; int err; if (vf->encupdh) { err = vf->encupdh(&st, ctx, vf, prm, vid); if (err) return err; } else { st = mem_zalloc(sizeof(*st), vidfilt_enc_destructor); if (!st) return ENOMEM; } st->vf = vf; list_append(filtl, &st->le, st); return 0; } static void vidfilt_dec_destructor(void *arg) { struct vidfilt_dec_st *st = arg; list_unlink(&st->le); } /** * Allocate a video-filter decode state and append to list * * @param filtl List of video-filter states * @param ctx Media context * @param vf Video filter * @param prm Video filter parameters * @param vid Pointer to video object (optional) * * @return 0 if success, otherwise errorcode */ int vidfilt_dec_append(struct list *filtl, void **ctx, const struct vidfilt *vf, struct vidfilt_prm *prm, const struct video *vid) { struct vidfilt_dec_st *st = NULL; int err; if (vf->decupdh) { err = vf->decupdh(&st, ctx, vf, prm, vid); if (err) return err; } else { st = mem_zalloc(sizeof(*st), vidfilt_dec_destructor); if (!st) return ENOMEM; } st->vf = vf; list_append(filtl, &st->le, st); return 0; } baresip-1.0.0/src/vidisp.c000066400000000000000000000055441372575704200154120ustar00rootroot00000000000000/** * @file vidisp.c Video Display * * Copyright (C) 2010 Creytiv.com */ #include #include #include "core.h" /** Video Display state */ struct vidisp_st { struct vidisp *vd; /**< Video Display */ }; static void destructor(void *arg) { struct vidisp *vd = arg; list_unlink(&vd->le); } /** * Register a Video output display * * @param vp Pointer to allocated Video Display * @param vidispl List of Video-displays * @param name Name of Video Display * @param alloch Allocation handler * @param updateh Update handler * @param disph Display handler * @param hideh Hide-window handler * * @return 0 if success, otherwise errorcode */ int vidisp_register(struct vidisp **vp, struct list *vidispl, const char *name, vidisp_alloc_h *alloch, vidisp_update_h *updateh, vidisp_disp_h *disph, vidisp_hide_h *hideh) { struct vidisp *vd; if (!vp || !vidispl) return EINVAL; vd = mem_zalloc(sizeof(*vd), destructor); if (!vd) return ENOMEM; list_append(vidispl, &vd->le, vd); vd->name = name; vd->alloch = alloch; vd->updateh = updateh; vd->disph = disph; vd->hideh = hideh; info("vidisp: %s\n", name); *vp = vd; return 0; } const struct vidisp *vidisp_find(const struct list *vidispl, const char *name) { struct le *le; for (le = list_head(vidispl); le; le = le->next) { struct vidisp *vd = le->data; if (str_isset(name) && 0 != str_casecmp(name, vd->name)) continue; /* Found */ return vd; } return NULL; } /** * Allocate a video display state * * @param stp Pointer to allocated display state * @param vidispl List of Video-displays * @param name Name of video display * @param prm Video display parameters (optional) * @param dev Display device * @param resizeh Window resize handler * @param arg Handler argument * * @return 0 if success, otherwise errorcode */ int vidisp_alloc(struct vidisp_st **stp, struct list *vidispl, const char *name, struct vidisp_prm *prm, const char *dev, vidisp_resize_h *resizeh, void *arg) { struct vidisp *vd = (struct vidisp *)vidisp_find(vidispl, name); if (!vd) return ENOENT; return vd->alloch(stp, vd, prm, dev, resizeh, arg); } /** * Display a video frame * * @param st Video display state * @param title Display title * @param frame Video frame * @param timestamp Frame timestamp in VIDEO_TIMEBASE units * * @return 0 if success, otherwise errorcode */ int vidisp_display(struct vidisp_st *st, const char *title, const struct vidframe *frame, uint64_t timestamp) { if (!st || !frame) return EINVAL; return st->vd->disph(st, title, frame, timestamp); } /** * Get the video display module from a video display state * * @param st Video display state * * @return Video display module */ struct vidisp *vidisp_get(struct vidisp_st *st) { return st ? st->vd : NULL; } baresip-1.0.0/src/vidsrc.c000066400000000000000000000052751372575704200154070ustar00rootroot00000000000000/** * @file vidsrc.c Video Source * * Copyright (C) 2010 Creytiv.com */ #include #include #include "core.h" /** Video Source state */ struct vidsrc_st { struct vidsrc *vs; /**< Video Source */ }; static void destructor(void *arg) { struct vidsrc *vs = arg; list_flush(&vs->dev_list); list_unlink(&vs->le); } /** * Register a Video Source * * @param vsp Pointer to allocated Video Source * @param vidsrcl List of Video Sources * @param name Name of Video Source * @param alloch Allocation handler * @param updateh Update handler * * @return 0 if success, otherwise errorcode */ int vidsrc_register(struct vidsrc **vsp, struct list *vidsrcl, const char *name, vidsrc_alloc_h *alloch, vidsrc_update_h *updateh) { struct vidsrc *vs; if (!vsp || !vidsrcl) return EINVAL; vs = mem_zalloc(sizeof(*vs), destructor); if (!vs) return ENOMEM; list_append(vidsrcl, &vs->le, vs); vs->name = name; vs->alloch = alloch; vs->updateh = updateh; info("vidsrc: %s\n", name); *vsp = vs; return 0; } /** * Find a Video Source by name * * @param vidsrcl List of Video Sources * @param name Name of the Video Source to find * * @return Matching Video Source if found, otherwise NULL */ const struct vidsrc *vidsrc_find(const struct list *vidsrcl, const char *name) { struct le *le; for (le=list_head(vidsrcl); le; le=le->next) { struct vidsrc *vs = le->data; if (str_isset(name) && 0 != str_casecmp(name, vs->name)) continue; return vs; } return NULL; } /** * Allocate a new video source state * * @param stp Pointer to allocated state * @param vidsrcl List of Video Sources * @param name Name of the video source * @param ctx Optional media context * @param prm Video source parameters * @param size Wanted video size of the source * @param fmt Format parameter * @param dev Video device * @param frameh Video frame handler * @param errorh Error handler (optional) * @param arg Handler argument * * @return 0 if success, otherwise errorcode */ int vidsrc_alloc(struct vidsrc_st **stp, struct list *vidsrcl, const char *name, struct media_ctx **ctx, struct vidsrc_prm *prm, const struct vidsz *size, const char *fmt, const char *dev, vidsrc_frame_h *frameh, vidsrc_error_h *errorh, void *arg) { struct vidsrc *vs = (struct vidsrc *)vidsrc_find(vidsrcl, name); if (!vs) return ENOENT; return vs->alloch(stp, vs, ctx, prm, size, fmt, dev, frameh, errorh, arg); } /** * Get the video source module from a video source state * * @param st Video source state * * @return Video source module */ struct vidsrc *vidsrc_get(struct vidsrc_st *st) { return st ? st->vs : NULL; } baresip-1.0.0/src/vidutil.c000066400000000000000000000024721372575704200155710ustar00rootroot00000000000000/** * @file vidutil.c Video utility functions * * Copyright (C) 2017 Creytiv.com */ #include #include #include #include "core.h" /** * Calculate the timestamp in seconds from the RTP timestamp. * * @param rtp_ts RTP Timestamp * * @return Timestamp in seconds */ double video_calc_seconds(uint64_t rtp_ts) { double timestamp; /* convert from RTP clockrate to seconds */ timestamp = (double)rtp_ts / (double)VIDEO_SRATE; return timestamp; } /** * Convert a video timestamp to seconds * * @param timestamp Timestamp in VIDEO_TIMEBASE units * * @return Timestamp in seconds */ double video_timestamp_to_seconds(uint64_t timestamp) { return (double)timestamp / (double)VIDEO_TIMEBASE; } /** * Calculate the RTP timestamp from a timestamp in VIDEO_TIMEBASE units * * @param timestamp Timestamp in VIDEO_TIMEBASE units * * @return Extended RTP Timestamp */ uint64_t video_calc_rtp_timestamp_fix(uint64_t timestamp) { uint64_t rtp_ts; rtp_ts = timestamp * VIDEO_SRATE / VIDEO_TIMEBASE; return rtp_ts; } /** * Calculate timestamp in VIDEO_TIMEBASE units from RTP timestamp * * @param rtp_ts Extended RTP timestamp * * @return Timestamp in VIDEO_TIMEBASE units */ uint64_t video_calc_timebase_timestamp(uint64_t rtp_ts) { return rtp_ts * VIDEO_TIMEBASE / VIDEO_SRATE; } baresip-1.0.0/test/000077500000000000000000000000001372575704200141305ustar00rootroot00000000000000baresip-1.0.0/test/account.c000066400000000000000000000045111372575704200157310ustar00rootroot00000000000000/** * @file test/account.c Tests for account * * Copyright (C) 2010 - 2017 Creytiv.com */ #include #include #include #include "test.h" #define DEBUG_MODULE "account" #define DEBUG_LEVEL 5 #include static const char str[] = "\"Mr User\" " ";answermode=auto" ";auth_user=xuser" ";auth_pass=pass" ";outbound=\"sip:edge.domain.com\"" ";ptime=10" ";regint=600" ";pubint=700" ";sipnat=outbound" ";stunuser=bob@bob.com" ";stunpass=taj:aa" ";stunserver=\"stun:stunserver.org\"" ";mwi=no" ";call_transfer=no" ";audio_source=null,null" ";audio_codecs=RAW-CODEC" ; int test_account(void) { struct account *acc = NULL; struct sip_addr *addr; const struct aucodec *ac; struct list *lst; int err = 0; mock_aucodec_register(baresip_aucodecl()); err = account_alloc(&acc, str); TEST_ERR(err); ASSERT_TRUE(acc != NULL); /* verify the decoded SIP aor */ addr = account_laddr(acc); ASSERT_TRUE(addr != NULL); TEST_STRCMP("Mr User", 7, addr->dname.p, addr->dname.l); TEST_STRCMP("sip", 3, addr->uri.scheme.p, addr->uri.scheme.l); TEST_STRCMP("user", 4, addr->uri.user.p, addr->uri.user.l); TEST_STRCMP("", 0, addr->uri.password.p, addr->uri.password.l); TEST_STRCMP("domain.com", 10, addr->uri.host.p, addr->uri.host.l); ASSERT_EQ(0, addr->uri.params.l); ASSERT_TRUE(addr->params.l > 0); /* verify all decoded parameters */ ASSERT_STREQ("Mr User", account_display_name(acc)); ASSERT_TRUE(ANSWERMODE_AUTO == account_answermode(acc)); ASSERT_STREQ("xuser", account_auth_user(acc)); ASSERT_STREQ("pass", account_auth_pass(acc)); ASSERT_STREQ("sip:edge.domain.com", account_outbound(acc, 0)); ASSERT_TRUE(NULL == account_outbound(acc, 1)); ASSERT_TRUE(NULL == account_outbound(acc, 333)); ASSERT_EQ(10, account_ptime(acc)); ASSERT_EQ(600, account_regint(acc)); ASSERT_EQ(700, account_pubint(acc)); ASSERT_STREQ("bob@bob.com", account_stun_user(acc)); ASSERT_STREQ("taj:aa", account_stun_pass(acc)); ASSERT_STREQ("stunserver.org", account_stun_host(acc)); ASSERT_STREQ("no", account_mwi(acc)); ASSERT_STREQ("no", account_call_transfer(acc)); lst = account_aucodecl(acc); ac = list_ledata(list_head(lst)); ASSERT_EQ(1, list_count(lst)); ASSERT_STREQ("RAW-CODEC", ac->name); out: mock_aucodec_unregister(); mem_deref(acc); return err; } baresip-1.0.0/test/aulevel.c000066400000000000000000000023571372575704200157400ustar00rootroot00000000000000/** * @file test/aulevel.c Baresip selftest -- audio levels * * Copyright (C) 2010 - 2017 Creytiv.com */ #include #include #include #include "test.h" #define DEBUG_MODULE "aulevel" #define DEBUG_LEVEL 5 #include #define PREC .6 int test_aulevel(void) { static const struct { int16_t sampv[2]; double level; } testv[] = { { { 0, -0}, -96.0 }, { { 0, 1}, -93.0 }, { { 1, -1}, -90.0 }, { { 2, -2}, -84.0 }, { { 4, -4}, -78.0 }, { { 8, -8}, -72.0 }, { { 16, -16}, -66.0 }, { { 32, -32}, -60.0 }, { { 64, -64}, -54.0 }, { { 128, -128}, -48.0 }, { { 256, -256}, -42.0 }, { { 512, -512}, -36.0 }, { { 1024, -1024}, -30.0 }, { { 2048, -2048}, -24.0 }, { { 4096, -4096}, -18.0 }, { { 8192, -8192}, -12.0 }, { {16384, -16384}, -6.0 }, { {32767, -32768}, 0.0 }, }; size_t i; int err = 0; for (i=0; i #include #include #include #include #include "test.h" #define MAGIC 0x7004ca11 enum behaviour { BEHAVIOUR_ANSWER = 0, BEHAVIOUR_PROGRESS, BEHAVIOUR_REJECT, BEHAVIOUR_GET_HDRS, }; enum action { ACTION_RECANCEL = 0, ACTION_HANGUP_A, ACTION_HANGUP_B, ACTION_NOTHING, ACTION_TRANSFER }; struct agent { struct fixture *fix; /* pointer to parent */ struct agent *peer; struct ua *ua; uint16_t close_scode; bool failed; unsigned n_incoming; unsigned n_progress; unsigned n_established; unsigned n_closed; unsigned n_dtmf_recv; unsigned n_transfer; unsigned n_mediaenc; unsigned n_rtpestab; unsigned n_rtcp; }; struct fixture { uint32_t magic; struct agent a, b, c; struct sa laddr_udp; struct sa laddr_tcp; enum behaviour behaviour; enum action estab_action; char buri[256]; char buri_tcp[256]; int err; unsigned exp_estab; unsigned exp_closed; bool stop_on_rtp; bool stop_on_rtcp; }; #define fixture_init_prm(f, prm) \ memset(f, 0, sizeof(*f)); \ \ f->a.fix = f; \ f->b.fix = f; \ f->c.fix = f; \ \ err = ua_init("test", true, true, false); \ TEST_ERR(err); \ \ f->magic = MAGIC; \ f->estab_action = ACTION_RECANCEL; \ f->exp_estab = 1; \ f->exp_closed = 1; \ /* NOTE: See Makefile TEST_MODULES */ \ err = module_load(".", "g711"); \ TEST_ERR(err); \ \ err = ua_alloc(&f->a.ua, \ "A ;regint=0" prm); \ TEST_ERR(err); \ err = ua_alloc(&f->b.ua, \ "B ;regint=0" prm); \ TEST_ERR(err); \ \ f->a.peer = &f->b; \ f->b.peer = &f->a; \ \ err = uag_event_register(event_handler, f); \ TEST_ERR(err); \ \ err = sip_transp_laddr(uag_sip(), &f->laddr_udp, \ SIP_TRANSP_UDP, NULL); \ TEST_ERR(err); \ \ err = sip_transp_laddr(uag_sip(), &f->laddr_tcp, \ SIP_TRANSP_TCP, NULL); \ TEST_ERR(err); \ \ debug("test: local SIP transp: UDP=%J, TCP=%J\n", \ &f->laddr_udp, &f->laddr_tcp); \ \ re_snprintf(f->buri, sizeof(f->buri), \ "sip:b@%J", &f->laddr_udp); \ re_snprintf(f->buri_tcp, sizeof(f->buri_tcp), \ "sip:b@%J;transport=tcp", &f->laddr_tcp); #define fixture_init(f) \ fixture_init_prm((f), ""); #define fixture_close(f) \ mem_deref(f->c.ua); \ mem_deref(f->b.ua); \ mem_deref(f->a.ua); \ \ module_unload("g711"); \ \ uag_event_unregister(event_handler); \ \ ua_stop_all(true); \ ua_close(); #define fixture_abort(f, error) \ do { \ (f)->err = (error); \ re_cancel(); \ } while (0) static const struct list *hdrs; static const char dtmf_digits[] = "123"; static void event_handler(struct ua *ua, enum ua_event ev, struct call *call, const char *prm, void *arg) { struct fixture *f = arg; struct call *call2 = NULL; struct agent *ag; char curi[256]; int err = 0; (void)prm; #if 1 info("test: [ %s ] event: %s (%s)\n", ua_aor(ua), uag_event_str(ev), prm); #endif ASSERT_TRUE(f != NULL); ASSERT_EQ(MAGIC, f->magic); if (ua == f->a.ua) ag = &f->a; else if (ua == f->b.ua) ag = &f->b; else if (ua == f->c.ua) ag = &f->c; else { return; } switch (ev) { case UA_EVENT_CALL_INCOMING: ++ag->n_incoming; switch (f->behaviour) { case BEHAVIOUR_ANSWER: err = ua_answer(ua, call, VIDMODE_ON); if (err) { warning("ua_answer failed (%m)\n", err); goto out; } break; case BEHAVIOUR_PROGRESS: err = call_progress(call); if (err) { warning("call_progress failed (%m)\n", err); goto out; } break; case BEHAVIOUR_REJECT: ua_hangup(ua, call, 0, 0); call = NULL; ag->failed = true; break; case BEHAVIOUR_GET_HDRS: hdrs = call_get_custom_hdrs(call); err = ua_answer(ua, call, VIDMODE_ON); if (err) { warning("ua_answer failed (%m)\n", err); goto out; } break; default: break; } break; case UA_EVENT_CALL_PROGRESS: ++ag->n_progress; re_cancel(); break; case UA_EVENT_CALL_ESTABLISHED: ++ag->n_established; ASSERT_TRUE(str_isset(call_id(call))); /* are both agents established? */ if (ag->n_established >= f->exp_estab && ag->peer->n_established >= f->exp_estab) { switch (f->estab_action) { case ACTION_RECANCEL: re_cancel(); break; case ACTION_HANGUP_A: f->a.failed = true; ua_hangup(f->a.ua, NULL, 0, 0); break; case ACTION_HANGUP_B: f->b.failed = true; ua_hangup(f->b.ua, NULL, 0, 0); break; case ACTION_NOTHING: /* Do nothing, wait */ break; case ACTION_TRANSFER: f->estab_action = ACTION_NOTHING; re_snprintf(curi, sizeof(curi), "sip:c@%J", &f->laddr_udp); err = call_transfer(ua_call(f->a.ua), curi); if (err) goto out; break; } } break; case UA_EVENT_CALL_CLOSED: ++ag->n_closed; ag->close_scode = call_scode(call); if (ag->close_scode) ag->failed = true; if (ag->n_closed >= f->exp_closed && ag->peer->n_closed >= f->exp_closed) { re_cancel(); } break; case UA_EVENT_CALL_TRANSFER: ++ag->n_transfer; err = ua_call_alloc(&call2, ua, VIDMODE_ON, NULL, call, call_localuri(call), true); if (!err) { struct pl pl; pl_set_str(&pl, prm); err = call_connect(call2, &pl); if (err) { warning("ua: transfer: connect error: %m\n", err); } } if (err) { (void)call_notify_sipfrag(call, 500, "Call Error"); mem_deref(call2); } break; case UA_EVENT_CALL_MENC: ++ag->n_mediaenc; ASSERT_TRUE(stream_is_secure(audio_strm(call_audio(call)))); break; case UA_EVENT_CALL_DTMF_START: ASSERT_EQ(1, str_len(prm)); ASSERT_EQ(dtmf_digits[ag->n_dtmf_recv], prm[0]); ++ag->n_dtmf_recv; if (ag->n_dtmf_recv >= str_len(dtmf_digits)) { re_cancel(); } break; case UA_EVENT_CALL_RTPESTAB: ++ag->n_rtpestab; if (f->stop_on_rtp && ag->peer->n_rtpestab > 0) re_cancel(); break; case UA_EVENT_CALL_RTCP: ++ag->n_rtcp; if (f->stop_on_rtcp && ag->peer->n_rtcp > 0) re_cancel(); break; default: break; } if (ag->failed && ag->peer->failed) { info("test: re_cancel on call failed\n"); re_cancel(); return; } out: if (err) { warning("error in event-handler (%m)\n", err); f->err = err; re_cancel(); } } int test_call_answer(void) { struct fixture fix, *f = &fix; int err = 0; fixture_init(f); f->behaviour = BEHAVIOUR_ANSWER; /* Make a call from A to B */ err = ua_connect(f->a.ua, 0, NULL, f->buri, VIDMODE_OFF); TEST_ERR(err); /* run main-loop with timeout, wait for events */ err = re_main_timeout(5000); TEST_ERR(err); TEST_ERR(fix.err); ASSERT_EQ(0, fix.a.n_incoming); ASSERT_EQ(1, fix.a.n_established); ASSERT_EQ(0, fix.a.n_closed); ASSERT_EQ(0, fix.a.close_scode); ASSERT_EQ(1, fix.b.n_incoming); ASSERT_EQ(1, fix.b.n_established); ASSERT_EQ(0, fix.b.n_closed); out: fixture_close(f); return err; } int test_call_reject(void) { struct fixture fix, *f = &fix; int err = 0; fixture_init(f); f->behaviour = BEHAVIOUR_REJECT; /* Make a call from A to B */ err = ua_connect(f->a.ua, 0, NULL, f->buri, VIDMODE_OFF); TEST_ERR(err); /* run main-loop with timeout, wait for events */ err = re_main_timeout(5000); TEST_ERR(err); TEST_ERR(fix.err); ASSERT_EQ(0, fix.a.n_incoming); ASSERT_EQ(0, fix.a.n_established); ASSERT_EQ(1, fix.a.n_closed); ASSERT_EQ(1, fix.b.n_incoming); ASSERT_EQ(0, fix.b.n_established); out: fixture_close(f); return err; } int test_call_answer_hangup_a(void) { struct fixture fix, *f = &fix; int err = 0; fixture_init(f); f->behaviour = BEHAVIOUR_ANSWER; f->estab_action = ACTION_HANGUP_A; /* Make a call from A to B */ err = ua_connect(f->a.ua, 0, NULL, f->buri, VIDMODE_OFF); TEST_ERR(err); /* run main-loop with timeout, wait for events */ err = re_main_timeout(5000); TEST_ERR(err); TEST_ERR(fix.err); ASSERT_EQ(1, fix.a.n_established); ASSERT_EQ(1, fix.a.n_closed); ASSERT_EQ(0, fix.a.close_scode); ASSERT_EQ(1, fix.b.n_established); ASSERT_EQ(1, fix.b.n_closed); ASSERT_EQ(0, fix.b.close_scode); out: fixture_close(f); return err; } int test_call_answer_hangup_b(void) { struct fixture fix, *f = &fix; char uri[256]; int err = 0; fixture_init(f); f->behaviour = BEHAVIOUR_ANSWER; f->estab_action = ACTION_HANGUP_B; /* add angle brackets */ re_snprintf(uri, sizeof(uri), "<%s>", f->buri); /* Make a call from A to B */ err = ua_connect(f->a.ua, 0, NULL, uri, VIDMODE_OFF); TEST_ERR(err); /* run main-loop with timeout, wait for events */ err = re_main_timeout(5000); TEST_ERR(err); TEST_ERR(fix.err); ASSERT_EQ(1, fix.a.n_established); ASSERT_EQ(1, fix.a.n_closed); ASSERT_EQ(0, fix.a.close_scode); ASSERT_EQ(1, fix.b.n_established); ASSERT_EQ(1, fix.b.n_closed); ASSERT_EQ(0, fix.b.close_scode); out: fixture_close(f); return err; } int test_call_rtp_timeout(void) { #define RTP_TIMEOUT_MS 1 struct fixture fix, *f = &fix; struct call *call; int err = 0; fixture_init(f); f->behaviour = BEHAVIOUR_ANSWER; f->estab_action = ACTION_NOTHING; /* Make a call from A to B */ err = ua_connect(f->a.ua, 0, NULL, f->buri, VIDMODE_OFF); TEST_ERR(err); call = ua_call(f->a.ua); ASSERT_TRUE(call != NULL); call_enable_rtp_timeout(call, RTP_TIMEOUT_MS); /* run main-loop with timeout, wait for events */ err = re_main_timeout(5000); TEST_ERR(err); TEST_ERR(fix.err); ASSERT_EQ(1, fix.a.n_established); ASSERT_EQ(1, fix.a.n_closed); ASSERT_EQ(701, fix.a.close_scode); /* verify timeout */ ASSERT_EQ(1, fix.b.n_established); ASSERT_EQ(1, fix.b.n_closed); ASSERT_EQ(0, fix.b.close_scode); out: fixture_close(f); return err; } /* veriy that line-numbers are in sequence */ static bool linenum_are_sequential(const struct ua *ua) { uint32_t linenum = 0; struct le *le; for (le = list_head(ua_calls(ua)) ; le ; le = le->next) { struct call *call = le->data; if (call_linenum(call) <= linenum) return false; linenum = call_linenum(call); } return true; } int test_call_multiple(void) { struct fixture fix, *f = &fix; struct le *le; unsigned i; int err = 0; fixture_init(f); f->behaviour = BEHAVIOUR_ANSWER; f->exp_estab = 4; /* * Step 1 -- make 4 calls from A to B */ for (i=0; i<4; i++) { err = ua_connect(f->a.ua, 0, NULL, f->buri, VIDMODE_OFF); TEST_ERR(err); } err = re_main_timeout(5000); TEST_ERR(err); TEST_ERR(fix.err); ASSERT_EQ(0, fix.a.n_incoming); ASSERT_EQ(4, fix.a.n_established); ASSERT_EQ(0, fix.a.n_closed); ASSERT_EQ(4, fix.b.n_incoming); ASSERT_EQ(4, fix.b.n_established); ASSERT_EQ(0, fix.b.n_closed); ASSERT_EQ(4, list_count(ua_calls(f->a.ua))); ASSERT_EQ(4, list_count(ua_calls(f->b.ua))); ASSERT_TRUE(linenum_are_sequential(f->a.ua)); ASSERT_TRUE(linenum_are_sequential(f->b.ua)); /* * Step 2 -- hangup calls with even line-number */ f->exp_closed = 2; le = list_head(ua_calls(f->a.ua)); while (le) { struct call *call = le->data; le = le->next; if (!(call_linenum(call) % 2)) { ua_hangup(f->a.ua, call, 0, 0); } } err = re_main_timeout(5000); TEST_ERR(err); TEST_ERR(fix.err); ASSERT_EQ(2, list_count(ua_calls(f->a.ua))); ASSERT_EQ(2, list_count(ua_calls(f->b.ua))); ASSERT_TRUE(linenum_are_sequential(f->a.ua)); ASSERT_TRUE(linenum_are_sequential(f->b.ua)); /* * Step 3 -- make 2 calls from A to B */ f->a.n_established = 0; f->b.n_established = 0; f->exp_estab = 2; for (i=0; i<2; i++) { err = ua_connect(f->a.ua, 0, NULL, f->buri, VIDMODE_OFF); TEST_ERR(err); } err = re_main_timeout(5000); TEST_ERR(err); TEST_ERR(fix.err); ASSERT_EQ(4, list_count(ua_calls(f->a.ua))); ASSERT_EQ(4, list_count(ua_calls(f->b.ua))); out: fixture_close(f); return err; } int test_call_max(void) { struct fixture fix, *f = &fix; unsigned i; int err = 0; /* Set the max-calls limit */ conf_config()->call.max_calls = 1; fixture_init(f); f->behaviour = BEHAVIOUR_ANSWER; /* Make 2 calls, one should work and one should fail */ for (i=0; i<2; i++) { err = ua_connect(f->a.ua, 0, NULL, f->buri, VIDMODE_OFF); TEST_ERR(err); } f->b.failed = true; /* tiny hack to stop the runloop */ err = re_main_timeout(5000); TEST_ERR(err); TEST_ERR(fix.err); ASSERT_EQ(0, fix.a.n_incoming); ASSERT_EQ(1, fix.a.n_established); ASSERT_EQ(1, fix.a.n_closed); ASSERT_EQ(486, fix.a.close_scode); ASSERT_EQ(1, fix.b.n_incoming); ASSERT_EQ(0, fix.b.n_closed); out: fixture_close(f); /* Set the max-calls limit */ conf_config()->call.max_calls = 0; return err; } int test_call_dtmf(void) { struct fixture fix, *f = &fix; struct ausrc *ausrc = NULL; size_t i, n = str_len(dtmf_digits); int err = 0; /* Use a low packet time, so the test completes quickly */ fixture_init_prm(f, ";ptime=1"); /* audio-source is needed for dtmf/telev to work */ err = mock_ausrc_register(&ausrc, baresip_ausrcl()); TEST_ERR(err); f->behaviour = BEHAVIOUR_ANSWER; /* Make a call from A to B */ err = ua_connect(f->a.ua, 0, NULL, f->buri, VIDMODE_OFF); TEST_ERR(err); /* run main-loop with timeout, wait for events */ err = re_main_timeout(5000); TEST_ERR(err); TEST_ERR(fix.err); /* send some DTMF digits from A to B .. */ for (i=0; ia.ua), dtmf_digits[i]); TEST_ERR(err); } /* run main-loop with timeout, wait for events */ err = re_main_timeout(5000); TEST_ERR(err); TEST_ERR(fix.err); ASSERT_EQ(0, fix.a.n_dtmf_recv); ASSERT_EQ(n, fix.b.n_dtmf_recv); out: fixture_close(f); mem_deref(ausrc); return err; } static void mock_vidisp_handler(const struct vidframe *frame, uint64_t timestamp, void *arg) { struct fixture *fix = arg; int err = 0; (void)frame; (void)timestamp; (void)fix; ASSERT_EQ(MAGIC, fix->magic); ASSERT_EQ(conf_config()->video.enc_fmt, (int)frame->fmt); /* Stop the test */ re_cancel(); out: if (err) fixture_abort(fix, err); } int test_call_video(void) { struct fixture fix, *f = &fix; struct vidsrc *vidsrc = NULL; struct vidisp *vidisp = NULL; int err = 0; conf_config()->video.fps = 100; conf_config()->video.enc_fmt = VID_FMT_YUV420P; fixture_init(f); /* to enable video, we need one vidsrc and vidcodec */ mock_vidcodec_register(); err = mock_vidsrc_register(&vidsrc); TEST_ERR(err); err = mock_vidisp_register(&vidisp, mock_vidisp_handler, f); TEST_ERR(err); f->behaviour = BEHAVIOUR_ANSWER; f->estab_action = ACTION_NOTHING; /* Make a call from A to B */ err = ua_connect(f->a.ua, 0, NULL, f->buri, VIDMODE_ON); TEST_ERR(err); /* run main-loop with timeout, wait for events */ err = re_main_timeout(10000); TEST_ERR(err); TEST_ERR(fix.err); /* verify that video was enabled for this call */ ASSERT_EQ(1, fix.a.n_established); ASSERT_EQ(1, fix.b.n_established); ASSERT_TRUE(call_has_video(ua_call(f->a.ua))); ASSERT_TRUE(call_has_video(ua_call(f->b.ua))); out: fixture_close(f); mem_deref(vidisp); mem_deref(vidsrc); mock_vidcodec_unregister(); return err; } static void mock_sample_handler(const void *sampv, size_t sampc, void *arg) { struct fixture *fix = arg; bool got_aulevel; (void)sampv; (void)sampc; got_aulevel = 0 == audio_level_get(call_audio(ua_call(fix->a.ua)), NULL) && 0 == audio_level_get(call_audio(ua_call(fix->b.ua)), NULL); if (got_aulevel) re_cancel(); } int test_call_aulevel(void) { struct fixture fix, *f = &fix; struct ausrc *ausrc = NULL; struct auplay *auplay = NULL; double lvl; int err = 0; /* Use a low packet time, so the test completes quickly */ fixture_init_prm(f, ";ptime=1"); conf_config()->audio.level = true; err = mock_ausrc_register(&ausrc, baresip_ausrcl()); TEST_ERR(err); err = mock_auplay_register(&auplay, baresip_auplayl(), mock_sample_handler, f); TEST_ERR(err); f->behaviour = BEHAVIOUR_ANSWER; f->estab_action = ACTION_NOTHING; /* Make a call from A to B */ err = ua_connect(f->a.ua, 0, NULL, f->buri, VIDMODE_OFF); TEST_ERR(err); /* run main-loop with timeout, wait for events */ err = re_main_timeout(5000); TEST_ERR(err); TEST_ERR(fix.err); /* verify audio silence */ err = audio_level_get(call_audio(ua_call(f->a.ua)), &lvl); TEST_ERR(err); ASSERT_EQ(-96, lvl); err = audio_level_get(call_audio(ua_call(f->b.ua)), &lvl); TEST_ERR(err); ASSERT_EQ(-96, lvl); out: conf_config()->audio.level = false; fixture_close(f); mem_deref(auplay); mem_deref(ausrc); return err; } int test_call_progress(void) { struct fixture fix, *f = &fix; int err = 0; fixture_init(f); f->behaviour = BEHAVIOUR_PROGRESS; /* Make a call from A to B */ err = ua_connect(f->a.ua, 0, NULL, f->buri, VIDMODE_OFF); TEST_ERR(err); /* run main-loop with timeout, wait for events */ err = re_main_timeout(5000); TEST_ERR(err); TEST_ERR(fix.err); ASSERT_EQ(0, fix.a.n_incoming); ASSERT_EQ(1, fix.a.n_progress); ASSERT_EQ(0, fix.a.n_established); ASSERT_EQ(0, fix.a.n_closed); ASSERT_EQ(0, fix.a.close_scode); ASSERT_EQ(1, fix.b.n_incoming); ASSERT_EQ(0, fix.b.n_progress); ASSERT_EQ(0, fix.b.n_established); ASSERT_EQ(0, fix.b.n_closed); out: fixture_close(f); return err; } static void audio_sample_handler(const void *sampv, size_t sampc, void *arg) { struct fixture *fix = arg; int err = 0; (void)sampv; (void)sampc; ASSERT_EQ(MAGIC, fix->magic); /* Wait until the call is established and the incoming * audio samples are successfully decoded. */ if (sampc && fix->a.n_established && fix->b.n_established && audio_rxaubuf_started(call_audio(ua_call(fix->a.ua))) && audio_rxaubuf_started(call_audio(ua_call(fix->b.ua))) ) { re_cancel(); } out: if (err) fixture_abort(fix, err); } static int test_media_base(enum audio_mode txmode) { struct fixture fix, *f = &fix; struct ausrc *ausrc = NULL; struct auplay *auplay = NULL; int err = 0; fixture_init_prm(f, ";ptime=1"); conf_config()->audio.txmode = txmode; conf_config()->audio.src_fmt = AUFMT_FLOAT; conf_config()->audio.play_fmt = AUFMT_FLOAT; err = mock_ausrc_register(&ausrc, baresip_ausrcl()); TEST_ERR(err); err = mock_auplay_register(&auplay, baresip_auplayl(), audio_sample_handler, f); TEST_ERR(err); f->estab_action = ACTION_NOTHING; f->behaviour = BEHAVIOUR_ANSWER; /* Make a call from A to B */ err = ua_connect(f->a.ua, 0, NULL, f->buri, VIDMODE_OFF); TEST_ERR(err); /* run main-loop with timeout, wait for events */ err = re_main_timeout(15000); TEST_ERR(err); TEST_ERR(fix.err); ASSERT_EQ(0, fix.a.n_incoming); ASSERT_EQ(1, fix.a.n_established); ASSERT_EQ(0, fix.a.n_closed); ASSERT_EQ(0, fix.a.close_scode); ASSERT_EQ(1, fix.b.n_incoming); ASSERT_EQ(1, fix.b.n_established); ASSERT_EQ(0, fix.b.n_closed); out: conf_config()->audio.src_fmt = AUFMT_S16LE; conf_config()->audio.play_fmt = AUFMT_S16LE; fixture_close(f); mem_deref(auplay); mem_deref(ausrc); if (fix.err) return fix.err; return err; } int test_call_format_float(void) { int err; err = test_media_base(AUDIO_MODE_POLL); ASSERT_EQ(0, err); conf_config()->audio.txmode = AUDIO_MODE_POLL; out: return err; } int test_call_mediaenc(void) { struct fixture fix, *f = &fix; struct ausrc *ausrc = NULL; struct auplay *auplay = NULL; int err = 0; mock_menc_register(); /* Enable a dummy media encryption protocol */ fixture_init_prm(f, ";mediaenc=xrtp;ptime=1"); ASSERT_STREQ("xrtp", account_mediaenc(ua_account(f->a.ua))); err = mock_ausrc_register(&ausrc, baresip_ausrcl()); TEST_ERR(err); err = mock_auplay_register(&auplay, baresip_auplayl(), audio_sample_handler, f); TEST_ERR(err); f->estab_action = ACTION_NOTHING; f->behaviour = BEHAVIOUR_ANSWER; /* Make a call from A to B */ err = ua_connect(f->a.ua, 0, NULL, f->buri, VIDMODE_OFF); TEST_ERR(err); /* run main-loop with timeout, wait for events */ err = re_main_timeout(5000); TEST_ERR(err); TEST_ERR(fix.err); ASSERT_EQ(1, fix.a.n_established); ASSERT_EQ(0, fix.a.n_closed); ASSERT_EQ(1, fix.b.n_established); ASSERT_EQ(0, fix.b.n_closed); /* verify that the call was encrypted */ ASSERT_EQ(1, fix.a.n_mediaenc); ASSERT_EQ(1, fix.b.n_mediaenc); out: fixture_close(f); mem_deref(auplay); mem_deref(ausrc); mock_menc_unregister(); if (fix.err) return fix.err; return err; } int test_call_medianat(void) { struct fixture fix, *f = &fix; struct ausrc *ausrc = NULL; struct auplay *auplay = NULL; int err; mock_mnat_register(baresip_mnatl()); /* Enable a dummy media NAT-traversal protocol */ fixture_init_prm(f, ";medianat=XNAT;ptime=1"); ASSERT_STREQ("XNAT", account_medianat(ua_account(f->a.ua))); err = mock_ausrc_register(&ausrc, baresip_ausrcl()); TEST_ERR(err); err = mock_auplay_register(&auplay, baresip_auplayl(), audio_sample_handler, f); TEST_ERR(err); f->estab_action = ACTION_NOTHING; f->behaviour = BEHAVIOUR_ANSWER; /* Make a call from A to B */ err = ua_connect(f->a.ua, 0, NULL, f->buri, VIDMODE_OFF); TEST_ERR(err); /* run main-loop with timeout, wait for events */ err = re_main_timeout(5000); TEST_ERR(err); TEST_ERR(fix.err); ASSERT_EQ(1, fix.a.n_established); ASSERT_EQ(0, fix.a.n_closed); ASSERT_EQ(1, fix.b.n_established); ASSERT_EQ(0, fix.b.n_closed); out: fixture_close(f); mem_deref(auplay); mem_deref(ausrc); mock_mnat_unregister(); if (fix.err) return fix.err; return err; } int test_call_custom_headers(void) { struct fixture fix, *f = &fix; int err = 0; int some_id = 7; struct list custom_hdrs; bool headers_matched = true; fixture_init(f); ua_add_xhdr_filter(f->b.ua, "X-CALL_ID"); ua_add_xhdr_filter(f->b.ua, "X-HEADER_NAME"); f->behaviour = BEHAVIOUR_GET_HDRS; /* Make a call from A to B * with some custom headers in INVITE message */ list_init(&custom_hdrs); err = custom_hdrs_add(&custom_hdrs, "X-CALL_ID", "%d", some_id); err |= custom_hdrs_add(&custom_hdrs, "X-HEADER_NAME", "%s", "VALUE"); TEST_ERR(err); err = ua_set_custom_hdrs(f->a.ua, &custom_hdrs); TEST_ERR(err); err = ua_connect(f->a.ua, 0, NULL, f->buri, VIDMODE_OFF); TEST_ERR(err); list_flush(&custom_hdrs); TEST_ERR(err); /* run main-loop with timeout, wait for events */ err = re_main_timeout(5000); if (!list_isempty(hdrs)) { struct le *le; for (le = list_head(hdrs); le; le = le->next) { struct sip_hdr *hdr = le->data; if (pl_strcasecmp(&hdr->name, "X-CALL_ID") == 0) { char buf[20]; re_snprintf(buf, sizeof(buf), "%d", some_id); if (pl_strcasecmp(&hdr->val, buf) != 0) { headers_matched = false; } } if (pl_strcasecmp(&hdr->name, "X-HEADER_NAME") == 0) { if (pl_strcasecmp(&hdr->val, "VALUE") != 0) { headers_matched = false; } } } } else { headers_matched = false; } ASSERT_TRUE(headers_matched); TEST_ERR(err); TEST_ERR(fix.err); ASSERT_EQ(0, fix.a.n_incoming); ASSERT_EQ(1, fix.a.n_established); ASSERT_EQ(0, fix.a.n_closed); ASSERT_EQ(0, fix.a.close_scode); ASSERT_EQ(1, fix.b.n_incoming); ASSERT_EQ(1, fix.b.n_established); ASSERT_EQ(0, fix.b.n_closed); out: fixture_close(f); return err; } int test_call_tcp(void) { struct fixture fix, *f = &fix; int err = 0; fixture_init(f); f->behaviour = BEHAVIOUR_ANSWER; /* Make a call using TCP-transport */ err = ua_connect(f->a.ua, 0, NULL, f->buri_tcp, VIDMODE_OFF); TEST_ERR(err); /* run main-loop with timeout, wait for events */ err = re_main_timeout(5000); TEST_ERR(err); TEST_ERR(fix.err); ASSERT_EQ(1, fix.a.n_established); ASSERT_EQ(1, fix.b.n_established); out: fixture_close(f); return err; } /* * Step 1. Call from A to B * * Step 2. A transfer B to C * * Step 3. Call between B and C * No call for A */ int test_call_transfer(void) { struct fixture fix, *f = &fix; int err = 0; fixture_init(f); /* Create a 3rd useragent needed for transfer */ err = ua_alloc(&f->c.ua, "C ;regint=0"); TEST_ERR(err); f->c.peer = &f->b; f->behaviour = BEHAVIOUR_ANSWER; f->estab_action = ACTION_TRANSFER; err = ua_connect(f->a.ua, 0, NULL, f->buri, VIDMODE_OFF); TEST_ERR(err); /* run main-loop with timeout, wait for events */ err = re_main_timeout(5000); TEST_ERR(err); TEST_ERR(fix.err); ASSERT_EQ(0, fix.a.n_incoming); ASSERT_EQ(1, fix.a.n_established); ASSERT_EQ(1, fix.a.n_closed); ASSERT_EQ(0, fix.a.n_transfer); ASSERT_EQ(1, fix.b.n_incoming); ASSERT_EQ(2, fix.b.n_established); ASSERT_EQ(1, fix.b.n_closed); ASSERT_EQ(1, fix.b.n_transfer); ASSERT_EQ(1, fix.c.n_incoming); ASSERT_EQ(1, fix.c.n_established); ASSERT_EQ(0, fix.c.n_closed); ASSERT_EQ(0, fix.c.n_transfer); ASSERT_EQ(0, list_count(ua_calls(f->a.ua))); ASSERT_EQ(1, list_count(ua_calls(f->b.ua))); ASSERT_EQ(1, list_count(ua_calls(f->c.ua))); out: fixture_close(f); return err; } int test_call_rtcp(void) { struct fixture fix, *f = &fix; int err = 0; /* Use a low packet time, so the test completes quickly */ fixture_init_prm(f, ";ptime=1"); f->behaviour = BEHAVIOUR_ANSWER; f->estab_action = ACTION_NOTHING; f->stop_on_rtcp = true; /* Make a call from A to B */ err = ua_connect(f->a.ua, 0, NULL, f->buri, VIDMODE_OFF); TEST_ERR(err); /* run main-loop with timeout, wait for events */ err = re_main_timeout(5000); TEST_ERR(err); TEST_ERR(fix.err); /* verify that one or more RTCP packets were received */ ASSERT_TRUE(fix.a.n_rtcp > 0); ASSERT_TRUE(fix.b.n_rtcp > 0); out: fixture_close(f); return err; } int test_call_aufilt(void) { int err; mock_aufilt_register(baresip_aufiltl()); err = test_media_base(AUDIO_MODE_POLL); ASSERT_EQ(0, err); out: mock_aufilt_unregister(); return err; } /* * Simulate a complete WebRTC testcase */ int test_call_webrtc(void) { struct fixture fix, *f = &fix; struct ausrc *ausrc = NULL; struct vidsrc *vidsrc = NULL; struct sdp_media *sdp_a, *sdp_b; int err; mock_mnat_register(baresip_mnatl()); mock_menc_register(); err = mock_ausrc_register(&ausrc, baresip_ausrcl()); TEST_ERR(err); /* to enable video, we need one vidsrc and vidcodec */ mock_vidcodec_register(); err = mock_vidsrc_register(&vidsrc); TEST_ERR(err); fixture_init_prm(f, ";medianat=XNAT;mediaenc=xrtp"); f->estab_action = ACTION_NOTHING; f->behaviour = BEHAVIOUR_ANSWER; f->stop_on_rtp = true; /* Make a call from A to B */ err = ua_connect(f->a.ua, 0, NULL, f->buri, VIDMODE_ON); TEST_ERR(err); /* run main-loop with timeout, wait for events */ err = re_main_timeout(5000); TEST_ERR(err); TEST_ERR(fix.err); /* verify MNAT */ /* verify that MENC is secure */ ASSERT_TRUE( stream_is_secure(audio_strm(call_audio(ua_call(f->a.ua))))); ASSERT_TRUE( stream_is_secure(audio_strm(call_audio(ua_call(f->b.ua))))); ASSERT_TRUE( stream_is_secure(video_strm(call_video(ua_call(f->a.ua))))); ASSERT_TRUE( stream_is_secure(video_strm(call_video(ua_call(f->b.ua))))); /* verify that one or more RTP packets were received */ ASSERT_TRUE(fix.a.n_rtpestab > 0); ASSERT_TRUE(fix.b.n_rtpestab > 0); ASSERT_TRUE(call_has_video(ua_call(f->a.ua))); ASSERT_TRUE(call_has_video(ua_call(f->b.ua))); /* Verify SDP attributes */ sdp_a = stream_sdpmedia(audio_strm(call_audio(ua_call(f->a.ua)))); sdp_b = stream_sdpmedia(audio_strm(call_audio(ua_call(f->b.ua)))); ASSERT_TRUE(NULL != sdp_media_rattr(sdp_a, "ssrc")); ASSERT_EQ(20, atoi(sdp_media_rattr(sdp_a, "ptime"))); ASSERT_TRUE(NULL != sdp_media_rattr(sdp_b, "ssrc")); ASSERT_EQ(20, atoi(sdp_media_rattr(sdp_b, "ptime"))); out: fixture_close(f); mem_deref(vidsrc); mem_deref(ausrc); mock_vidcodec_unregister(); mock_menc_unregister(); mock_mnat_unregister(); if (fix.err) return fix.err; return err; } baresip-1.0.0/test/ccheck.py000077500000000000000000000265351372575704200157400ustar00rootroot00000000000000#! /usr/bin/env python3 # # ccheck.py Code Checker # # Copyright (C) 2005 - 2012 Alfred E. Heggestad # Copyright (C) 2010 - 2012 Creytiv.com # # 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. # # Contributors: # # Haavard Wik Thorkildssen # Mal Minhas # Sebastian Reimers # # # TODO: # - optimize regex functions # - count max y lines # import sys, os, re, fnmatch, getopt PROGRAM = 'ccheck' VERSION = '0.2.0' AUTHOR = 'Alfred E. Heggestad' ### ### Class definition ### class ccheck: def __init__(self): self.errors = 0 self.cur_filename = '' self.cur_lineno = 0 self.empty_lines_count = 0 self.cc_count = 0 self.files = {} self.extensions = ['c', 'cpp', 'h', 'mk', 'm4', 'py', 'm', 's', 'java', 'php'] self.operators = ["do", "if", "for", "while", "switch"] self.re_tab = re.compile('(\w+\W*)\(') self.re_else = re.compile('\s*\}\s*else') self.re_inc = re.compile('(^\s+\w+[+-]{2};)') self.re_hex = re.compile('0x([0-9A-Fa-f]+)') # empty dict for e in self.extensions: self.files[e] = [] # todo: global config self.common_checks = [self.check_whitespace, self.check_termination, self.check_hex_lowercase, self.check_pre_incr, self.check_file_unix] self.funcmap = { 'c': [self.check_brackets, self.check_c_preprocessor, self.check_indent_tab], 'h': [self.check_brackets, self.check_indent_tab], 'cpp': [self.check_brackets, self.check_indent_tab], 'mk': [self.check_indent_tab], 'm4': [self.check_brackets, self.check_c_comments, self.check_indent_tab], 'py': [self.check_brackets, self.check_indent_space], 'm': [self.check_brackets, self.check_c_preprocessor, self.check_indent_tab], 's': [self.check_indent_tab, self.check_c_preprocessor], 'java': [self.check_brackets, self.check_indent_tab], 'php': [self.check_brackets, self.check_indent_tab], } self.extmap = { 'c': ['*.c'], 'h': ['*.h'], 'cpp': ['*.cpp', '*.cc'], 'mk': ['*Makefile', '*.mk'], 'm4': ['*.m4'], 'py': ['*.py'], 'm': ['*.m'], 's': ['*.s', '*.S'], 'java': ['*.java'], 'php': ['*.php'], } self.maxsize = { 'c': (79, 3000), 'h': (79, 1000), 'cpp': (79, 3000), 'mk': (79, 1000), 'm4': (79, 3000), 'py': (79, 3000), 'm': (79, 3000), 's': (79, 3000), 'java': (179, 3000), 'php': (179, 3000), } def __del__(self): pass # # print an error message and increase error count # def error(self, msg): print("%s:%d: %s" % \ (self.cur_filename, self.cur_lineno, msg), file=sys.stderr) self.errors += 1 # # print statistics # def print_stats(self): print("Statistics:") print("~~~~~~~~~~~") print("Number of files processed: ", end=' ') for e in self.extensions: print(" %s: %d" % (e, len(self.files[e])), end=' ') print("") print("Number of lines with errors: %d" % self.errors) print("") # # check for strange white space # def check_whitespace(self, line, len): if len > 0: # general trailing whitespace check if line[-1] == ' ': self.error("has trailing space(s)") if line[-1] == '\t': self.error("has trailing tab(s)") # check for empty lines count if self.cur_lineno == 1: self.empty_lines_count = 0 if len == 0: self.empty_lines_count += 1 else: self.empty_lines_count = 0 if self.empty_lines_count > 2: self.error("should have maximum two empty lines (%d)" % \ self.empty_lines_count) self.empty_lines_count = 0 # # check for strange white space # def check_indent_tab(self, line, len): # make sure TAB is used for indentation for n in range(4, 17, 4): if len > n and line[0:n] == ' '*n and line[n] != ' ': self.error("starts with %d spaces, use tab instead" % n) def check_indent_space(self, line, len): if len > 1 and line[0] == '\t': self.error("starts with TAB, use 4 spaces instead") # # check for end of line termination issues # def check_termination(self, line, len): if len < 2: return if line[-2:] == ';;': self.error("has double semicolon") if line[-2:] == ' ;' and re.search('[\S]+[ \t]+;$', line): self.error("has spaces before terminator") # # check for C++ comments # def check_c_preprocessor(self, line, len): index = line.find('//') if index != -1 and line[index-1] != ':': if not re.search('["]+.*//.*["]+', line): self.error("C++ comment, use C comments /* ... */ instead") # # check that C comments are not used # def check_c_comments(self, line, len): if self.cur_lineno == 1: self.cc_count = 0 cc = False if line.find('/*') != -1: self.cc_count += 1 if line.find('*/') != -1: if self.cc_count > 0: cc = True self.cc_count = 0 if cc: self.error("C comment, use Perl-style comments # ... instead"); # # check max line length and number of lines # def check_xy_max(self, line, line_len, max_x): # expand TAB to 8 spaces l = len(line.expandtabs()) if l > max_x: self.error("line is too wide (" + str(l) + " - max " \ + str(max_x) + ")"); # TODO: # if ($line > $max_y) { # self.error("is too big ($lines lines - max $max_y)\n"); # # check that hexadecimal numbers are lowercase # def check_hex_lowercase(self, line, len): m = self.re_hex.search(line) if m: a = m.group(1) if re.search('[A-F]+', a): self.error("0x%s should be lowercase" % a) # # check for correct brackets usage in C/C++ # # TODO: this is too slow, optimize # def check_brackets(self, line, len): m = self.re_tab.search(line) if m: keyword = m.group(1) if keyword.strip() in self.operators: if not re.search('[ ]{1}', keyword): self.error("no single space after operator '%s()'" \ % keyword) # check that else statements do not have preceeding # end-bracket on the same line if self.re_else.search(line): self.error("else: ending if bracket should be on previous line") # # check that file is in Unix format # def check_file_unix(self, line, len): if len < 1: return if line[-1] == '\r': self.error("not in Unix format"); # # check for post-increment/decrement # def check_pre_incr(self, line, len): m = self.re_inc.search(line) if m: op = m.group(1) if op.find('++') != -1: self.error("Use pre-increment: %s" % op); else: self.error("Use pre-decrement: %s" % op); def process_line(self, line, funcs, ext): line = line.rstrip('\n') line_len = len(line) for func in self.common_checks: func(line, line_len) for func in funcs: func(line, line_len) if ext in self.maxsize: (x, y) = self.maxsize[ext]; self.check_xy_max(line, line_len, x) def parse_file(self, filename, ext): funcs = self.funcmap[ext] f = open(filename) self.cur_filename = filename while 1: lines = f.readlines(100000) if not lines: break self.cur_lineno = 0 for line in lines: self.cur_lineno += 1 self.process_line(line, funcs, ext) def parse_any_file(self, f): for e in self.extensions: em = self.extmap[e] for m in em: if fnmatch.fnmatch(f, m): self.files[e].append(f) self.parse_file(f, e) return print("unknown extension: " + f) def rec_quasiglob(self, top, patterns, exclude): for root, dirs, files in os.walk(top, topdown=False): for f in files: for pattern in patterns: if fnmatch.fnmatch(f, pattern): path = os.path.join(root, f) parse = True for excl in exclude: if path.find(excl) >= 0: parse = False if parse: self.parse_any_file(path) def build_file_list(self, top, exclude): for e in self.extensions: em = self.extmap[e] self.rec_quasiglob(top, em, exclude) ### ### END OF CLASS ### def usage(): print("%s version %s" % (PROGRAM, VERSION)) print("") print("Usage:") print("") print(" %s [options] [file]... [dir]..." % PROGRAM) print("") print("options:") print("") print(" -h --help Display help") print(" -V --version Show version info") print(" -q --quiet Print warnings only") print(" -e --exclude Exclude pattern(s)") # # main program # def main(): quiet = False exclude = [] try: opts, args = getopt.getopt(sys.argv[1:], \ 'hVqe:', ['help', 'version', 'quiet', 'exclude=']) except getopt.GetoptError as err: print(str(err)) usage() sys.exit(2) for o, a in opts: if o in ('-h', '--help'): usage() sys.exit() elif o in ('-V', '--version'): print("%s version %s, written by %s" % (PROGRAM, VERSION, AUTHOR)) sys.exit() elif o in ('-q', '--quiet'): quiet = True elif o in ('-e', '--exclude'): exclude.append(a) else: assert False, "unhandled option" cc = ccheck() if len(args) >= 1: for f in args[0:]: if os.path.isdir(f): cc.build_file_list(f, exclude) elif os.path.isfile(f): cc.parse_any_file(f) else: print("unknown file type: " + f) else: # scan all files recursively cc.build_file_list('.', exclude) # done - print stats if not quiet: cc.print_stats() sys.exit(cc.errors != 0) if __name__ == "__main__": main() baresip-1.0.0/test/cmd.c000066400000000000000000000055721372575704200150500ustar00rootroot00000000000000/** * @file test/cmd.c Baresip selftest -- cmd * * Copyright (C) 2010 Creytiv.com */ #include #include #include #include "test.h" struct test { unsigned cmd_called; }; static int cmd_test(struct re_printf *pf, void *arg) { struct cmd_arg *carg = arg; struct test *test = carg->data; int err = 0; (void)pf; ASSERT_EQ('@', carg->key); ASSERT_TRUE(NULL == carg->prm); ++test->cmd_called; out: return err; } static const struct cmd cmdv[] = { {NULL, '@', 0, "Test command", cmd_test}, }; static int vprintf_null(const char *p, size_t size, void *arg) { (void)p; (void)size; (void)arg; return 0; } static struct re_printf pf_null = {vprintf_null, 0}; int test_cmd(void) { struct commands *commands = NULL; struct cmd_ctx *ctx = 0; struct test test; int err = 0; memset(&test, 0, sizeof(test)); err = cmd_init(&commands); ASSERT_EQ(0, err); err = cmd_register(commands, cmdv, ARRAY_SIZE(cmdv)); ASSERT_EQ(0, err); /* it is not possible to register same block twice */ ASSERT_EQ(EALREADY, cmd_register(commands, cmdv, ARRAY_SIZE(cmdv))); /* issue a different command */ err = cmd_process(commands, &ctx, 'h', &pf_null, &test); ASSERT_EQ(0, err); ASSERT_EQ(0, test.cmd_called); /* issue our command, expect handler to be called */ err = cmd_process(commands, &ctx, '@', &pf_null, &test); ASSERT_EQ(0, err); ASSERT_EQ(1, test.cmd_called); cmd_unregister(commands, cmdv); /* verify that context was not created */ ASSERT_TRUE(NULL == ctx); out: mem_deref(commands); return err; } static int long_handler(struct re_printf *pf, void *arg) { struct cmd_arg *carg = arg; struct test *test = carg->data; int err = 0; (void)pf; ASSERT_STREQ("123", carg->prm); ++test->cmd_called; out: return err; } static const struct cmd longcmdv[] = { { "test", 0, 0, "Test Command", long_handler}, }; int test_cmd_long(void) { struct commands *commands = NULL; struct test test; const struct cmd *cmd; static const char *input_str = "/test 123\n"; struct cmd_ctx *ctx = NULL; size_t i; int err; memset(&test, 0, sizeof(test)); err = cmd_init(&commands); ASSERT_EQ(0, err); /* Verify that the command does not exist */ cmd = cmd_find_long(commands, "test"); ASSERT_TRUE(cmd == NULL); /* Register and verify command */ err = cmd_register(commands, longcmdv, ARRAY_SIZE(longcmdv)); ASSERT_EQ(0, err); cmd = cmd_find_long(commands, "test"); ASSERT_TRUE(cmd != NULL); /* Feed it some input data .. */ for (i=0; i #include #include #include "test.h" int test_contact(void) { struct contacts *contacts = NULL; struct contact *c; const char *addr = "Neil Young "; const char *uri = "sip:neil@young.com"; struct pl pl_addr; int err; err = contact_init(&contacts); ASSERT_EQ(0, err); /* Verify that we have no contacts */ ASSERT_EQ(0, list_count(contact_list(contacts))); c = contact_find(contacts, "sip:null@void.com"); ASSERT_TRUE(c == NULL); /* Add one contact, list should have one entry and find should return the added contact */ pl_set_str(&pl_addr, addr); err = contact_add(contacts, &c, &pl_addr); ASSERT_EQ(0, err); ASSERT_TRUE(c != NULL); ASSERT_EQ(1, list_count(contact_list(contacts))); c = contact_find(contacts, uri); ASSERT_TRUE(c != NULL); ASSERT_STREQ(addr, contact_str(c)); ASSERT_STREQ(uri, contact_uri(c)); /* Delete 1 contact, verify that list is empty */ mem_deref(c); ASSERT_EQ(0, list_count(contact_list(contacts))); out: mem_deref(contacts); return err; } baresip-1.0.0/test/event.c000066400000000000000000000020271372575704200154160ustar00rootroot00000000000000/** * @file test/event.c Baresip selftest -- event handling * * Copyright (C) 2010 Creytiv.com */ #include #include #include #include "test.h" int test_event(void) { struct odict *od = NULL; size_t i; int err = 0; static const enum ua_event eventv[] = { UA_EVENT_REGISTERING, UA_EVENT_REGISTER_OK, UA_EVENT_REGISTER_FAIL, UA_EVENT_UNREGISTERING, UA_EVENT_SHUTDOWN, UA_EVENT_EXIT /* .. more events .. */ }; for (i=0; i= 2); /* verify the mandatory entries */ entry = odict_lookup(od, "type"); ASSERT_TRUE(entry != NULL); ASSERT_EQ(ODICT_STRING, entry->type); ASSERT_STREQ(uag_event_str(ev), entry->u.str); od = mem_deref(od); } out: mem_deref(od); return err; } baresip-1.0.0/test/main.c000066400000000000000000000105011372575704200152150ustar00rootroot00000000000000/** * @file test/main.c Selftest for Baresip core * * Copyright (C) 2010 Creytiv.com */ #include #include #include #include "test.h" typedef int (test_exec_h)(void); struct test { test_exec_h *exec; const char *name; }; #define TEST(a) {a, #a} static const struct test tests[] = { TEST(test_account), TEST(test_aulevel), TEST(test_call_answer), TEST(test_call_answer_hangup_a), TEST(test_call_answer_hangup_b), TEST(test_call_aufilt), TEST(test_call_aulevel), TEST(test_call_custom_headers), TEST(test_call_dtmf), TEST(test_call_format_float), TEST(test_call_max), TEST(test_call_mediaenc), TEST(test_call_medianat), TEST(test_call_multiple), TEST(test_call_progress), TEST(test_call_reject), TEST(test_call_rtcp), TEST(test_call_rtp_timeout), TEST(test_call_tcp), TEST(test_call_transfer), TEST(test_call_video), TEST(test_call_webrtc), TEST(test_cmd), TEST(test_cmd_long), TEST(test_contact), TEST(test_event), TEST(test_message), TEST(test_network), TEST(test_play), TEST(test_ua_alloc), TEST(test_ua_options), TEST(test_ua_register), TEST(test_ua_register_auth), TEST(test_ua_register_auth_dns), TEST(test_ua_register_dns), TEST(test_uag_find_param), TEST(test_video), }; static int run_one_test(const struct test *test) { int err; re_printf("[ RUN ] %s\n", test->name); err = test->exec(); if (err) { warning("%s: test failed (%m)\n", test->name, err); return err; } re_printf("[ OK ]\n"); return 0; } static int run_tests(void) { size_t i; int err; for (i=0; i\n" "options:\n" "\t-l List all testcases and exit\n" "\t-v Verbose output (INFO level)\n" ); } int main(int argc, char *argv[]) { struct config *config; size_t i, ntests; bool verbose = false; int err; err = libre_init(); if (err) return err; log_enable_info(false); for (;;) { const int c = getopt(argc, argv, "hlv"); if (0 > c) break; switch (c) { case '?': case 'h': usage(); return -2; case 'l': test_listcases(); return 0; case 'v': if (verbose) log_enable_debug(true); else log_enable_info(true); verbose = true; break; default: break; } } if (argc >= (optind + 1)) ntests = argc - optind; else ntests = ARRAY_SIZE(tests); re_printf("running baresip selftest version %s with %zu tests\n", BARESIP_VERSION, ntests); /* note: run SIP-traffic on localhost */ config = conf_config(); if (!config) { err = ENOENT; goto out; } err = baresip_init(config); if (err) goto out; str_ncpy(config->sip.local, "127.0.0.1:0", sizeof(config->sip.local)); uag_set_exit_handler(ua_exit_handler, NULL); if (argc >= (optind + 1)) { for (i=0; i #include #include #include "test.h" struct test { enum sip_transp transp; int err; }; struct endpoint { struct test *test; struct endpoint *other; struct message *message; struct ua *ua; char uri[256]; unsigned n_msg; unsigned n_resp; }; static const char dummy_msg[] = "hei paa deg"; static const char text_plain[] = "text/plain"; static bool endpoint_is_complete(const struct endpoint *ep) { return ep->n_msg >= 1 || ep->n_resp >= 1; } static bool test_is_complete(struct endpoint *ep) { return endpoint_is_complete(ep) && endpoint_is_complete(ep->other); } static void message_recv_handler(struct ua *ua, const struct pl *peer, const struct pl *ctype, struct mbuf *body, void *arg) { struct endpoint *ep = arg; int err = 0; (void)ua; info("[ %s ] recv msg from %r: \"%b\"\n", ep->uri, peer, mbuf_buf(body), mbuf_get_left(body)); TEST_STRCMP(text_plain, strlen(text_plain), ctype->p, ctype->l); TEST_STRCMP(dummy_msg, str_len(dummy_msg), mbuf_buf(body), mbuf_get_left(body)); ++ep->n_msg; if (test_is_complete(ep)) { re_cancel(); return; } out: if (err) { ep->test->err = err; re_cancel(); } } static void send_resp_handler(int err, const struct sip_msg *msg, void *arg) { struct endpoint *ep = arg; ++ep->n_resp; if (err) { warning("sending failed: %m\n", err); goto out; } if (msg->scode >= 300) { warning("sending failed: %u %r\n", msg->scode, &msg->reason); err = EPROTO; goto out; } info("[ %s ] message sent OK\n", ep->uri); ASSERT_EQ(ep->test->transp, msg->tp); ASSERT_EQ(200, msg->scode); if (test_is_complete(ep)) { re_cancel(); return; } out: if (err) { ep->test->err = err; re_cancel(); } } static void endpoint_destructor(void *data) { struct endpoint *ep = data; mem_deref(ep->message); mem_deref(ep->ua); } static int endpoint_alloc(struct endpoint **epp, struct test *test, const char *name, enum sip_transp transp) { struct endpoint *ep = NULL; struct sa laddr; char aor[256]; int err = 0; err = sip_transp_laddr(uag_sip(), &laddr, transp, NULL); TEST_ERR(err); ep = mem_zalloc(sizeof(*ep), endpoint_destructor); if (!ep) return ENOMEM; ep->test = test; if (re_snprintf(aor, sizeof(aor), "%s ;regint=0", name, name, sip_transp_name(transp)) < 0) { err = ENOMEM; goto out; } if (re_snprintf(ep->uri, sizeof(ep->uri), "sip:%s@%J;transport=%s", name, &laddr, sip_transp_name(transp)) < 0) { err = ENOMEM; goto out; } err = ua_alloc(&ep->ua, aor); if (err) goto out; err = message_init(&ep->message); TEST_ERR(err); out: if (err) mem_deref(ep); else *epp = ep; return err; } static int test_message_transp(enum sip_transp transp) { struct test test; struct endpoint *a = NULL, *b = NULL; bool enable_udp, enable_tcp; int err = 0; enable_udp = transp == SIP_TRANSP_UDP; enable_tcp = transp == SIP_TRANSP_TCP; memset(&test, 0, sizeof(test)); test.transp = transp; err = ua_init("test", enable_udp, enable_tcp, false); TEST_ERR(err); err = endpoint_alloc(&a, &test, "a", transp); TEST_ERR(err); err = endpoint_alloc(&b, &test, "b", transp); TEST_ERR(err); a->other = b; b->other = a; /* NOTE: can only listen to one global instance for now */ err = message_listen(b->message, message_recv_handler, b); TEST_ERR(err); /* Send a message from A to B */ err = message_send(a->ua, b->uri, dummy_msg, send_resp_handler, a); TEST_ERR(err); err = re_main_timeout(1000); TEST_ERR(err); TEST_ERR(test.err); ASSERT_EQ(0, a->n_msg); ASSERT_EQ(1, a->n_resp); ASSERT_EQ(1, b->n_msg); ASSERT_EQ(0, b->n_resp); out: mem_deref(b); mem_deref(a); ua_close(); return err; } int test_message(void) { int err = 0; err = test_message_transp(SIP_TRANSP_UDP); TEST_ERR(err); err |= test_message_transp(SIP_TRANSP_TCP); TEST_ERR(err); out: return err; } baresip-1.0.0/test/mock/000077500000000000000000000000001372575704200150615ustar00rootroot00000000000000baresip-1.0.0/test/mock/cert.c000066400000000000000000000076311372575704200161710ustar00rootroot00000000000000/** * @file cert.c TLS Certificate * * Copyright (C) 2010 Creytiv.com */ #include #include "../test.h" /** * Dummy certificate for testing. * * * It was generated like this: * * $ openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem \ * -days 36500 -nodes * * * Dumping information: * * $ openssl x509 -subject -dates -fingerprint -in cert.pem * subject= /C=NO/ST=Retest/O=Retest AS/CN=Mr Retest/emailAddress=re@test.org * notBefore=Nov 23 18:40:38 2014 GMT * notAfter=Oct 30 18:40:38 2114 GMT * Fingerprint=49:A4:E9:F4:80:3A:D4:38:84:F1:64:C3:B9:4B:F9:BB:80:F7:07:76 */ const char test_certificate[] = "-----BEGIN CERTIFICATE-----\r\n" "MIIDmTCCAoGgAwIBAgIJAIt1/MAlTpB7MA0GCSqGSIb3DQEBCwUAMGIxCzAJBgNV\r\n" "BAYTAk5PMQ8wDQYDVQQIDAZSZXRlc3QxEjAQBgNVBAoMCVJldGVzdCBBUzESMBAG\r\n" "A1UEAwwJTXIgUmV0ZXN0MRowGAYJKoZIhvcNAQkBFgtyZUB0ZXN0Lm9yZzAgFw0x\r\n" "NDExMjMxODQwMzhaGA8yMTE0MTAzMDE4NDAzOFowYjELMAkGA1UEBhMCTk8xDzAN\r\n" "BgNVBAgMBlJldGVzdDESMBAGA1UECgwJUmV0ZXN0IEFTMRIwEAYDVQQDDAlNciBS\r\n" "ZXRlc3QxGjAYBgkqhkiG9w0BCQEWC3JlQHRlc3Qub3JnMIIBIjANBgkqhkiG9w0B\r\n" "AQEFAAOCAQ8AMIIBCgKCAQEAqnX4j6WK6tcN/X+C8C9ZSSlhVT2OdPB/lAPa3T3w\r\n" "eB3wu2C9gnZcCSvekBhyFKSi4w0Az5HNjJWWQqpSeYW2MCEKI97DIu0hg/5qn2le\r\n" "2sDjo4u/SNdH0CQHaLD2Xu0hhvZ/dTIulxpy5hLVmxs8/UZ8QKZ3vxDFE92p4LBL\r\n" "tLYz6+TvWovmUqYL97J+2muXUMcZCCTbk8DQSGLBbsawXejVF8RgPiFHCvefybUQ\r\n" "JCbtTDTfMykVnMEv3yMmfcXG/mwG8CLDRv7y8wh632aDdWfKN+g70gH0CFdjn070\r\n" "eIZyJ3TyRi4b55RSC4FAdP2YKToOUH55N86wrbprnHb8swIDAQABo1AwTjAdBgNV\r\n" "HQ4EFgQUcaZeVPUmMPFvKwYzn27b8BUJV3AwHwYDVR0jBBgwFoAUcaZeVPUmMPFv\r\n" "KwYzn27b8BUJV3AwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAbsMt\r\n" "zruNpBUZv08vdoWN9QWaJrmv8fvcx/RcuVLRuAaLYExEUJnoz3+dNFbR38BvncVC\r\n" "LlDcSIK06JIHX6E7gJegWQdECoO/YgQGCwoIoQJtNCybxtZccb5uAGY/+qO3uOx0\r\n" "Vx1NxrAMh5cpOIhZ8XiSYA2+JB71prW97diSQS+cU9xWCJxPU7UqQ10nV7PbfSmp\r\n" "XTnj+togZPXYzJmSQR4RoM4Vqu27syo7xYQ90twoRKpRYTPdDTArpkTn6KuUuCJ1\r\n" "t2v9LOkkxOvF11rLY6rLf0BG4XYkhnz4CLLt428wvAPykPcs95Q9TwpF/nKEwyfh\r\n" "J+cC3FZTiBf/YmPPaA==\r\n" "-----END CERTIFICATE-----\r\n" "-----BEGIN PRIVATE KEY-----\r\n" "MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCqdfiPpYrq1w39\r\n" "f4LwL1lJKWFVPY508H+UA9rdPfB4HfC7YL2CdlwJK96QGHIUpKLjDQDPkc2MlZZC\r\n" "qlJ5hbYwIQoj3sMi7SGD/mqfaV7awOOji79I10fQJAdosPZe7SGG9n91Mi6XGnLm\r\n" "EtWbGzz9RnxApne/EMUT3angsEu0tjPr5O9ai+ZSpgv3sn7aa5dQxxkIJNuTwNBI\r\n" "YsFuxrBd6NUXxGA+IUcK95/JtRAkJu1MNN8zKRWcwS/fIyZ9xcb+bAbwIsNG/vLz\r\n" "CHrfZoN1Z8o36DvSAfQIV2OfTvR4hnIndPJGLhvnlFILgUB0/ZgpOg5Qfnk3zrCt\r\n" "umucdvyzAgMBAAECggEAC1xxhKFz8NMEi7DD+V4uhUHMyvGfXQvqdOMM41INhPP5\r\n" "54M7HkblO3dBDjmS4O1YLenf8/WzzXrq2OahOJhA3FRXaKygNOO5KCL82EMdn1bb\r\n" "1TqrNR+kGatNEx04TntfkK89L4J4uHl6zvrSYdQe7IKWJXjy4jkr6XcMq30Ujqa6\r\n" "Val03Cr40VL0ZSYXnwTf/P65GtQTdyTOemYkUbMH9qRoxHmE7ZsPRpbXU4k30JWh\r\n" "6VYy+7h5XmjrX+VdIiia6sMjy0mbtsxJb6DOo19ro4DfF5JmFZpXnBhsJGhMxiEM\r\n" "94QEC5Tv6b0hWomFpOm3I5jOnktavCFQ1NsNHUspgQKBgQDUQm2+F06YdC6Pgt+9\r\n" "COnd9rz2lB2TjGRIJvis6MW7EfQ7XHkH9y/sDGLzINBVn6DkaHmQZDrIg77Mey+H\r\n" "LG0QL6+7WK7c1X/Zga6LKvkLlmcMWq6i1uu+Q3UODu7XcFh6f8kDThP+BubfUWpw\r\n" "rCRq74gF1JzQISoKqmyW/AXMZQKBgQDNln0jzgh/ySWRjJbuh6GqPQunDQsh3K3I\r\n" "4WDHK40NHFgIzPomKO+pqsOu3V/X81NARqfUyoIp/455YRheLHBUJg7maLfxrBq/\r\n" "qQPEUwSAI6lheMz1WNWri65GvwBlVENajVuMh/xfmKVL1KVV+LXGO5L1UClWITCM\r\n" "VSC0QT8XNwKBgQC7bYUWS+JdAIp0su36MDrCgzPM0HFlbpzGkZMYq9qeG3Z8TGWb\r\n" "QQyR9UYSxjDwyqn5xr9BXyABG0SJr2UCiZosps8YMXEHE4d3eumzfdi4ALEx2YlH\r\n" "xVwZf9uG9Gy21D9svBW102YX8+Q94diJcZgezTBhZaKqrf4/uMl2cUh1eQKBgQDB\r\n" "heZYXOqdN0A5CUlOUbg5YutkHaAcCPpBvP33niRRchvgdOsIHsKzSL6ZDWPaCP+V\r\n" "4qy7XsE2PYzk7yQcCeLXI1glRe/Y+3PWdIfKN4dmA6u+yBLO5QeFSqALkmISAEbC\r\n" "p4vE9oD3j94RSqM0EUEy0ANfDk1K+UUU5FE7vKth8wKBgQCoKvPNfC3FmyhLK7EK\r\n" "zgfIYAcoi52EFu6xQ9PvZHg60ptYvq1L+H6LR8cxYfcrPTt3aDbFf41RahPkokNh\r\n" "2HDxiHd4HwWkAGiqZXCTA2znb+rnJ9fheI6g/Wb3p+oGeCFHMcdUcsl1qWBFDtax\r\n" "ygS/tEFgy1z2dVMLbLKqEUscsA==\r\n" "-----END PRIVATE KEY-----\r\n" ; baresip-1.0.0/test/mock/dnssrv.c000066400000000000000000000101121372575704200165370ustar00rootroot00000000000000/** * @file mock/dnssrv.c Mock DNS server * * Copyright (C) 2010 - 2016 Creytiv.com */ #include #include #include "../test.h" #define DEBUG_MODULE "mock/dnssrv" #define DEBUG_LEVEL 5 #include #define LOCAL_PORT 0 static void dns_server_match(struct dns_server *srv, struct list *rrl, const char *name, uint16_t type) { struct dnsrr *rr0 = NULL; struct le *le; le = srv->rrl.head; while (le) { struct dnsrr *rr = le->data; le = le->next; if (type == rr->type && 0==str_casecmp(name, rr->name)) { if (!rr0) rr0 = rr; list_append(rrl, &rr->le_priv, rr); } } /* If rotation is enabled, then rotate multiple entries in a deterministic way (no randomness please) */ if (srv->rotate && rr0) { list_unlink(&rr0->le); list_append(&srv->rrl, &rr0->le, rr0); } } static void decode_dns_query(struct dns_server *srv, const struct sa *src, struct mbuf *mb) { struct list rrl = LIST_INIT; struct dnshdr hdr; struct le *le; char *qname = NULL; size_t start, end; uint16_t type, dnsclass; int err = 0; start = mb->pos; end = mb->end; if (dns_hdr_decode(mb, &hdr) || hdr.qr || hdr.nq != 1) { DEBUG_WARNING("unable to decode query header\n"); return; } err = dns_dname_decode(mb, &qname, start); if (err) { DEBUG_WARNING("unable to decode query name\n"); goto out; } if (mbuf_get_left(mb) < 4) { err = EBADMSG; DEBUG_WARNING("unable to decode query type/class\n"); goto out; } type = ntohs(mbuf_read_u16(mb)); dnsclass = ntohs(mbuf_read_u16(mb)); DEBUG_INFO("dnssrv: type=%s query-name='%s'\n", dns_rr_typename(type), qname); if (dnsclass == DNS_CLASS_IN) { dns_server_match(srv, &rrl, qname, type); } hdr.qr = true; hdr.tc = false; hdr.rcode = DNS_RCODE_OK; hdr.nq = 1; hdr.nans = list_count(&rrl); mb->pos = start; err = dns_hdr_encode(mb, &hdr); if (err) goto out; mb->pos = end; DEBUG_INFO("dnssrv: @@ found %u answers for %s\n", list_count(&rrl), qname); for (le = rrl.head; le; le = le->next) { struct dnsrr *rr = le->data; err = dns_rr_encode(mb, rr, 0, NULL, start); if (err) goto out; } mb->pos = start; (void)udp_send(srv->us, src, mb); out: list_clear(&rrl); mem_deref(qname); } static void udp_recv(const struct sa *src, struct mbuf *mb, void *arg) { struct dns_server *srv = arg; decode_dns_query(srv, src, mb); } static void destructor(void *arg) { struct dns_server *srv = arg; list_flush(&srv->rrl); mem_deref(srv->us); } int dns_server_alloc(struct dns_server **srvp, bool rotate) { struct dns_server *srv; int err; if (!srvp) return EINVAL; srv = mem_zalloc(sizeof(*srv), destructor); if (!srv) return ENOMEM; err = sa_set_str(&srv->addr, "127.0.0.1", LOCAL_PORT); if (err) goto out; err = udp_listen(&srv->us, &srv->addr, udp_recv, srv); if (err) goto out; err = udp_local_get(srv->us, &srv->addr); if (err) goto out; srv->rotate = rotate; out: if (err) mem_deref(srv); else *srvp = srv; return err; } int dns_server_add_a(struct dns_server *srv, const char *name, uint32_t addr) { struct dnsrr *rr; int err; if (!srv || !name) return EINVAL; rr = dns_rr_alloc(); if (!rr) return ENOMEM; err = str_dup(&rr->name, name); if (err) goto out; rr->type = DNS_TYPE_A; rr->dnsclass = DNS_CLASS_IN; rr->ttl = 3600; rr->rdlen = 0; rr->rdata.a.addr = addr; list_append(&srv->rrl, &rr->le, rr); out: if (err) mem_deref(rr); return err; } int dns_server_add_srv(struct dns_server *srv, const char *name, uint16_t pri, uint16_t weight, uint16_t port, const char *target) { struct dnsrr *rr; int err; if (!srv || !name || !port || !target) return EINVAL; rr = dns_rr_alloc(); if (!rr) return ENOMEM; err = str_dup(&rr->name, name); if (err) goto out; rr->type = DNS_TYPE_SRV; rr->dnsclass = DNS_CLASS_IN; rr->ttl = 3600; rr->rdlen = 0; rr->rdata.srv.pri = pri; rr->rdata.srv.weight = weight; rr->rdata.srv.port = port; str_dup(&rr->rdata.srv.target, target); list_append(&srv->rrl, &rr->le, rr); out: if (err) mem_deref(rr); return err; } baresip-1.0.0/test/mock/mock_aucodec.c000066400000000000000000000025561372575704200176510ustar00rootroot00000000000000/** * @file mock/mock_aucodec.c Mock audio codec * * Copyright (C) 2010 - 2016 Creytiv.com */ #include #include #include #include #include "../test.h" static int mock_raw_encode(struct auenc_state *st, bool *marker, uint8_t *buf, size_t *len, int fmt, const void *sampv, size_t sampc) { const size_t sampsz = aufmt_sample_size(fmt); size_t bytes; (void)st; (void)marker; if (!buf || !len || !sampv) return EINVAL; if (sampsz == 0) return ENOTSUP; bytes = sampc * sampsz; if (bytes > *len) return ENOMEM; memcpy(buf, sampv, bytes); *len = bytes; return 0; } static int mock_raw_decode(struct audec_state *st, int fmt, void *sampv, size_t *sampc, bool marker, const uint8_t *buf, size_t len) { const size_t sampsz = aufmt_sample_size(fmt); (void)st; (void)marker; if (!buf || !len || !sampv) return EINVAL; if (sampsz == 0) return ENOTSUP; if (len / sampsz > *sampc) return ENOMEM; memcpy(sampv, buf, len); *sampc = len / sampsz; return 0; } static struct aucodec ac_dummy = { .name = "RAW-CODEC", .srate = 8000, .crate = 8000, .ch = 1, .pch = 1, .ench = mock_raw_encode, .dech = mock_raw_decode, }; void mock_aucodec_register(struct list *aucodecl) { aucodec_register(aucodecl, &ac_dummy); } void mock_aucodec_unregister(void) { aucodec_unregister(&ac_dummy); } baresip-1.0.0/test/mock/mock_aufilt.c000066400000000000000000000047431372575704200175320ustar00rootroot00000000000000/** * @file mock/mock_aufilt.c Mock audio filter * * Copyright (C) 2019 Creytiv.com */ #include #include #include #include #include "../test.h" struct mock_enc { struct aufilt_enc_st af; /* inheritance */ }; struct mock_dec { struct aufilt_enc_st af; /* inheritance */ }; static void enc_destructor(void *arg) { struct mock_enc *st = (struct mock_enc *)arg; list_unlink(&st->af.le); } static void dec_destructor(void *arg) { struct mock_dec *st = (struct mock_dec *)arg; list_unlink(&st->af.le); } static int mock_encode_update(struct aufilt_enc_st **stp, void **ctx, const struct aufilt *af, struct aufilt_prm *prm, const struct audio *au) { struct mock_enc *st; (void)ctx; (void)au; if (!stp || !af || !prm) return EINVAL; if (prm->srate==0 || prm->ch==0 || aufmt_sample_size(prm->fmt)==0) { warning("mock_aufilt: enc: invalid srate/ch/fmt params\n"); return EINVAL; } if (*stp) return 0; st = (struct mock_enc *)mem_zalloc(sizeof(*st), enc_destructor); if (!st) return ENOMEM; *stp = (struct aufilt_enc_st *)st; return 0; } static int mock_decode_update(struct aufilt_dec_st **stp, void **ctx, const struct aufilt *af, struct aufilt_prm *prm, const struct audio *au) { struct mock_dec *st; (void)ctx; (void)au; if (!stp || !af || !prm) return EINVAL; if (prm->srate==0 || prm->ch==0 || aufmt_sample_size(prm->fmt)==0) { warning("mock_aufilt: dec: invalid srate/ch/fmt params\n"); return EINVAL; } if (*stp) return 0; st = (struct mock_dec *)mem_zalloc(sizeof(*st), dec_destructor); if (!st) return ENOMEM; *stp = (struct aufilt_dec_st *)st; return 0; } static int mock_encode(struct aufilt_enc_st *st, struct auframe *af) { if (!st || !af) return EINVAL; if (0 == auframe_size(af) || !af->sampv) { warning("mock_aufilt: encode: invalid auframe\n"); return EINVAL; } return 0; } static int mock_decode(struct aufilt_dec_st *st, struct auframe *af) { if (!st || !af) return EINVAL; if (0 == auframe_size(af) || !af->sampv) { warning("mock_aufilt: decode: invalid auframe\n"); return EINVAL; } return 0; } static struct aufilt af_dummy = { .name = "MOCK-AUFILT", .encupdh = mock_encode_update, .ench = mock_encode, .decupdh = mock_decode_update, .dech = mock_decode, }; void mock_aufilt_register(struct list *aufiltl) { aufilt_register(aufiltl, &af_dummy); } void mock_aufilt_unregister(void) { aufilt_unregister(&af_dummy); } baresip-1.0.0/test/mock/mock_auplay.c000066400000000000000000000033651372575704200175400ustar00rootroot00000000000000/** * @file mock/mock_auplay.c Mock audio player * * Copyright (C) 2010 - 2016 Creytiv.com */ #include #include #include #include "../test.h" struct auplay_st { const struct auplay *ap; /* inheritance */ struct tmr tmr; struct auplay_prm prm; void *sampv; size_t sampc; auplay_write_h *wh; void *arg; }; static struct { mock_sample_h *sampleh; void *arg; } mock; static void auplay_destructor(void *arg) { struct auplay_st *st = arg; tmr_cancel(&st->tmr); mem_deref(st->sampv); } static void tmr_handler(void *arg) { struct auplay_st *st = arg; tmr_start(&st->tmr, st->prm.ptime, tmr_handler, st); if (st->wh) st->wh(st->sampv, st->sampc, st->arg); /* feed the audio-samples back to the test */ if (mock.sampleh) mock.sampleh(st->sampv, st->sampc, mock.arg); } static int mock_auplay_alloc(struct auplay_st **stp, const struct auplay *ap, struct auplay_prm *prm, const char *device, auplay_write_h *wh, void *arg) { struct auplay_st *st; int err = 0; (void)device; if (!stp || !ap || !prm) return EINVAL; st = mem_zalloc(sizeof(*st), auplay_destructor); if (!st) return ENOMEM; st->ap = ap; st->prm = *prm; st->wh = wh; st->arg = arg; st->sampc = prm->srate * prm->ch * prm->ptime / 1000; st->sampv = mem_zalloc(aufmt_sample_size(prm->fmt) * st->sampc, NULL); if (!st->sampv) { err = ENOMEM; goto out; } tmr_start(&st->tmr, 0, tmr_handler, st); out: if (err) mem_deref(st); else *stp = st; return err; } int mock_auplay_register(struct auplay **auplayp, struct list *auplayl, mock_sample_h *sampleh, void *arg) { mock.sampleh = sampleh; mock.arg = arg; return auplay_register(auplayp, auplayl, "mock-auplay", mock_auplay_alloc); } baresip-1.0.0/test/mock/mock_ausrc.c000066400000000000000000000032241372575704200173540ustar00rootroot00000000000000/** * @file mock/mock_ausrc.c Mock audio source * * Copyright (C) 2010 - 2016 Creytiv.com */ #include #include #include #include "../test.h" struct ausrc_st { const struct ausrc *as; /* inheritance */ struct tmr tmr; struct ausrc_prm prm; void *sampv; size_t sampc; ausrc_read_h *rh; void *arg; }; static void ausrc_destructor(void *arg) { struct ausrc_st *st = arg; tmr_cancel(&st->tmr); mem_deref(st->sampv); } static void tmr_handler(void *arg) { struct ausrc_st *st = arg; struct auframe af = { .fmt = st->prm.fmt, .sampv = st->sampv, .sampc = st->sampc, .timestamp = tmr_jiffies_usec() }; tmr_start(&st->tmr, st->prm.ptime, tmr_handler, st); if (st->rh) st->rh(&af, st->arg); } static int mock_ausrc_alloc(struct ausrc_st **stp, const struct ausrc *as, struct media_ctx **ctx, struct ausrc_prm *prm, const char *device, ausrc_read_h *rh, ausrc_error_h *errh, void *arg) { struct ausrc_st *st; int err = 0; (void)ctx; (void)device; (void)errh; if (!stp || !as || !prm) return EINVAL; st = mem_zalloc(sizeof(*st), ausrc_destructor); if (!st) return ENOMEM; st->as = as; st->prm = *prm; st->rh = rh; st->arg = arg; st->sampc = prm->srate * prm->ch * prm->ptime / 1000; st->sampv = mem_zalloc(aufmt_sample_size(prm->fmt) * st->sampc, NULL); if (!st->sampv) { err = ENOMEM; goto out; } tmr_start(&st->tmr, 0, tmr_handler, st); out: if (err) mem_deref(st); else *stp = st; return err; } int mock_ausrc_register(struct ausrc **ausrcp, struct list *ausrcl) { return ausrc_register(ausrcp, ausrcl, "mock-ausrc", mock_ausrc_alloc); } baresip-1.0.0/test/mock/mock_menc.c000066400000000000000000000060731372575704200171660ustar00rootroot00000000000000/** * @file mock/mock_menc.c Mock media encryption * * Copyright (C) 2010 - 2018 Creytiv.com */ #include #include #include #include "../test.h" #define SECRET_KEY 0xdd struct menc_sess { menc_event_h *eventh; void *arg; }; struct menc_media { struct udp_sock *rtpsock; struct udp_helper *uh_rtp; }; /* * Encrypt/decrypt an RTP payload with a dummy key. * We use a simple XOR scheme for simplicity. */ static void mock_crypt(struct mbuf *mb) { size_t i, len = mbuf_get_left(mb); for (i = RTP_HEADER_SIZE; i < len; i++) { mb->buf[mb->pos + i] ^= SECRET_KEY; } } static void media_destructor(void *data) { struct menc_media *mm = data; mem_deref(mm->uh_rtp); mem_deref(mm->rtpsock); } static bool send_handler(int *err, struct sa *dst, struct mbuf *mb, void *arg) { struct menc_media *mm = arg; (void)mm; (void)err; (void)dst; mock_crypt(mb); return false; /* continue processing */ } static bool recv_handler(struct sa *src, struct mbuf *mb, void *arg) { struct menc_media *mm = arg; (void)mm; (void)src; mock_crypt(mb); return false; /* continue processing */ } static void sess_destructor(void *arg) { struct menc_sess *sess = arg; (void)sess; } static int mock_session_alloc(struct menc_sess **sessp, struct sdp_session *sdp, bool offerer, menc_event_h *eventh, menc_error_h *errorh, void *arg) { struct menc_sess *sess; (void)offerer; (void)errorh; if (!sessp || !sdp) return EINVAL; sess = mem_zalloc(sizeof(*sess), sess_destructor); if (!sess) return ENOMEM; sess->eventh = eventh; sess->arg = arg; *sessp = sess; return 0; } static int mock_media_alloc(struct menc_media **mmp, struct menc_sess *sess, struct rtp_sock *rtp, struct udp_sock *rtpsock, struct udp_sock *rtcpsock, const struct sa *raddr_rtp, const struct sa *raddr_rtcp, struct sdp_media *sdpm, const struct stream *strm) { struct menc_media *mm; const int layer = 10; /* above zero */ int err = 0; (void)sess; (void)rtp; (void)rtcpsock; (void)raddr_rtp; (void)raddr_rtcp; if (!mmp || !sdpm) return EINVAL; mm = *mmp; if (!mm) { mm = mem_zalloc(sizeof(*mm), media_destructor); if (!mm) return ENOMEM; mm->rtpsock = mem_ref(rtpsock); err = udp_register_helper(&mm->uh_rtp, rtpsock, layer, send_handler, recv_handler, mm); if (err) goto out; *mmp = mm; } err = sdp_media_set_lattr(sdpm, true, "xrtp", NULL); if (err) goto out; if (sdp_media_rattr(sdpm, "xrtp")) { char buf[64]; re_snprintf(buf, sizeof(buf), "%s,xrtp", sdp_media_name(sdpm)); if (sess->eventh) sess->eventh(MENC_EVENT_SECURE, buf, (struct stream *)strm, sess->arg); } out: if (err) mem_deref(mm); return err; } static struct menc menc_mock = { .id = "XRTP", .sdp_proto = "RTP/XAVP", .wait_secure = true, .sessh = mock_session_alloc, .mediah = mock_media_alloc }; void mock_menc_register(void) { menc_register(baresip_mencl(), &menc_mock); } void mock_menc_unregister(void) { menc_unregister(&menc_mock); } baresip-1.0.0/test/mock/mock_mnat.c000066400000000000000000000055241372575704200172030ustar00rootroot00000000000000/** * @file mock/mock_mnat.c Mock media NAT-traversal * * Copyright (C) 2010 - 2018 Creytiv.com */ #include #include #include "../test.h" struct mnat_sess { struct list medial; struct tmr tmr; mnat_estab_h *estabh; void *arg; }; struct mnat_media { struct le le; struct sdp_media *sdpm; mnat_connected_h *connh; void *arg; }; static void sess_destructor(void *data) { struct mnat_sess *sess = data; tmr_cancel(&sess->tmr); list_flush(&sess->medial); } static void media_destructor(void *arg) { struct mnat_media *m = arg; list_unlink(&m->le); mem_deref(m->sdpm); } static void tmr_handler(void *data) { struct mnat_sess *sess = data; if (sess->estabh) sess->estabh(0, 0, "ok", sess->arg); } static int mnat_session_alloc(struct mnat_sess **sessp, const struct mnat *mnat, struct dnsc *dnsc, int af, const struct stun_uri *srv, const char *user, const char *pass, struct sdp_session *sdp, bool offerer, mnat_estab_h *estabh, void *arg) { struct mnat_sess *sess; (void)dnsc; (void)af; (void)srv; (void)user; (void)pass; (void)sdp; (void)offerer; if (!sessp || !mnat) return EINVAL; sess = mem_zalloc(sizeof(*sess), sess_destructor); if (!sess) return ENOMEM; sess->estabh = estabh; sess->arg = arg; /* Simulate async network traffic */ tmr_start(&sess->tmr, 0, tmr_handler, sess); *sessp = sess; return 0; } static int mnat_media_alloc(struct mnat_media **mp, struct mnat_sess *sess, struct udp_sock *sock1, struct udp_sock *sock2, struct sdp_media *sdpm, mnat_connected_h *connh, void *arg) { struct mnat_media *m; int err; (void)mp; (void)sess; (void)sock1; (void)sock2; (void)connh; (void)arg; if (!mp || !sess || !sock1 || !sdpm) return EINVAL; m = mem_zalloc(sizeof(*m), media_destructor); if (!m) return ENOMEM; err = sdp_media_set_lattr(sdpm, true, "xnat", NULL); if (err) goto out; m->sdpm = mem_ref(sdpm); m->connh = connh; m->arg = arg; list_append(&sess->medial, &m->le, m); out: if (err) mem_deref(m); else *mp = m; return err; } static int mnat_session_update(struct mnat_sess *sess) { struct le *le; if (!sess) return EINVAL; for (le = sess->medial.head; le; le = le->next) { struct mnat_media *m = le->data; struct sa rtp, rtcp; rtp = *sdp_media_raddr(m->sdpm); sdp_media_raddr_rtcp(m->sdpm, &rtcp); if (sa_isset(&rtp, SA_ALL) && sa_isset(&rtcp, SA_ALL)) { if (m->connh) m->connh(&rtp, &rtcp, m->arg); } } return 0; } static struct mnat mnat_mock = { .id = "XNAT", .wait_connected = true, .sessh = mnat_session_alloc, .mediah = mnat_media_alloc, .updateh = mnat_session_update, }; void mock_mnat_register(struct list *mnatl) { mnat_register(mnatl, &mnat_mock); } void mock_mnat_unregister(void) { mnat_unregister(&mnat_mock); } baresip-1.0.0/test/mock/mock_vidcodec.c000066400000000000000000000065751372575704200200330ustar00rootroot00000000000000/** * @file mock/mock_vidcodec.c Mock video codec * * Copyright (C) 2010 - 2016 Creytiv.com */ #include #include #include #include #include "../test.h" #define HDR_SIZE 12 struct hdr { enum vidfmt fmt; unsigned width; unsigned height; }; struct videnc_state { double fps; videnc_packet_h *pkth; void *arg; }; struct viddec_state { struct vidframe *frame; }; static int hdr_decode(struct hdr *hdr, struct mbuf *mb) { if (mbuf_get_left(mb) < HDR_SIZE) return EBADMSG; hdr->fmt = ntohl(mbuf_read_u32(mb)); hdr->width = ntohl(mbuf_read_u32(mb)); hdr->height = ntohl(mbuf_read_u32(mb)); return 0; } static void decode_destructor(void *arg) { struct viddec_state *vds = arg; mem_deref(vds->frame); } static int mock_encode_update(struct videnc_state **vesp, const struct vidcodec *vc, struct videnc_param *prm, const char *fmtp, videnc_packet_h *pkth, void *arg) { struct videnc_state *ves; (void)fmtp; if (!vesp || !vc || !prm || prm->pktsize < (HDR_SIZE + 1)) return EINVAL; ves = *vesp; if (!ves) { ves = mem_zalloc(sizeof(*ves), NULL); if (!ves) return ENOMEM; *vesp = ves; } ves->fps = prm->fps; ves->pkth = pkth; ves->arg = arg; return 0; } static int mock_encode(struct videnc_state *ves, bool update, const struct vidframe *frame, uint64_t timestamp) { struct mbuf *hdr; uint8_t payload[2] = {0,0}; uint64_t rtp_ts; int err; (void)update; if (!ves || !frame) return EINVAL; hdr = mbuf_alloc(16); err = mbuf_write_u32(hdr, htonl(frame->fmt)); err |= mbuf_write_u32(hdr, htonl(frame->size.w)); err |= mbuf_write_u32(hdr, htonl(frame->size.h)); if (err) goto out; rtp_ts = video_calc_rtp_timestamp_fix(timestamp); err = ves->pkth(true, rtp_ts, hdr->buf, hdr->end, payload, sizeof(payload), ves->arg); if (err) goto out; out: mem_deref(hdr); return err; } static int mock_decode_update(struct viddec_state **vdsp, const struct vidcodec *vc, const char *fmtp) { struct viddec_state *vds; (void)vc; (void)fmtp; if (!vdsp) return EINVAL; vds = *vdsp; if (vds) return 0; vds = mem_zalloc(sizeof(*vds), decode_destructor); if (!vds) return ENOMEM; *vdsp = vds; return 0; } static int mock_decode(struct viddec_state *vds, struct vidframe *frame, bool *intra, bool marker, uint16_t seq, struct mbuf *mb) { struct vidsz size; struct hdr hdr; int err, i; (void)marker; (void)seq; if (!vds || !frame || !intra || !mb) return EINVAL; *intra = false; err = hdr_decode(&hdr, mb); if (err) { warning("mock_vidcodec: could not decode header (%m)\n", err); return err; } size.w = hdr.width; size.h = hdr.height; if (!vds->frame) { err = vidframe_alloc(&vds->frame, hdr.fmt, &size); if (err) goto out; } for (i=0; i<4; i++) { frame->data[i] = vds->frame->data[i]; frame->linesize[i] = vds->frame->linesize[i]; } frame->size.w = vds->frame->size.w; frame->size.h = vds->frame->size.h; frame->fmt = vds->frame->fmt; out: return err; } static struct vidcodec vc_dummy = { .name = "H266", .encupdh = mock_encode_update, .ench = mock_encode, .decupdh = mock_decode_update, .dech = mock_decode, }; void mock_vidcodec_register(void) { vidcodec_register(baresip_vidcodecl(), &vc_dummy); } void mock_vidcodec_unregister(void) { vidcodec_unregister(&vc_dummy); } baresip-1.0.0/test/mock/mock_vidisp.c000066400000000000000000000035661372575704200175460ustar00rootroot00000000000000/** * @file mock/mock_vidisp.c Mock video display * * Copyright (C) 2010 - 2016 Creytiv.com */ #include #include #include #include "../test.h" #define MAX_WIDTH 65536 #define MAX_HEIGHT 65536 struct vidisp_st { const struct vidisp *vd; /* inheritance */ unsigned n_frame; }; static struct { mock_vidisp_h *disph; void *arg; } mock; static void disp_destructor(void *arg) { struct vidisp_st *st = arg; (void)st; } static int mock_disp_alloc(struct vidisp_st **stp, const struct vidisp *vd, struct vidisp_prm *prm, const char *dev, vidisp_resize_h *resizeh, void *arg) { struct vidisp_st *st; (void)prm; (void)dev; (void)resizeh; (void)arg; if (!stp || !vd) return EINVAL; st = mem_zalloc(sizeof(*st), disp_destructor); if (!st) return ENOMEM; st->vd = vd; *stp = st; return 0; } static int mock_display(struct vidisp_st *st, const char *title, const struct vidframe *frame, uint64_t timestamp) { unsigned width, height; (void)title; (void)timestamp; if (!st || !frame) return EINVAL; width = frame->size.w; height = frame->size.h; if (!vidframe_isvalid(frame)) { warning("mock_vidisp: got invalid frame\n"); return EPROTO; } /* verify that the video frame is good */ if (frame->fmt >= VID_FMT_N) return EPROTO; if (width == 0 || width > MAX_WIDTH) return EPROTO; if (height == 0 || height > MAX_HEIGHT) return EPROTO; if (frame->linesize[0] == 0) return EPROTO; ++st->n_frame; if (st->n_frame >= 10) { info("mock_vidisp: got %u frames\n", st->n_frame); if (mock.disph) mock.disph(frame, timestamp, mock.arg); } return 0; } int mock_vidisp_register(struct vidisp **vidispp, mock_vidisp_h *disph, void *arg) { mock.disph = disph; mock.arg = arg; return vidisp_register(vidispp, baresip_vidispl(), "mock-vidisp", mock_disp_alloc, NULL, mock_display, NULL); } baresip-1.0.0/test/mock/mock_vidsrc.c000066400000000000000000000033261372575704200175340ustar00rootroot00000000000000/** * @file mock/mock_vidsrc.c Mock video source * * Copyright (C) 2010 - 2016 Creytiv.com */ #include #include #include #include "../test.h" struct vidsrc_st { const struct vidsrc *vs; /* inheritance */ struct vidframe *frame; struct tmr tmr; uint64_t timestamp; double fps; vidsrc_frame_h *frameh; void *arg; }; static void tmr_handler(void *arg) { struct vidsrc_st *st = arg; tmr_start(&st->tmr, 1000/st->fps, tmr_handler, st); if (st->frameh) st->frameh(st->frame, st->timestamp, st->arg); st->timestamp += VIDEO_TIMEBASE / st->fps; } static void vidsrc_destructor(void *arg) { struct vidsrc_st *st = arg; tmr_cancel(&st->tmr); mem_deref(st->frame); } static int mock_vidsrc_alloc(struct vidsrc_st **stp, const struct vidsrc *vs, struct media_ctx **ctx, struct vidsrc_prm *prm, const struct vidsz *size, const char *fmt, const char *dev, vidsrc_frame_h *frameh, vidsrc_error_h *errorh, void *arg) { struct vidsrc_st *st; int err = 0; (void)ctx; (void)fmt; (void)dev; (void)errorh; if (!stp || !prm || !size || !frameh) return EINVAL; st = mem_zalloc(sizeof(*st), vidsrc_destructor); if (!st) return ENOMEM; st->vs = vs; st->fps = prm->fps; st->frameh = frameh; st->arg = arg; err = vidframe_alloc(&st->frame, prm->fmt, size); if (err) goto out; tmr_start(&st->tmr, 0, tmr_handler, st); info("mock_vidsrc: new instance with size %u x %u (%.2f fps)\n", size->w, size->h, prm->fps); out: if (err) mem_deref(st); else *stp = st; return err; } int mock_vidsrc_register(struct vidsrc **vidsrcp) { return vidsrc_register(vidsrcp, baresip_vidsrcl(), "mock-vidsrc", mock_vidsrc_alloc, NULL); } baresip-1.0.0/test/net.c000066400000000000000000000014461372575704200150670ustar00rootroot00000000000000/** * @file test/net.c Baresip selftest -- networking * * Copyright (C) 2010 - 2016 Creytiv.com */ #include #include #include #include "test.h" static struct config_net default_config = { .af = AF_INET }; static void net_change_handler(void *arg) { unsigned *count = arg; ++*count; info("network changed\n"); } int test_network(void) { struct network *net = NULL; unsigned change_count = 0; int err; err = net_alloc(&net, &default_config); TEST_ERR(err); ASSERT_TRUE(net != NULL); ASSERT_TRUE( net_af_enabled(net, AF_INET)); ASSERT_TRUE(!net_af_enabled(net, AF_INET6)); net_change(net, 1, net_change_handler, &change_count); ASSERT_EQ(0, change_count); net_force_change(net); ASSERT_EQ(1, change_count); out: mem_deref(net); return err; } baresip-1.0.0/test/play.c000066400000000000000000000036151372575704200152460ustar00rootroot00000000000000/** * @file test/play.c Baresip selftest -- audio file player * * Copyright (C) 2010 Creytiv.com */ #include #include #include #include "test.h" #define NUM_SAMPLES 320 /* 8000 Hz, 1 channel, 40ms */ struct test { struct mbuf *mb_samp; }; static struct mbuf *generate_tone(void) { struct mbuf *mb; unsigned i; int err = 0; mb = mbuf_alloc(NUM_SAMPLES * 2); if (!mb) return NULL; for (i=0; ipos = 0; if (err) return mem_deref(mb); else return mb; } static void sample_handler(const void *sampv, size_t sampc, void *arg) { struct test *test = arg; size_t bytec = sampc * 2; int err = 0; if (!test->mb_samp) { test->mb_samp = mbuf_alloc(bytec); ASSERT_TRUE(test->mb_samp != NULL); } /* save the samples that was played */ err = mbuf_write_mem(test->mb_samp, (void *)sampv, bytec); out: /* stop the test? */ if (err || test->mb_samp->end >= (NUM_SAMPLES*2)) re_cancel(); } int test_play(void) { struct auplay *auplay = NULL; struct player *player = NULL; struct play *play = NULL; struct mbuf *mb_tone = NULL; char *play_mod = NULL; char *play_dev = NULL; struct test test = {0}; int err; /* use a mock audio-driver to save the audio-samples */ err = mock_auplay_register(&auplay, baresip_auplayl(), sample_handler, &test); ASSERT_EQ(0, err); err = play_init(&player); ASSERT_EQ(0, err); mb_tone = generate_tone(); ASSERT_TRUE(mb_tone != NULL); err = play_tone(&play, player, mb_tone, 8000, 1, 0, play_mod, play_dev); ASSERT_EQ(0, err); err = re_main_timeout(10000); ASSERT_EQ(0, err); /* verify the audio-samples that was played */ TEST_MEMCMP(mb_tone->buf, NUM_SAMPLES*2, test.mb_samp->buf, test.mb_samp->end); out: mem_deref(test.mb_samp); mem_deref(mb_tone); mem_deref(play); mem_deref(player); mem_deref(auplay); return err; } baresip-1.0.0/test/sip/000077500000000000000000000000001372575704200147235ustar00rootroot00000000000000baresip-1.0.0/test/sip/aor.c000066400000000000000000000030051372575704200156460ustar00rootroot00000000000000/** * @file sip/aor.c Mock SIP server -- SIP Address of Record * * Copyright (C) 2010 - 2016 Creytiv.com */ #include #include #include "sipsrv.h" static void destructor(void *arg) { struct aor *aor = arg; list_flush(&aor->locl); hash_unlink(&aor->he); mem_deref(aor->uri); } static int uri_canon(char **curip, const struct uri *uri) { if (pl_isset(&uri->user)) return re_sdprintf(curip, "%r:%H@%r", &uri->scheme, uri_user_unescape, &uri->user, &uri->host); else return re_sdprintf(curip, "%r:%r", &uri->scheme, &uri->host); } int aor_create(struct sip_server *srv, struct aor **aorp, const struct uri *uri) { struct aor *aor; int err; if (!aorp || !uri) return EINVAL; aor = mem_zalloc(sizeof(*aor), destructor); if (!aor) return ENOMEM; err = uri_canon(&aor->uri, uri); if (err) goto out; hash_append(srv->ht_aor, hash_joaat_str_ci(aor->uri), &aor->he, aor); out: if (err) mem_deref(aor); else *aorp = aor; return err; } int aor_find(struct sip_server *srv, struct aor **aorp, const struct uri *uri) { struct list *lst; struct aor *aor = NULL; struct le *le; char *curi; int err; if (!uri) return EINVAL; err = uri_canon(&curi, uri); if (err) return err; lst = hash_list(srv->ht_aor, hash_joaat_str_ci(curi)); for (le=list_head(lst); le; le=le->next) { aor = le->data; if (!str_casecmp(curi, aor->uri)) break; } mem_deref(curi); if (!le) return ENOENT; if (aorp) *aorp = aor; return 0; } baresip-1.0.0/test/sip/auth.c000066400000000000000000000027541372575704200160400ustar00rootroot00000000000000/** * @file sip/auth.c Mock SIP server -- authentication * * Copyright (C) 2010 - 2016 Creytiv.com */ #include #include #include #include "sipsrv.h" enum { NONCE_MIN_SIZE = 33, }; int auth_print(struct re_printf *pf, const struct auth *auth) { uint8_t key[MD5_SIZE]; uint64_t nv[2]; if (!auth) return EINVAL; nv[0] = time(NULL); nv[1] = auth->srv->secret; md5((uint8_t *)nv, sizeof(nv), key); return re_hprintf(pf, "Digest realm=\"%s\", nonce=\"%w%llx\", " "qop=\"auth\"%s", auth->realm, key, sizeof(key), nv[0], auth->stale ? ", stale=true" : ""); } int auth_chk_nonce(struct sip_server *srv, const struct pl *nonce, uint32_t expires) { uint8_t nkey[MD5_SIZE], ckey[MD5_SIZE]; uint64_t nv[2]; struct pl pl; int64_t age; unsigned i; if (!nonce || !nonce->p || nonce->l < NONCE_MIN_SIZE) return EINVAL; pl = *nonce; for (i=0; isecret; md5((uint8_t *)nv, sizeof(nv), ckey); if (memcmp(nkey, ckey, MD5_SIZE)) return EAUTH; age = time(NULL) - nv[0]; if (age < 0 || age > expires) return ETIMEDOUT; return 0; } int auth_set_realm(struct auth *auth, const char *realm) { size_t len; if (!auth || !realm) return EINVAL; len = strlen(realm); if (len >= sizeof(auth->realm)) return ENOMEM; memcpy(auth->realm, realm, len); auth->realm[len] = '\0'; return 0; } baresip-1.0.0/test/sip/domain.c000066400000000000000000000060701372575704200163410ustar00rootroot00000000000000/** * @file sip/domain.c Mock SIP server -- domain handling * * Copyright (C) 2010 - 2016 Creytiv.com */ #include #include "sipsrv.h" #define DEBUG_MODULE "mock/sipsrv" #define DEBUG_LEVEL 5 #include enum { NONCE_EXPIRES = 300, }; static void destructor(void *arg) { struct domain *dom = arg; hash_unlink(&dom->he); hash_flush(dom->ht_usr); mem_deref(dom->ht_usr); mem_deref(dom->name); } static struct domain *lookup(struct sip_server *srv, const struct pl *name) { struct list *lst; struct le *le; lst = hash_list(srv->ht_dom, hash_joaat_ci(name->p, name->l)); for (le=list_head(lst); le; le=le->next) { struct domain *dom = le->data; if (pl_strcasecmp(name, dom->name)) continue; return dom; } return NULL; } int domain_add(struct sip_server *srv, const char *name) { struct domain *dom; int err; dom = mem_zalloc(sizeof(*dom), destructor); if (!dom) return ENOMEM; err = str_dup(&dom->name, name); if (err) goto out; err = hash_alloc(&dom->ht_usr, 32); if (err) return err; hash_append(srv->ht_dom, hash_joaat_str_ci(name), &dom->he, dom); out: if (err) mem_deref(dom); return err; } int domain_find(struct sip_server *srv, const struct uri *uri) { int err = ENOENT; struct sa addr; if (!uri) return EINVAL; if (!sa_set(&addr, &uri->host, uri->port)) { if (!uri->port) { uint16_t port = SIP_PORT; if (!pl_strcasecmp(&uri->scheme, "sips")) port = SIP_PORT_TLS; sa_set_port(&addr, port); } if (sip_transp_isladdr(srv->sip, SIP_TRANSP_NONE, &addr)) return 0; return ENOENT; } err = lookup(srv, &uri->host) ? 0 : ENOENT; return err; } int domain_auth(struct sip_server *srv, const struct uri *uri, bool user_match, const struct sip_msg *msg, enum sip_hdrid hdrid, struct auth *auth) { struct domain *dom; struct list *lst; struct le *le; int err = ENOENT; if (!uri || !msg || !auth) return EINVAL; dom = lookup(srv, &uri->host); if (!dom) { DEBUG_WARNING("domain not found (%r)\n", &uri->host); return ENOENT; } err = auth_set_realm(auth, dom->name); if (err) return err; auth->stale = false; lst = hash_list(msg->hdrht, hdrid); for (le=list_head(lst); le; le=le->next) { const struct sip_hdr *hdr = le->data; struct httpauth_digest_resp resp; const struct user *usr; if (hdr->id != hdrid) continue; if (httpauth_digest_response_decode(&resp, &hdr->val)) continue; if (pl_strcasecmp(&resp.realm, dom->name)) continue; if (auth_chk_nonce(srv, &resp.nonce, NONCE_EXPIRES)) { auth->stale = true; continue; } auth->stale = false; usr = user_find(dom->ht_usr, &resp.username); if (!usr) { DEBUG_WARNING("user not found (%r)\n", &resp.username); break; } err = httpauth_digest_response_auth(&resp, &msg->met, user_ha1(usr)); if (err) return err; if (user_match && pl_cmp(&resp.username, &uri->user)) return EPERM; return 0; } return EAUTH; } struct domain *domain_lookup(struct sip_server *srv, const char *name) { struct pl pl; pl_set_str(&pl, name); return lookup(srv, &pl); } baresip-1.0.0/test/sip/location.c000066400000000000000000000120401372575704200166740ustar00rootroot00000000000000/** * @file sip/location.c Mock SIP server -- location handling * * Copyright (C) 2010 - 2016 Creytiv.com */ #include #include #include "sipsrv.h" struct loctmp { struct sa src; struct uri duri; char *uri; char *callid; uint32_t expires; uint32_t cseq; double q; }; static void destructor_loctmp(void *arg) { struct loctmp *tmp = arg; mem_deref(tmp->uri); mem_deref(tmp->callid); } static void destructor_location(void *arg) { struct location *loc = arg; list_unlink(&loc->le); mem_deref(loc->uri); mem_deref(loc->callid); mem_deref(loc->tmp); } static int param_handler(const struct pl *pname, const struct pl *pvalue, void *arg) { struct pl *other_params = arg; struct pl other_pvalue = PL_INIT; bool both; if (0 == pl_strcmp(pname, "user")) both = true; else if (0 == pl_strcmp(pname, "ttl")) both = true; else if (0 == pl_strcmp(pname, "method")) both = true; else if (0 == pl_strcmp(pname, "maddr")) both = true; else if (0 == pl_strcmp(pname, "transport")) both = true; else both = false; if (uri_param_get(other_params, pname, &other_pvalue)) return both ? ENOENT : 0; return pl_casecmp(pvalue, &other_pvalue); } static int header_handler(const struct pl *hname, const struct pl *hvalue, void *arg) { struct pl *other_headers = arg; struct pl other_hvalue; int err; err = uri_header_get(other_headers, hname, &other_hvalue); if (err) return err; return pl_casecmp(hvalue, &other_hvalue); } /** * Compare two URIs - see RFC 3261 Section 19.1.4 * * @param l Left-hand URI object * @param r Right-hand URI object * * @return true if match, otherwise false */ static bool my_uri_cmp(const struct uri *l, const struct uri *r) { int err; if (!l || !r) return false; if (l == r) return true; /* A SIP and SIPS URI are never equivalent. */ if (pl_casecmp(&l->scheme, &r->scheme)) return false; /* Comparison of the userinfo of SIP and SIPS URIs is case-sensitive */ if (pl_cmp(&l->user, &r->user)) return false; if (pl_cmp(&l->password, &r->password)) return false; if (pl_casecmp(&l->host, &r->host)) return false; if (l->af != r->af) return false; if (l->port != r->port) return false; /* URI parameters */ err = uri_params_apply(&l->params, param_handler, (void *)&r->params); if (err) return false; err = uri_params_apply(&r->params, param_handler, (void *)&l->params); if (err) return false; /* URI headers */ err = uri_headers_apply(&l->headers, header_handler, (void *)&r->headers); if (err) return false; err = uri_headers_apply(&r->headers, header_handler, (void *)&l->headers); if (err) return false; /* Match */ return true; } static bool cmp_handler(struct le *le, void *arg) { struct location *loc = le->data; return my_uri_cmp(&loc->duri, arg); } int location_update(struct list *locl, const struct sip_msg *msg, const struct sip_addr *contact, uint32_t expires) { struct location *loc, *loc_new = NULL; struct loctmp *tmp; struct pl pl; int err; if (!locl || !msg || !contact) return EINVAL; loc = list_ledata(list_apply(locl, true, cmp_handler, (void *)&contact->uri)); if (!loc) { if (expires == 0) return 0; loc = loc_new = mem_zalloc(sizeof(*loc), destructor_location); if (!loc) return ENOMEM; list_append(locl, &loc->le, loc); } else { if (!pl_strcmp(&msg->callid, loc->callid) && msg->cseq.num <= loc->cseq) return EPROTO; if (expires == 0) { loc->rm = true; return 0; } } tmp = mem_zalloc(sizeof(*tmp), destructor_loctmp); if (!tmp) { err = ENOMEM; goto out; } err = pl_strdup(&tmp->uri, &contact->auri); if (err) goto out; pl_set_str(&pl, tmp->uri); if (uri_decode(&tmp->duri, &pl)) { err = EBADMSG; goto out; } err = pl_strdup(&tmp->callid, &msg->callid); if (err) goto out; if (!msg_param_decode(&contact->params, "q", &pl)) tmp->q = pl_float(&pl); else tmp->q = 1; tmp->cseq = msg->cseq.num; tmp->expires = expires; tmp->src = msg->src; out: if (err) { mem_deref(loc_new); mem_deref(tmp); } else { mem_deref(loc->tmp); loc->tmp = tmp; } return err; } void location_commit(struct list *locl) { time_t now = time(NULL); struct le *le; if (!locl) return; for (le=locl->head; le; ) { struct location *loc = le->data; le = le->next; if (loc->rm) { list_unlink(&loc->le); mem_deref(loc); } else if (loc->tmp) { mem_deref(loc->uri); mem_deref(loc->callid); loc->uri = mem_ref(loc->tmp->uri); loc->callid = mem_ref(loc->tmp->callid); loc->duri = loc->tmp->duri; loc->cseq = loc->tmp->cseq; loc->expires = loc->tmp->expires + now; loc->src = loc->tmp->src; loc->q = loc->tmp->q; loc->tmp = mem_deref(loc->tmp); } } } void location_rollback(struct list *locl) { struct le *le; if (!locl) return; for (le=locl->head; le; ) { struct location *loc = le->data; le = le->next; if (!loc->uri) { list_unlink(&loc->le); mem_deref(loc); } else { loc->tmp = mem_deref(loc->tmp); loc->rm = false; } } } baresip-1.0.0/test/sip/sipsrv.c000066400000000000000000000144321372575704200164210ustar00rootroot00000000000000/** * @file sip/sipsrv.c Mock SIP server * * Copyright (C) 2010 - 2015 Creytiv.com */ #include #include #include #include #include "../test.h" #include "sipsrv.h" #define DEBUG_MODULE "mock/sipsrv" #define DEBUG_LEVEL 5 #include #define LOCAL_PORT 0 #define LOCAL_SECURE_PORT 0 #define EXPIRES_MIN 60 #define EXPIRES_MAX 3600 static int print_contact(struct re_printf *pf, const struct aor *aor) { const uint64_t now = (uint64_t)time(NULL); struct le *le; int err = 0; for (le=aor->locl.head; le; le=le->next) { const struct location *loc = le->data; if (loc->expires < now) continue; err |= re_hprintf(pf, "Contact: <%s>;expires=%lli\r\n", loc->uri, loc->expires - now); } return err; } static bool handle_register(struct sip_server *srv, const struct sip_msg *msg) { struct auth auth = { srv, "", false }; struct sip *sip = srv->sip; struct list *lst; struct aor *aor; struct le *le; int err; /* Request URI */ err = domain_find(srv, &msg->uri); if (err) { if (err == ENOENT) { warning("domain not found\n"); return false; } sip_reply(sip, msg, 500, strerror(err)); warning("domain find error: %s\n", strerror(err)); return true; } /* Authorize */ if (srv->auth_enabled) err = domain_auth(srv, &msg->to.uri, true, msg, SIP_HDR_AUTHORIZATION, &auth); else err = domain_find(srv, &msg->to.uri); if (err && err != EAUTH) { DEBUG_NOTICE("domain auth/find error: %m\n", err); } switch (err) { case 0: break; case EAUTH: sip_replyf(sip, msg, 401, "Unauthorized", "WWW-Authenticate: %H\r\n" "Content-Length: 0\r\n\r\n", auth_print, &auth); return true; case EPERM: sip_reply(sip, msg, 403, "Forbidden"); return true; case ENOENT: sip_reply(sip, msg, 404, "Not Found"); return true; default: sip_reply(sip, msg, 500, strerror(err)); warning("domain error: %s\n", strerror(err)); return true; } /* Find AoR */ err = aor_find(srv, &aor, &msg->to.uri); if (err) { if (err != ENOENT) { sip_reply(sip, msg, 500, strerror(err)); warning("aor find error: %s\n", strerror(err)); return true; } err = aor_create(srv, &aor, &msg->to.uri); if (err) { sip_reply(sip, msg, 500, strerror(err)); warning("aor create error: %s\n", strerror(err)); return true; } } /* Process Contacts */ lst = hash_list(msg->hdrht, SIP_HDR_CONTACT); for (le=list_head(lst); le; le=le->next) { const struct sip_hdr *hdr = le->data; struct sip_addr contact; uint32_t expires; struct pl pl; if (hdr->id != SIP_HDR_CONTACT) continue; err = sip_addr_decode(&contact, &hdr->val); if (err) { sip_reply(sip, msg, 400, "Bad Contact"); goto fail; } if (!msg_param_decode(&contact.params, "expires", &pl)) expires = pl_u32(&pl); else if (pl_isset(&msg->expires)) expires = pl_u32(&msg->expires); else expires = 3600; if (expires > 0 && expires < EXPIRES_MIN) { sip_replyf(sip, msg, 423, "Interval Too Brief", "Min-Expires: %u\r\n" "Content-Length: 0\r\n\r\n", EXPIRES_MIN); goto fail; } expires = min(expires, EXPIRES_MAX); err = location_update(&aor->locl, msg, &contact, expires); if (err) { sip_reply(sip, msg, 500, strerror(err)); if (err != EPROTO) warning("location update error: %s\n", strerror(err)); goto fail; } } location_commit(&aor->locl); sip_treplyf(NULL, NULL, sip, msg, false, 200, "OK", "%H" "Date: %H\r\n" "Content-Length: 0\r\n\r\n", print_contact, aor, fmt_gmtime, NULL); return true; fail: location_rollback(&aor->locl); return true; } static bool sip_msg_handler(const struct sip_msg *msg, void *arg) { struct sip_server *srv = arg; int err = 0; #if 0 DEBUG_NOTICE("[%u] recv %r via %s\n", srv->instance, &msg->met, sip_transp_name(msg->tp)); #endif srv->tp_last = msg->tp; if (0 == pl_strcmp(&msg->met, "REGISTER")) { ++srv->n_register_req; if (handle_register(srv, msg)) goto out; sip_reply(srv->sip, msg, 503, "Server Error"); } else { DEBUG_NOTICE("method not handled (%r)\n", &msg->met); return false; } if (srv->terminate) err = sip_reply(srv->sip, msg, 503, "Server Error"); if (err) { DEBUG_WARNING("could not reply: %m\n", err); } out: if (srv->terminate) { if (srv->exith) srv->exith(srv->arg); } return true; } static void destructor(void *arg) { struct sip_server *srv = arg; srv->terminate = true; sip_close(srv->sip, false); mem_deref(srv->sip); hash_flush(srv->ht_aor); mem_deref(srv->ht_aor); hash_flush(srv->ht_dom); mem_deref(srv->ht_dom); } int sip_server_alloc(struct sip_server **srvp, sip_exit_h *exith, void *arg) { struct sip_server *srv; struct sa laddr, laddrs; struct tls *tls = NULL; int err; if (!srvp) return EINVAL; srv = mem_zalloc(sizeof(*srv), destructor); if (!srv) return ENOMEM; err = sa_set_str(&laddr, "127.0.0.1", LOCAL_PORT); err |= sa_set_str(&laddrs, "127.0.0.1", LOCAL_SECURE_PORT); if (err) goto out; err = sip_alloc(&srv->sip, NULL, 16, 16, 16, "mock SIP server", NULL, NULL); if (err) goto out; err |= sip_transp_add(srv->sip, SIP_TRANSP_UDP, &laddr); err |= sip_transp_add(srv->sip, SIP_TRANSP_TCP, &laddr); if (err) goto out; #ifdef USE_TLS err = tls_alloc(&tls, TLS_METHOD_SSLV23, NULL, NULL); if (err) goto out; err = tls_set_certificate(tls, test_certificate, strlen(test_certificate)); if (err) goto out; err |= sip_transp_add(srv->sip, SIP_TRANSP_TLS, &laddrs, tls); #endif if (err) goto out; err = sip_listen(&srv->lsnr, srv->sip, true, sip_msg_handler, srv); if (err) goto out; srv->secret = rand_u64(); err = hash_alloc(&srv->ht_dom, 32); if (err) goto out; err = hash_alloc(&srv->ht_aor, 32); if (err) goto out; srv->exith = exith; srv->arg = arg; out: mem_deref(tls); if (err) mem_deref(srv); else *srvp = srv; return err; } int sip_server_uri(struct sip_server *srv, char *uri, size_t sz, enum sip_transp tp) { struct sa laddr; int err; if (!srv || !uri || !sz) return EINVAL; err = sip_transp_laddr(srv->sip, &laddr, tp, NULL); if (err) return err; /* NOTE: angel brackets needed to parse ;transport parameter */ if (re_snprintf(uri, sz, "", &laddr, sip_transp_param(tp)) < 0) return ENOMEM; return 0; } baresip-1.0.0/test/sip/sipsrv.h000066400000000000000000000043071372575704200164260ustar00rootroot00000000000000/** * @file sip/sipsrv.h Mock SIP server -- interface * * Copyright (C) 2010 - 2016 Creytiv.com */ struct auth; /* * SIP Server */ struct sip_server { struct sip *sip; struct sip_lsnr *lsnr; bool auth_enabled; bool terminate; unsigned instance; unsigned n_register_req; enum sip_transp tp_last; uint64_t secret; struct hash *ht_dom; struct hash *ht_aor; sip_exit_h *exith; void *arg; }; int sip_server_alloc(struct sip_server **srvp, sip_exit_h *exith, void *arg); int sip_server_uri(struct sip_server *srv, char *uri, size_t sz, enum sip_transp tp); /* * AoR */ struct aor { struct le he; struct list locl; char *uri; }; int aor_create(struct sip_server *srv, struct aor **aorp, const struct uri *uri); int aor_find(struct sip_server *srv, struct aor **aorp, const struct uri *uri); /* * Auth */ struct auth { const struct sip_server *srv; char realm[256]; bool stale; }; int auth_print(struct re_printf *pf, const struct auth *auth); int auth_chk_nonce(struct sip_server *srv, const struct pl *nonce, uint32_t expires); int auth_set_realm(struct auth *auth, const char *realm); /* * Domain */ struct domain { struct le he; struct hash *ht_usr; char *name; }; int domain_add(struct sip_server *srv, const char *name); int domain_find(struct sip_server *srv, const struct uri *uri); int domain_auth(struct sip_server *srv, const struct uri *uri, bool user_match, const struct sip_msg *msg, enum sip_hdrid hdrid, struct auth *auth); struct domain *domain_lookup(struct sip_server *srv, const char *name); /* * Location */ struct location { struct le le; struct sa src; struct uri duri; char *uri; char *callid; struct loctmp *tmp; uint64_t expires; uint32_t cseq; double q; bool rm; }; int location_update(struct list *locl, const struct sip_msg *msg, const struct sip_addr *contact, uint32_t expires); void location_commit(struct list *locl); void location_rollback(struct list *locl); /* * User */ struct user; int user_add(struct hash *ht, const char *username, const char *password, const char *realm); struct user *user_find(struct hash *ht, const struct pl *name); const uint8_t *user_ha1(const struct user *usr); baresip-1.0.0/test/sip/user.c000066400000000000000000000023671372575704200160550ustar00rootroot00000000000000/** * @file sip/user.c Mock SIP server -- user handling * * Copyright (C) 2010 - 2016 Creytiv.com */ #include #include "sipsrv.h" struct user { struct le he; uint8_t ha1[MD5_SIZE]; char *name; }; static void destructor(void *arg) { struct user *usr = arg; hash_unlink(&usr->he); mem_deref(usr->name); } int user_add(struct hash *ht, const char *username, const char *password, const char *realm) { struct user *usr; int err; usr = mem_zalloc(sizeof(*usr), destructor); if (!usr) { err = ENOMEM; goto out; } err = str_dup(&usr->name, username); if (err) { goto out; } err = md5_printf(usr->ha1, "%s:%s:%s", username, realm, password); if (err) { goto out; } hash_append(ht, hash_joaat_str(username), &usr->he, usr); out: if (err) { mem_deref(usr); } return err; } struct user *user_find(struct hash *ht, const struct pl *name) { struct list *lst; struct le *le; if (!ht || !name) return NULL; lst = hash_list(ht, hash_joaat((uint8_t *)name->p, name->l)); for (le=list_head(lst); le; le=le->next) { struct user *usr = le->data; if (pl_strcmp(name, usr->name)) continue; return usr; } return NULL; } const uint8_t *user_ha1(const struct user *usr) { return usr ? usr->ha1 : NULL; } baresip-1.0.0/test/srcs.mk000066400000000000000000000016071372575704200154370ustar00rootroot00000000000000# # srcs.mk All application source files. # # Copyright (C) 2010 Creytiv.com # # # Test-cases: # TEST_SRCS += account.c TEST_SRCS += aulevel.c TEST_SRCS += call.c TEST_SRCS += cmd.c TEST_SRCS += contact.c TEST_SRCS += event.c TEST_SRCS += message.c TEST_SRCS += net.c TEST_SRCS += play.c TEST_SRCS += ua.c TEST_SRCS += video.c # # Mocks # TEST_SRCS += mock/dnssrv.c TEST_SRCS += sip/aor.c TEST_SRCS += sip/auth.c TEST_SRCS += sip/domain.c TEST_SRCS += sip/location.c TEST_SRCS += sip/sipsrv.c TEST_SRCS += sip/user.c ifneq ($(USE_TLS),) TEST_SRCS += mock/cert.c endif TEST_SRCS += mock/mock_aucodec.c TEST_SRCS += mock/mock_aufilt.c TEST_SRCS += mock/mock_auplay.c TEST_SRCS += mock/mock_ausrc.c TEST_SRCS += mock/mock_mnat.c TEST_SRCS += mock/mock_menc.c TEST_SRCS += mock/mock_vidsrc.c TEST_SRCS += mock/mock_vidcodec.c TEST_SRCS += mock/mock_vidisp.c TEST_SRCS += test.c TEST_SRCS += main.c baresip-1.0.0/test/test.c000066400000000000000000000036651372575704200152650ustar00rootroot00000000000000/** * @file test.c Selftest for Baresip core * * Copyright (C) 2010 Creytiv.com */ #include #include #include #include "test.h" static void timeout_handler(void *arg) { int *err = arg; warning("selftest: re_main() loop timed out -- test hung..\n"); *err = ETIMEDOUT; re_cancel(); } static void signal_handler(int sig) { re_fprintf(stderr, "test interrupted by signal %d\n", sig); re_cancel(); } int re_main_timeout(uint32_t timeout_ms) { struct tmr tmr; int err = 0; tmr_init(&tmr); tmr_start(&tmr, timeout_ms, timeout_handler, &err); re_main(signal_handler); tmr_cancel(&tmr); return err; } bool test_cmp_double(double a, double b, double precision) { return fabs(a - b) < precision; } void test_hexdump_dual(FILE *f, const void *ep, size_t elen, const void *ap, size_t alen) { const uint8_t *ebuf = ep; const uint8_t *abuf = ap; size_t i, j, len; #define WIDTH 8 if (!f || !ep || !ap) return; len = max(elen, alen); (void)re_fprintf(f, "\nOffset: Expected (%zu bytes): " " Actual (%zu bytes):\n", elen, alen); for (i=0; i < len; i += WIDTH) { (void)re_fprintf(f, "0x%04zx ", i); for (j=0; j= alen; if (wrong) (void)re_fprintf(f, "\x1b[35m"); (void)re_fprintf(f, " %02x", ebuf[pos]); if (wrong) (void)re_fprintf(f, "\x1b[;m"); } else (void)re_fprintf(f, " "); } (void)re_fprintf(f, " "); for (j=0; j #include #include #include "test.h" #include "sip/sipsrv.h" #define MAGIC 0x9044bbfc struct test { struct sip_server *srvv[16]; size_t srvc; struct ua *ua; int err; unsigned got_register_ok; unsigned n_resp; uint32_t magic; enum sip_transp tp_resp; }; static void test_init(struct test *t) { memset(t, 0, sizeof(*t)); t->magic = MAGIC; } static void test_reset(struct test *t) { size_t i; for (i=0; isrvv); i++) mem_deref(t->srvv[i]); mem_deref(t->ua); memset(t, 0, sizeof(*t)); } static void test_abort(struct test *t, int err) { t->err = err; re_cancel(); } static void ua_event_handler(struct ua *ua, enum ua_event ev, struct call *call, const char *prm, void *arg) { struct test *t = arg; size_t i; int err = 0; (void)call; (void)prm; ASSERT_TRUE(t != NULL); if (ua != t->ua) return; if (ev == UA_EVENT_REGISTER_OK) { info("event: Register OK!\n"); ++t->got_register_ok; /* verify register success */ ASSERT_TRUE(ua_isregistered(t->ua)); /* Terminate SIP Server, then De-REGISTER */ for (i=0; isrvc; i++) t->srvv[i]->terminate = true; t->ua = mem_deref(t->ua); } else if (ev == UA_EVENT_REGISTER_FAIL) { err = EAUTH; re_cancel(); } out: if (err) { warning("selftest: event handler error: %m\n", err); t->err = err; } } static void sip_server_exit_handler(void *arg) { (void)arg; re_cancel(); } static int reg(enum sip_transp tp) { struct test t; char aor[256]; int err; memset(&t, 0, sizeof(t)); err = sip_server_alloc(&t.srvv[0], sip_server_exit_handler, NULL); if (err) { warning("failed to create sip server (%d/%m)\n", err, err); goto out; } t.srvc = 1; err = sip_server_uri(t.srvv[0], aor, sizeof(aor), tp); TEST_ERR(err); err = ua_alloc(&t.ua, aor); TEST_ERR(err); err = ua_register(t.ua); TEST_ERR(err); err = uag_event_register(ua_event_handler, &t); if (err) goto out; /* run main-loop with timeout, wait for events */ err = re_main_timeout(5000); if (err) goto out; if (t.err) err = t.err; ASSERT_TRUE(t.srvv[0]->n_register_req > 0); ASSERT_EQ(tp, t.srvv[0]->tp_last); ASSERT_TRUE(t.got_register_ok > 0); out: if (err) { warning("selftest: ua_register test failed (%m)\n", err); } uag_event_unregister(ua_event_handler); test_reset(&t); return err; } int test_ua_register(void) { int err = 0; err = ua_init("test", true, true, true); TEST_ERR(err); err |= reg(SIP_TRANSP_UDP); err |= reg(SIP_TRANSP_TCP); #ifdef USE_TLS err |= reg(SIP_TRANSP_TLS); #endif ua_stop_all(true); ua_close(); out: return err; } int test_ua_alloc(void) { struct ua *ua; struct mbuf *mb = mbuf_alloc(512); uint32_t n_uas = list_count(uag_list()); int err = 0; /* make sure we dont have that UA already */ ASSERT_TRUE(NULL == uag_find_aor("sip:user@127.0.0.1")); err = ua_alloc(&ua, "Foo ;regint=0"); if (err) return err; /* verify this UA-instance */ ASSERT_TRUE(!ua_isregistered(ua)); ASSERT_STREQ("sip:user@127.0.0.1", ua_aor(ua)); ASSERT_TRUE(NULL == ua_call(ua)); /* verify global UA keeper */ ASSERT_EQ((n_uas + 1), list_count(uag_list())); ASSERT_TRUE(ua == uag_find_aor("sip:user@127.0.0.1")); /* verify URI complete function */ err = ua_uri_complete(ua, mb, "bob"); ASSERT_EQ(0, err); TEST_STRCMP("sip:bob@127.0.0.1", 17, mb->buf, mb->end); mem_deref(ua); ASSERT_EQ((n_uas), list_count(uag_list())); out: mem_deref(mb); return err; } int test_uag_find_param(void) { struct ua *ua1 = NULL, *ua2 = NULL; int err = 0; ASSERT_TRUE(NULL == uag_find_param("not", "found")); err = ua_alloc(&ua1, ";regint=0;abc"); err |= ua_alloc(&ua2, ";regint=0;def=123"); if (err) goto out; ASSERT_TRUE(ua1 == uag_find_param("abc", NULL)); ASSERT_TRUE(NULL == uag_find_param("abc", "123")); ASSERT_TRUE(ua2 == uag_find_param("def", NULL)); ASSERT_TRUE(ua2 == uag_find_param("def", "123")); ASSERT_TRUE(NULL == uag_find_param("not", "found")); out: mem_deref(ua2); mem_deref(ua1); return err; } static const char *_sip_transp_srvid(enum sip_transp tp) { switch (tp) { case SIP_TRANSP_UDP: return "_sip._udp"; case SIP_TRANSP_TCP: return "_sip._tcp"; case SIP_TRANSP_TLS: return "_sips._tcp"; default: return "???"; } } static int reg_dns(enum sip_transp tp) { struct dns_server *dnssrv = NULL; struct test t; const char *domain = "test.invalid"; struct network *net = baresip_network(); unsigned server_count = 1; char aor[256]; char srv[256]; size_t i; int err; memset(&t, 0, sizeof(t)); /* * Setup server-side mocks: */ err = dns_server_alloc(&dnssrv, true); TEST_ERR(err); info("| DNS-server on %J\n", &dnssrv->addr); /* NOTE: must be done before ua_init() */ err = net_use_nameserver(net, &dnssrv->addr, 1); TEST_ERR(err); for (i=0; isip, &sip_addr, tp, NULL); TEST_ERR(err); info("| SIP-server on %J\n", &sip_addr); re_snprintf(arec, sizeof(arec), "alpha%u.%s", i+1, domain); re_snprintf(srv, sizeof(srv), "%s.%s", _sip_transp_srvid(tp), domain); err = dns_server_add_srv(dnssrv, srv, 20, 0, sa_port(&sip_addr), arec); TEST_ERR(err); err = dns_server_add_a(dnssrv, arec, sa_in(&sip_addr)); TEST_ERR(err); } t.srvc = server_count; /* NOTE: angel brackets needed to parse ;transport parameter */ if (re_snprintf(aor, sizeof(aor), "", domain, sip_transp_name(tp)) < 0) return ENOMEM; /* * Start SIP client: */ err = ua_init("test", true, true, true); TEST_ERR(err); err = ua_alloc(&t.ua, aor); TEST_ERR(err); err = ua_register(t.ua); TEST_ERR(err); err = uag_event_register(ua_event_handler, &t); if (err) goto out; /* run main-loop with timeout, wait for events */ err = re_main_timeout(5000); if (err) goto out; if (t.err) err = t.err; /* verify that all SIP requests was sent to the first * SIP-server. */ ASSERT_TRUE(t.srvv[0]->n_register_req > 0); ASSERT_EQ(tp, t.srvv[0]->tp_last); ASSERT_TRUE(t.got_register_ok > 0); out: if (err) { warning("selftest: ua_register test failed (%m)\n", err); } uag_event_unregister(ua_event_handler); test_reset(&t); ua_stop_all(true); ua_close(); mem_deref(dnssrv); return err; } int test_ua_register_dns(void) { int err = 0; err |= reg_dns(SIP_TRANSP_UDP); TEST_ERR(err); err |= reg_dns(SIP_TRANSP_TCP); TEST_ERR(err); #ifdef USE_TLS err |= reg_dns(SIP_TRANSP_TLS); TEST_ERR(err); #endif out: return err; } #define USER "alfredh" #define PASS "pass@word" #define DOMAIN "localhost" static int reg_auth(enum sip_transp tp) { struct sa laddr; struct test t; char aor[256]; int err; memset(&t, 0, sizeof(t)); err = sip_server_alloc(&t.srvv[0], sip_server_exit_handler, NULL); if (err) { warning("failed to create sip server (%d/%m)\n", err, err); goto out; } t.srvc = 1; err = domain_add(t.srvv[0], DOMAIN); TEST_ERR(err); err = user_add(domain_lookup(t.srvv[0], DOMAIN)->ht_usr, USER, PASS, DOMAIN); TEST_ERR(err); t.srvv[0]->auth_enabled = true; err = sip_transp_laddr(t.srvv[0]->sip, &laddr, tp, NULL); if (err) return err; /* NOTE: angel brackets needed to parse ;transport parameter */ if (re_snprintf(aor, sizeof(aor), "" ";auth_pass=%s" ";outbound=\"sip:%J;transport=%s\"", USER, DOMAIN, PASS, &laddr, sip_transp_name(tp)) < 0) return ENOMEM; err = ua_alloc(&t.ua, aor); TEST_ERR(err); err = ua_register(t.ua); TEST_ERR(err); err = uag_event_register(ua_event_handler, &t); if (err) goto out; /* run main-loop with timeout, wait for events */ err = re_main_timeout(5000); if (err) goto out; if (t.err) { err = t.err; goto out; } ASSERT_TRUE(t.srvv[0]->n_register_req > 0); ASSERT_EQ(tp, t.srvv[0]->tp_last); ASSERT_TRUE(t.got_register_ok > 0); out: if (err) { warning("selftest: ua_register test failed (%m)\n", err); } uag_event_unregister(ua_event_handler); test_reset(&t); return err; } int test_ua_register_auth(void) { int err; err = ua_init("test", true, true, true); TEST_ERR(err); err |= reg_auth(SIP_TRANSP_UDP); TEST_ERR(err); err |= reg_auth(SIP_TRANSP_TCP); TEST_ERR(err); #ifdef USE_TLS err |= reg_auth(SIP_TRANSP_TLS); TEST_ERR(err); #endif out: ua_stop_all(true); ua_close(); return err; } static int reg_auth_dns(enum sip_transp tp) { struct network *net = baresip_network(); struct dns_server *dnssrv = NULL; struct test t; const char *username = "alfredh"; const char *password = "password"; const char *domain = "test.invalid"; unsigned server_count = 2; char aor[256]; char srv[256]; unsigned i; unsigned total_req = 0; int err; memset(&t, 0, sizeof(t)); /* * Setup server-side mocks: */ err = dns_server_alloc(&dnssrv, true); TEST_ERR(err); info("| DNS-server on %J\n", &dnssrv->addr); /* NOTE: must be done before ua_init() */ err = net_use_nameserver(net, &dnssrv->addr, 1); TEST_ERR(err); for (i=0; iinstance = i; #if 1 /* Comment this out to have different random secrets * on each SIP-Server instance */ t.srvv[i]->secret = 42; #endif err = domain_add(t.srvv[i], domain); if (err) goto out; err = user_add(domain_lookup(t.srvv[i], domain)->ht_usr, username, password, domain); TEST_ERR(err); t.srvv[i]->auth_enabled = true; err = sip_transp_laddr(t.srvv[i]->sip, &sip_addr, tp, NULL); TEST_ERR(err); info("| SIP-server on %J\n", &sip_addr); re_snprintf(arec, sizeof(arec), "alpha%u.%s", i+1, domain); re_snprintf(srv, sizeof(srv), "%s.%s", _sip_transp_srvid(tp), domain); err = dns_server_add_srv(dnssrv, srv, 20, 0, sa_port(&sip_addr), arec); TEST_ERR(err); err = dns_server_add_a(dnssrv, arec, sa_in(&sip_addr)); TEST_ERR(err); } t.srvc = server_count; /* NOTE: angel brackets needed to parse ;transport parameter */ if (re_snprintf(aor, sizeof(aor), ";auth_pass=%s", username, domain, sip_transp_name(tp), password) < 0) return ENOMEM; /* * Start SIP client: */ err = ua_init("test", true, true, true); TEST_ERR(err); err = ua_alloc(&t.ua, aor); TEST_ERR(err); err = ua_register(t.ua); TEST_ERR(err); err = uag_event_register(ua_event_handler, &t); if (err) goto out; /* run main-loop with timeout, wait for events */ err = re_main_timeout(5000); if (err) goto out; if (t.err) { err = t.err; goto out; } /* verify that all SIP requests was sent to the * SIP-servers. */ for (i=0; in_register_req; if (t.srvv[i]->n_register_req) { ASSERT_EQ(tp, t.srvv[i]->tp_last); } } ASSERT_TRUE(total_req >= 2); ASSERT_TRUE(t.got_register_ok > 0); out: if (err) { warning("selftest: ua_register test failed (%m)\n", err); } uag_event_unregister(ua_event_handler); test_reset(&t); ua_stop_all(true); ua_close(); mem_deref(dnssrv); return err; } int test_ua_register_auth_dns(void) { int err = 0; err |= reg_auth_dns(SIP_TRANSP_UDP); TEST_ERR(err); err |= reg_auth_dns(SIP_TRANSP_TCP); TEST_ERR(err); #ifdef USE_TLS err |= reg_auth_dns(SIP_TRANSP_TLS); TEST_ERR(err); #endif out: return err; } static void options_resp_handler(int err, const struct sip_msg *msg, void *arg) { struct test *t = arg; const struct sip_hdr *hdr; struct pl content; uint32_t clen; ASSERT_EQ(MAGIC, t->magic); if (err) { test_abort(t, err); return; } if (msg->scode != 200) { test_abort(t, EPROTO); return; } ++t->n_resp; t->tp_resp = msg->tp; /* Verify SIP headers */ ASSERT_TRUE(sip_msg_hdr_has_value(msg, SIP_HDR_ALLOW, "INVITE")); ASSERT_TRUE(sip_msg_hdr_has_value(msg, SIP_HDR_ALLOW, "ACK")); ASSERT_TRUE(sip_msg_hdr_has_value(msg, SIP_HDR_ALLOW, "BYE")); ASSERT_TRUE(sip_msg_hdr_has_value(msg, SIP_HDR_ALLOW, "CANCEL")); hdr = sip_msg_hdr(msg, SIP_HDR_CONTACT); ASSERT_TRUE(hdr != NULL); ASSERT_TRUE(hdr->val.l != 0); ASSERT_EQ(0, pl_strcasecmp(&msg->ctyp.type, "application")); ASSERT_EQ(0, pl_strcasecmp(&msg->ctyp.subtype, "sdp")); clen = pl_u32(&msg->clen); ASSERT_TRUE(clen > 0); /* Verify the SDP content */ pl_set_mbuf(&content, msg->mb); ASSERT_EQ(0, re_regex(content.p, content.l, "v=0")); ASSERT_EQ(0, re_regex(content.p, content.l, "a=tool:baresip")); ASSERT_EQ(0, re_regex(content.p, content.l, "m=audio")); out: if (err) t->err = err; re_cancel(); } static int test_ua_options_base(enum sip_transp transp) { struct test t; struct sa laddr; char uri[256]; int n, err = 0; test_init(&t); err = ua_init("test", transp == SIP_TRANSP_UDP, transp == SIP_TRANSP_TCP, false); TEST_ERR(err); err = sip_transp_laddr(uag_sip(), &laddr, transp, NULL); TEST_ERR(err); err = ua_alloc(&t.ua, "Foo ;regint=0"); TEST_ERR(err); /* NOTE: no angle brackets in the Request URI */ n = re_snprintf(uri, sizeof(uri), "sip:user@127.0.0.1:%u%s", sa_port(&laddr), sip_transp_param(transp)); ASSERT_TRUE(n > 0); err = ua_options_send(t.ua, uri, options_resp_handler, &t); TEST_ERR(err); /* run main-loop with timeout, wait for events */ err = re_main_timeout(5000); if (err) goto out; if (t.err) { err = t.err; goto out; } /* verify after test is complete */ ASSERT_EQ(1, t.n_resp); ASSERT_EQ(transp, t.tp_resp); out: test_reset(&t); ua_stop_all(true); ua_close(); return err; } int test_ua_options(void) { int err = 0; err |= test_ua_options_base(SIP_TRANSP_UDP); TEST_ERR(err); err |= test_ua_options_base(SIP_TRANSP_TCP); TEST_ERR(err); out: return err; } baresip-1.0.0/test/video.c000066400000000000000000000014071372575704200154040ustar00rootroot00000000000000/** * @file test/video.c Baresip selftest -- video * * Copyright (C) 2010 - 2017 Creytiv.com */ #include #include #include "test.h" #define DEBUG_MODULE "video" #define DEBUG_LEVEL 5 #include int test_video(void) { int err = 0; ASSERT_EQ(0, video_calc_rtp_timestamp_fix(0)); ASSERT_EQ(90, video_calc_rtp_timestamp_fix(1000)); ASSERT_EQ(90000, video_calc_rtp_timestamp_fix(1000000)); ASSERT_EQ(90000000, video_calc_rtp_timestamp_fix(1000000000)); ASSERT_EQ(0, video_calc_timebase_timestamp(0)); ASSERT_EQ(1000, video_calc_timebase_timestamp(90)); ASSERT_EQ(1000000, video_calc_timebase_timestamp(90000)); ASSERT_EQ(1000000000, video_calc_timebase_timestamp(90000000)); out: return err; }